OpenCores
URL https://opencores.org/ocsvn/amber/amber/trunk

Subversion Repositories amber

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /amber
    from Rev 78 to Rev 77
    Reverse comparison

Rev 78 → Rev 77

/trunk/hw/fpga/bin/Makefile
38,9 → 38,9
# //
# ----------------------------------------------------------------
 
# ----------------------------------------------------
# ----------------------------------------------------
# Environment Configuration
# ----------------------------------------------------
# ----------------------------------------------------
 
# Directories
BIN_FOLDER = ../bin
61,7 → 61,7
BOOT_LOADER_DEF = BOOT_LOADER_ETHMAC
else
BOOT_LOADER_DIR = ../../../sw/boot-loader-serial
BOOT_LOADER_DEF =
BOOT_LOADER_DEF =
endif
 
VERILOG_INCLUDE_PATH = ../../vlog/lib ../../vlog/tb $(BOOT_LOADER_DIR)
71,9 → 71,9
 
 
 
# ----------------------------------------------------
# ----------------------------------------------------
# Build Configuration
# ----------------------------------------------------
# ----------------------------------------------------
 
# AMBER_CLK_DIVIDER
# Sets the system clock frequency
86,7 → 86,7
ifdef A25
AMBER_CORE = AMBER_A25_CORE
else
AMBER_CORE = AMBER_A23_CORE
AMBER_CORE = AMBER_A23_CORE
endif
 
 
93,7 → 93,7
 
# The spartan6 device used on SP605 Development board
XILINX_FPGA = xc6slx45tfgg484-3
XST_DEFINES = XILINX_FPGA XILINX_SPARTAN6_FPGA $(AMBER_CORE) AMBER_CLK_DIVIDER=21 $(BOOT_LOADER_DEF)
XST_DEFINES = XILINX_FPGA XILINX_SPARTAN6_FPGA $(AMBER_CORE) AMBER_CLK_DIVIDER=20 $(BOOT_LOADER_DEF)
# Xilinx placement and timing constraints
XST_CONST_FILE = xs6_constraints.ucf
# List of verilog source files for Xilinx Spartan-6 device
101,14 → 101,14
 
 
 
# ----------------------------------------------------
# Focus on speed or area
# ----------------------------------------------------
# ----------------------------------------------------
# Focus on speed or area
# ----------------------------------------------------
#OPT = area
OPT = speed
 
 
# ----------------------------------------------------
# ----------------------------------------------------
# Xilinx XST Compile Options
# ----------------------------------------------------
 
203,10 → 203,10
cd $(WORK_FOLDER); \
trce -v 5 -l 5 -n 5 -xml $(RTL_TOP) $(RTL_TOP).ncd \
-o $(WORK_FOLDER)/$(RTL_TOP).trc.twr \
$(RTL_TOP).pcf
$(RTL_TOP).pcf
cp $(WORK_FOLDER)/$(RTL_TOP).trc.twr $(LOG_FOLDER)/$(RTL_TOP).trc.$(RUN_ID).twr
 
 
# ----------------------------------------------------
# bitgen
# ----------------------------------------------------
252,8 → 252,8
$(RTL_TOP).ngd \
$(RTL_TOP).pcf
cp $(WORK_FOLDER)/$(RTL_TOP).map.mrp $(LOG_FOLDER)/$(RTL_TOP).map.$(RUN_ID).mrp
 
 
# ----------------------------------------------------
# ngdbuild
# ----------------------------------------------------
261,7 → 261,7
cd $(WORK_FOLDER); \
ngdbuild -intstyle xflow -verbose -p $(XILINX_FPGA) \
-dd _ngo -nt on \
-uc $(BIN_FOLDER)/$(XST_CONST_FILE) $(RTL_TOP).ngc $(RTL_TOP).ngd
-uc $(BIN_FOLDER)/$(XST_CONST_FILE) $(RTL_TOP).ngc $(RTL_TOP).ngd
 
 
# ----------------------------------------------------
/trunk/hw/vlog/system/system.v
41,11 → 41,11
//////////////////////////////////////////////////////////////////
 
 
module system
module system
(
input brd_rst,
input brd_clk_n,
input brd_clk_p,
input brd_clk_n,
input brd_clk_p,
 
 
// UART 0 Interface
70,14 → 70,15
output ddr3_ck_p,
output ddr3_ck_n,
 
`ifdef XILINX_SPARTAN6_FPGA
`ifdef XILINX_SPARTAN6_FPGA
inout mcb3_rzq,
//inout mcb3_zio,
`endif
 
 
// Ethmac B100 MAC to PHY Interface
input mtx_clk_pad_i,
output [3:0] mtxd_pad_o,
output [3:0] mtxd_pad_o,
output mtxen_pad_o,
output mtxerr_pad_o,
input mrx_clk_pad_i,
87,7 → 88,7
input mcoll_pad_i,
input mcrs_pad_i,
inout md_pad_io,
output mdc_pad_o,
output mdc_pad_o,
output phy_reset_n,
 
output [3:0] led
95,7 → 96,7
 
 
wire sys_clk; // System clock
wire sys_rst; // Active high reset, synchronous to sys_clk
wire sys_rst; // Active low reset, synchronous to sys_clk
wire clk_200; // 200MHz from board
 
 
102,7 → 103,7
// ======================================
// Xilinx MCB DDR3 Controller connections
// ======================================
`ifdef XILINX_SPARTAN6_FPGA
`ifdef XILINX_SPARTAN6_FPGA
wire c3_p0_cmd_en;
wire [2:0] c3_p0_cmd_instr;
wire [29:0] c3_p0_cmd_byte_addr;
166,25 → 167,25
wire [WB_SLAVES-1:0] s_wb_ack ;
wire [WB_SLAVES-1:0] s_wb_err ;
 
wire [31:0] emm_wb_adr;
wire [3:0] emm_wb_sel;
wire emm_wb_we;
wire [31:0] emm_wb_rdat;
wire [31:0] emm_wb_wdat;
wire emm_wb_cyc;
wire emm_wb_stb;
wire emm_wb_ack;
wire emm_wb_err;
wire [31:0] emm_wb_adr;
wire [3:0] emm_wb_sel;
wire emm_wb_we;
wire [31:0] emm_wb_rdat;
wire [31:0] emm_wb_wdat;
wire emm_wb_cyc;
wire emm_wb_stb;
wire emm_wb_ack;
wire emm_wb_err;
 
wire [31:0] ems_wb_adr;
wire [3:0] ems_wb_sel;
wire ems_wb_we;
wire [31:0] ems_wb_rdat;
wire [31:0] ems_wb_wdat;
wire ems_wb_cyc;
wire ems_wb_stb;
wire ems_wb_ack;
wire ems_wb_err;
wire [31:0] ems_wb_adr;
wire [3:0] ems_wb_sel;
wire ems_wb_we;
wire [31:0] ems_wb_rdat;
wire [31:0] ems_wb_wdat;
wire ems_wb_cyc;
wire ems_wb_stb;
wire ems_wb_ack;
wire ems_wb_err;
 
 
// ======================================
205,15 → 206,15
// ======================================
clocks_resets u_clocks_resets (
.i_brd_rst ( brd_rst ),
.i_brd_clk_n ( brd_clk_n ),
.i_brd_clk_p ( brd_clk_p ),
.i_brd_clk_n ( brd_clk_n ),
.i_brd_clk_p ( brd_clk_p ),
.i_ddr_calib_done ( phy_init_done ),
.o_sys_rst ( sys_rst ),
.o_sys_clk ( sys_clk ),
.o_clk_200 ( clk_200 )
);
 
 
// -------------------------------------------------------------
// Instantiate Amber Processor Core
// -------------------------------------------------------------
223,12 → 224,12
a23_core u_amber (
`endif
.i_clk ( sys_clk ),
 
.i_irq ( amber_irq ),
.i_firq ( amber_firq ),
 
.i_system_rdy ( system_rdy ),
 
.o_wb_adr ( m_wb_adr [1] ),
.o_wb_sel ( m_wb_sel [1] ),
.o_wb_we ( m_wb_we [1] ),
244,31 → 245,32
// -------------------------------------------------------------
// Instantiate B100 Ethernet MAC
// -------------------------------------------------------------
eth_top u_eth_top (
.wb_clk_i ( sys_clk ),
.wb_rst_i ( sys_rst ),
 
// WISHBONE slave
.wb_adr_i ( ems_wb_adr [11:2] ),
.wb_sel_i ( ems_wb_sel ),
.wb_we_i ( ems_wb_we ),
.wb_cyc_i ( ems_wb_cyc ),
.wb_stb_i ( ems_wb_stb ),
.wb_ack_o ( ems_wb_ack ),
.wb_dat_i ( ems_wb_wdat ),
.wb_dat_o ( ems_wb_rdat ),
.wb_err_o ( ems_wb_err ),
.wb_adr_i ( ems_wb_adr [11:2] ),
.wb_sel_i ( ems_wb_sel ),
.wb_we_i ( ems_wb_we ),
.wb_cyc_i ( ems_wb_cyc ),
.wb_stb_i ( ems_wb_stb ),
.wb_ack_o ( ems_wb_ack ),
.wb_dat_i ( ems_wb_wdat ),
.wb_dat_o ( ems_wb_rdat ),
.wb_err_o ( ems_wb_err ),
 
// WISHBONE master
.m_wb_adr_o ( emm_wb_adr ),
.m_wb_sel_o ( emm_wb_sel ),
.m_wb_we_o ( emm_wb_we ),
.m_wb_dat_i ( emm_wb_rdat ),
.m_wb_dat_o ( emm_wb_wdat ),
.m_wb_cyc_o ( emm_wb_cyc ),
.m_wb_stb_o ( emm_wb_stb ),
.m_wb_ack_i ( emm_wb_ack ),
.m_wb_err_i ( emm_wb_err ),
.m_wb_adr_o ( emm_wb_adr ),
.m_wb_sel_o ( emm_wb_sel ),
.m_wb_we_o ( emm_wb_we ),
.m_wb_dat_i ( emm_wb_rdat ),
.m_wb_dat_o ( emm_wb_wdat ),
.m_wb_cyc_o ( emm_wb_cyc ),
.m_wb_stb_o ( emm_wb_stb ),
.m_wb_ack_i ( emm_wb_ack ),
.m_wb_err_i ( emm_wb_err ),
 
// MAC to PHY I/F
.mtx_clk_pad_i ( mtx_clk_pad_i ),
278,13 → 280,13
.mrx_clk_pad_i ( mrx_clk_pad_i ),
.mrxd_pad_i ( mrxd_pad_i ),
.mrxdv_pad_i ( mrxdv_pad_i ),
.mrxerr_pad_i ( mrxerr_pad_i ),
.mcoll_pad_i ( mcoll_pad_i ),
.mcrs_pad_i ( mcrs_pad_i ),
.md_pad_i ( md_pad_i ),
.mdc_pad_o ( mdc_pad_o ),
.md_pad_o ( md_pad_o ),
.md_padoe_o ( md_padoe_o ),
.mrxerr_pad_i ( mrxerr_pad_i ),
.mcoll_pad_i ( mcoll_pad_i ),
.mcrs_pad_i ( mcrs_pad_i ),
.md_pad_i ( md_pad_i ),
.mdc_pad_o ( mdc_pad_o ),
.md_pad_o ( md_pad_o ),
.md_padoe_o ( md_padoe_o ),
 
// Interrupt
.int_o ( ethmac_int )
299,14 → 301,16
`else
generic_iobuf u_iobuf (
`endif
.O ( md_pad_i ),
.IO ( md_pad_io ),
.I ( md_pad_o ),
.O ( md_pad_i ),
.IO ( md_pad_io ),
.I ( md_pad_o ),
// T is high for tri-state output
.T ( ~md_padoe_o )
.T ( ~md_padoe_o )
);
 
// Ethernet MII PHY reset
//assign phy_reset_n = !sys_rst;
 
// Halt core until system is ready
assign system_rdy = phy_init_done && !sys_rst;
 
357,12 → 361,12
.i_clk ( sys_clk ),
 
.o_uart_int ( uart0_int ),
 
.i_uart_cts_n ( i_uart0_rts ),
.o_uart_txd ( o_uart0_rx ),
.o_uart_rts_n ( o_uart0_cts ),
.i_uart_rxd ( i_uart0_tx ),
 
.i_wb_adr ( s_wb_adr [3] ),
.i_wb_sel ( s_wb_sel [3] ),
.i_wb_we ( s_wb_we [3] ),
381,12 → 385,12
uart #(
.WB_DWIDTH ( WB_DWIDTH ),
.WB_SWIDTH ( WB_SWIDTH )
)
)
u_uart1 (
.i_clk ( sys_clk ),
 
.o_uart_int ( uart1_int ),
 
// These are not connected. ONly pins for 1 UART
// on my development board
.i_uart_cts_n ( 1'd1 ),
393,7 → 397,7
.o_uart_txd ( ),
.o_uart_rts_n ( ),
.i_uart_rxd ( 1'd1 ),
 
.i_wb_adr ( s_wb_adr [4] ),
.i_wb_sel ( s_wb_sel [4] ),
.i_wb_we ( s_wb_we [4] ),
413,10 → 417,10
test_module #(
.WB_DWIDTH ( WB_DWIDTH ),
.WB_SWIDTH ( WB_SWIDTH )
)
)
u_test_module (
.i_clk ( sys_clk ),
 
.o_irq ( test_reg_irq ),
.o_firq ( test_reg_firq ),
.o_mem_ctrl ( test_mem_ctrl ),
440,13 → 444,13
timer_module #(
.WB_DWIDTH ( WB_DWIDTH ),
.WB_SWIDTH ( WB_SWIDTH )
)
)
u_timer_module (
.i_clk ( sys_clk ),
 
// Interrupt outputs
.o_timer_int ( timer_int ),
 
// Wishbone interface
.i_wb_adr ( s_wb_adr [6] ),
.i_wb_sel ( s_wb_sel [6] ),
469,11 → 473,11
)
u_interrupt_controller (
.i_clk ( sys_clk ),
 
// Interrupt outputs
.o_irq ( amber_irq ),
.o_firq ( amber_firq ),
 
// Interrupt inputs
.i_uart0_int ( uart0_int ),
.i_uart1_int ( uart1_int ),
481,7 → 485,7
.i_test_reg_irq ( test_reg_irq ),
.i_test_reg_firq ( test_reg_firq ),
.i_tm_timer_int ( timer_int ),
 
// Wishbone interface
.i_wb_adr ( s_wb_adr [7] ),
.i_wb_sel ( s_wb_sel [7] ),
501,31 → 505,31
// ======================================
// Instantiate non-synthesizable main memory model
// ======================================
 
assign phy_init_done = 1'd1;
 
main_mem #(
.WB_DWIDTH ( WB_DWIDTH ),
.WB_SWIDTH ( WB_SWIDTH )
)
)
u_main_mem (
.i_clk ( sys_clk ),
.i_mem_ctrl ( test_mem_ctrl ),
.i_wb_adr ( s_wb_adr [2] ),
.i_wb_sel ( s_wb_sel [2] ),
.i_wb_we ( s_wb_we [2] ),
.o_wb_dat ( s_wb_dat_r[2] ),
.i_wb_dat ( s_wb_dat_w[2] ),
.i_wb_cyc ( s_wb_cyc [2] ),
.i_wb_stb ( s_wb_stb [2] ),
.o_wb_ack ( s_wb_ack [2] ),
.o_wb_err ( s_wb_err [2] )
.i_wb_adr ( s_wb_adr [2] ),
.i_wb_sel ( s_wb_sel [2] ),
.i_wb_we ( s_wb_we [2] ),
.o_wb_dat ( s_wb_dat_r[2] ),
.i_wb_dat ( s_wb_dat_w[2] ),
.i_wb_cyc ( s_wb_cyc [2] ),
.i_wb_stb ( s_wb_stb [2] ),
.o_wb_ack ( s_wb_ack [2] ),
.o_wb_err ( s_wb_err [2] )
);
 
