From a6c88411ffa8cfb46699872bd995fbfbea65c6c1 Mon Sep 17 00:00:00 2001 From: PMiranda Date: Mon, 13 May 2024 15:04:22 +0100 Subject: [PATCH 1/8] feat(spi): connect SPI to flash pins - update SPI submodule - add synthesis constraints to connect SPI ports to QSPI pins in ku040 board - update firmware/boot to access spi memory --- .../iob_soc_opencryptolinux_fpga_wrapper.v | 346 ++++++++++++++++++ ...b_soc_opencryptolinux_fpga_wrapper_dev.sdc | 149 ++++++++ iob_soc_opencryptolinux.py | 2 - software/src/iob_soc_opencryptolinux_boot.c | 137 +++++-- .../src/iob_soc_opencryptolinux_firmware.c | 98 ++++- software/sw_build.mk | 1 + submodules/SPI | 2 +- 7 files changed, 698 insertions(+), 37 deletions(-) create mode 100644 hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper.v create mode 100644 hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper_dev.sdc diff --git a/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper.v b/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper.v new file mode 100644 index 00000000..6d36ba57 --- /dev/null +++ b/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper.v @@ -0,0 +1,346 @@ +`timescale 1ns / 1ps +`include "bsp.vh" +`include "iob_soc_opencryptolinux_conf.vh" + +module iob_soc_opencryptolinux_fpga_wrapper ( + + //differential clock input and reset + input c0_sys_clk_clk_p, + input c0_sys_clk_clk_n, + input reset, + + //uart + output txd_o, + input rxd_i, + + //spi + output spi_SS_o, + output spi_SCLK_o, + inout spi_MISO_io, + inout spi_MOSI_io, + inout spi_WP_N_io, + inout spi_HOLD_N_io, + +`ifdef IOB_SOC_OPENCRYPTOLINUX_USE_EXTMEM + output c0_ddr4_act_n, + output [16:0] c0_ddr4_adr, + output [ 1:0] c0_ddr4_ba, + output [ 0:0] c0_ddr4_bg, + output [ 0:0] c0_ddr4_cke, + output [ 0:0] c0_ddr4_odt, + output [ 0:0] c0_ddr4_cs_n, + output [ 0:0] c0_ddr4_ck_t, + output [ 0:0] c0_ddr4_ck_c, + output c0_ddr4_reset_n, + inout [ 3:0] c0_ddr4_dm_dbi_n, + inout [31:0] c0_ddr4_dq, + inout [ 3:0] c0_ddr4_dqs_c, + inout [ 3:0] c0_ddr4_dqs_t, +`endif + +`ifdef IOB_SOC_OPENCRYPTOLINUX_USE_ETHERNET + output ENET_RESETN, + input ENET_RX_CLK, + output ENET_GTX_CLK, + input ENET_RX_D0, + input ENET_RX_D1, + input ENET_RX_D2, + input ENET_RX_D3, + input ENET_RX_DV, + //input ENET_RX_ERR, + output ENET_TX_D0, + output ENET_TX_D1, + output ENET_TX_D2, + output ENET_TX_D3, + output ENET_TX_EN, + //output ENET_TX_ERR, +`endif + + output trap +); + + localparam AXI_ID_W = 4; + localparam AXI_LEN_W = 8; + localparam AXI_ADDR_W = `DDR_ADDR_W; + localparam AXI_DATA_W = `DDR_DATA_W; + + `include "iob_soc_opencryptolinux_wrapper_pwires.vs" + + wire clk; + wire arst; + + + // + // Logic to contatenate data pins and ethernet clock + // +`ifdef IOB_SOC_OPENCRYPTOLINUX_USE_ETHERNET + //buffered eth clock + wire ETH_Clk; + + //eth clock + IBUFG rxclk_buf ( + .I(ENET_RX_CLK), + .O(ETH_Clk) + ); + ODDRE1 ODDRE1_inst ( + .Q (ENET_GTX_CLK), + .C (ETH_Clk), + .D1(1'b1), + .D2(1'b0), + .SR(~ENET_RESETN) + ); + + //MII + assign ETH0_MRxClk = ETH_Clk; + assign ETH0_MRxD = {ENET_RX_D3, ENET_RX_D2, ENET_RX_D1, ENET_RX_D0}; + assign ETH0_MRxDv = ENET_RX_DV; + //assign ETH0_MRxErr = ENET_RX_ERR; + assign ETH0_MRxErr = 1'b0; + + assign ETH0_MTxClk = ETH_Clk; + assign {ENET_TX_D3, ENET_TX_D2, ENET_TX_D1, ENET_TX_D0} = ETH0_MTxD; + assign ENET_TX_EN = ETH0_MTxEn; + //assign ENET_TX_ERR = ETH0_MTxErr; + + assign ENET_RESETN = ETH0_phy_rstn_o; + + assign ETH0_MColl = 1'b0; + assign ETH0_MCrS = 1'b0; +`endif + + + // + // IOb-SoC + // + + iob_soc_opencryptolinux #( + .AXI_ID_W (AXI_ID_W), + .AXI_LEN_W (AXI_LEN_W), + .AXI_ADDR_W(AXI_ADDR_W), + .AXI_DATA_W(AXI_DATA_W) + ) iob_soc_opencryptolinux0 ( + `include "iob_soc_opencryptolinux_pportmaps.vs" + .clk_i (clk), + .cke_i (1'b1), + .arst_i(arst), + .trap_o(trap) + ); + + // UART + assign txd_o = uart_txd_o; + assign uart_rxd_i = rxd_i; + assign uart_cts_i = 1'b1; + // uart_rts_o unconnected + + // SPI + assign spi_SS_o = spi_SS; + assign spi_SCLK_o = spi_SCLK; + assign spi_MISO_io = spi_MISO; + assign spi_MOSI_io = spi_MOSI; + assign spi_WP_N_io = spi_WP_N; + assign spi_HOLD_N_io = spi_HOLD_N; + + // + // DDR4 CONTROLLER + // + +`ifdef IOB_SOC_OPENCRYPTOLINUX_USE_EXTMEM + localparam DDR4_AXI_ID_W = AXI_ID_W; + localparam DDR4_AXI_LEN_W = AXI_LEN_W; + localparam DDR4_AXI_ADDR_W = AXI_ADDR_W; + localparam DDR4_AXI_DATA_W = AXI_DATA_W; + + + `include "iob_soc_opencryptolinux_ku040_rstn.vs" + + //axi wires between ddr4 contrl and axi interconnect + `include "ddr4_axi_wire.vs" + + //DDR4 controller axi side clocks and resets + wire c0_ddr4_ui_clk; //controller output clock 200MHz + wire ddr4_axi_arstn; //controller input + + wire c0_ddr4_ui_clk_sync_rst; + + wire calib_done; + + + // + // ASYNC AXI BRIDGE (between user logic (clk) and DDR controller (c0_ddr4_ui_clk) + // + axi_interconnect_0 axi_async_bridge ( + .INTERCONNECT_ACLK (c0_ddr4_ui_clk), //from ddr4 controller + .INTERCONNECT_ARESETN(~c0_ddr4_ui_clk_sync_rst), //from ddr4 controller + + `include "iob_soc_opencryptolinux_ku040_interconnect_s_portmap.vs" + + // + // DDR CONTROLLER SIDE (master) + // + + .M00_AXI_ARESET_OUT_N(ddr4_axi_arstn), //to ddr controller axi slave port + .M00_AXI_ACLK (c0_ddr4_ui_clk), //from ddr4 controller 200MHz clock + + //Write address + .M00_AXI_AWID (ddr4_axi_awid), + .M00_AXI_AWADDR (ddr4_axi_awaddr), + .M00_AXI_AWLEN (ddr4_axi_awlen), + .M00_AXI_AWSIZE (ddr4_axi_awsize), + .M00_AXI_AWBURST(ddr4_axi_awburst), + .M00_AXI_AWLOCK (ddr4_axi_awlock[0]), + .M00_AXI_AWCACHE(ddr4_axi_awcache), + .M00_AXI_AWPROT (ddr4_axi_awprot), + .M00_AXI_AWQOS (ddr4_axi_awqos), + .M00_AXI_AWVALID(ddr4_axi_awvalid), + .M00_AXI_AWREADY(ddr4_axi_awready), + + //Write data + .M00_AXI_WDATA (ddr4_axi_wdata), + .M00_AXI_WSTRB (ddr4_axi_wstrb), + .M00_AXI_WLAST (ddr4_axi_wlast), + .M00_AXI_WVALID(ddr4_axi_wvalid), + .M00_AXI_WREADY(ddr4_axi_wready), + + //Write response + .M00_AXI_BID (ddr4_axi_bid), + .M00_AXI_BRESP (ddr4_axi_bresp), + .M00_AXI_BVALID(ddr4_axi_bvalid), + .M00_AXI_BREADY(ddr4_axi_bready), + + //Read address + .M00_AXI_ARID (ddr4_axi_arid), + .M00_AXI_ARADDR (ddr4_axi_araddr), + .M00_AXI_ARLEN (ddr4_axi_arlen), + .M00_AXI_ARSIZE (ddr4_axi_arsize), + .M00_AXI_ARBURST(ddr4_axi_arburst), + .M00_AXI_ARLOCK (ddr4_axi_arlock[0]), + .M00_AXI_ARCACHE(ddr4_axi_arcache), + .M00_AXI_ARPROT (ddr4_axi_arprot), + .M00_AXI_ARQOS (ddr4_axi_arqos), + .M00_AXI_ARVALID(ddr4_axi_arvalid), + .M00_AXI_ARREADY(ddr4_axi_arready), + + //Read data + .M00_AXI_RID (ddr4_axi_rid), + .M00_AXI_RDATA (ddr4_axi_rdata), + .M00_AXI_RRESP (ddr4_axi_rresp), + .M00_AXI_RLAST (ddr4_axi_rlast), + .M00_AXI_RVALID(ddr4_axi_rvalid), + .M00_AXI_RREADY(ddr4_axi_rready) + ); + + ddr4_0 ddr4_ctrl ( + .sys_rst (reset), + .c0_sys_clk_p(c0_sys_clk_clk_p), + .c0_sys_clk_n(c0_sys_clk_clk_n), + + .dbg_clk(), + .dbg_bus(), + + //USER LOGIC CLOCK AND RESET + .c0_ddr4_ui_clk_sync_rst(c0_ddr4_ui_clk_sync_rst), //to axi intercon + .addn_ui_clkout1 (clk), //to user logic + + //AXI INTERFACE (slave) + .c0_ddr4_ui_clk (c0_ddr4_ui_clk), //to axi intercon general and master clocks + .c0_ddr4_aresetn(ddr4_axi_arstn), //from interconnect axi master + + //address write + .c0_ddr4_s_axi_awid (ddr4_axi_awid), + .c0_ddr4_s_axi_awaddr (ddr4_axi_awaddr), + .c0_ddr4_s_axi_awlen (ddr4_axi_awlen), + .c0_ddr4_s_axi_awsize (ddr4_axi_awsize), + .c0_ddr4_s_axi_awburst(ddr4_axi_awburst), + .c0_ddr4_s_axi_awlock (ddr4_axi_awlock[0]), + .c0_ddr4_s_axi_awprot (ddr4_axi_awprot), + .c0_ddr4_s_axi_awcache(ddr4_axi_awcache), + .c0_ddr4_s_axi_awqos (ddr4_axi_awqos), + .c0_ddr4_s_axi_awvalid(ddr4_axi_awvalid), + .c0_ddr4_s_axi_awready(ddr4_axi_awready), + + //write + .c0_ddr4_s_axi_wvalid(ddr4_axi_wvalid), + .c0_ddr4_s_axi_wready(ddr4_axi_wready), + .c0_ddr4_s_axi_wdata (ddr4_axi_wdata), + .c0_ddr4_s_axi_wstrb (ddr4_axi_wstrb), + .c0_ddr4_s_axi_wlast (ddr4_axi_wlast), + + //write response + .c0_ddr4_s_axi_bready(ddr4_axi_bready), + .c0_ddr4_s_axi_bid (ddr4_axi_bid), + .c0_ddr4_s_axi_bresp (ddr4_axi_bresp), + .c0_ddr4_s_axi_bvalid(ddr4_axi_bvalid), + + //address read + .c0_ddr4_s_axi_arid (ddr4_axi_arid), + .c0_ddr4_s_axi_araddr (ddr4_axi_araddr), + .c0_ddr4_s_axi_arlen (ddr4_axi_arlen), + .c0_ddr4_s_axi_arsize (ddr4_axi_arsize), + .c0_ddr4_s_axi_arburst(ddr4_axi_arburst), + .c0_ddr4_s_axi_arlock (ddr4_axi_arlock[0]), + .c0_ddr4_s_axi_arcache(ddr4_axi_arcache), + .c0_ddr4_s_axi_arprot (ddr4_axi_arprot), + .c0_ddr4_s_axi_arqos (ddr4_axi_arqos), + .c0_ddr4_s_axi_arvalid(ddr4_axi_arvalid), + .c0_ddr4_s_axi_arready(ddr4_axi_arready), + + //read + .c0_ddr4_s_axi_rready(ddr4_axi_rready), + .c0_ddr4_s_axi_rid (ddr4_axi_rid), + .c0_ddr4_s_axi_rdata (ddr4_axi_rdata), + .c0_ddr4_s_axi_rresp (ddr4_axi_rresp), + .c0_ddr4_s_axi_rlast (ddr4_axi_rlast), + .c0_ddr4_s_axi_rvalid(ddr4_axi_rvalid), + + //DDR4 INTERFACE (master of external DDR4 module) + .c0_ddr4_act_n (c0_ddr4_act_n), + .c0_ddr4_adr (c0_ddr4_adr), + .c0_ddr4_ba (c0_ddr4_ba), + .c0_ddr4_bg (c0_ddr4_bg), + .c0_ddr4_cke (c0_ddr4_cke), + .c0_ddr4_odt (c0_ddr4_odt), + .c0_ddr4_cs_n (c0_ddr4_cs_n), + .c0_ddr4_ck_t (c0_ddr4_ck_t), + .c0_ddr4_ck_c (c0_ddr4_ck_c), + .c0_ddr4_reset_n (c0_ddr4_reset_n), + .c0_ddr4_dm_dbi_n (c0_ddr4_dm_dbi_n), + .c0_ddr4_dq (c0_ddr4_dq), + .c0_ddr4_dqs_c (c0_ddr4_dqs_c), + .c0_ddr4_dqs_t (c0_ddr4_dqs_t), + .c0_init_calib_complete(calib_done) + ); + + +`else + //if DDR not used use PLL to generate system clock + clock_wizard #( + .OUTPUT_PER(10), + .INPUT_PER (4) + ) clk_250_to_100_MHz ( + .clk_in1_p(c0_sys_clk_clk_p), + .clk_in1_n(c0_sys_clk_clk_n), + .clk_out1 (clk) + ); + + wire start; + iob_reset_sync start_sync ( + .clk_i (clk), + .arst_i(reset), + .arst_o(start) + ); + + //create reset pulse as reset is never activated manually + //also, during bitstream loading, the reset pin is not pulled high + iob_pulse_gen #( + .START (5), + .DURATION(10) + ) reset_pulse ( + .clk_i (clk), + .arst_i (reset), + .cke_i (1'b1), + .start_i(start), + .pulse_o(arst) + ); +`endif + +endmodule diff --git a/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper_dev.sdc b/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper_dev.sdc new file mode 100644 index 00000000..5a3e2451 --- /dev/null +++ b/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper_dev.sdc @@ -0,0 +1,149 @@ +## System Clock +set clk_period 4.0 +set clk_port c0_sys_clk_clk_p + +# LVDS Programmable Clock Generator (CDCM61002) +#set_property PACKAGE_PIN M5 [get_ports LVDS_CLK0_N] +#set_property PACKAGE_PIN M6 [get_ports LVDS_CLK0_P] +#set_property PACKAGE_PIN P5 [get_ports LVDS_CLK1_N] +#set_property PACKAGE_PIN P6 [get_ports LVDS_CLK1_P] + +#set_property IOSTANDARD LVDS [get_ports LVDS_CLK0_N] +#set_property IOSTANDARD LVDS [get_ports LVDS_CLK0_P] +#set_property IOSTANDARD LVDS [get_ports LVDS_CLK1_N] +#set_property IOSTANDARD LVDS [get_ports LVDS_CLK1_P] + +##DDR clocks +set_property PACKAGE_PIN H22 [get_ports {c0_sys_clk_clk_p}] +set_property PACKAGE_PIN H23 [get_ports {c0_sys_clk_clk_n}] +set_property IOSTANDARD DIFF_SSTL12 [get_ports {c0_sys_clk_clk_p}] +set_property IOSTANDARD DIFF_SSTL12 [get_ports {c0_sys_clk_clk_n}] + +set_property CONFIG_VOLTAGE 2.5 [current_design] + +#derive_pll_clocks +#derive_clock_uncertainty + +set_property CFGBVS VCCO [current_design] + +## USB-UART Interface +set_property PACKAGE_PIN D20 [get_ports {txd_o}] +set_property IOSTANDARD LVCMOS18 [get_ports {txd_o}] +set_property PACKAGE_PIN C19 [get_ports {rxd_i}] +set_property IOSTANDARD LVCMOS18 [get_ports {rxd_i}] + +###### User LEDs +#set_property PACKAGE_PIN D16 [get_ports {led[6]}] +#set_property IOSTANDARD LVCMOS18 [get_ports {led[6]}] + +#set_property PACKAGE_PIN G16 [get_ports {led[5]}] +#set_property IOSTANDARD LVCMOS18 [get_ports {led[5]}] + +#set_property PACKAGE_PIN H16 [get_ports {led[4]}] +#set_property IOSTANDARD LVCMOS18 [get_ports {led[4]}] + +#set_property PACKAGE_PIN E18 [get_ports {led[3]}] +#set_property IOSTANDARD LVCMOS18 [get_ports {led[3]}] + +#set_property PACKAGE_PIN E17 [get_ports {led[2]}] +#set_property IOSTANDARD LVCMOS18 [get_ports {led[2]}] + +#set_property PACKAGE_PIN E16 [get_ports {led[1]}] +#set_property IOSTANDARD LVCMOS18 [get_ports {led[1]}] + +#set_property PACKAGE_PIN H18 [get_ports {led[0]}] +#set_property IOSTANDARD LVCMOS18 [get_ports {led[0]}] + +set_property PACKAGE_PIN H17 [get_ports {trap}] +set_property IOSTANDARD LVCMOS18 [get_ports {trap}] + +####### User PUSH Switches +#set_property PACKAGE_PIN N24 [get_ports {reset}] +#set_property IOSTANDARD LVCMOS12 [get_ports {reset}] +set_property PACKAGE_PIN K20 [get_ports {reset}] +set_property IOSTANDARD LVCMOS12 [get_ports {reset}] + +#set_property PACKAGE_PIN K18 [get_ports {gpio_push_sw_tri_i[0]}] +#set_property IOSTANDARD LVCMOS12 [get_ports {gpio_push_sw_tri_i[0]}] + +#set_property PACKAGE_PIN L18 [get_ports {gpio_push_sw_tri_i[1]}] +#set_property IOSTANDARD LVCMOS12 [get_ports {gpio_push_sw_tri_i[1]}] + +#set_property PACKAGE_PIN K21 [get_ports {gpio_push_sw_tri_i[2]}] +#set_property IOSTANDARD LVCMOS12 [get_ports {gpio_push_sw_tri_i[2]}] + +#set_property PACKAGE_PIN K20 [get_ports {gpio_push_sw_tri_i[3]}] +#set_property IOSTANDARD LVCMOS12 [get_ports {gpio_push_sw_tri_i[3]}] + +####### Ethernet 100 MHz +create_clock -name enet_clk -period 40 [get_ports {ENET_RX_CLK}] + +## Ethernet #1 Interface (J1) +set_property PACKAGE_PIN D9 [get_ports ENET_RESETN] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_RESETN] + +set_property PACKAGE_PIN A10 [get_ports ENET_RX_D0] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_RX_D0] + +set_property PACKAGE_PIN B10 [get_ports ENET_RX_D1] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_RX_D1] + +set_property PACKAGE_PIN B11 [get_ports ENET_RX_D2] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_RX_D2] + +set_property PACKAGE_PIN C11 [get_ports ENET_RX_D3] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_RX_D3] + +set_property PACKAGE_PIN D11 [get_ports ENET_RX_DV] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_RX_DV] + +set_property PACKAGE_PIN E11 [get_ports ENET_RX_CLK] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_RX_CLK] + +set_property PACKAGE_PIN H8 [get_ports ENET_TX_D0] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_TX_D0] + +set_property PACKAGE_PIN H9 [get_ports ENET_TX_D1] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_TX_D1] + +set_property PACKAGE_PIN J9 [get_ports ENET_TX_D2] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_TX_D2] + +set_property PACKAGE_PIN J10 [get_ports ENET_TX_D3] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_TX_D3] + +set_property PACKAGE_PIN G9 [get_ports ENET_TX_EN] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_TX_EN] + +set_property PACKAGE_PIN G10 [get_ports ENET_GTX_CLK] +set_property IOSTANDARD LVCMOS18 [get_ports ENET_GTX_CLK] + +set_property IOB TRUE [get_ports ENET_TX_D0] +set_property IOB TRUE [get_ports ENET_TX_D1] +set_property IOB TRUE [get_ports ENET_TX_D2] +set_property IOB TRUE [get_ports ENET_TX_D3] +set_property IOB TRUE [get_ports ENET_TX_EN] + + +# +# User Code/Data QSPI Interface +# + +# CS +set_property PACKAGE_PIN D19 [get_ports spi_SS_o] +set_property IOSTANDARD LVCMOS18 [get_ports spi_SS_o] +# CLK +set_property PACKAGE_PIN F10 [get_ports spi_SCLK_o] +set_property IOSTANDARD LVCMOS18 [get_ports spi_SCLK_o] +# DQ0 +set_property PACKAGE_PIN G11 [get_ports spi_MOSI_io] +set_property IOSTANDARD LVCMOS18 [get_ports spi_MOSI_io] +# DQ1 +set_property PACKAGE_PIN H11 [get_ports spi_MISO_io] +set_property IOSTANDARD LVCMOS18 [get_ports spi_MISO_io] +# DQ2 +set_property PACKAGE_PIN J11 [get_ports spi_WP_N_io] +set_property IOSTANDARD LVCMOS18 [get_ports spi_WP_N_io] +# DQ3 +set_property PACKAGE_PIN H12 [get_ports spi_HOLD_N_io] +set_property IOSTANDARD LVCMOS18 [get_ports spi_HOLD_N_io] diff --git a/iob_soc_opencryptolinux.py b/iob_soc_opencryptolinux.py index 37cd6658..05fba2c2 100755 --- a/iob_soc_opencryptolinux.py +++ b/iob_soc_opencryptolinux.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 import os -import sys import shutil import math @@ -129,7 +128,6 @@ def _create_submodules_list(cls, extra_submodules=[]): iob_reset_sync, iob_ram_sp, cls.versatType, - # iob_spi_master, iob_eth, iob_spi_master, (N25Qxxx, {"purpose": "simulation"}), diff --git a/software/src/iob_soc_opencryptolinux_boot.c b/software/src/iob_soc_opencryptolinux_boot.c index 0a8193f2..1c95c472 100644 --- a/software/src/iob_soc_opencryptolinux_boot.c +++ b/software/src/iob_soc_opencryptolinux_boot.c @@ -1,11 +1,14 @@ #include "bsp.h" #include "clint.h" +#include "iob-eth.h" +#include "iob-spi.h" +#include "iob-spidefs.h" +#include "iob-spiplatform.h" #include "iob-uart16550.h" #include "iob_soc_opencryptolinux_conf.h" -#include "iob_soc_opencryptolinux_system.h" #include "iob_soc_opencryptolinux_periphs.h" +#include "iob_soc_opencryptolinux_system.h" #include "printf.h" -#include "iob-eth.h" #include #define PROGNAME "IOb-Bootloader" @@ -13,34 +16,36 @@ #define DC1 17 // Device Control 1 (used to indicate end of bootloader) #define EXT_MEM 0x80000000 +#define NSAMPLES 16 // Ethernet utility functions -//NOTE: These functions are not compatible with malloc() and free(). +// NOTE: These functions are not compatible with malloc() and free(). // These are specifically made for use with the current iob-eth.c drivers. // (These assume that there is only one block allocated at a time) -static void* mem_alloc(size_t size){ - return (void *)(EXT_MEM | (1<> 8); +// printf("UNIQUE ID:\n"); +// printf("\tData to follow: (%x)\n", (readid[0] & 0xFFFFFF00) >> 3*8); +// printf("\tExt Device ID: (%x)\n", (readid[1] & 0xFFFF)); +// printf("\tCustom Factory data[0-1]: (%x)\n", readid[1] >> 2*8); +// printf("\tCustom Factory data[5-2]: (%x)\n", readid[2]); +// printf("\tCustom Factory data[9-6]: (%x)\n", readid[3]); +// printf("\tCustom Factory data[13-10]: (%x)\n", readid[4]); +// +// printf("Testing program flash\n"); +// char prog_data[NSAMPLES] = {0}; +// char *char_data = NULL; +// unsigned int read_data[NSAMPLES] = {0}; +// int sample = 0; +// int test_result = 0; +// for (sample = 0; sample < NSAMPLES; sample++) { +// prog_data[sample] = 0xFF - sample; +// } +// +// spi_read_all_regs(); +// +// spiflash_memProgram(prog_data, NSAMPLES, 0x0); +// printf("After program\n"); +// +// spi_read_all_regs(); +// +// for (sample = 0; sample < NSAMPLES; sample = sample + 4) { +// read_data[sample >> 2] = spiflash_readmem(0x0 + sample); +// } +// // check prog vs read data +// char_data = (char *)read_data; +// for (sample = 0; sample < NSAMPLES; sample++) { +// if (prog_data[sample] != char_data[sample]) { +// printf("Error: data[%x] = %02x != read_data[%x] = %02x\n", sample, +// prog_data[sample], sample, char_data[sample]); +// test_result = 1; +// } +// } +// if (test_result) { +// printf("Flash test failed!\n"); +// } +// #endif // ifndef VERILATOR + #ifndef IOB_SOC_OPENCRYPTOLINUX_INIT_MEM // Init ethernet and printf (for ethernet) printf_init(&uart16550_putc); eth_init(ETH0_BASE, &clear_cache); - // Use custom memory alloc/free functions to ensure it allocates in external memory + // Use custom memory alloc/free functions to ensure it allocates in external + // memory eth_init_mem_alloc(&mem_alloc, &mem_free); // Wait for PHY reset to finish eth_wait_phy_rst(); - file_size = uart16550_recvfile("../iob_soc_opencryptolinux_mem.config", prog_start_addr); + file_size = uart16550_recvfile("../iob_soc_opencryptolinux_mem.config", + prog_start_addr); // compute_mem_load_txt int state = 0; int file_name_count = 0; @@ -104,7 +191,7 @@ int main() { int i = 0; for (i = 0; i < file_size; i++) { hexChar = *(prog_start_addr + i); - //uart16550_puts(&hexChar); /* Used for debugging. */ + // uart16550_puts(&hexChar); /* Used for debugging. */ if (state == 0) { if (hexChar == ' ') { file_name_array[file_count][file_name_count] = '\0'; @@ -130,8 +217,8 @@ int main() { uart16550_puts(PROGNAME); uart16550_puts(": invalid hexadecimal character.\n"); } - file_address_array[file_count-1] = - file_address_array[file_count-1] * 16 + hexDecimal; + file_address_array[file_count - 1] = + file_address_array[file_count - 1] * 16 + hexDecimal; } } } @@ -141,7 +228,7 @@ int main() { // Receive data from console via Ethernet #ifndef SIMULATION file_size = uart_recvfile_ethernet(file_name_array[i]); - eth_rcv_file(prog_start_addr,file_size); + eth_rcv_file(prog_start_addr, file_size); #else file_size = uart16550_recvfile(file_name_array[i], prog_start_addr); #endif @@ -149,21 +236,21 @@ int main() { // Check if running Linux for (i = 0; i < file_count; i++) { - if (!strcmp(file_name_array[i], "rootfs.cpio.gz")){ + if (!strcmp(file_name_array[i], "rootfs.cpio.gz")) { #ifdef SIMULATION // Running Linux: setup required dependencies uart16550_sendfile("test.log", 12, "Test passed!"); uart16550_putc((char)DC1); #endif - run_linux=1; + run_linux = 1; break; } } #else // INIT_MEM = 1 #ifdef IOB_SOC_OPENCRYPTOLINUX_RUN_LINUX - // Running Linux: setup required dependencies - uart16550_sendfile("test.log", 12, "Test passed!"); - uart16550_putc((char)DC1); + // Running Linux: setup required dependencies + uart16550_sendfile("test.log", 12, "Test passed!"); + uart16550_putc((char)DC1); #endif #endif diff --git a/software/src/iob_soc_opencryptolinux_firmware.c b/software/src/iob_soc_opencryptolinux_firmware.c index 1a92b272..0932b8d1 100644 --- a/software/src/iob_soc_opencryptolinux_firmware.c +++ b/software/src/iob_soc_opencryptolinux_firmware.c @@ -101,6 +101,28 @@ int GetTime(){ return clint_getTime(CLINT0_BASE); } +void spi_read_all_regs(){ + unsigned int status_reg = 0, lock_reg = 0, flag_reg = 0; + unsigned int non_vol_cfg = 0, vol_cfg = 0, enh_vol_cfg = 0; + unsigned int ext_addr = 0; + + spiflash_readStatusReg(&status_reg); + spiflash_readLockReg(&lock_reg); + spiflash_readFlagReg(&flag_reg); + spiflash_readNonVolConfigReg(&non_vol_cfg); + spiflash_readVolConfigReg(&vol_cfg); + spiflash_readEnhancedVolConfigReg(&enh_vol_cfg); + spiflash_readExtendedAddrReg(&ext_addr); + + printf("\nStatus Reg: (%x)\n", status_reg); + printf("Lock Reg: (%x)\n", lock_reg); + printf("Flag Reg: (%x)\n", flag_reg); + printf("NonVol Cfg Reg: (%x)\n", non_vol_cfg); + printf("Vol Cfg Reg: (%x)\n", vol_cfg); + printf("Enhanced Vol Cfg Reg: (%x)\n", enh_vol_cfg); + printf("Extended Addr Reg: (%x)\n", ext_addr); +} + int main() { char pass_string[] = "Test passed!"; uint_xlen_t irq_entry_copy; @@ -126,7 +148,7 @@ int main() { #endif //#ifndef SIMULATION - InitializeCryptoSide(VERSAT0_BASE); + // InitializeCryptoSide(VERSAT0_BASE); //#endif printf("\n\n\nHello world!\n\n\n"); @@ -137,15 +159,73 @@ int main() { // Tests are too big and slow to perform during simulation. // Comment out the source files in sw_build.mk to also reduce binary size and speedup simulation. -#ifndef SIMULATION - test_result |= VersatSHATests(); - test_result |= VersatAESTests(); - test_result |= VersatMcElieceTests(); -#else - test_result |= VersatSimpleSHATests(); - test_result |= VersatSimpleAESTests(); -#endif +// #ifndef SIMULATION +// test_result |= VersatSHATests(); +// test_result |= VersatAESTests(); +// test_result |= VersatMcElieceTests(); +// #else +// test_result |= VersatSimpleSHATests(); +// test_result |= VersatSimpleAESTests(); +// #endif + + // + // Test FPGA SPI Flash controller + // + + // init spit flash controller + spiflash_init(SPI0_BASE); + printf("\nResetting flash registers...\n"); + spiflash_resetmem(); + // Read Identifications + // Manufacturer ID | Device ID | Unique ID + unsigned int readid[5] = {0}, id_bytes = 0; + for (id_bytes = 0; id_bytes < 20; id_bytes += 4) { + spiflash_executecommand(COMMANS, 0, id_bytes, ((4 * 8) << 8) | READ_ID, + &(readid[id_bytes / 4])); + } + printf("\nMANUFACTURER ID: (%x)\n", (readid[0] & 0xFF)); + printf("DEVICE ID: (%x)\n", (readid[0] & 0xFFFF00) >> 8); + printf("UNIQUE ID:\n"); + printf("\tData to follow: (%x)\n", (readid[0] & 0xFFFFFF00) >> 3*8); + printf("\tExt Device ID: (%x)\n", (readid[1] & 0xFFFF)); + printf("\tCustom Factory data[0-1]: (%x)\n", readid[1] >> 2*8); + printf("\tCustom Factory data[5-2]: (%x)\n", readid[2]); + printf("\tCustom Factory data[9-6]: (%x)\n", readid[3]); + printf("\tCustom Factory data[13-10]: (%x)\n", readid[4]); + printf("Testing program flash\n"); + char prog_data[NSAMPLES] = {0}; + char *char_data = NULL; + unsigned int read_data[NSAMPLES] = {0}; + int sample = 0; + // int test_result = 0; + for (sample = 0; sample < NSAMPLES; sample++) { + prog_data[sample] = 0xFF; + // prog_data[sample] = sample; + } + + spi_read_all_regs(); + + spiflash_memProgram(prog_data, NSAMPLES, 0x0); + printf("\nAfter program\n"); + + spi_read_all_regs(); + + for (sample = 0; sample < NSAMPLES; sample = sample + 4) { + read_data[sample >> 2] = spiflash_readmem(0x0 + sample); + } + // check prog vs read data + char_data = (char *)read_data; + for (sample = 0; sample < NSAMPLES; sample++) { + if (prog_data[sample] != char_data[sample]) { + printf("Error: data[%x] = %02x != read_data[%x] = %02x\n", sample, + prog_data[sample], sample, char_data[sample]); + test_result = 1; + } + } + if (test_result) { + printf("Flash test failed!\n"); + } #ifdef SIMULATION #ifndef VERILATOR unsigned int word = 0xA3A2A1A0; diff --git a/software/sw_build.mk b/software/sw_build.mk index 71ded418..ed188480 100644 --- a/software/sw_build.mk +++ b/software/sw_build.mk @@ -107,6 +107,7 @@ IOB_SOC_OPENCRYPTOLINUX_BOOT_SRC+=src/iob_soc_opencryptolinux_boot.c IOB_SOC_OPENCRYPTOLINUX_BOOT_SRC+=$(filter-out %_emul.c, $(wildcard src/iob*uart*.c)) IOB_SOC_OPENCRYPTOLINUX_BOOT_SRC+=$(filter-out %_emul.c, $(wildcard src/iob*cache*.c)) IOB_SOC_OPENCRYPTOLINUX_BOOT_SRC+=$(filter-out %_emul.c, $(wildcard src/iob*eth*.c)) +IOB_SOC_OPENCRYPTOLINUX_BOOT_SRC+=$(filter-out %_emul.c, $(wildcard src/iob*spi*.c)) IOB_SOC_OPENCRYPTOLINUX_BOOT_SRC+=src/printf.c build_iob_soc_opencryptolinux_software: iob_soc_opencryptolinux_firmware iob_soc_opencryptolinux_boot diff --git a/submodules/SPI b/submodules/SPI index f9fcc139..7dbaf494 160000 --- a/submodules/SPI +++ b/submodules/SPI @@ -1 +1 @@ -Subproject commit f9fcc1390cc4e1bb774869c1a3ae54148154335f +Subproject commit 7dbaf49485ddd9f6a980f98bb941e0ac89da90f2 From a2dd40a430d6977e645c8fa697a85c5eebd0def6 Mon Sep 17 00:00:00 2001 From: PMiranda Date: Fri, 24 May 2024 16:03:47 +0100 Subject: [PATCH 2/8] feat(SPI): flash write/read working on AES-KU040 - update SPI submodule - fix wrapper constraints to place SPI output register in IO - fix wrapper top level with correct clock primitive for KU040 board - initial working firmware example with SPI Flash write and read operations --- .../iob_soc_opencryptolinux_fpga_wrapper.v | 3 +- ...b_soc_opencryptolinux_fpga_wrapper_dev.sdc | 7 ++++ .../src/iob_soc_opencryptolinux_firmware.c | 34 ++++++++++++++++--- submodules/SPI | 2 +- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper.v b/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper.v index 6d36ba57..c9142e74 100644 --- a/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper.v +++ b/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper.v @@ -78,8 +78,9 @@ module iob_soc_opencryptolinux_fpga_wrapper ( wire ETH_Clk; //eth clock - IBUFG rxclk_buf ( + BUFGCE_1 rxclk_buf ( .I(ENET_RX_CLK), + .CE(1'b1), .O(ETH_Clk) ); ODDRE1 ODDRE1_inst ( diff --git a/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper_dev.sdc b/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper_dev.sdc index 5a3e2451..a08e26d7 100644 --- a/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper_dev.sdc +++ b/hardware/fpga/vivado/AES-KU040-DB-G/iob_soc_opencryptolinux_fpga_wrapper_dev.sdc @@ -147,3 +147,10 @@ set_property IOSTANDARD LVCMOS18 [get_ports spi_WP_N_io] # DQ3 set_property PACKAGE_PIN H12 [get_ports spi_HOLD_N_io] set_property IOSTANDARD LVCMOS18 [get_ports spi_HOLD_N_io] + +set_property IOB TRUE [get_ports spi_SS_o] +set_property IOB TRUE [get_ports spi_SCLK_o] +set_property IOB TRUE [get_cells iob_soc_opencryptolinux0/SPI0/fl_spi0/dq_out_r_reg[0]] +set_property IOB TRUE [get_cells iob_soc_opencryptolinux0/SPI0/fl_spi0/dq_out_r_reg[1]] +set_property IOB TRUE [get_cells iob_soc_opencryptolinux0/SPI0/fl_spi0/dq_out_r_reg[2]] +set_property IOB TRUE [get_cells iob_soc_opencryptolinux0/SPI0/fl_spi0/dq_out_r_reg[3]] diff --git a/software/src/iob_soc_opencryptolinux_firmware.c b/software/src/iob_soc_opencryptolinux_firmware.c index 0932b8d1..43c81a60 100644 --- a/software/src/iob_soc_opencryptolinux_firmware.c +++ b/software/src/iob_soc_opencryptolinux_firmware.c @@ -25,7 +25,7 @@ #define MTIMER_SECONDS_TO_CLOCKS(SEC) ((uint64_t)(((SEC) * (FREQ)))) -#define NSAMPLES 16 +#define NSAMPLES 256 // Machine mode interrupt service routine static void irq_entry(void) __attribute__((interrupt("machine"))); @@ -197,22 +197,45 @@ int main() { char prog_data[NSAMPLES] = {0}; char *char_data = NULL; unsigned int read_data[NSAMPLES] = {0}; + unsigned int flash_addr = 0; int sample = 0; // int test_result = 0; for (sample = 0; sample < NSAMPLES; sample++) { - prog_data[sample] = 0xFF; + prog_data[sample] = sample; // prog_data[sample] = sample; } spi_read_all_regs(); - spiflash_memProgram(prog_data, NSAMPLES, 0x0); + printf("\nBefore erase\n"); + for (sample = 0; sample < NSAMPLES; sample = sample + 4) { + read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); + } + // check prog vs read data + char_data = (char *)read_data; + for (sample = 0; sample < NSAMPLES; sample++) { + printf("\tread_data[%x] = %02x\n", sample, char_data[sample]); + } + + spiflash_erase_address_range(flash_addr, NSAMPLES); + + printf("\nAfter erase\n"); + for (sample = 0; sample < NSAMPLES; sample = sample + 4) { + read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); + } + // check prog vs read data + char_data = (char *)read_data; + for (sample = 0; sample < NSAMPLES; sample++) { + printf("\tread_data[%x] = %02x\n", sample, char_data[sample]); + } + + spiflash_memProgram(prog_data, NSAMPLES, flash_addr); printf("\nAfter program\n"); spi_read_all_regs(); for (sample = 0; sample < NSAMPLES; sample = sample + 4) { - read_data[sample >> 2] = spiflash_readmem(0x0 + sample); + read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); } // check prog vs read data char_data = (char *)read_data; @@ -221,6 +244,9 @@ int main() { printf("Error: data[%x] = %02x != read_data[%x] = %02x\n", sample, prog_data[sample], sample, char_data[sample]); test_result = 1; + } else { + printf("Valid: data[%x] = %02x == read_data[%x] = %02x\n", sample, + prog_data[sample], sample, char_data[sample]); } } if (test_result) { diff --git a/submodules/SPI b/submodules/SPI index 7dbaf494..4a7d3677 160000 --- a/submodules/SPI +++ b/submodules/SPI @@ -1 +1 @@ -Subproject commit 7dbaf49485ddd9f6a980f98bb941e0ac89da90f2 +Subproject commit 4a7d3677541ab0c400200e40cc6611f33ddc39f0 From 5517a3aa0acbfe311c94eacad319fe5aefeed254 Mon Sep 17 00:00:00 2001 From: PMiranda Date: Fri, 24 May 2024 16:48:55 +0100 Subject: [PATCH 3/8] feat(sw): flash test at boot, clean firmware - add fpga_wrapper_tool.sdc constraints to remove synthesis warning - clean firmware program - add flash test to bootloader --- ..._soc_opencryptolinux_fpga_wrapper_tool.sdc | 9 ++ software/src/iob_soc_opencryptolinux_boot.c | 150 +++++++++--------- .../src/iob_soc_opencryptolinux_firmware.c | 130 ++------------- 3 files changed, 92 insertions(+), 197 deletions(-) create mode 100644 hardware/fpga/vivado/iob_soc_opencryptolinux_fpga_wrapper_tool.sdc diff --git a/hardware/fpga/vivado/iob_soc_opencryptolinux_fpga_wrapper_tool.sdc b/hardware/fpga/vivado/iob_soc_opencryptolinux_fpga_wrapper_tool.sdc new file mode 100644 index 00000000..9362913a --- /dev/null +++ b/hardware/fpga/vivado/iob_soc_opencryptolinux_fpga_wrapper_tool.sdc @@ -0,0 +1,9 @@ +################################################################################ +## Synchronizers +################################################################################ +set_property ASYNC_REG TRUE [get_cells -hier {*iob_r_data_o*[*]}] + +################################################################################ +## Clock groups +################################################################################# +set_clock_groups -asynchronous -group {c0_sys_clk_clk_p} -group {enet_clk} diff --git a/software/src/iob_soc_opencryptolinux_boot.c b/software/src/iob_soc_opencryptolinux_boot.c index 1c95c472..e27206ca 100644 --- a/software/src/iob_soc_opencryptolinux_boot.c +++ b/software/src/iob_soc_opencryptolinux_boot.c @@ -59,28 +59,6 @@ uint32_t uart_recvfile_ethernet(char *file_name) { return file_size; } -void spi_read_all_regs(){ - unsigned int status_reg = 0, lock_reg = 0, flag_reg = 0; - unsigned int non_vol_cfg = 0, vol_cfg = 0, enh_vol_cfg = 0; - unsigned int ext_addr = 0; - - spiflash_readStatusReg(&status_reg); - spiflash_readLockReg(&lock_reg); - spiflash_readFlagReg(&flag_reg); - spiflash_readNonVolConfigReg(&non_vol_cfg); - spiflash_readVolConfigReg(&vol_cfg); - spiflash_readEnhancedVolConfigReg(&enh_vol_cfg); - spiflash_readExtendedAddrReg(&ext_addr); - - printf("\nStatus Reg: (%x)\n", status_reg); - printf("Lock Reg: (%x)\n", lock_reg); - printf("Flag Reg: (%x)\n", flag_reg); - printf("NonVol Cfg Reg: (%x)\n", non_vol_cfg); - printf("Vol Cfg Reg: (%x)\n", vol_cfg); - printf("Enhanced Vol Cfg Reg: (%x)\n", enh_vol_cfg); - printf("Extended Addr Reg: (%x)\n", ext_addr); -} - int main() { int run_linux = 0; int file_size; @@ -110,63 +88,77 @@ int main() { uart16550_puts(": Waiting for Console ACK.\n"); } -// #ifndef VERILATOR -// // Init printf -// printf_init(&uart16550_putc); -// // init spit flash controller -// spiflash_init(SPI0_BASE); -// printf("\nResetting flash registers...\n"); -// spiflash_resetmem(); -// // Read ID -// // Manufacturer ID -// unsigned int readid[5] = {0}, id_bytes = 0; -// for (id_bytes = 0; id_bytes < 20; id_bytes += 4) { -// spiflash_executecommand(COMMANS, 0, id_bytes, ((4 * 8) << 8) | READ_ID, -// &(readid[id_bytes / 4])); -// } -// printf("\nMANUFACTURER ID: (%x)\n", (readid[0] & 0xFF)); -// printf("DEVICE ID: (%x)\n", (readid[0] & 0xFFFF00) >> 8); -// printf("UNIQUE ID:\n"); -// printf("\tData to follow: (%x)\n", (readid[0] & 0xFFFFFF00) >> 3*8); -// printf("\tExt Device ID: (%x)\n", (readid[1] & 0xFFFF)); -// printf("\tCustom Factory data[0-1]: (%x)\n", readid[1] >> 2*8); -// printf("\tCustom Factory data[5-2]: (%x)\n", readid[2]); -// printf("\tCustom Factory data[9-6]: (%x)\n", readid[3]); -// printf("\tCustom Factory data[13-10]: (%x)\n", readid[4]); -// -// printf("Testing program flash\n"); -// char prog_data[NSAMPLES] = {0}; -// char *char_data = NULL; -// unsigned int read_data[NSAMPLES] = {0}; -// int sample = 0; -// int test_result = 0; -// for (sample = 0; sample < NSAMPLES; sample++) { -// prog_data[sample] = 0xFF - sample; -// } -// -// spi_read_all_regs(); -// -// spiflash_memProgram(prog_data, NSAMPLES, 0x0); -// printf("After program\n"); -// -// spi_read_all_regs(); -// -// for (sample = 0; sample < NSAMPLES; sample = sample + 4) { -// read_data[sample >> 2] = spiflash_readmem(0x0 + sample); -// } -// // check prog vs read data -// char_data = (char *)read_data; -// for (sample = 0; sample < NSAMPLES; sample++) { -// if (prog_data[sample] != char_data[sample]) { -// printf("Error: data[%x] = %02x != read_data[%x] = %02x\n", sample, -// prog_data[sample], sample, char_data[sample]); -// test_result = 1; -// } -// } -// if (test_result) { -// printf("Flash test failed!\n"); -// } -// #endif // ifndef VERILATOR +#ifndef VERILATOR + // Init printf + printf_init(&uart16550_putc); + // init spit flash controller + spiflash_init(SPI0_BASE); + printf("\nResetting flash registers...\n"); + spiflash_resetmem(); + + printf("Testing program flash\n"); + char prog_data[NSAMPLES] = {0}; + char *char_data = NULL; + unsigned int read_data[NSAMPLES] = {0}; + unsigned int flash_addr = 0x0; + int sample = 0; + int flash_failed = 0; + + // set samples to write + for (sample = 0; sample < NSAMPLES; sample++) { + prog_data[sample] = sample; + } + + // Flash data before erase + printf("\nFlash data before erase:\n"); + for (sample = 0; sample < NSAMPLES; sample = sample + 4) { + read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); + } + char_data = (char *)read_data; + for (sample = 0; sample < NSAMPLES; sample++) { + printf("\tflash[%x] = %02x\n", flash_addr + sample, char_data[sample]); + } + + spiflash_erase_address_range(flash_addr, NSAMPLES); + + // Flash data after erase + printf("\nFlash data after erase:\n"); + for (sample = 0; sample < NSAMPLES; sample = sample + 4) { + read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); + } + char_data = (char *)read_data; + for (sample = 0; sample < NSAMPLES; sample++) { + printf("\tflash[%x] = %02x\n", flash_addr + sample, char_data[sample]); + if (char_data[sample] != 0xFF){ + printf("Error: flash[%x] = %02x != 0xFF\n", flash_addr + sample, char_data[sample]); + flash_failed = 1; + } + } + + spiflash_memProgram(prog_data, NSAMPLES, 0x0); + + printf("\nFlash data after program:\n"); + for (sample = 0; sample < NSAMPLES; sample = sample + 4) { + read_data[sample >> 2] = spiflash_readmem(0x0 + sample); + } + char_data = (char *)read_data; + for (sample = 0; sample < NSAMPLES; sample++) { + if (prog_data[sample] != char_data[sample]) { + printf("Error: expected[%x] = %02x != flash[%x] = %02x\n", flash_addr + sample, + prog_data[sample], flash_addr + sample, char_data[sample]); + flash_failed = 1; + } else { + printf("Valid: expected[%x] = %02x == flash[%x] = %02x\n", flash_addr + sample, + prog_data[sample], flash_addr + sample, char_data[sample]); + } + } + + if (flash_failed) { + printf("ERROR: Flash test failed!\n"); + } else { + printf("SUCCESS: Flash test passed!\n"); + } +#endif // ifndef VERILATOR #ifndef IOB_SOC_OPENCRYPTOLINUX_INIT_MEM // Init ethernet and printf (for ethernet) diff --git a/software/src/iob_soc_opencryptolinux_firmware.c b/software/src/iob_soc_opencryptolinux_firmware.c index 43c81a60..e3a6e7a2 100644 --- a/software/src/iob_soc_opencryptolinux_firmware.c +++ b/software/src/iob_soc_opencryptolinux_firmware.c @@ -25,7 +25,7 @@ #define MTIMER_SECONDS_TO_CLOCKS(SEC) ((uint64_t)(((SEC) * (FREQ)))) -#define NSAMPLES 256 +#define NSAMPLES 16 // Machine mode interrupt service routine static void irq_entry(void) __attribute__((interrupt("machine"))); @@ -101,28 +101,6 @@ int GetTime(){ return clint_getTime(CLINT0_BASE); } -void spi_read_all_regs(){ - unsigned int status_reg = 0, lock_reg = 0, flag_reg = 0; - unsigned int non_vol_cfg = 0, vol_cfg = 0, enh_vol_cfg = 0; - unsigned int ext_addr = 0; - - spiflash_readStatusReg(&status_reg); - spiflash_readLockReg(&lock_reg); - spiflash_readFlagReg(&flag_reg); - spiflash_readNonVolConfigReg(&non_vol_cfg); - spiflash_readVolConfigReg(&vol_cfg); - spiflash_readEnhancedVolConfigReg(&enh_vol_cfg); - spiflash_readExtendedAddrReg(&ext_addr); - - printf("\nStatus Reg: (%x)\n", status_reg); - printf("Lock Reg: (%x)\n", lock_reg); - printf("Flag Reg: (%x)\n", flag_reg); - printf("NonVol Cfg Reg: (%x)\n", non_vol_cfg); - printf("Vol Cfg Reg: (%x)\n", vol_cfg); - printf("Enhanced Vol Cfg Reg: (%x)\n", enh_vol_cfg); - printf("Extended Addr Reg: (%x)\n", ext_addr); -} - int main() { char pass_string[] = "Test passed!"; uint_xlen_t irq_entry_copy; @@ -147,9 +125,9 @@ int main() { uart16550_putc(buffer[i]); #endif -//#ifndef SIMULATION - // InitializeCryptoSide(VERSAT0_BASE); -//#endif +#ifndef SIMULATION + InitializeCryptoSide(VERSAT0_BASE); +#endif printf("\n\n\nHello world!\n\n\n"); @@ -159,99 +137,15 @@ int main() { // Tests are too big and slow to perform during simulation. // Comment out the source files in sw_build.mk to also reduce binary size and speedup simulation. -// #ifndef SIMULATION -// test_result |= VersatSHATests(); -// test_result |= VersatAESTests(); -// test_result |= VersatMcElieceTests(); -// #else -// test_result |= VersatSimpleSHATests(); -// test_result |= VersatSimpleAESTests(); -// #endif - - // - // Test FPGA SPI Flash controller - // - - // init spit flash controller - spiflash_init(SPI0_BASE); - printf("\nResetting flash registers...\n"); - spiflash_resetmem(); - // Read Identifications - // Manufacturer ID | Device ID | Unique ID - unsigned int readid[5] = {0}, id_bytes = 0; - for (id_bytes = 0; id_bytes < 20; id_bytes += 4) { - spiflash_executecommand(COMMANS, 0, id_bytes, ((4 * 8) << 8) | READ_ID, - &(readid[id_bytes / 4])); - } - printf("\nMANUFACTURER ID: (%x)\n", (readid[0] & 0xFF)); - printf("DEVICE ID: (%x)\n", (readid[0] & 0xFFFF00) >> 8); - printf("UNIQUE ID:\n"); - printf("\tData to follow: (%x)\n", (readid[0] & 0xFFFFFF00) >> 3*8); - printf("\tExt Device ID: (%x)\n", (readid[1] & 0xFFFF)); - printf("\tCustom Factory data[0-1]: (%x)\n", readid[1] >> 2*8); - printf("\tCustom Factory data[5-2]: (%x)\n", readid[2]); - printf("\tCustom Factory data[9-6]: (%x)\n", readid[3]); - printf("\tCustom Factory data[13-10]: (%x)\n", readid[4]); - - printf("Testing program flash\n"); - char prog_data[NSAMPLES] = {0}; - char *char_data = NULL; - unsigned int read_data[NSAMPLES] = {0}; - unsigned int flash_addr = 0; - int sample = 0; - // int test_result = 0; - for (sample = 0; sample < NSAMPLES; sample++) { - prog_data[sample] = sample; - // prog_data[sample] = sample; - } - - spi_read_all_regs(); - - printf("\nBefore erase\n"); - for (sample = 0; sample < NSAMPLES; sample = sample + 4) { - read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); - } - // check prog vs read data - char_data = (char *)read_data; - for (sample = 0; sample < NSAMPLES; sample++) { - printf("\tread_data[%x] = %02x\n", sample, char_data[sample]); - } - - spiflash_erase_address_range(flash_addr, NSAMPLES); - - printf("\nAfter erase\n"); - for (sample = 0; sample < NSAMPLES; sample = sample + 4) { - read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); - } - // check prog vs read data - char_data = (char *)read_data; - for (sample = 0; sample < NSAMPLES; sample++) { - printf("\tread_data[%x] = %02x\n", sample, char_data[sample]); - } - - spiflash_memProgram(prog_data, NSAMPLES, flash_addr); - printf("\nAfter program\n"); - - spi_read_all_regs(); +#ifndef SIMULATION + test_result |= VersatSHATests(); + test_result |= VersatAESTests(); + test_result |= VersatMcElieceTests(); +#else + test_result |= VersatSimpleSHATests(); + test_result |= VersatSimpleAESTests(); +#endif - for (sample = 0; sample < NSAMPLES; sample = sample + 4) { - read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); - } - // check prog vs read data - char_data = (char *)read_data; - for (sample = 0; sample < NSAMPLES; sample++) { - if (prog_data[sample] != char_data[sample]) { - printf("Error: data[%x] = %02x != read_data[%x] = %02x\n", sample, - prog_data[sample], sample, char_data[sample]); - test_result = 1; - } else { - printf("Valid: data[%x] = %02x == read_data[%x] = %02x\n", sample, - prog_data[sample], sample, char_data[sample]); - } - } - if (test_result) { - printf("Flash test failed!\n"); - } #ifdef SIMULATION #ifndef VERILATOR unsigned int word = 0xA3A2A1A0; From 224df86178ea7f028f83d4cded6fb0c8cd75b18d Mon Sep 17 00:00:00 2001 From: PMiranda Date: Fri, 24 May 2024 17:01:33 +0100 Subject: [PATCH 4/8] fix(CI): update checkout to v4 - checkout v4 uses node.js version 20 --- .github/workflows/ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b56bb73c..d9f19d8d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: if: ${{ !cancelled() }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: 'recursive' - name: run spi test @@ -43,7 +43,7 @@ jobs: if: ${{ !cancelled() }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: 'recursive' - name: run uart16550 test @@ -56,7 +56,7 @@ jobs: if: ${{ !cancelled() }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: 'recursive' - name: clean @@ -73,7 +73,7 @@ jobs: if: ${{ !cancelled() }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: 'recursive' - name: clean @@ -93,7 +93,7 @@ jobs: needs: [ verilator-baremetal ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: 'recursive' - name: test baremetal @@ -110,7 +110,7 @@ jobs: needs: [ verilator-baremetal ] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: 'recursive' - name: test baremetal @@ -125,7 +125,7 @@ jobs: ## needs: [ cyclonev, aes-ku040 ] ## ## steps: -## - uses: actions/checkout@v3 +## - uses: actions/checkout@v4 ## with: ## submodules: 'recursive' ## - name: clean From 7bbac47f81042c278d0655dd6094de42a9874219 Mon Sep 17 00:00:00 2001 From: PMiranda Date: Mon, 27 May 2024 10:55:38 +0100 Subject: [PATCH 5/8] fix(sim): fix verilator and icarus simulations - initialize crypto side on simulations - only run bootloader SPI test if INIT_MEM=0 --- software/src/iob_soc_opencryptolinux_boot.c | 10 +++++----- software/src/iob_soc_opencryptolinux_firmware.c | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/software/src/iob_soc_opencryptolinux_boot.c b/software/src/iob_soc_opencryptolinux_boot.c index e27206ca..09971dae 100644 --- a/software/src/iob_soc_opencryptolinux_boot.c +++ b/software/src/iob_soc_opencryptolinux_boot.c @@ -88,9 +88,12 @@ int main() { uart16550_puts(": Waiting for Console ACK.\n"); } -#ifndef VERILATOR - // Init printf + +#ifndef IOB_SOC_OPENCRYPTOLINUX_INIT_MEM + // Init ethernet and printf (for ethernet) printf_init(&uart16550_putc); + +#ifndef VERILATOR // init spit flash controller spiflash_init(SPI0_BASE); printf("\nResetting flash registers...\n"); @@ -160,9 +163,6 @@ int main() { } #endif // ifndef VERILATOR -#ifndef IOB_SOC_OPENCRYPTOLINUX_INIT_MEM - // Init ethernet and printf (for ethernet) - printf_init(&uart16550_putc); eth_init(ETH0_BASE, &clear_cache); // Use custom memory alloc/free functions to ensure it allocates in external // memory diff --git a/software/src/iob_soc_opencryptolinux_firmware.c b/software/src/iob_soc_opencryptolinux_firmware.c index e3a6e7a2..aeb545b5 100644 --- a/software/src/iob_soc_opencryptolinux_firmware.c +++ b/software/src/iob_soc_opencryptolinux_firmware.c @@ -125,9 +125,7 @@ int main() { uart16550_putc(buffer[i]); #endif -#ifndef SIMULATION InitializeCryptoSide(VERSAT0_BASE); -#endif printf("\n\n\nHello world!\n\n\n"); From 2993fc76d6e4b5635493e25fe84ae9be0aeb0c9b Mon Sep 17 00:00:00 2001 From: PMiranda Date: Mon, 27 May 2024 13:12:07 +0100 Subject: [PATCH 6/8] fix(cyclonev): Exclude SPI for Verilator and Intel - update bootloader to support SPI tests for all simulators except Verilator and for AMD boards --- software/src/iob_soc_opencryptolinux_boot.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/software/src/iob_soc_opencryptolinux_boot.c b/software/src/iob_soc_opencryptolinux_boot.c index 09971dae..60b84030 100644 --- a/software/src/iob_soc_opencryptolinux_boot.c +++ b/software/src/iob_soc_opencryptolinux_boot.c @@ -18,6 +18,22 @@ #define NSAMPLES 16 +// Set SPI Support: +// Simulation: Enabled, except for Verilator +// FPGA: Disabled, except for AMD +#ifdef SIMULATION +# ifdef VERILATOR + // no SPI support +# else +# define SPI_SUPPORT +# endif // ifndef VERILATOR +#else // ifdef SIMULATION: FPGA case +# ifdef AMD +# define SPI_SUPPORT +# endif // ifdef AMD + // no SPI support +#endif // ifdef SIMULATION + // Ethernet utility functions // NOTE: These functions are not compatible with malloc() and free(). // These are specifically made for use with the current iob-eth.c drivers. @@ -93,7 +109,7 @@ int main() { // Init ethernet and printf (for ethernet) printf_init(&uart16550_putc); -#ifndef VERILATOR +#ifdef SPI_SUPPORT // init spit flash controller spiflash_init(SPI0_BASE); printf("\nResetting flash registers...\n"); @@ -161,7 +177,7 @@ int main() { } else { printf("SUCCESS: Flash test passed!\n"); } -#endif // ifndef VERILATOR +#endif // ifdef SPI_SUPPORT eth_init(ETH0_BASE, &clear_cache); // Use custom memory alloc/free functions to ensure it allocates in external From 0433baf1b9d99858d5408acd4e122449b95a5b16 Mon Sep 17 00:00:00 2001 From: PMiranda Date: Thu, 30 May 2024 00:59:32 +0100 Subject: [PATCH 7/8] feat(Flash): boot from flash - update SPI submodule - add `BOOT_FLOW` makefile variable: - CONSOLE_TO_FLASH: program flash with files from `mem.config` - FLASH_TO_EXTMEM: load programs from flash - CONSOLE_TO_EXTMEM: (default) load programs from console --- .github/workflows/ci.yml | 2 +- Makefile | 7 +- iob_soc_opencryptolinux.py | 2 + software/src/iob_soc_opencryptolinux_boot.c | 300 +++++++++++--------- software/sw_build.mk | 13 +- submodules/SPI | 2 +- 6 files changed, 183 insertions(+), 143 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d9f19d8d..171290d2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -116,7 +116,7 @@ jobs: - name: test baremetal run: make fpga-run RUN_LINUX=0 BOARD=AES-KU040-DB-G - name: test linux - run: make test-linux-fpga-connect BOARD=AES-KU040-DB-G + run: make test-linux-fpga-connect BOARD=AES-KU040-DB-G BOOT_FLOW=FLASH_TO_EXTMEM ## doc: ## runs-on: self-hosted diff --git a/Makefile b/Makefile index dcfdb4e5..1befe9d7 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ include $(LIB_DIR)/setup.mk INIT_MEM ?= 0 RUN_LINUX ?= 1 USE_EXTMEM := 1 +BOOT_FLOW ?= CONSOLE_TO_EXTMEM ifeq ($(INIT_MEM),1) SETUP_ARGS += INIT_MEM @@ -39,12 +40,12 @@ sim-test-spi: fpga-run: nix-shell --run 'make clean setup INIT_MEM=$(INIT_MEM) USE_EXTMEM=$(USE_EXTMEM)' nix-shell --run 'make -C ../$(CORE)_V*/ fpga-fw-build BOARD=$(BOARD) RUN_LINUX=$(RUN_LINUX)' - make -C ../$(CORE)_V*/ fpga-run BOARD=$(BOARD) RUN_LINUX=$(RUN_LINUX) + make -C ../$(CORE)_V*/ fpga-run BOARD=$(BOARD) RUN_LINUX=$(RUN_LINUX) BOOT_FLOW=$(BOOT_FLOW) fpga-connect: nix-shell --run 'make -C ../$(CORE)_V*/ fpga-fw-build BOARD=$(BOARD) RUN_LINUX=$(RUN_LINUX)' # Should run under 'bash', running with 'fish' as a shell gives an error - make -C ../$(CORE)_V*/ fpga-run BOARD=$(BOARD) RUN_LINUX=$(RUN_LINUX) + make -C ../$(CORE)_V*/ fpga-run BOARD=$(BOARD) RUN_LINUX=$(RUN_LINUX) BOOT_FLOW=$(BOOT_FLOW) fpga-test: make clean setup fpga-run INIT_MEM=0 @@ -58,6 +59,6 @@ test-all: test-linux-fpga-connect: build_dir_name -rm $(BUILD_DIR)/hardware/fpga/test.log -ln -s minicom_test1.txt $(BUILD_DIR)/hardware/fpga/minicom_linux_script.txt - make fpga-connect RUN_LINUX=1 + make fpga-connect RUN_LINUX=1 BOOT_FLOW=$(BOOT_FLOW) .PHONY: sim-test fpga-test test-all test-linux-fpga-connect diff --git a/iob_soc_opencryptolinux.py b/iob_soc_opencryptolinux.py index 05fba2c2..f2251fc9 100755 --- a/iob_soc_opencryptolinux.py +++ b/iob_soc_opencryptolinux.py @@ -201,10 +201,12 @@ def _post_setup(cls): # Set custom ethernet CONSOLE_CMD contents.append( f""" +RUN_DEPS+=boot_flow GRAB_TIMEOUT = 600 ### Launch minicom if running Linux # pass CI variable over ssh commands UFLAGS+=CI=$(CI) +UFLAGS+=BOOT_FLOW=$(BOOT_FLOW) ifeq ($(shell grep -o rootfs.cpio.gz ../{cls.name}_mem.config),rootfs.cpio.gz) ifneq ($(wildcard minicom_linux_script.txt),) SCRIPT_STR:=-S minicom_linux_script.txt diff --git a/software/src/iob_soc_opencryptolinux_boot.c b/software/src/iob_soc_opencryptolinux_boot.c index 60b84030..98d9a6fc 100644 --- a/software/src/iob_soc_opencryptolinux_boot.c +++ b/software/src/iob_soc_opencryptolinux_boot.c @@ -9,6 +9,7 @@ #include "iob_soc_opencryptolinux_periphs.h" #include "iob_soc_opencryptolinux_system.h" #include "printf.h" +#include #include #define PROGNAME "IOb-Bootloader" @@ -16,23 +17,8 @@ #define DC1 17 // Device Control 1 (used to indicate end of bootloader) #define EXT_MEM 0x80000000 -#define NSAMPLES 16 - -// Set SPI Support: -// Simulation: Enabled, except for Verilator -// FPGA: Disabled, except for AMD -#ifdef SIMULATION -# ifdef VERILATOR - // no SPI support -# else -# define SPI_SUPPORT -# endif // ifndef VERILATOR -#else // ifdef SIMULATION: FPGA case -# ifdef AMD -# define SPI_SUPPORT -# endif // ifdef AMD - // no SPI support -#endif // ifdef SIMULATION +#define FLASH_FILE_SIZE_OFFSET 0x0 // sector 0, subsector 0 +#define FLASH_FIRMWARE_OFFSET 0x1000 // sector 0, subsector 1 // Ethernet utility functions // NOTE: These functions are not compatible with malloc() and free(). @@ -75,6 +61,132 @@ uint32_t uart_recvfile_ethernet(char *file_name) { return file_size; } +int compute_mem_load_txt(char file_name_array[4][50], + long int file_address_array[4], char *file_start_addr, + uint32_t file_size) { + int state = 0; + int file_name_count = 0; + int file_count = 0; + char hexChar = 0; + int hexDecimal = 0; + int i = 0; + for (i = 0; i < file_size; i++) { + hexChar = *(file_start_addr + i); + // uart16550_puts(&hexChar); /* Used for debugging. */ + if (state == 0) { + if (hexChar == ' ') { + file_name_array[file_count][file_name_count] = '\0'; + file_name_count = 0; + file_address_array[file_count] = 0; + file_count = file_count + 1; + state = 1; + } else { + file_name_array[file_count][file_name_count] = hexChar; + file_name_count = file_name_count + 1; + } + } else if (state == 1) { + if (hexChar == '\n') { + state = 0; + } else { + if ('0' <= hexChar && hexChar <= '9') { + hexDecimal = hexChar - '0'; + } else if ('a' <= hexChar && hexChar <= 'f') { + hexDecimal = 10 + hexChar - 'a'; + } else if ('A' <= hexChar && hexChar <= 'F') { + hexDecimal = 10 + hexChar - 'A'; + } else { + uart16550_puts(PROGNAME); + uart16550_puts(": invalid hexadecimal character.\n"); + } + file_address_array[file_count - 1] = + file_address_array[file_count - 1] * 16 + hexDecimal; + } + } + } + + return file_count; +} + +void console_get_files(int file_count, long int file_address_array[4], + char *file_start_addr, char file_name_array[4][50], + int file_sizes[4]) { + int i = 0; + char *file_addr = NULL; + for (i = 0; i < file_count; i++) { + file_addr = (char *)(file_start_addr + file_address_array[i]); + // Receive data from console via Ethernet +#ifndef SIMULATION + file_sizes[i] = uart_recvfile_ethernet(file_name_array[i]); + eth_rcv_file(file_addr, file_sizes[i]); +#else + file_sizes[i] = uart16550_recvfile(file_name_array[i], file_addr); +#endif + } +} + +void program_flash(int file_count, long int file_address_array[4], + char *file_start_addr, int file_sizes[4]) { + int i = 0; + unsigned int flash_addr = 0x0; + char *prog_data = NULL; + int next_subsector = 0; + + // erase SPI Flash + flash_addr = FLASH_FILE_SIZE_OFFSET; + spiflash_erase_address_range(flash_addr, 4 * file_count); + + // store file sizes + prog_data = (char *)file_sizes; + spiflash_memProgram(prog_data, 4 * file_count, flash_addr); + + for (i = 0; i < file_count; i++) { + flash_addr = FLASH_FIRMWARE_OFFSET + (next_subsector*SUBSECTOR_SIZE); + prog_data = file_start_addr + file_address_array[i]; + spiflash_erase_address_range(flash_addr, file_sizes[i]); + printf("Program %d: addr: %p\tflash: %x\tsize: %d\n", i, prog_data, + flash_addr, file_sizes[i]); + spiflash_memProgram(prog_data, file_sizes[i], flash_addr); + printf("Program %d: complete\n", i); + next_subsector += (((file_sizes[i]+SUBSECTOR_SIZE-1)/SUBSECTOR_SIZE)); + } +} + +void read_flash(int file_count, long int file_address_array[4], + char *file_start_addr) { + int i = 0; + int sample = 0; + unsigned int *read_array = NULL; + unsigned int spi_data = 0; + unsigned int flash_file_start = 0; + int read_cnt = 0, read_total = 0; + int file_sizes[4] = {0}; + int next_subsector = 0; + + // get file sizes + for (sample = 0; sample < 4 * file_count; sample = sample + 4) { + file_sizes[sample >> 2] = spiflash_readmem(FLASH_FILE_SIZE_OFFSET + sample); + } + + for (i = 0; i < file_count; i++) { + read_array = (unsigned int *)(file_start_addr + file_address_array[i]); + flash_file_start = FLASH_FIRMWARE_OFFSET + (next_subsector*SUBSECTOR_SIZE); + read_total = file_sizes[i] / 4; + read_cnt = 0; + + printf("Read %d: flash: %x\tmem: %p\tsize: %d\n", i, flash_file_start, + read_array, file_sizes[i]); + for (sample = 0; sample < file_sizes[i]; sample = sample + 4) { + read_array[sample >> 2] = spiflash_readmem(flash_file_start + sample); + // progress every 10% + if (read_cnt % (read_total / 10) == 0) { + printf("\tRead %d: %d%%\n", i, read_cnt * 100 / read_total); + } + read_cnt++; + } + next_subsector += (((file_sizes[i]+SUBSECTOR_SIZE-1)/SUBSECTOR_SIZE)); + } +} + int main() { int run_linux = 0; int file_size; @@ -104,81 +216,10 @@ int main() { uart16550_puts(": Waiting for Console ACK.\n"); } - #ifndef IOB_SOC_OPENCRYPTOLINUX_INIT_MEM // Init ethernet and printf (for ethernet) printf_init(&uart16550_putc); -#ifdef SPI_SUPPORT - // init spit flash controller - spiflash_init(SPI0_BASE); - printf("\nResetting flash registers...\n"); - spiflash_resetmem(); - - printf("Testing program flash\n"); - char prog_data[NSAMPLES] = {0}; - char *char_data = NULL; - unsigned int read_data[NSAMPLES] = {0}; - unsigned int flash_addr = 0x0; - int sample = 0; - int flash_failed = 0; - - // set samples to write - for (sample = 0; sample < NSAMPLES; sample++) { - prog_data[sample] = sample; - } - - // Flash data before erase - printf("\nFlash data before erase:\n"); - for (sample = 0; sample < NSAMPLES; sample = sample + 4) { - read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); - } - char_data = (char *)read_data; - for (sample = 0; sample < NSAMPLES; sample++) { - printf("\tflash[%x] = %02x\n", flash_addr + sample, char_data[sample]); - } - - spiflash_erase_address_range(flash_addr, NSAMPLES); - - // Flash data after erase - printf("\nFlash data after erase:\n"); - for (sample = 0; sample < NSAMPLES; sample = sample + 4) { - read_data[sample >> 2] = spiflash_readmem(flash_addr + sample); - } - char_data = (char *)read_data; - for (sample = 0; sample < NSAMPLES; sample++) { - printf("\tflash[%x] = %02x\n", flash_addr + sample, char_data[sample]); - if (char_data[sample] != 0xFF){ - printf("Error: flash[%x] = %02x != 0xFF\n", flash_addr + sample, char_data[sample]); - flash_failed = 1; - } - } - - spiflash_memProgram(prog_data, NSAMPLES, 0x0); - - printf("\nFlash data after program:\n"); - for (sample = 0; sample < NSAMPLES; sample = sample + 4) { - read_data[sample >> 2] = spiflash_readmem(0x0 + sample); - } - char_data = (char *)read_data; - for (sample = 0; sample < NSAMPLES; sample++) { - if (prog_data[sample] != char_data[sample]) { - printf("Error: expected[%x] = %02x != flash[%x] = %02x\n", flash_addr + sample, - prog_data[sample], flash_addr + sample, char_data[sample]); - flash_failed = 1; - } else { - printf("Valid: expected[%x] = %02x == flash[%x] = %02x\n", flash_addr + sample, - prog_data[sample], flash_addr + sample, char_data[sample]); - } - } - - if (flash_failed) { - printf("ERROR: Flash test failed!\n"); - } else { - printf("SUCCESS: Flash test passed!\n"); - } -#endif // ifdef SPI_SUPPORT - eth_init(ETH0_BASE, &clear_cache); // Use custom memory alloc/free functions to ensure it allocates in external // memory @@ -186,64 +227,49 @@ int main() { // Wait for PHY reset to finish eth_wait_phy_rst(); + char boot_flow[20] = {0}; + + file_size = uart16550_recvfile("boot.flow", boot_flow); + if (file_size > 20) { + printf("Error: boot.flow file size is too large\n"); + return -1; + } + file_size = uart16550_recvfile("../iob_soc_opencryptolinux_mem.config", prog_start_addr); + // compute_mem_load_txt - int state = 0; - int file_name_count = 0; - int file_count = 0; char file_name_array[4][50]; long int file_address_array[4]; - char hexChar = 0; - int hexDecimal = 0; - int i = 0; - for (i = 0; i < file_size; i++) { - hexChar = *(prog_start_addr + i); - // uart16550_puts(&hexChar); /* Used for debugging. */ - if (state == 0) { - if (hexChar == ' ') { - file_name_array[file_count][file_name_count] = '\0'; - file_name_count = 0; - file_address_array[file_count] = 0; - file_count = file_count + 1; - state = 1; - } else { - file_name_array[file_count][file_name_count] = hexChar; - file_name_count = file_name_count + 1; - } - } else if (state == 1) { - if (hexChar == '\n') { - state = 0; - } else { - if ('0' <= hexChar && hexChar <= '9') { - hexDecimal = hexChar - '0'; - } else if ('a' <= hexChar && hexChar <= 'f') { - hexDecimal = 10 + hexChar - 'a'; - } else if ('A' <= hexChar && hexChar <= 'F') { - hexDecimal = 10 + hexChar - 'A'; - } else { - uart16550_puts(PROGNAME); - uart16550_puts(": invalid hexadecimal character.\n"); - } - file_address_array[file_count - 1] = - file_address_array[file_count - 1] * 16 + hexDecimal; - } - } - } + int file_sizes[4] = {0}; + int file_count = compute_mem_load_txt(file_name_array, file_address_array, + prog_start_addr, file_size); - for (i = 0; i < file_count; i++) { - prog_start_addr = (char *)(EXT_MEM + file_address_array[i]); - // Receive data from console via Ethernet -#ifndef SIMULATION - file_size = uart_recvfile_ethernet(file_name_array[i]); - eth_rcv_file(prog_start_addr, file_size); -#else - file_size = uart16550_recvfile(file_name_array[i], prog_start_addr); -#endif + if (!strcmp(boot_flow, "CONSOLE_TO_FLASH")) { + uart16550_puts(PROGNAME); + uart16550_puts(": CONSOLE_TO_FLASH\n"); + // init spi flash controller + spiflash_init(SPI0_BASE); + // Read files from console + console_get_files(file_count, file_address_array, prog_start_addr, + file_name_array, file_sizes); + program_flash(file_count, file_address_array, prog_start_addr, file_sizes); + } else if (!strcmp(boot_flow, "FLASH_TO_EXTMEM")) { + uart16550_puts(PROGNAME); + uart16550_puts(": FLASH_TO_EXTMEM\n"); + // init spi flash controller + spiflash_init(SPI0_BASE); + read_flash(file_count, file_address_array, prog_start_addr); + } else { + uart16550_puts(PROGNAME); + uart16550_puts(": CONSOLE_TO_EXTMEM\n"); + // Read files from console to external memory + console_get_files(file_count, file_address_array, prog_start_addr, + file_name_array, file_sizes); } // Check if running Linux - for (i = 0; i < file_count; i++) { + for (int i = 0; i < file_count; i++) { if (!strcmp(file_name_array[i], "rootfs.cpio.gz")) { #ifdef SIMULATION // Running Linux: setup required dependencies diff --git a/software/sw_build.mk b/software/sw_build.mk index ed188480..3a423cbe 100644 --- a/software/sw_build.mk +++ b/software/sw_build.mk @@ -5,6 +5,17 @@ ROOT_DIR ?=.. # Local embedded makefile settings for custom bootloader and firmware targets. +# Bootloader flow options: +# 1. CONSOLE_TO_EXTMEM: default: load firmware from console to external memory +# 2. CONSOLE_TO_FLASH: program flash with firmware +# 3. FLASH_TO_EXTMEM: load firmware from flash to external memory +BOOT_FLOW ?= CONSOLE_TO_EXTMEM +UTARGETS += boot_flow + +boot_flow: + echo -n "$(BOOT_FLOW)" > boot.flow + # -n to avoid newline + #Function to obtain parameter named $(1) in verilog header file located in $(2) #Usage: $(call GET_MACRO,,) GET_MACRO = $(shell grep "define $(1)" $(2) | rev | cut -d" " -f1 | rev) @@ -56,7 +67,7 @@ fw_jump.bin iob_soc.dtb: cp $(FPGA_TOOL)/$(BOARD)/$@ .;\ fi # Set targets as PHONY to ensure that they are copied even if $(BOARD) is changed -.PHONY: fw_jump.bin iob_soc.dtb +.PHONY: fw_jump.bin iob_soc.dtb boot_flow ../../software/%.bin: make -C ../../ fw-build diff --git a/submodules/SPI b/submodules/SPI index 4a7d3677..ad98d928 160000 --- a/submodules/SPI +++ b/submodules/SPI @@ -1 +1 @@ -Subproject commit 4a7d3677541ab0c400200e40cc6611f33ddc39f0 +Subproject commit ad98d928485cff1421ce069a916a34a87e5f7d97 From ef9feb0f7c22dbae0db253d8458c74a18c939cfd Mon Sep 17 00:00:00 2001 From: PMiranda Date: Thu, 30 May 2024 23:20:48 +0100 Subject: [PATCH 8/8] fix(sim): create `boot.flow` file in sim - update simulations build makefile to create `boot.flow` file required by new bootloader --- hardware/simulation/sim_build.mk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hardware/simulation/sim_build.mk b/hardware/simulation/sim_build.mk index 3244fd40..60803ab2 100644 --- a/hardware/simulation/sim_build.mk +++ b/hardware/simulation/sim_build.mk @@ -1,5 +1,6 @@ # Add iob_soc_opencryptolinux software as a build dependency HEX+=iob_soc_opencryptolinux_boot.hex iob_soc_opencryptolinux_firmware.hex +HEX+=boot_flow ROOT_DIR :=../.. include $(ROOT_DIR)/software/sw_build.mk @@ -23,3 +24,5 @@ GRAB_TIMEOUT ?= 7200 TEST_LIST+=test1 test1: make -C ../../ fw-clean SIMULATOR=$(SIMULATOR) && make -C ../../ sim-clean SIMULATOR=$(SIMULATOR) && make run SIMULATOR=$(SIMULATOR) + +.PHONY: boot_flow