`endif
 
 
`ifdef XILINX_SPARTAN6_FPGA
`ifdef XILINX_SPARTAN6_FPGA
// -------------------------------------------------------------
// Instantiate Wishbone to Xilinx Spartan-6 DDR3 Bridge
// -------------------------------------------------------------
537,30 → 541,30
u_wb_xs6_ddr3_bridge(
.i_clk ( sys_clk ),
 
.o_cmd_en ( c3_p0_cmd_en ),
.o_cmd_instr ( c3_p0_cmd_instr ),
.o_cmd_byte_addr ( c3_p0_cmd_byte_addr ),
.i_cmd_full ( c3_p0_cmd_full ),
.i_wr_full ( c3_p0_wr_full ),
.o_wr_en ( c3_p0_wr_en ),
.o_wr_mask ( c3_p0_wr_mask ),
.o_wr_data ( c3_p0_wr_data ),
.i_rd_data ( c3_p0_rd_data ),
.o_cmd_en ( c3_p0_cmd_en ),
.o_cmd_instr ( c3_p0_cmd_instr ),
.o_cmd_byte_addr ( c3_p0_cmd_byte_addr ),
.i_cmd_full ( c3_p0_cmd_full ),
.i_wr_full ( c3_p0_wr_full ),
.o_wr_en ( c3_p0_wr_en ),
.o_wr_mask ( c3_p0_wr_mask ),
.o_wr_data ( c3_p0_wr_data ),
.i_rd_data ( c3_p0_rd_data ),
.i_rd_empty ( c3_p0_rd_empty ),
 
.i_mem_ctrl ( test_mem_ctrl ),
.i_wb_adr ( s_wb_adr [2] ),
.i_wb_sel ( s_wb_sel [2] ),
.i_wb_we ( s_wb_we [2] ),
.o_wb_dat ( s_wb_dat_r[2] ),
.i_wb_dat ( s_wb_dat_w[2] ),
.i_wb_cyc ( s_wb_cyc [2] ),
.i_wb_stb ( s_wb_stb [2] ),
.o_wb_ack ( s_wb_ack [2] ),
.o_wb_err ( s_wb_err [2] )
.i_wb_adr ( s_wb_adr [2] ),
.i_wb_sel ( s_wb_sel [2] ),
.i_wb_we ( s_wb_we [2] ),
.o_wb_dat ( s_wb_dat_r[2] ),
.i_wb_dat ( s_wb_dat_w[2] ),
.i_wb_cyc ( s_wb_cyc [2] ),
.i_wb_stb ( s_wb_stb [2] ),
.o_wb_ack ( s_wb_ack [2] ),
.o_wb_err ( s_wb_err [2] )
);
 
 
// -------------------------------------------------------------
// Instantiate Xilinx Spartan-6 FPGA MCB-DDR3 Controller
// -------------------------------------------------------------
579,6 → 583,7
.mcb3_dram_udm ( ddr3_dm[1] ),
.mcb3_dram_dm ( ddr3_dm[0] ),
.mcb3_rzq ( mcb3_rzq ),
// .mcb3_zio ( mcb3_zio ),
.mcb3_dram_udqs ( ddr3_dqs_p[1] ),
.mcb3_dram_dqs ( ddr3_dqs_p[0] ),
.mcb3_dram_udqs_n ( ddr3_dqs_n[1] ),
585,15 → 590,15
.mcb3_dram_dqs_n ( ddr3_dqs_n[0] ),
.mcb3_dram_ck ( ddr3_ck_p ),
.mcb3_dram_ck_n ( ddr3_ck_n ),
 
.c3_sys_clk ( clk_200 ),
.c3_sys_clk ( clk_200 ),
.c3_sys_rst_i ( brd_rst ), // active-high
.c3_clk0 ( ),
.c3_rst0 ( ),
.c3_calib_done ( phy_init_done ),
 
.c3_p0_cmd_clk ( sys_clk ),
 
.c3_p0_cmd_en ( c3_p0_cmd_en ),
.c3_p0_cmd_instr ( c3_p0_cmd_instr ),
.c3_p0_cmd_bl ( 6'd0 ),
600,9 → 605,9
.c3_p0_cmd_byte_addr ( c3_p0_cmd_byte_addr ),
.c3_p0_cmd_empty ( ),
.c3_p0_cmd_full ( c3_p0_cmd_full ),
 
.c3_p0_wr_clk ( sys_clk ),
 
.c3_p0_wr_en ( c3_p0_wr_en ),
.c3_p0_wr_mask ( c3_p0_wr_mask ),
.c3_p0_wr_data ( c3_p0_wr_data ),
611,9 → 616,9
.c3_p0_wr_count ( ),
.c3_p0_wr_underrun ( ),
.c3_p0_wr_error ( ),
 
.c3_p0_rd_clk ( sys_clk ),
 
.c3_p0_rd_en ( 1'd1 ),
.c3_p0_rd_data ( c3_p0_rd_data ),
.c3_p0_rd_full ( ),
/trunk/hw/vlog/system/register_addresses.v
78,26 → 78,26
 
 
// Interrupt Controller
localparam AMBER_IC_IRQ0_STATUS = 16'h0000;
localparam AMBER_IC_IRQ0_RAWSTAT = 16'h0004;
localparam AMBER_IC_IRQ0_ENABLESET = 16'h0008;
localparam AMBER_IC_IRQ0_ENABLECLR = 16'h000c;
localparam AMBER_IC_IRQ0_STATUS = 16'h0000;
localparam AMBER_IC_IRQ0_RAWSTAT = 16'h0004;
localparam AMBER_IC_IRQ0_ENABLESET = 16'h0008;
localparam AMBER_IC_IRQ0_ENABLECLR = 16'h000c;
localparam AMBER_IC_INT_SOFTSET_0 = 16'h0010;
localparam AMBER_IC_INT_SOFTCLEAR_0 = 16'h0014;
localparam AMBER_IC_FIRQ0_STATUS = 16'h0020;
localparam AMBER_IC_FIRQ0_RAWSTAT = 16'h0024;
localparam AMBER_IC_FIRQ0_ENABLESET = 16'h0028;
localparam AMBER_IC_FIRQ0_ENABLECLR = 16'h002c;
localparam AMBER_IC_IRQ1_STATUS = 16'h0040;
localparam AMBER_IC_IRQ1_RAWSTAT = 16'h0044;
localparam AMBER_IC_IRQ1_ENABLESET = 16'h0048;
localparam AMBER_IC_IRQ1_ENABLECLR = 16'h004c;
localparam AMBER_IC_FIRQ0_STATUS = 16'h0020;
localparam AMBER_IC_FIRQ0_RAWSTAT = 16'h0024;
localparam AMBER_IC_FIRQ0_ENABLESET = 16'h0028;
localparam AMBER_IC_FIRQ0_ENABLECLR = 16'h002c;
localparam AMBER_IC_IRQ1_STATUS = 16'h0040;
localparam AMBER_IC_IRQ1_RAWSTAT = 16'h0044;
localparam AMBER_IC_IRQ1_ENABLESET = 16'h0048;
localparam AMBER_IC_IRQ1_ENABLECLR = 16'h004c;
localparam AMBER_IC_INT_SOFTSET_1 = 16'h0050;
localparam AMBER_IC_INT_SOFTCLEAR_1 = 16'h0054;
localparam AMBER_IC_FIRQ1_STATUS = 16'h0060;
localparam AMBER_IC_FIRQ1_RAWSTAT = 16'h0064;
localparam AMBER_IC_FIRQ1_ENABLESET = 16'h0068;
localparam AMBER_IC_FIRQ1_ENABLECLR = 16'h006c;
localparam AMBER_IC_FIRQ1_STATUS = 16'h0060;
localparam AMBER_IC_FIRQ1_RAWSTAT = 16'h0064;
localparam AMBER_IC_FIRQ1_ENABLESET = 16'h0068;
localparam AMBER_IC_FIRQ1_ENABLECLR = 16'h006c;
localparam AMBER_IC_INT_SOFTSET_2 = 16'h0090;
localparam AMBER_IC_INT_SOFTCLEAR_2 = 16'h0094;
localparam AMBER_IC_INT_SOFTSET_3 = 16'h00d0;
/trunk/hw/vlog/system/interrupt_controller.v
116,13 → 116,13
assign o_wb_ack = i_wb_stb && ( wb_start_write || wb_start_read_d1 );
 
generate
if (WB_DWIDTH == 128)
if (WB_DWIDTH == 128)
begin : wb128
assign wb_wdata32 = i_wb_adr[3:2] == 2'd3 ? i_wb_dat[127:96] :
i_wb_adr[3:2] == 2'd2 ? i_wb_dat[ 95:64] :
i_wb_adr[3:2] == 2'd1 ? i_wb_dat[ 63:32] :
i_wb_dat[ 31: 0] ;
 
assign o_wb_dat = {4{wb_rdata32}};
end
else
136,28 → 136,28
// ======================================
// Interrupts
// ======================================
assign raw_interrupts = {23'd0,
assign raw_interrupts = {23'd0,
i_ethmac_int, // 8: Ethernet MAC interrupt
 
i_tm_timer_int[2], // 7: Timer Module Interrupt 2
i_tm_timer_int[1], // 6: Timer Module Interrupt 1
i_tm_timer_int[0], // 5: Timer Module Interrupt 0
1'd0,
 
1'd0,
i_uart1_int, // 2: Uart 1 interrupt
i_uart0_int, // 1: Uart 0 interrupt
1'd0 // 0: Software interrupt not
1'd0 // 0: Software interrupt not
}; // here because its not maskable
 
assign irq0_interrupts = {raw_interrupts[31:1], softint_0_reg} & irq0_enable_reg;
assign firq0_interrupts = raw_interrupts & firq0_enable_reg;
assign firq0_interrupts = raw_interrupts & firq0_enable_reg;
assign irq1_interrupts = {raw_interrupts[31:1], softint_1_reg} & irq1_enable_reg;
assign firq1_interrupts = raw_interrupts & firq1_enable_reg;
assign firq1_interrupts = raw_interrupts & firq1_enable_reg;
 
// The interrupts from the test registers module are not masked,
// just to keep their usage really simple
assign irq_0 = |{irq0_interrupts, i_test_reg_irq};
assign irq_0 = |{irq0_interrupts, i_test_reg_irq};
assign firq_0 = |{firq0_interrupts, i_test_reg_firq};
assign irq_1 = |irq1_interrupts;
assign firq_1 = |firq1_interrupts;
165,7 → 165,6
assign o_irq = irq_0 | irq_1;
assign o_firq = firq_0 | firq_1;
 
 
// ========================================================
// Register Writes
// ========================================================
176,15 → 175,15
AMBER_IC_IRQ0_ENABLECLR: irq0_enable_reg <= irq0_enable_reg & (~i_wb_dat);
AMBER_IC_FIRQ0_ENABLESET: firq0_enable_reg <= firq0_enable_reg | ( i_wb_dat);
AMBER_IC_FIRQ0_ENABLECLR: firq0_enable_reg <= firq0_enable_reg & (~i_wb_dat);
 
AMBER_IC_INT_SOFTSET_0: softint_0_reg <= softint_0_reg | ( i_wb_dat[0]);
AMBER_IC_INT_SOFTCLEAR_0: softint_0_reg <= softint_0_reg & (~i_wb_dat[0]);
 
AMBER_IC_IRQ1_ENABLESET: irq1_enable_reg <= irq1_enable_reg | ( i_wb_dat);
AMBER_IC_IRQ1_ENABLECLR: irq1_enable_reg <= irq1_enable_reg & (~i_wb_dat);
AMBER_IC_FIRQ1_ENABLESET: firq1_enable_reg <= firq1_enable_reg | ( i_wb_dat);
AMBER_IC_FIRQ1_ENABLECLR: firq1_enable_reg <= firq1_enable_reg & (~i_wb_dat);
 
AMBER_IC_INT_SOFTSET_1: softint_1_reg <= softint_1_reg | ( i_wb_dat[0]);
AMBER_IC_INT_SOFTCLEAR_1: softint_1_reg <= softint_1_reg & (~i_wb_dat[0]);
endcase
196,9 → 195,9
always @( posedge i_clk )
if ( wb_start_read )
case ( i_wb_adr[15:0] )
 
AMBER_IC_IRQ0_ENABLESET: wb_rdata32 <= irq0_enable_reg;
AMBER_IC_FIRQ0_ENABLESET: wb_rdata32 <= firq0_enable_reg;
AMBER_IC_IRQ0_ENABLESET: wb_rdata32 <= irq0_enable_reg;
AMBER_IC_FIRQ0_ENABLESET: wb_rdata32 <= firq0_enable_reg;
AMBER_IC_IRQ0_RAWSTAT: wb_rdata32 <= raw_interrupts;
AMBER_IC_IRQ0_STATUS: wb_rdata32 <= irq0_interrupts;
AMBER_IC_FIRQ0_RAWSTAT: wb_rdata32 <= raw_interrupts;
205,10 → 204,10
AMBER_IC_FIRQ0_STATUS: wb_rdata32 <= firq0_interrupts;
 
AMBER_IC_INT_SOFTSET_0: wb_rdata32 <= {31'd0, softint_0_reg};
AMBER_IC_INT_SOFTCLEAR_0: wb_rdata32 <= {31'd0, softint_0_reg};
AMBER_IC_INT_SOFTCLEAR_0: wb_rdata32 <= {31'd0, softint_0_reg};
 
AMBER_IC_IRQ1_ENABLESET: wb_rdata32 <= irq1_enable_reg;
AMBER_IC_FIRQ1_ENABLESET: wb_rdata32 <= firq1_enable_reg;
AMBER_IC_IRQ1_ENABLESET: wb_rdata32 <= irq1_enable_reg;
AMBER_IC_FIRQ1_ENABLESET: wb_rdata32 <= firq1_enable_reg;
AMBER_IC_IRQ1_RAWSTAT: wb_rdata32 <= raw_interrupts;
AMBER_IC_IRQ1_STATUS: wb_rdata32 <= irq1_interrupts;
AMBER_IC_FIRQ1_RAWSTAT: wb_rdata32 <= raw_interrupts;
215,10 → 214,10
AMBER_IC_FIRQ1_STATUS: wb_rdata32 <= firq1_interrupts;
 
AMBER_IC_INT_SOFTSET_1: wb_rdata32 <= {31'd0, softint_1_reg};
AMBER_IC_INT_SOFTCLEAR_1: wb_rdata32 <= {31'd0, softint_1_reg};
 
AMBER_IC_INT_SOFTCLEAR_1: wb_rdata32 <= {31'd0, softint_1_reg};
default: wb_rdata32 <= 32'h22334455;
 
endcase
 
 
231,74 → 230,74
 
 
//synopsys translate_off
`ifdef AMBER_IC_DEBUG
`ifdef AMBER_IC_DEBUG
 
wire wb_read_ack = i_wb_stb && ( wb_start_write || wb_start_read_d1 );
 
// -----------------------------------------------
// Report Interrupt Controller Register accesses
// -----------------------------------------------
// -----------------------------------------------
always @(posedge i_clk)
if ( wb_read_ack || wb_start_write )
begin
`TB_DEBUG_MESSAGE
 
if ( wb_start_write )
$write("Write 0x%08x to ", i_wb_dat);
else
$write("Read 0x%08x from ", o_wb_dat);
 
case ( i_wb_adr[15:0] )
AMBER_IC_IRQ0_STATUS:
$write(" Interrupt Controller module IRQ0 Status");
$write(" Interrupt Controller module IRQ0 Status");
AMBER_IC_IRQ0_RAWSTAT:
$write(" Interrupt Controller module IRQ0 Raw Status");
$write(" Interrupt Controller module IRQ0 Raw Status");
AMBER_IC_IRQ0_ENABLESET:
$write(" Interrupt Controller module IRQ0 Enable Set");
$write(" Interrupt Controller module IRQ0 Enable Set");
AMBER_IC_IRQ0_ENABLECLR:
$write(" Interrupt Controller module IRQ0 Enable Clear");
$write(" Interrupt Controller module IRQ0 Enable Clear");
AMBER_IC_FIRQ0_STATUS:
$write(" Interrupt Controller module FIRQ0 Status");
$write(" Interrupt Controller module FIRQ0 Status");
AMBER_IC_FIRQ0_RAWSTAT:
$write(" Interrupt Controller module FIRQ0 Raw Status");
$write(" Interrupt Controller module FIRQ0 Raw Status");
AMBER_IC_FIRQ0_ENABLESET:
$write(" Interrupt Controller module FIRQ0 Enable set");
$write(" Interrupt Controller module FIRQ0 Enable set");
AMBER_IC_FIRQ0_ENABLECLR:
$write(" Interrupt Controller module FIRQ0 Enable Clear");
AMBER_IC_INT_SOFTSET_0:
$write(" Interrupt Controller module SoftInt 0 Set");
$write(" Interrupt Controller module FIRQ0 Enable Clear");
AMBER_IC_INT_SOFTSET_0:
$write(" Interrupt Controller module SoftInt 0 Set");
AMBER_IC_INT_SOFTCLEAR_0:
$write(" Interrupt Controller module SoftInt 0 Clear");
$write(" Interrupt Controller module SoftInt 0 Clear");
AMBER_IC_IRQ1_STATUS:
$write(" Interrupt Controller module IRQ1 Status");
$write(" Interrupt Controller module IRQ1 Status");
AMBER_IC_IRQ1_RAWSTAT:
$write(" Interrupt Controller module IRQ1 Raw Status");
$write(" Interrupt Controller module IRQ1 Raw Status");
AMBER_IC_IRQ1_ENABLESET:
$write(" Interrupt Controller module IRQ1 Enable Set");
$write(" Interrupt Controller module IRQ1 Enable Set");
AMBER_IC_IRQ1_ENABLECLR:
$write(" Interrupt Controller module IRQ1 Enable Clear");
$write(" Interrupt Controller module IRQ1 Enable Clear");
AMBER_IC_FIRQ1_STATUS:
$write(" Interrupt Controller module FIRQ1 Status");
$write(" Interrupt Controller module FIRQ1 Status");
AMBER_IC_FIRQ1_RAWSTAT:
$write(" Interrupt Controller module FIRQ1 Raw Status");
$write(" Interrupt Controller module FIRQ1 Raw Status");
AMBER_IC_FIRQ1_ENABLESET:
$write(" Interrupt Controller module FIRQ1 Enable set");
$write(" Interrupt Controller module FIRQ1 Enable set");
AMBER_IC_FIRQ1_ENABLECLR:
$write(" Interrupt Controller module FIRQ1 Enable Clear");
AMBER_IC_INT_SOFTSET_1:
$write(" Interrupt Controller module SoftInt 1 Set");
$write(" Interrupt Controller module FIRQ1 Enable Clear");
AMBER_IC_INT_SOFTSET_1:
$write(" Interrupt Controller module SoftInt 1 Set");
AMBER_IC_INT_SOFTCLEAR_1:
$write(" Interrupt Controller module SoftInt 1 Clear");
$write(" Interrupt Controller module SoftInt 1 Clear");
 
default:
begin
$write(" unknown Amber IC Register region");
$write(", Address 0x%08h\n", i_wb_adr);
$write(", Address 0x%08h\n", i_wb_adr);
`TB_ERROR_MESSAGE
end
endcase
 
$write(", Address 0x%08h\n", i_wb_adr);
$write(", Address 0x%08h\n", i_wb_adr);
end
`endif
 
/trunk/sw/boot-loader-serial/fpga-version.h
1,74 → 230,74
#define AMBER_FPGA_VERSION "20130506123001"
#define AMBER_FPGA_VERSION "20130428184629"
/trunk/sw/boot-loader-ethmac/telnet.h
42,6 → 42,11
#define MAX_TELNET_TX 1024
 
 
#define telnet_broadcast(args ...) \
do { put_line (socket0_g->telnet_txbuf, args); \
put_line (socket1_g->telnet_txbuf, args); } while (0)
 
 
void parse_telnet_options (char *, socket_t*);
void parse_telnet_payload (char *, socket_t*);
void telnet_options (socket_t*);
/trunk/sw/boot-loader-ethmac/ethmac.c
7,7 → 7,7
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
55,10 → 55,10
{
/* Disable EthMac interrupts in Ethmac core */
*(unsigned int *) ( ADR_ETHMAC_INT_MASK ) = 0x0;
 
/* Disable Ethmac interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
 
/* Disable Rx & Tx - MODER Register
[15] = Add pads to short frames
[13] = CRCEN
67,8 → 67,8
[5] = 1 for promiscuous, 0 rx only frames that match mac address
[1] = txen
[0] = rxen */
*(unsigned int *) ( ADR_ETHMAC_MODER ) = 0xa420;
 
*(unsigned int *) ( ADR_ETHMAC_MODER ) = 0xa420;
/* Put the PHY into reset */
phy_rst(0); /* reset is active low */
 
81,7 → 81,7
int packet;
int n;
unsigned int d32;
 
/* Disable Ethmac interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x100;
 
88,10 → 88,10
/* Set my MAC address */
d32 = self_g.mac[2]<<24|self_g.mac[3]<<16|self_g.mac[4]<<8|self_g.mac[5];
*(unsigned int *) ( ADR_ETHMAC_MAC_ADDR0 ) = d32;
 
d32 = self_g.mac[0]<<8|self_g.mac[1];
*(unsigned int *) ( ADR_ETHMAC_MAC_ADDR1 ) = d32;
 
if (!config_phy()) return 0;
 
/* Write the Receive Packet Buffer Descriptor */
98,32 → 98,31
/* Buffer Pointer */
for (packet=0; packet<ETHMAC_RX_BUFFERS; packet++) {
*(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x204 + packet*8 ) = ETHMAC_RX_BUFFER + packet * 0x1000;
/* Ready Rx buffer
[31:16] = length in bytes,
/* Ready Rx buffer
[31:16] = length in bytes,
[15] = empty
[14] = Enable IRQ
[13] = wrap bit */
/* set empty flag again */
if (packet == ETHMAC_RX_BUFFERS-1) /* last receive buffer ? */
/* Set wrap bit is last buffer */
/* Set wrap bit is last buffer */
*(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + packet*8 ) = 0x0000e000;
else
*(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + packet*8 ) = 0x0000c000;
}
 
 
/* Enable EthMac interrupts in Ethmac core */
/* Receive frame and receive error botgh enabled */
/* When a bad frame is received is still gets written to a buffer
so needs to be dealt with */
*(unsigned int *) ( ADR_ETHMAC_INT_MASK ) = 0xc;
 
/* Enable Ethmac interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x100;
 
/* Set transmit packet buffer location */
*(unsigned int *) ( ADR_ETHMAC_BDBASE + 4 ) = ETHMAC_TX_BUFFER;
 
/* Set the ready bit, bit 15, low */
*(unsigned int *) ( ADR_ETHMAC_BDBASE + 0 ) = 0x7800;
 
136,7 → 135,7
[1] = txen
[0] = rxen */
*(unsigned int *) ( ADR_ETHMAC_MODER ) = 0xa423;
 
return 1;
}
 
144,8 → 143,8
void tx_packet(int len)
{
unsigned int status = 0;
 
 
/* Poll the ready bit.
Wait until the ready bit is cleared by the ethmac hardware
This holds everything up while the packet is being transmitted, but
158,10 → 157,10
 
 
/* Enable packet tx
[31:16] = length in bytes,
[31:16] = length in bytes,
[15] = ready
[14] = tx int
[13] = wrap bit
[13] = wrap bit
[12] = pad enable for short packets
[11] = crc en
*/
177,13 → 176,14
int stat;
int phy_id;
int link_up = 1;
 
time_t* link_timer;
 
link_timer = init_timer();
 
/* Bring PHY out of reset */
phy_rst(1); /* reset is active low */
 
/* Discover phy addr by searching addrs in order {1,0,2,..., 31} */
for(addr = 0; addr < 32; addr++) {
phy_id = (addr == 0) ? 1 : (addr == 1) ? 0 : addr;
191,12 → 191,9
stat = mdio_read(phy_id, MII_BMSR);
stat = mdio_read(phy_id, MII_BMSR);
if(!((bmcr == 0xFFFF) || ((stat == 0) && (bmcr == 0))))
break;
break;
}
/* Failed to find a PHY on the md bus */
if (addr == 32)
return 0;
 
/* Reset PHY */
bmcr = mdio_read(phy_id, MII_BMCR);
mdio_write(phy_id, MII_BMCR, bmcr | BMCR_RESET);
205,23 → 202,22
/* Set bits 9.8, 9.9 to 0 */
bmcr = mdio_read(phy_id, MII_CTRL1000);
mdio_write(phy_id, MII_CTRL1000, bmcr & 0xfcff );
 
/* Restart autoneg */
bmcr = mdio_read(phy_id, MII_BMCR);
mdio_write(phy_id, MII_BMCR, bmcr | BMCR_ANRESTART);
 
/* Wait for link up */
/* Print PHY status MII_BMSR = Basic Mode Status Register*/
/* allow a few seconds for the link to come up before giving up */
set_timer(link_timer, 5000);
 
/* allow 2 seconds for the link to come up before giving up */
set_timer(link_timer, 5000);
while (!((stat = mdio_read(phy_id, MII_BMSR)) & BMSR_LSTATUS)) {
if (timer_expired(link_timer)) {
link_up = 0;
break;
link_up = 0;
break;
}
}
 
return link_up;
}
 
240,7 → 236,7
 
/*
addr = PHY address
reg = register address within PHY
reg = register address within PHY
*/
unsigned short mdio_ctrl(unsigned int addr, unsigned int dir, unsigned int reg, unsigned short data)
{
247,23 → 243,23
unsigned int data_out = 0;
unsigned int i;
unsigned long flags;
mdio_ready();
 
mdio_ready();
 
*(volatile unsigned int *)(ADR_ETHMAC_MIIADDRESS) = (reg << 8) | (addr & 0x1f);
 
if (dir == mdi_write) {
*(volatile unsigned int *)(ADR_ETHMAC_MIITXDATA) = data;
/* Execute Write ! */
*(volatile unsigned int *)(ADR_ETHMAC_MIICOMMAND) = 0x4;
}
else {
/* Execute Read ! */
*(volatile unsigned int *)(ADR_ETHMAC_MIICOMMAND) = 0x2;
mdio_ready();
data_out = *(volatile unsigned int *)(ADR_ETHMAC_MIIRXDATA);
}
 
if (dir == mdi_write) {
*(volatile unsigned int *)(ADR_ETHMAC_MIITXDATA) = data;
/* Execute Write ! */
*(volatile unsigned int *)(ADR_ETHMAC_MIICOMMAND) = 0x4;
}
else {
/* Execute Read ! */
*(volatile unsigned int *)(ADR_ETHMAC_MIICOMMAND) = 0x2;
mdio_ready();
data_out = *(volatile unsigned int *)(ADR_ETHMAC_MIIRXDATA);
}
return (unsigned short) data_out;
}
 
270,13 → 266,13
 
/* Wait until its ready */
void mdio_ready()
{
{
int i;
for (;;) {
/* Bit 1 is high when the MD i/f is busy */
if ((*(volatile unsigned int *)(ADR_ETHMAC_MIISTATUS) & 0x2) == 0x0)
/* Bit 1 is high when the MD i/f is busy */
if ((*(volatile unsigned int *)(ADR_ETHMAC_MIISTATUS) & 0x2) == 0x0)
break;
 
i++;
if (i==10000000) {
i=0;
287,31 → 283,29
 
 
void ethmac_interrupt(void)
{
{
int buffer;
unsigned int int_src;
unsigned int rx_buf_status;
 
/* Mask ethmac interrupts */
*(volatile unsigned int *) ( ADR_ETHMAC_INT_MASK ) = 0;
 
int_src = *(volatile unsigned int *) ( ADR_ETHMAC_INT_SOURCE );
 
if (int_src) {
for (buffer=0; buffer<ETHMAC_RX_BUFFERS; buffer++) {
 
rx_buf_status = *(volatile unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 );
 
if ((rx_buf_status & 0x8000) == 0) {
 
parse_rx_packet((char*)(ETHMAC_RX_BUFFER+buffer*0x1000), rx_packet_g);
 
/* set empty flag again */
if (buffer == ETHMAC_RX_BUFFERS-1) /* last receive buffer ? */
*(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 ) = 0x0000e000;
else
*(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 ) = 0x0000c000;
}
for (buffer=0; buffer<ETHMAC_RX_BUFFERS; buffer++) {
rx_buf_status = *(volatile unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 );
if ((rx_buf_status & 0x8000) == 0) {
parse_rx_packet((char*)(ETHMAC_RX_BUFFER+buffer*0x1000), rx_packet_g);
/* set empty flag again */
if (buffer == ETHMAC_RX_BUFFERS-1) /* last receive buffer ? */
*(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 ) = 0x0000e000;
else
*(unsigned int *) ( ADR_ETHMAC_BDBASE + 0x200 + buffer*8 ) = 0x0000c000;
}
}
 
/trunk/sw/boot-loader-ethmac/boot-loader-ethmac.c
7,7 → 7,7
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
41,23 → 41,29
// //
----------------------------------------------------------------*/
 
// TODO list
// tcp.c clean up
// Cleanup self_g structure and usage
// tcp window - what is it, whats it set to? Add it to status stuff
// Get A25 version working
// test with booting linux
 
#include "amber_registers.h"
#include "address_map.h"
#include "line-buffer.h"
#include "timer.h"
#include "utilities.h"
 
#include "ethmac.h"
#include "packet.h"
#include "tcp.h"
#include "udp.h"
#include "telnet.h"
#include "serial.h"
 
#include "elfsplitter.h"
#include "boot-loader-ethmac.h"
 
 
 
int main ( void ) {
char* line;
time_t* led_flash_timer;
64,52 → 70,41
time_t* reboot_timer;
socket_t* socket = socket0_g;
int reboot_stage = 0;
 
 
/* Enable the serial debug port */
init_serial();
print_serial("Amber debug port\n\r");
 
 
/* Turn off all LEDs */
/* Turn off all LEDs as a starting point */
led_clear();
 
 
/* initialize the memory allocation system */
/* this must be first, because all the other init functions call malloc */
init_malloc();
 
 
/* Initialize current time and some timers */
init_current_time();
led_flash_timer = init_timer();
set_timer(led_flash_timer, 500);
set_timer(led_flash_timer, 500);
reboot_timer = init_timer();
 
 
/* receive packet buffer */
rx_packet_g = malloc(sizeof(packet_t));
 
 
/* initialize two tcp sockets */
/* socket init */
socket0_g = init_socket(0);
socket1_g = init_socket(1);
 
 
/* open ethernet port and wait for connection requests
/* open ethernet port and wait for connection requests
keep trying forever */
while (!open_link());
 
 
/* infinite loop. Everything is timer, interrupt and queue driven from here on down */
while (1) {
 
/* Flash a heartbeat LED */
if (timer_expired(led_flash_timer)) {
led_flip(0);
set_timer(led_flash_timer, 500);
}
 
 
/* Check for newly downloaded tftp file. Add to all tx buffers */
/* Has a file been uploaded via tftp ? */
if (udp_file_g != NULL) {
116,24 → 111,17
/* Notify telnet clients that file has been received */
if (udp_file_g->ready) {
udp_file_g->ready = 0;
 
print_serial("Received file %s, %d bytes",
udp_file_g->filename, udp_file_g->total_bytes);
if (udp_file_g->linux_boot)
print_serial(", linux image detected\r\n");
else
print_serial("\r\n");
 
if (process_file(socket0_g) == 0) {
telnet_broadcast("Received file %s, %d bytes, linux %d\r\n",
udp_file_g->filename, udp_file_g->total_bytes, udp_file_g->linux_boot);
if (process_file(socket0_g) == 0)
/* Disconnect in 1 second */
set_timer(reboot_timer, 1000);
}
else
print_serial("Not an elf file\r\n");
telnet_broadcast("Not an elf file\r\n");
}
}
 
 
/* reboot timer expired */
if (timer_expired(reboot_timer)) {
/* First stage of reboot sequence is to nicely disconnect */
142,7 → 130,7
reboot_stage = 1;
socket0_g->tcp_disconnect = 1;
socket1_g->tcp_disconnect = 1;
}
}
else {
/* Second stage of reboot sequence is to turn off ethmac and then jump to restart vector */
close_link();
156,8 → 144,8
socket = socket1_g;
else
socket = socket0_g;
 
 
/* Check if any tcp packets need to be re-transmitted */
tcp_retransmit(socket);
 
166,8 → 154,8
if (socket->tcp_disconnect && socket->tcp_connection_state == TCP_OPEN) {
tcp_disconnect(socket);
}
 
 
/* Reset connection */
if (socket->tcp_reset) {
socket->tcp_connection_state = TCP_CLOSED;
176,15 → 164,15
tcp_reply(socket, NULL, 0);
socket->tcp_reset = 0;
}
 
 
/* Send telnet options */
/* Send telnet options */
if (socket->tcp_connection_state == TCP_OPEN && !socket->telnet_options_sent){
telnet_options(socket);
socket->telnet_options_sent = 1;
}
 
/* telnet connection open
/* telnet connection open
Communicate with client */
else if (socket->telnet_connection_state == TELNET_OPEN) {
/* Send telnet greeting */
192,9 → 180,9
put_line (socket->telnet_txbuf, "Amber Processor Boot Loader\r\n> ");
socket->telnet_sent_opening_message = 1;
}
 
/* Parse telnet rx buffer */
if (get_line(socket->telnet_rxbuf, &line))
if (get_line(socket->telnet_rxbuf, &line))
parse_command (socket, line);
 
/* Transmit text from telnet tx buffer */
207,13 → 195,13
 
/* Parse a command line passed from main and execute the command */
/* returns the length of the reply string */
int parse_command (socket_t* socket, char* line)
{
int parse_command (socket_t* socket, char* line)
{
unsigned int start_addr;
unsigned int address;
unsigned int range;
int len, error = 0;
 
/* All commands are just a single character.
Just ignore anything else */
switch (line[0]) {
220,52 → 208,52
/* Disconnect */
case 'e':
case 'x':
case 'q':
case 'q':
socket->tcp_disconnect = 1;
return 0;
 
case 'r': /* Read mem */
case 'r': /* Read mem */
{
if (len = get_hex (&line[2], &start_addr)) {
if (len = get_hex (&line[2], &start_addr)) {
if (len = get_hex (&line[3+len], &range)) {
for (address=start_addr; address<start_addr+range; address+=4) {
put_line (socket->telnet_txbuf, "0x%08x 0x%08x\r\n",
put_line (socket->telnet_txbuf, "0x%08x 0x%08x\r\n",
address, *(unsigned int *)address);
}
}
else {
put_line (socket->telnet_txbuf, "0x%08x 0x%08x\r\n",
put_line (socket->telnet_txbuf, "0x%08x 0x%08x\r\n",
start_addr, *(unsigned int *)start_addr);
}
}
else
else
error=1;
break;
break;
}
 
 
case 'h': {/* Help */
case 'h': {/* Help */
put_line (socket->telnet_txbuf, "You need help alright\r\n");
break;
break;
}
 
 
case 's': {/* Status */
case 's': {/* Status */
put_line (socket->telnet_txbuf, "Socket ID %d\r\n", socket->id);
put_line (socket->telnet_txbuf, "Packets received %d\r\n", socket->packets_received);
put_line (socket->telnet_txbuf, "Packets transmitted %d\r\n", socket->packets_sent);
put_line (socket->telnet_txbuf, "Packets resent %d\r\n", socket->packets_resent);
put_line (socket->telnet_txbuf, "TCP checksum errors %d\r\n", tcp_checksum_errors_g);
 
put_line (socket->telnet_txbuf, "Counterparty IP %d.%d.%d.%d\r\n",
socket->rx_packet->src_ip[0],
socket->rx_packet->src_ip[1],
socket->rx_packet->src_ip[2],
socket->rx_packet->src_ip[3]);
 
put_line (socket->telnet_txbuf, "Counterparty Port %d\r\n",
socket->rx_packet->tcp_src_port);
 
put_line (socket->telnet_txbuf, "Malloc pointer 0x%08x\r\n",
*(unsigned int *)(ADR_MALLOC_POINTER));
put_line (socket->telnet_txbuf, "Malloc count %d\r\n",
273,18 → 261,18
put_line (socket->telnet_txbuf, "Uptime %d seconds\r\n", current_time_g->seconds);
break;
}
 
 
default: {
error=1; break;
}
}
}
 
 
if (error)
put_line (socket->telnet_txbuf, "You're not making any sense\r\n",
put_line (socket->telnet_txbuf, "You're not making any sense\r\n",
line[0], line[1], line[2]);
 
put_line (socket->telnet_txbuf, "> ");
return 0;
}
293,7 → 281,7
/* copy tftp file into a single contiguous buffer so
if can be processed by elf splitter */
int process_file(socket_t* socket)
{
{
block_t* block;
char* buf512;
char* tftp_file;
300,12 → 288,12
char* line;
int line_len;
int ret;
 
tftp_file = malloc(udp_file_g->total_bytes);
 
block = udp_file_g;
buf512= tftp_file;
 
while (block->next) {
memcpy(buf512, block->buf512, block->bytes);
buf512=&buf512[512];
313,7 → 301,7
}
memcpy(buf512, block->buf512, block->bytes);
buf512=&buf512[512];
 
return elfsplitter(tftp_file, socket);
}
 
325,9 → 313,9
void reboot()
{
int i;
 
/* Disable all interrupts */
/* Disable ethmac_int interrupt */
/* Disable ethmac_int interrupt */
/* Disable timer 0 interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x120;
 
334,14 → 322,10
for(i=0;i<MEM_BUF_ENTRIES;i++)
if (elf_mem0_g->entry[i].valid)
*(char *)(i) = elf_mem0_g->entry[i].data;
 
if (udp_file_g->linux_boot) {
print_serial("linux reboot\n\r");
_jump_to_program(LINUX_JUMP_ADR);
}
else {
print_serial("normal reboot\n\r");
_restart();
}
if (udp_file_g->linux_boot)
_jump_to_program(LINUX_JUMP_ADR);
else
_restart();
}
 
/trunk/sw/boot-loader-ethmac/start.S
66,31 → 66,31
 
 
.section .text
.globl start
start:
.globl start
start:
/* 0x00 Reset Interrupt vector address */
b startup
 
/* 0x04 Undefined Instruction Interrupt vector address */
b _testfail
 
/* 0x08 SWI Interrupt vector address */
b _testfail
 
/* 0x0c Prefetch abort Interrupt vector address */
b _testfail
 
/* 0x10 Data abort Interrupt vector address */
b _testfail
b _testfail
 
/* 0x18 IRQ vector address */
b service_irq
 
/* 0x1c FIRQ vector address */
b _testfail
 
 
.global _restart
_restart:
@ jump to address 0 in irq mode
105,23 → 105,23
mov r0, #0
ldr r1, AdrExecBase
1: ldm r0!, {r2-r9}
stm r1!, {r2-r9}
stm r1!, {r2-r9}
cmp r0, #0x4000
bne 1b
 
/* Fix the interrupt jump pointers */
ldr r0, AdrExecBase
ldr r0, AdrExecBase
mov r1, r0, lsr #2
mov r2, #0
 
2: ldr r3, [r2]
orr r3, r3, r1
str r3, [r2], #4
cmp r2, #0x1c
bne 2b
 
/* Jump to 2f but offset from ExecBase not current location */
3: ldr r0, AdrExecBase
3: ldr r0, AdrExecBase
ldr r1, AdrJumpPoint
orr r0, r0, r1
mov pc, r0
130,21 → 130,21
 
/* Switch to IRQ Mode */
mov r0, #0x00000002
teqp pc, r0
teqp pc, r0
/* Set IRQ Mode stack pointer */
ldr sp, AdrIRQStack
 
/* Switch to SVC mode and Unset interrupt mask bits */
mov r0, #0x00000003
teqp pc, r0
 
teqp pc, r0
@ Enable the cache
@ set region 24 to be uncached. Used for packet buffers
mov r0, #0xfeffffff
mcr 15, 0, r0, cr3, cr0, 0 @ cacheable area
mcr 15, 0, r0, cr3, cr0, 0 @ cacheable area
mov r0, #1
mcr 15, 0, r0, cr2, cr0, 0 @ cache enable
 
mcr 15, 0, r0, cr2, cr0, 0 @ cache enable
@ init SP
ldr sp, AdrStack
 
152,15 → 152,15
ldr r0, AdrMemCtrl
mov r1, #1
str r1, [r0]
 
.extern main
bl main
 
@ jump to program at r0
.globl _jump_to_program
.globl _jump_to_program
_jump_to_program:
 
 
@ ----------------------------------------------
@ Copy ATAG structure to AdrBootParams
@ ----------------------------------------------
167,54 → 167,52
ldr r1, AdrBootParams
ldr r2, AdrATAGBase
ldr r3, AdeEndATAG
 
1: cmp r2, r3
beq 2f
ldr r4, [r2], #4
str r4, [r1], #4
b 1b
 
@ Set memc page tables
2: ldr r2, AdrPageTabes
2: ldr r2, AdrPageTabes
mov r3, #0
mov r4, #40
3: str r3,[r2],#4
subs r4, r4, #1
bne 3b
 
@ ----------------------------------------------
@ jump to start of program in svc mode with interrupts disabled
@ ----------------------------------------------
mov r4, r0
orr r4, #0x0c000003
mov r0, #0
mov r0, #0
mov pc, r4
 
 
service_irq:
@ As this is an interrupt, need tp save all registers to the stack
stmfd sp!, {r0-r3, lr}
@ Save all registers to the stack
stmfd sp!, {r0-r12, lr}
 
@ is it a timer interrupt ?
ldr r0, AdrInterruptStatus
ldr r3, [r0]
ands r2, r3, #0x20
ldr r1, [r0]
ands r2, r1, #0x20
beq 1f @ not timer int, jump
@ Remember that registers r0 to r2 can be changed by this function
.extern timer_interrupt
bl timer_interrupt
 
bl timer_interrupt
@ is it an ethernet interrupt ?
1: ands r2, r3, #0x100
beq 2f @ not ethmac int, jump
1: ands r2, r1, #0x100
beq 2f @ not ethmac int, jump
.extern ethmac_interrupt
@ Remember that registers r0 to r2 can be changed by this function
bl ethmac_interrupt
 
 
2: @ Restore all registers from the stack
ldmfd sp!, {r0-r3, lr}
 
ldmfd sp!, {r0-r12, lr}
@ Jump straight back to normal execution
subs pc, lr, #4
 
222,17 → 220,17
 
/* _testfail: Used to terminate execution in Verilog simulations */
/* On the board just puts the processor into an infinite loop */
.globl _testfail
.globl _testfail
_testfail:
ldr r11, AdrTestStatus
str r0, [r11]
b _testfail
 
 
/* _testpass: Used to terminate execution in Verilog simulations */
/* On the board just puts the processor into an infinite loop */
.globl _testpass
_testpass:
.globl _testpass
_testpass:
ldr r11, AdrTestStatus
mov r10, #17
str r10, [r11]
239,8 → 237,8
b _testpass
 
 
 
 
/* _div: Integer division function */
@ Divide r0 by r1
@ Answer returned in r1
258,22 → 256,22
@ Invert negative numbers
tst r0, #0x80000000
mvnne r0, r0
addne r0, r0, #1
addne r0, r0, #1
 
tst r1, #0x80000000
mvnne r1, r1
addne r1, r1, #1
addne r1, r1, #1
 
@ divide r1 by r2, also use registers r0 and r4
mov r2, r1
mov r1, r0
 
cmp r2, #0
beq 3f
 
@ In order to divide r1 by r2, the first thing we need to do is to shift r2
@ left by the necessary number of places. The easiest method of doing this
@ is simply by trial and error - shift until we discover that r2 has become
@ In order to divide r1 by r2, the first thing we need to do is to shift r2
@ left by the necessary number of places. The easiest method of doing this
@ is simply by trial and error - shift until we discover that r2 has become
@ too big, then stop.
mov r0,#0 @ clear r0 to accumulate result
mov r3,#1 @ set bit 0 in r3, which will be
290,14 → 288,14
@ shift r3 left in parallel in order to flag how far we have to go
 
@ r0 will be used to hold the result. The role of r3 is more complicated.
@ In effect, we are using r3 to mark where the right-hand end of r2 has got to
@ - if we shift r2 three places left, this will be indicated by a value of %1000
@ in r3. However, we also add it to r0 every time we manage a successful subtraction,
@ since it marks the position of the digit currently being calculated in the answer.
 
@ so at the time of the first subtraction, r3 would have been %100, at the time
@ of the second (which failed) it would have been %10, and at the time of the
@ third %1. Adding it to r0 after each successful subtraction would have
@ In effect, we are using r3 to mark where the right-hand end of r2 has got to
@ - if we shift r2 three places left, this will be indicated by a value of %1000
@ in r3. However, we also add it to r0 every time we manage a successful subtraction,
@ since it marks the position of the digit currently being calculated in the answer.
 
@ so at the time of the first subtraction, r3 would have been %100, at the time
@ of the second (which failed) it would have been %10, and at the time of the
@ third %1. Adding it to r0 after each successful subtraction would have
@ given us, once again, the answer of %101!
 
@ Now for the loop that actually does the work:
307,19 → 305,19
addcs r0,r0,r3 @ and add the current bit in r3 to
@ the accumulating answer in r0
 
@ In subtraction (a cmp instruction simulates a subtraction in
@ order to set the flags), if r1 - r2 gives a positive answer and no 'borrow'
@ is required, the carry flag is set. This is required in order to make SBC
@ (Subtract with Carry) work properly when used to carry out a 64-bit subtraction,
@ In subtraction (a cmp instruction simulates a subtraction in
@ order to set the flags), if r1 - r2 gives a positive answer and no 'borrow'
@ is required, the carry flag is set. This is required in order to make SBC
@ (Subtract with Carry) work properly when used to carry out a 64-bit subtraction,
@ but it is confusing!
 
@ In this case, we are turning it to our advantage. The carry flag is set to
@ indicate that a successful subtraction is possible, i.e. one that doesn't
@ generate a negative result, and the two following instructions are carried
@ out only when the condition Carry Set applies. Note that the 'S' on the end
@ of these instructions is part of the 'CS' condition code and does not mean
@ In this case, we are turning it to our advantage. The carry flag is set to
@ indicate that a successful subtraction is possible, i.e. one that doesn't
@ generate a negative result, and the two following instructions are carried
@ out only when the condition Carry Set applies. Note that the 'S' on the end
@ of these instructions is part of the 'CS' condition code and does not mean
@ that they set the flags!
 
movs r3,r3,lsr #1 @ Shift r3 right into carry flag
movcc r2,r2,lsr #1 @ and if bit 0 of r3 was zero, also
@ shift r2 right
326,20 → 324,20
bcc 2b @ If carry not clear, r3 has shifted
@ back to where it started, and we
@ can end
 
@ if one of the inputs is negetive then return a negative result
@ if one of the inputs is negetive then return a negative result
tst r4, #0x80000000
mvnne r0, r0
addne r0, r0, #1
addne r0, r0, #1
3: ldmia sp!, {r4, pc}^
 
 
/* strcpy: String copy function
/* strcpy: String copy function
char * strcpy ( char * destination, const char * source );
destination is returned
*/
*/
@ r0 points to destination
@ r1 points to source string which terminates with a 0
@ r1 points to source string which terminates with a 0
.globl strcpy
strcpy:
stmdb sp!, {r4-r6, lr}
353,22 → 351,22
strb r3, [r6], #1
cmp r3, #0
ldmeqia sp!, {r4-r6, pc}^
 
ldrb r3, [r1], #1
strb r3, [r6], #1
cmp r3, #0
ldmeqia sp!, {r4-r6, pc}^
 
ldrb r3, [r1], #1
strb r3, [r6], #1
cmp r3, #0
ldmeqia sp!, {r4-r6, pc}^
 
ldrb r3, [r1], #1
strb r3, [r6], #1
cmp r3, #0
ldmeqia sp!, {r4-r6, pc}^
 
b strcpy_main
 
 
378,7 → 376,7
@ r1 points to source string
@ r2 is the number of bytes to copy
.globl strncpy
strncpy:
strncpy:
stmdb sp!, {r4, lr}
cmp r2, #0
beq 2f
399,26 → 397,26
.globl strncmp
strncmp:
stmdb sp!, {r4, r5, r6, lr}
 
@ check for 0 length
cmp r2, #0
moveq r0, #1
beq 2f
 
mov r3, #0
 
1: add r3, r3, #1
ldrb r4, [r0], #1
ldrb r5, [r1], #1
 
subs r6, r4, r5
movne r0, r6
bne 2f
 
cmp r3, r2
moveq r0, #0
beq 2f
 
b 1b
2: ldmia sp!, {r4, r5, r6, pc}^
 
429,12 → 427,12
ldr r0, AdrMallocBase
ldr r1, AdrMallocPointer
str r0, [r1]
 
@ initialize the counter to 0
ldr r1, AdrMallocCount
mov r2, #0
str r2, [r1]
 
mov pc, lr
 
 
445,38 → 443,25
ldr r1, AdrMallocPointer
ldr r2, [r1] /* r2 now containts the starting address of the next memory block to use */
add r3, r0, r2 /* r3 contains the address after the end of the new object */
 
/* Round r3 up to the nearest 0x100 to keep memory aligned */
tst r3, #0xff
beq 1f
bic r3, r3, #0xff
add r3, r3, #0x100
 
1: str r3, [r1] /* Update the malloc pointer */
mov r0, r2 /* Return the address from before the pointer was updated */
 
@ Update the block count
ldr r1, AdrMallocCount
ldr r2, [r1]
add r2, r2, #1
str r2, [r1]
 
mov pc, lr
 
 
.global serial_putchar_
serial_putchar_:
ldr r1, AdrUARTDR
ldr r3, AdrUARTFR
@ Check the tx_full flag
1: ldr r2, [r3]
and r2, r2, #0x20
cmp r2, #0
streqb r0, [r1]
moveqs pc, lr @ return
bne 1b
 
 
/* stack at top of ddr3 memory space */
AdrJumpPoint: .word _jump_point
AdrExecBase: .word ADR_EXEC_BASE
490,9 → 475,6
AdrTestStatus: .word ADR_AMBER_TEST_STATUS
AdrInterruptStatus: .word ADR_AMBER_IC_IRQ0_STATUS
 
AdrUARTDR: .word ADR_AMBER_UART0_DR
AdrUARTFR: .word ADR_AMBER_UART0_FR
 
.align 2
AdrATAGBase: .word ATAGBase
AdeEndATAG: .word EndATAG
502,7 → 484,7
.word FLAG_READONLY @ flags
.word 4096 @ page size
.word 0x0 @ rootdev
 
.word ATAG_MEM_SIZE
.word ATAG_MEM
.word 32*1024*1024 @ size - 32MB
518,7 → 500,7
.word ATAG_INITRD
.word 0x02800000 @ virtual address of start of initrd image
.word 0x00032000 @ size = 200k
 
.word ATAG_NONE
.word 0x0
EndATAG: .word 0x0
/trunk/sw/boot-loader-ethmac/utilities.h
44,7 → 44,6
int get_hex (char*, unsigned int*);
int next_string (char*);
int strcmp (char*, char*);
int serial_putchar_ (char *);
 
void led_clear (void);
void led_flip (int);
/trunk/sw/boot-loader-ethmac/timer.c
7,7 → 7,7
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
62,7 → 62,7
 
 
/*Initialize a global variable that keeps
track of the current up time. Timers are
track of the current up time. Timers are
compared against this running value.
*/
void init_current_time()
70,7 → 70,7
/* Configure timer 0 */
/* Counts down from this value and generates an interrupt every 1/100 seconds */
*(unsigned int *) ( ADR_AMBER_TM_TIMER0_LOAD ) = 1562; // 16-bit, x 256
*(unsigned int *) ( ADR_AMBER_TM_TIMER0_CTRL ) = 0xc8; // enable[7], periodic[6],
*(unsigned int *) ( ADR_AMBER_TM_TIMER0_CTRL ) = 0xc8; // enable[7], periodic[6],
 
/* Enable timer 0 interrupt */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x020;
86,7 → 86,7
{
/* Clear timer 0 interrupt in timer */
*(unsigned int *) ( ADR_AMBER_TM_TIMER0_CLR ) = 1;
 
/* Disable timer 0 interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLECLR ) = 0x020;
 
98,9 → 98,9
else {
current_time_g->milliseconds+=10;
}
 
/* Enable timer 0 interrupt in interrupt controller */
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x020;
*(unsigned int *) ( ADR_AMBER_IC_IRQ0_ENABLESET ) = 0x020;
}
 
 
109,13 → 109,13
{
if (!expiry_time->seconds && !expiry_time->milliseconds)
/* timer is not set */
return 0;
return 0;
else if (expiry_time->seconds < current_time_g->seconds)
return 1;
else if ((expiry_time->seconds == current_time_g->seconds) &&
else if ((expiry_time->seconds == current_time_g->seconds) &&
(expiry_time->milliseconds < current_time_g->milliseconds))
return 1;
else
else
return 0;
}
 
125,8 → 125,8
{
int seconds = _div(milliseconds, 1000);
int mseconds = milliseconds - seconds*1000; /* milliseconds % 1000 */
 
 
if (current_time_g->milliseconds >= (1000 - mseconds)) {
timer->seconds = current_time_g->seconds + 1;
timer->milliseconds = current_time_g->milliseconds + mseconds - 1000;
135,7 → 135,7
timer->seconds = current_time_g->seconds;
timer->milliseconds = current_time_g->milliseconds + mseconds;
}
 
timer->seconds += seconds;
}
 
/trunk/sw/boot-loader-ethmac/udp.c
7,7 → 7,7
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
60,58 → 60,59
unsigned int udp_src_port = buf[0]<<8|buf[1];
unsigned int udp_dst_port = buf[2]<<8|buf[3];
unsigned int udp_len = buf[4]<<8|buf[5];
 
unsigned short prot_udp=17;
unsigned short word16;
unsigned long sum = 0;
unsigned long sum = 0;
unsigned int checksum;
int mode_offset;
int binary_mode;
int i;
 
 
for (i=0;i<4;i=i+2){
word16 =((rx_packet->src_ip[i]<<8)&0xFF00)+(rx_packet->src_ip[i+1]&0xFF);
sum=sum+word16;
sum=sum+word16;
}
for (i=0;i<4;i=i+2){
word16 =((rx_packet->dst_ip[i]<<8)&0xFF00)+(rx_packet->dst_ip[i+1]&0xFF);
sum=sum+word16;
sum=sum+word16;
}
// the protocol number and the length of the TCP packet
sum = sum + prot_udp + udp_len;
 
checksum = header_checksum16(buf, udp_len, sum);
 
if (checksum)
udp_checksum_errors_g++;
 
 
/* TFTP */
if (checksum)
udp_checksum_errors_g++;
/* TFTP */
if (udp_dst_port == 69 && !checksum) {
unsigned int opcode = buf[8]<<8|buf[9];
unsigned int block = buf[10]<<8|buf[11];
int tftp_len = udp_len - 12;
 
mode_offset = next_string(&buf[10]);
binary_mode = strcmp("octet", &buf[10+mode_offset]);
 
switch (opcode) {
 
case UDP_READ:
udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ERROR);
break;
 
case UDP_WRITE:
udp_file_g = init_buffer_512();
udp_file_g->filename = malloc(256);
strcpy(udp_file_g->filename, &buf[10]);
 
if (strncmp(&buf[10], "vmlinux", 7) == 0)
udp_file_g->linux_boot = 1;
 
if (strncmp(&buf[10], "vmlinux") == 0)
udp_file_g->linux_boot == 1;
udp_current_block_g = udp_file_g;
 
if (binary_mode)
udp_reply(rx_packet, udp_dst_port, udp_src_port, 0, UDP_ACK);
else
121,21 → 122,21
 
case UDP_DATA:
udp_reply(rx_packet, udp_dst_port, udp_src_port, block, UDP_ACK);
 
if (block > udp_file_g->last_block) {
// Have not already received this block
udp_file_g->last_block = block;
 
/* receive and save a block */
udp_current_block_g->bytes = tftp_len;
udp_file_g->total_bytes += tftp_len;
udp_file_g->total_blocks++;
 
memcpy(udp_current_block_g->buf512, &buf[12], tftp_len);
 
/* Prepare the next block */
if (tftp_len == 512) {
udp_current_block_g->next = init_buffer_512();
udp_current_block_g->next = init_buffer_512();
udp_current_block_g = udp_current_block_g->next;
}
else { /* Last block */
143,8 → 144,8
}
}
break;
 
 
default: break;
}
}
159,10 → 160,10
unsigned short prot_udp=17;
unsigned short udp_len;
unsigned short word16;
unsigned long sum = 0;
unsigned long sum = 0;
int i;
mac_ip_t target;
 
target.mac[0] = rx_packet->src_mac[0];
target.mac[1] = rx_packet->src_mac[1];
target.mac[2] = rx_packet->src_mac[2];
179,8 → 180,8
buf[35] = udp_src_port & 0xff;
buf[36] = (udp_dst_port & 0xff00)>>8;
buf[37] = udp_dst_port & 0xff;
 
if (reply_type == UDP_ACK)
if (reply_type == UDP_ACK)
udp_len = 8+4;
else /* error */
udp_len = 8+2+2+14;
188,17 → 189,17
 
buf[38] = (udp_len & 0xff00)>>8;
buf[39] = udp_len & 0xff;
 
buf[40] = 0; // checksum
buf[41] = 0; // checksum
 
// -------------------------------------
// tftf payload
// tftf payload
// -------------------------------------
// Opcode
buf[42] = 0;
buf[43] = reply_type & 0xff; // Acknowledgment
 
buf[42] = 0;
buf[43] = reply_type & 0xff; // Acknowledgment
if (reply_type == UDP_ACK) {
// block
buf[44] = (block & 0xff00)>>8;
211,18 → 212,18
// 46 to 59
strncpy(&buf[46], "Not supported", 14);
}
 
 
// -------------------------------------
// UDP Checksum calculation
// -------------------------------------
for (i=0;i<4;i=i+2){
word16 =((rx_packet->src_ip[i]<<8)&0xFF00)+(rx_packet->src_ip[i+1]&0xFF);
sum=sum+word16;
sum=sum+word16;
}
for (i=0;i<4;i=i+2){
word16 =((rx_packet->dst_ip[i]<<8)&0xFF00)+(rx_packet->dst_ip[i+1]&0xFF);
sum=sum+word16;
sum=sum+word16;
}
// the protocol number and the length of the TCP packet
sum = sum + prot_udp + udp_len;
230,7 → 231,7
checksum = header_checksum16(&buf[34], udp_len, sum);
buf[40] = (checksum & 0xff00)>>8; // checksum
buf[41] = checksum & 0xff; // checksum
 
ip_header(&buf[14], &target, 20+udp_len, 17); /* 20 byes of tcp options, bytes 14 to 33, ip_proto = 17, UDP */
ethernet_header(buf, &target, 0x0800); /*bytes 0 to 13*/
tx_packet(34+udp_len); // packet length in bytes
248,7 → 249,6
block->total_blocks = 0;
block->ready = 0;
block->filename = NULL;
block->linux_boot = 0;
return block;
}
 
/trunk/sw/boot-loader-ethmac/telnet.c
7,7 → 7,7
// //
// Description //
// The main functions for the boot loader application. This //
// application is embedded in the FPGA's SRAM and is used //
// application is embedded in the FPGA's SRAM and is used //
// to load larger applications into the DDR3 memory on //
// the development board. //
// //
53,22 → 53,22
int i;
int stage = 0;
char stage1;
 
for (i=0;i<socket->rx_packet->tcp_payload_len;i++) {
 
if (stage == 0) {
switch (buf[i]) {
case 241: stage = 0; break; // NOP
case 255: stage = 1;
case 255: stage = 1;
if (socket->telnet_connection_state == TELNET_CLOSED) {
socket->telnet_connection_state = TELNET_OPEN;
}
break; // IAC
 
default: if (buf[i] < 128)
default: if (buf[i] < 128)
goto telnet_payload;
}
 
} else if (stage == 1) {
stage1 = buf[i];
switch (buf[i]) {
80,9 → 80,9
case TELNET_DONT: stage = 2; break; // 0xfe DONT
default : stage = 2; break;
}
 
} else { // stage = 2
stage = 0;
stage = 0;
switch (buf[i]) {
case 1: // echo
/* Client request that server echos stuff back to client */
92,7 → 92,7
else if (stage1 == TELNET_DONT)
socket->telnet_echo_mode = 0;
break;
 
case 3: break; // suppress go ahead
case 5: break; // status
case 6: break; // time mark
108,8 → 108,8
}
}
 
return;
 
return;
telnet_payload:
socket->rx_packet->telnet_payload_len = socket->rx_packet->tcp_payload_len - i;
parse_telnet_payload(&buf[i], socket);
122,7 → 122,7
int cr = 0;
int windows = 0;
for (i=0;i<socket->rx_packet->telnet_payload_len;i++) {
if (buf[i] == '\n')
if (buf[i] == '\n')
windows = 1;
else if (buf[i] < 128 && buf[i] != 0) {
/* end of a line */
130,13 → 130,13
if (buf[i] == '\r') {
cr=1;
put_byte(socket->telnet_rxbuf, buf[i], 1); /* last byte of line */
}
}
else {
put_byte(socket->telnet_rxbuf, buf[i], 0); /* not last byte of line */
}
}
}
}
 
if (socket->telnet_echo_mode) {
if (cr && !windows) {
buf[socket->rx_packet->telnet_payload_len] = '\n';
153,7 → 153,7
 
// telnet options
// Will echo - advertise that I have the ability to echo back commands to the client
buf[0] = 0xff; buf[1] = TELNET_WILL; buf[2] = 0x01;
buf[0] = 0xff; buf[1] = TELNET_WILL; buf[2] = 0x01;
tcp_reply(socket, buf, 3);
 
}
165,17 → 165,27
int total_line_len;
char* line;
char* first_line;
/* Parse telnet tx buffer
Grab as many lines as possible to stuff into a packet to transmit */
line_len = get_line(txbuf, &first_line);
if (line_len) {
total_line_len = line_len;
while (total_line_len < MAX_TELNET_TX && line_len) {
line_len = get_line(txbuf, &line);
total_line_len += line_len;
}
tcp_tx(socket, first_line, total_line_len);
}
}
 
/* Parse telnet tx buffer
Grab as many lines as possible to stuff into a packet to transmit */
line_len = get_line(txbuf, &first_line);
if (line_len) {
total_line_len = line_len;
while (total_line_len < MAX_TELNET_TX && line_len) {
line_len = get_line(txbuf, &line);
total_line_len += line_len;
}
tcp_tx(socket, first_line, total_line_len);
}
/*
void telnet_broadcast (const char *fmt, ...)
{
register unsigned long *varg = (unsigned long *)(&fmt);
*varg++;
put_line (socket0_g->telnet_txbuf, fmt, varg);
put_line (socket1_g->telnet_txbuf, fmt, varg);
}
 
*/
/trunk/sw/boot-loader-ethmac/Makefile
41,9 → 41,9
# Assembly source files
 
SRC = boot-loader-ethmac.c line-buffer.c timer.c print.c elfsplitter.c utilities.c \
serial.c ethmac.c packet.c tcp.c udp.c telnet.c start.S ../mini-libc/memcpy.c
ethmac.c packet.c tcp.c udp.c telnet.c start.S ../mini-libc/memcpy.c
DEP = address_map.h boot-loader-ethmac.h line-buffer.h timer.h utilities.h \
serial.h ethmac.h tcp.h udp.h telnet.h packet.h elfsplitter.h
ethmac.h tcp.h udp.h telnet.h packet.h elfsplitter.h
TGT = boot-loader-ethmac.elf
LDS = sections.lds
 
55,5 → 55,5
 
all : debug
../tools/check_mem_size.sh $(MEM) "@000040"
 
include ../include/common.mk
/trunk/sw/boot-loader-ethmac/print.c
48,16 → 48,13
#define PRINT_BUF_LEN 16
 
 
/* format and print a string, inserting variables, to dst char buffer,
return the number of characters printed. If dst is 0, the string is
sent to the serial output
*/
 
int print(char** dst, const char *format, unsigned long *varg)
{
register int width, pad;
register int pc = 0;
char scr[2];
 
for (; *format != 0; ++format) {
if (*format == '%') {
++format;
107,10 → 104,8
}
else {
out:
if (dst)
*(*dst)++ = *format;
else
serial_putchar_(*format);
//outbyte (dst, *format);
*(*dst)++ = *format;
++pc;
}
}
124,39 → 119,33
{
register int pc = 0, padchar = ' ';
 
if (width > 0) {
register int len = 0;
register const char *ptr;
for (ptr = string; *ptr; ++ptr) ++len;
if (len >= width) width = 0;
else width -= len;
if (pad & PAD_ZERO) padchar = '0';
}
if (!(pad & PAD_RIGHT)) {
for ( ; width > 0; --width) {
if (dst)
*(*dst)++ = padchar;
else
serial_putchar_(padchar);
++pc;
}
}
for ( ; *string ; ++string) {
if (dst)
*(*dst)++ = *string;
else
serial_putchar_(*string);
++pc;
}
for ( ; width > 0; --width) {
if (dst)
if (width > 0) {
register int len = 0;
register const char *ptr;
for (ptr = string; *ptr; ++ptr) ++len;
if (len >= width) width = 0;
else width -= len;
if (pad & PAD_ZERO) padchar = '0';
}
if (!(pad & PAD_RIGHT)) {
for ( ; width > 0; --width) {
//outbyte(dst, padchar);
*(*dst)++ = padchar;
else
serial_putchar_(padchar);
++pc;
}
++pc;
}
}
for ( ; *string ; ++string) {
//outbyte(dst, *string);
*(*dst)++ = *string;
++pc;
}
for ( ; width > 0; --width) {
//outbyte(dst, padchar);
*(*dst)++ = padchar;
++pc;
}
 
return pc;
return pc;
}
 
 
185,11 → 174,11
while (u) {
if ( b == 16 ) t = u & 0xf; /* hex modulous */
else t = u - ( _div (u, b) * b ); /* Modulous */
 
if( t >= 10 )
t += letbase - '0' - 10;
*--s = t + '0';
 
/* u /= b; */
if ( b == 16) u = u >> 4; /* divide by 16 */
else u = _div(u, b);
197,10 → 186,8
 
if (neg) {
if( width && (pad & PAD_ZERO) ) {
if (dst)
*(*dst)++ = '-';
else
serial_putchar_('-');
//outbyte(dst,'-');
*(*dst)++ = '-';
++pc;
--width;
}
/trunk/sw/boot-loader-ethmac/elfsplitter.c
59,7 → 59,8
unsigned int outP;
int interrupt_table_written = 0;
int interrupt_table_zero_written = 0;
 
/* Create buffer to hold interrupt vector memory values
Can't copy these into mem0 locations until ready to pass control
t new program
67,8 → 68,8
elf_mem0_g = malloc(sizeof(mem_buf_t));
for(i=0;i<MEM_BUF_ENTRIES;i++)
elf_mem0_g->entry[i].valid = 0;
 
 
elfHeader=(ElfHeader*)inbuf;
 
 
75,54 → 76,60
if (strncmp((char*)elfHeader->e_ident+1,"ELF",3)) {
return(1);
}
 
if (elfHeader->e_machine != 40) {
print_serial ("%s:L%d ERROR: ELF file not targetting correct processor type.\r\n",
__FILE__, __LINE__);
telnet_broadcast ("%s ERROR: ELF file not targetting correct processor type.\r\n",
__func__);
return(1);
}
 
for (i=0;i<elfHeader->e_shnum;++i) {
elfSection=(Elf32_Shdr*)(inbuf+elfHeader->e_shoff+elfHeader->e_shentsize*i);
 
for (i=0;i<elfHeader->e_shnum;++i) {
elfSection=(Elf32_Shdr*)(inbuf+elfHeader->e_shoff+elfHeader->e_shentsize*i);
 
/* section with non-zero bits, can be either text or data */
if (elfSection->sh_type == SHT_PROGBITS && elfSection->sh_size != 0) {
for (j=0; j<elfSection->sh_size; j++) {
k = j + elfSection->sh_offset;
outP = elfSection->sh_addr + j;
 
/* debug */
if (outP >= ADR_EXEC_BASE)
print_serial("%s:L%d ERROR: 1 outP value 0x%08x\r\n",__FILE__, __LINE__, outP);
else if (outP > MEM_BUF_ENTRIES)
outbuf[outP] = inbuf[k];
else {
elf_mem0_g->entry[outP].valid = 1;
elf_mem0_g->entry[outP].data = inbuf[k];
/* section with non-zero bits, can be either text or data */
if (elfSection->sh_type == SHT_PROGBITS && elfSection->sh_size != 0) {
for (j=0; j<elfSection->sh_size; j++) {
k = j + elfSection->sh_offset;
outP = elfSection->sh_addr + j;
/* debug */
if (outP >= ADR_EXEC_BASE)
telnet_broadcast("%s ERROR: 1 outP value 0x%08x\r\n",__func__, outP);
else if (outP > MEM_BUF_ENTRIES)
outbuf[outP] = inbuf[k];
else {
elf_mem0_g->entry[outP].valid = 1;
elf_mem0_g->entry[outP].data = inbuf[k];
interrupt_table_written = 1;
}
}
}
 
if (elfSection->sh_type == SHT_NOBITS && elfSection->sh_size != 0) {
for (j=0; j<elfSection->sh_size; j++) {
outP = j + elfSection->sh_addr;
 
/* debug */
if (outP >= ADR_EXEC_BASE)
print_serial("%s:L%d ERROR: 2 outP value 0x%08x\r\n",__FILE__, __LINE__, outP);
else if (outP > MEM_BUF_ENTRIES)
outbuf[outP] = 0;
else {
elf_mem0_g->entry[outP].valid = 1;
elf_mem0_g->entry[outP].data = 0;
}
}
if (elfSection->sh_type == SHT_NOBITS && elfSection->sh_size != 0) {
for (j=0; j<elfSection->sh_size; j++) {
outP = j + elfSection->sh_addr;
/* debug */
if (outP >= ADR_EXEC_BASE)
telnet_broadcast("%s ERROR: 2 outP value 0x%08x\r\n",__func__, outP);
else if (outP > MEM_BUF_ENTRIES)
outbuf[outP] = 0;
else {
elf_mem0_g->entry[outP].valid = 1;
elf_mem0_g->entry[outP].data = 0;
interrupt_table_zero_written = 1;
}
}
}
}
 
}
}
}
/*
if (interrupt_table_written)
telnet_broadcast ("%s WARNING: Interrupt table writes\r\n",__func__);
if (interrupt_table_zero_written)
telnet_broadcast ("%s WARNING: Interrupt table ZERO writes\r\n",__func__);
*/
return 0;
}
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.