fpga/fw: Resize ROM and FW_RAM, add RESETINFO partition

In order to be able to leave data for firmware signalling the
intention with a reset or to leave data for the next app in a chain of
apps, we introduce a part of FW_RAM that can be used to store this
data. In order to do this, we:

- Change size of ROM from 6 KB to 8 KB.
- Change size of FW_RAM, from 2 KB to 4 KB.
- Add RESETINFO memory partition inside FW_RAM.
- Add generation of map file.
- Change CFLAGS from using -O2 to using -Os.
- Update address ranges for valid access to ROM and FW_RAM.
- Move stack to be located before data+bss and the RESETINFO data
  above them. This also means we introduce hardware stack overflow
  protection through the Security Monitor.
- Revise firmware README to the new use of FW_RAM.
This commit is contained in:
Jonas Thörnblad 2025-02-19 16:45:05 +01:00 committed by Michael Cardell Widerkrantz
parent 3126a9c51e
commit 8f2f312531
No known key found for this signature in database
GPG key ID: D3DB3DDF57E704E5
13 changed files with 310 additions and 77 deletions

View file

@ -32,7 +32,7 @@ TARGET_FREQ ?= 24
# Size in 32-bit words, must be divisible by 256 (pairs of EBRs, because 16 # Size in 32-bit words, must be divisible by 256 (pairs of EBRs, because 16
# bits wide; an EBR is 128 32-bits words) # bits wide; an EBR is 128 32-bits words)
BRAM_FW_SIZE ?= 1536 BRAM_FW_SIZE ?= 2048
PIN_FILE ?= application_fpga_tk1.pcf PIN_FILE ?= application_fpga_tk1.pcf
@ -47,7 +47,7 @@ CFLAGS = \
-mabi=ilp32 \ -mabi=ilp32 \
-static \ -static \
-std=gnu99 \ -std=gnu99 \
-O2 \ -Os \
-ffast-math \ -ffast-math \
-fno-common \ -fno-common \
-fno-builtin-printf \ -fno-builtin-printf \
@ -156,7 +156,10 @@ all: application_fpga.bin
# incorrect BRAM_FW_SIZE # incorrect BRAM_FW_SIZE
# ------------------------------------------------------------------- # -------------------------------------------------------------------
%_size_mismatch: %.elf phony_explicit %_size_mismatch: %.elf phony_explicit
@test $$($(SIZE) $< | awk 'NR==2{print $$4}') -le $$(( 32 / 8 * $(BRAM_FW_SIZE) )) \ @test $$(( \
$$($(SIZE) -A $< | grep text | awk 'NR==1{print $$2}') + \
$$($(SIZE) -A $< | grep text | awk 'NR==2{print $$2}') \
)) -le $$(( 32 / 8 * $(BRAM_FW_SIZE) )) \
|| { printf "The 'BRAM_FW_SIZE' variable needs to be increased\n"; \ || { printf "The 'BRAM_FW_SIZE' variable needs to be increased\n"; \
[[ $< =~ testfw ]] && printf "Note that testfw fits if built with -Os\n"; \ [[ $< =~ testfw ]] && printf "Note that testfw fits if built with -Os\n"; \
false; } false; }
@ -177,17 +180,19 @@ secret:
# Firmware generation. # Firmware generation.
# Included in the bitstream. # Included in the bitstream.
#------------------------------------------------------------------- #-------------------------------------------------------------------
LDFLAGS = -T $(P)/fw/tk1/firmware.lds LDFLAGS = \
-T $(P)/fw/tk1/firmware.lds \
-Wl,--cref,-M
$(FIRMWARE_OBJS): $(FIRMWARE_DEPS) $(FIRMWARE_OBJS): $(FIRMWARE_DEPS)
$(TESTFW_OBJS): $(FIRMWARE_DEPS) $(TESTFW_OBJS): $(FIRMWARE_DEPS)
firmware.elf: $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds firmware.elf: $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds
$(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(LDFLAGS) -o $@ $(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(LDFLAGS) -o $@ > $(basename $@).map
simfirmware.elf: CFLAGS += -DSIMULATION simfirmware.elf: CFLAGS += -DSIMULATION
simfirmware.elf: $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds simfirmware.elf: $(FIRMWARE_OBJS) $(P)/fw/tk1/firmware.lds
$(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(LDFLAGS) -o $@ $(CC) $(CFLAGS) $(FIRMWARE_OBJS) $(LDFLAGS) -o $@ > $(basename $@).map
qemu_firmware.elf: CFLAGS += -DQEMU_CONSOLE qemu_firmware.elf: CFLAGS += -DQEMU_CONSOLE
qemu_firmware.elf: firmware.elf qemu_firmware.elf: firmware.elf
@ -221,7 +226,7 @@ splint:
$(FIRMWARE_SOURCES) $(FIRMWARE_SOURCES)
testfw.elf: $(TESTFW_OBJS) $(P)/fw/tk1/firmware.lds testfw.elf: $(TESTFW_OBJS) $(P)/fw/tk1/firmware.lds
$(CC) $(CFLAGS) $(TESTFW_OBJS) $(LDFLAGS) -o $@ $(CC) $(CFLAGS) $(TESTFW_OBJS) $(LDFLAGS) -o $@ > $(basename $@).map
# Generate a fake BRAM file that will be filled in later after place-n-route # Generate a fake BRAM file that will be filled in later after place-n-route
bram_fw.hex: bram_fw.hex:
@ -242,9 +247,6 @@ check-binary-hashes:
sha256sum -c application_fpga.bin.sha256 sha256sum -c application_fpga.bin.sha256
%.bin: %.elf %.bin: %.elf
$(SIZE) $<
@test "$$($(SIZE) $< | awk 'NR==2{print $$2, $$3}')" = "0 0" \
|| { printf "Non-empty data or bss section!\n"; false; }
$(OBJCOPY) --input-target=elf32-littleriscv --output-target=binary $< $@ $(OBJCOPY) --input-target=elf32-littleriscv --output-target=binary $< $@
chmod -x $@ chmod -x $@
@ -371,7 +373,7 @@ synth.json: $(FPGA_VERILOG_SRCS) $(VERILOG_SRCS) $(PICORV32_SRCS) bram_fw.hex
application_fpga_par.json: synth.json $(P)/data/$(PIN_FILE) application_fpga_par.json: synth.json $(P)/data/$(PIN_FILE)
$(NEXTPNR_PATH)nextpnr-ice40 \ $(NEXTPNR_PATH)nextpnr-ice40 \
-l application_fpga_par.txt \ -l application_fpga_par.txt \
--seed 9106179903728618585 \ --seed 16549106670644347421 \
--freq $(TARGET_FREQ) \ --freq $(TARGET_FREQ) \
--ignore-loops \ --ignore-loops \
--up5k \ --up5k \
@ -484,15 +486,15 @@ clean: clean_sim clean_fw clean_tb
.PHONY: clean .PHONY: clean
clean_fw: clean_fw:
rm -f firmware.{elf,elf.map,bin,hex} rm -f firmware.{elf,map,bin,hex}
rm -f $(FIRMWARE_OBJS) rm -f $(FIRMWARE_OBJS)
rm -f testfw.{elf,elf.map,bin,hex} rm -f testfw.{elf,map,bin,hex}
rm -f $(TESTFW_OBJS) rm -f $(TESTFW_OBJS)
rm -f qemu_firmware.elf rm -f qemu_firmware.elf
.PHONY: clean_fw .PHONY: clean_fw
clean_sim: clean_sim:
rm -f simfirmware.{elf,elf.map,bin,hex} rm -f simfirmware.{elf,map,bin,hex}
rm -f tb_application_fpga_sim.fst rm -f tb_application_fpga_sim.fst
rm -f tb_application_fpga_sim.fst.hier rm -f tb_application_fpga_sim.fst.hier
rm -f tb/output_spram*.hex rm -f tb/output_spram*.hex

View file

@ -1 +1 @@
93e311e4bfa7e2f8c3c89f194b5fbe7b83eff81e6d32fd73c8859d5d76324b48 application_fpga.bin 5287588b9929a5709859e5fd85cc585dda6524821740bd06829258be7e9fad7d application_fpga.bin

View file

@ -21,7 +21,7 @@ module fw_ram (
input wire cs, input wire cs,
input wire [ 3 : 0] we, input wire [ 3 : 0] we,
input wire [ 8 : 0] address, input wire [ 9 : 0] address,
input wire [31 : 0] write_data, input wire [31 : 0] write_data,
output wire [31 : 0] read_data, output wire [31 : 0] read_data,
output wire ready output wire ready
@ -34,10 +34,14 @@ module fw_ram (
reg [31 : 0] tmp_read_data; reg [31 : 0] tmp_read_data;
reg [31 : 0] mem_read_data0; reg [31 : 0] mem_read_data0;
reg [31 : 0] mem_read_data1; reg [31 : 0] mem_read_data1;
reg [31 : 0] mem_read_data2;
reg [31 : 0] mem_read_data3;
reg ready_reg; reg ready_reg;
wire system_mode_cs; wire system_mode_cs;
reg bank0; reg bank0;
reg bank1; reg bank1;
reg bank2;
reg bank3;
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -51,7 +55,24 @@ module fw_ram (
//---------------------------------------------------------------- //----------------------------------------------------------------
// Block RAM instances. // Block RAM instances.
//---------------------------------------------------------------- //----------------------------------------------------------------
SB_RAM40_4K fw_ram0_0 ( SB_RAM40_4K #(
.INIT_0(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_4(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_5(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_6(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_7(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_8(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_9(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000)
) fw_ram0_0 (
.RDATA(mem_read_data0[15 : 0]), .RDATA(mem_read_data0[15 : 0]),
.RADDR({3'h0, address[7 : 0]}), .RADDR({3'h0, address[7 : 0]}),
.RCLK(clk), .RCLK(clk),
@ -65,7 +86,24 @@ module fw_ram (
.MASK({{8{~we[1]}}, {8{~we[0]}}}) .MASK({{8{~we[1]}}, {8{~we[0]}}})
); );
SB_RAM40_4K fw_ram0_1 ( SB_RAM40_4K #(
.INIT_0(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_4(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_5(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_6(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_7(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_8(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_9(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000)
) fw_ram0_1 (
.RDATA(mem_read_data0[31 : 16]), .RDATA(mem_read_data0[31 : 16]),
.RADDR({3'h0, address[7 : 0]}), .RADDR({3'h0, address[7 : 0]}),
.RCLK(clk), .RCLK(clk),
@ -79,8 +117,24 @@ module fw_ram (
.MASK({{8{~we[3]}}, {8{~we[2]}}}) .MASK({{8{~we[3]}}, {8{~we[2]}}})
); );
SB_RAM40_4K #(
SB_RAM40_4K fw_ram1_0 ( .INIT_0(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_4(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_5(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_6(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_7(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_8(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_9(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000)
) fw_ram1_0 (
.RDATA(mem_read_data1[15 : 0]), .RDATA(mem_read_data1[15 : 0]),
.RADDR({3'h0, address[7 : 0]}), .RADDR({3'h0, address[7 : 0]}),
.RCLK(clk), .RCLK(clk),
@ -94,7 +148,24 @@ module fw_ram (
.MASK({{8{~we[1]}}, {8{~we[0]}}}) .MASK({{8{~we[1]}}, {8{~we[0]}}})
); );
SB_RAM40_4K fw_ram1_1 ( SB_RAM40_4K #(
.INIT_0(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_4(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_5(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_6(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_7(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_8(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_9(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000)
) fw_ram1_1 (
.RDATA(mem_read_data1[31 : 16]), .RDATA(mem_read_data1[31 : 16]),
.RADDR({3'h0, address[7 : 0]}), .RADDR({3'h0, address[7 : 0]}),
.RCLK(clk), .RCLK(clk),
@ -108,6 +179,130 @@ module fw_ram (
.MASK({{8{~we[3]}}, {8{~we[2]}}}) .MASK({{8{~we[3]}}, {8{~we[2]}}})
); );
SB_RAM40_4K #(
.INIT_0(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_4(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_5(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_6(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_7(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_8(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_9(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000)
) fw_ram2_0 (
.RDATA(mem_read_data2[15 : 0]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(system_mode_cs & bank2),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[15 : 0]),
.WE((|we & system_mode_cs & bank2)),
.MASK({{8{~we[1]}}, {8{~we[0]}}})
);
SB_RAM40_4K #(
.INIT_0(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_4(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_5(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_6(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_7(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_8(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_9(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000)
) fw_ram2_1 (
.RDATA(mem_read_data2[31 : 16]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(system_mode_cs & bank2),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[31 : 16]),
.WE((|we & system_mode_cs & bank2)),
.MASK({{8{~we[3]}}, {8{~we[2]}}})
);
SB_RAM40_4K #(
.INIT_0(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_4(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_5(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_6(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_7(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_8(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_9(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000)
) fw_ram3_0 (
.RDATA(mem_read_data3[15 : 0]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(system_mode_cs & bank3),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[15 : 0]),
.WE((|we & system_mode_cs & bank3)),
.MASK({{8{~we[1]}}, {8{~we[0]}}})
);
SB_RAM40_4K #(
.INIT_0(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_1(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_2(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_3(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_4(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_5(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_6(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_7(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_8(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_9(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_A(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_B(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_C(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_D(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_E(256'h0000000000000000000000000000000000000000000000000000000000000000),
.INIT_F(256'h0000000000000000000000000000000000000000000000000000000000000000)
) fw_ram3_1 (
.RDATA(mem_read_data3[31 : 16]),
.RADDR({3'h0, address[7 : 0]}),
.RCLK(clk),
.RCLKE(1'h1),
.RE(system_mode_cs & bank3),
.WADDR({3'h0, address[7 : 0]}),
.WCLK(clk),
.WCLKE(1'h1),
.WDATA(write_data[31 : 16]),
.WE((|we & system_mode_cs & bank3)),
.MASK({{8{~we[3]}}, {8{~we[2]}}})
);
//---------------------------------------------------------------- //----------------------------------------------------------------
// reg_update // reg_update
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -127,17 +322,29 @@ module fw_ram (
always @* begin : rw_mux always @* begin : rw_mux
bank0 = 1'h0; bank0 = 1'h0;
bank1 = 1'h0; bank1 = 1'h0;
bank2 = 1'h0;
bank3 = 1'h0;
tmp_read_data = 32'h0; tmp_read_data = 32'h0;
if (system_mode_cs) begin if (system_mode_cs) begin
if (address[8]) begin case (address[9:8])
2'b11: begin
bank3 = 1'h1;
tmp_read_data = mem_read_data3;
end
2'b10: begin
bank2 = 1'h1;
tmp_read_data = mem_read_data2;
end
2'b01: begin
bank1 = 1'h1; bank1 = 1'h1;
tmp_read_data = mem_read_data1; tmp_read_data = mem_read_data1;
end end
else begin 2'b00: begin
bank0 = 1'h1; bank0 = 1'h1;
tmp_read_data = mem_read_data0; tmp_read_data = mem_read_data0;
end end
endcase
end end
end end

View file

@ -105,7 +105,7 @@ module tk1 #(
localparam TK1_VERSION = 32'h00000005; localparam TK1_VERSION = 32'h00000005;
localparam FW_RAM_FIRST = 32'hd0000000; localparam FW_RAM_FIRST = 32'hd0000000;
localparam FW_RAM_LAST = 32'hd00007ff; localparam FW_RAM_LAST = 32'hd0000fff; // 4 KB
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -395,7 +395,7 @@ module tk1 #(
if (cpu_valid) begin if (cpu_valid) begin
// Outside ROM area // Outside ROM area
if (cpu_addr[31 : 30] == 2'h0 & |cpu_addr[29 : 14]) begin if (cpu_addr[31 : 30] == 2'h0 & |cpu_addr[29 : 13]) begin
force_trap_set = 1'h1; force_trap_set = 1'h1;
end end
@ -443,7 +443,7 @@ module tk1 #(
end end
// Outside FW_RAM // Outside FW_RAM
if (cpu_addr[29 : 24] == 6'h10 & |cpu_addr[23 : 11]) begin if (cpu_addr[29 : 24] == 6'h10 & |cpu_addr[23 : 12]) begin
force_trap_set = 1'h1; force_trap_set = 1'h1;
end end

View file

@ -1 +1 @@
5e655ba4f25e7f5bc033ce0d9707c9a0b8990258c4b87470c2bcef90d50df79813705c1ef9d22c8670a37aff68f0e5146e5d0c21406916aabf7704579eb7f15c firmware.bin 866ad99a5fe0466f49b81d4b12b4ec81c3e0d6dba3ef8ad94ae44e6fa190ff495c95fbc5571214e890302f88997d0db45034e12fc8b8880fa01c10411b26f960 firmware.bin

View file

@ -73,7 +73,10 @@ Dev Handbook for specific details.
## Memory constraints ## Memory constraints
- ROM: 6 kByte. - ROM: 6 kByte.
- FW\_RAM: 2 kByte. - FW\_RAM: 4 kByte.
- fw stack: 3824 bytes.
- resetinfo: 256 bytes.
- rest is available for .data and .bss.
- RAM: 128 kByte. - RAM: 128 kByte.
## Firmware behaviour ## Firmware behaviour
@ -158,7 +161,7 @@ in the memory map, so it's still possible to execute firmware code in
application mode, but with no privileged access. application mode, but with no privileged access.
Firmware loads the application at the start of RAM (`0x4000_0000`). It Firmware loads the application at the start of RAM (`0x4000_0000`). It
uses the special FW\_RAM for its own stack. use a part of the special FW\_RAM for its own stack.
When reset is released, the CPU starts executing the firmware. It When reset is released, the CPU starts executing the firmware. It
begins by clearing all CPU registers, clears all FW\_RAM, sets up a begins by clearing all CPU registers, clears all FW\_RAM, sets up a
@ -203,9 +206,9 @@ Typical expected use scenario:
let the device application know where it is loaded and how large let the device application know where it is loaded and how large
it is, if it wants to relocate in RAM. it is, if it wants to relocate in RAM.
7. The firmware now clears the special `FW_RAM` where it keeps it 7. The firmware now clears the part of the special `FW_RAM` where it
stack. After this it performs no more function calls and uses no keeps it stack. After this it performs no more function calls and
more automatic variables. uses no more automatic variables.
8. Firmware starts the application by first switching from firmware 8. Firmware starts the application by first switching from firmware
mode to application mode by writing to the `SYSTEM_MODE_CTRL` mode to application mode by writing to the `SYSTEM_MODE_CTRL`
@ -245,8 +248,8 @@ implementation in the FPGA at this time.
The firmware instead does the CDI computation using the special The firmware instead does the CDI computation using the special
firmware-only `FW_RAM` which is invisible after switching to app mode. firmware-only `FW_RAM` which is invisible after switching to app mode.
We keep the entire firmware stack in `FW_RAM` and clear it just before We keep the entire firmware stack in `FW_RAM` and clear the stack just
switching to app mode just in case. before switching to app mode just in case.
We sleep for a random number of cycles before reading out the UDS, We sleep for a random number of cycles before reading out the UDS,
call `blake2s_update()` with it and then immediately call call `blake2s_update()` with it and then immediately call
@ -259,10 +262,6 @@ Then we continue with the CDI computation by updating with an optional
USS and then finalizing the hash, storing the resulting digest in USS and then finalizing the hash, storing the resulting digest in
`CDI`. `CDI`.
We also clear the entire `FW_RAM` where the stack lived, including the
BLAKE2s context with the UDS, very soon after that, just before
jumping to the application.
### Firmware services ### Firmware services
The firmware exposes a BLAKE2s function through a function pointer The firmware exposes a BLAKE2s function through a function pointer

View file

@ -295,7 +295,7 @@ int main(void)
} }
// Test FW_RAM. // Test FW_RAM.
puts("\r\nTesting FW_RAM (takes 15s on hw)...\r\n"); puts("\r\nTesting FW_RAM (takes 50s on hw)...\r\n");
for (unsigned int i = 0; i < TK1_MMIO_FW_RAM_SIZE; i++) { for (unsigned int i = 0; i < TK1_MMIO_FW_RAM_SIZE; i++) {
zero_fwram(); zero_fwram();
*(volatile uint8_t *)(TK1_MMIO_FW_RAM_BASE + i) = 0x42; *(volatile uint8_t *)(TK1_MMIO_FW_RAM_BASE + i) = 0x42;

View file

@ -3,12 +3,17 @@
* SPDX-License-Identifier: GPL-2.0-only * SPDX-License-Identifier: GPL-2.0-only
*/ */
OUTPUT_ARCH( "riscv" ) OUTPUT_ARCH("riscv")
ENTRY(_start) ENTRY(_start)
/* Define stack size */
STACK_SIZE = 0xEF0; /* 3824 B */
MEMORY MEMORY
{ {
ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x20000 /* 128 KB */ ROM (rx) : ORIGIN = 0x00000000, LENGTH = 0x2000 /* 8 KB */
FWRAM (rw) : ORIGIN = 0xd0000000, LENGTH = 0xF00 /* 3840 B */
RESETINFO (rw) : ORIGIN = 0xd0000F00, LENGTH = 0x100 /* 256 B (part of FW_RAM area) */
RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */ RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 0x20000 /* 128 KB */
} }
@ -28,31 +33,38 @@ SECTIONS
.text : .text :
{ {
. = ALIGN(4); . = ALIGN(4);
_stext = .;
*(.text) /* .text sections (code) */ *(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */ *(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.srodata) /* .rodata sections (constants, strings, etc.) */ *(.srodata) /* .srodata sections (constants, strings, etc.) */
*(.srodata*) /* .rodata* sections (constants, strings, etc.) */ *(.srodata*) /* .srodata* sections (constants, strings, etc.) */
. = ALIGN(4); . = ALIGN(4);
_etext = .; _etext = .;
_sidata = _etext;
} >ROM } >ROM
/* XXX We don't allow any data or BSS - but they need be defined or linking will fail */ .stack (NOLOAD) :
{
. = ALIGN(16);
_sstack = .;
. += STACK_SIZE;
. = ALIGN(16);
_estack = .;
} >FWRAM
.data : AT (_etext) .data :
{ {
. = ALIGN(4); . = ALIGN(4);
_sdata = .; _sdata = .;
. = ALIGN(4);
*(.data) /* .data sections */ *(.data) /* .data sections */
*(.data*) /* .data* sections */ *(.data*) /* .data* sections */
*(.sdata) /* .sdata sections */ *(.sdata) /* .sdata sections */
*(.sdata*) /* .sdata* sections */ *(.sdata*) /* .sdata* sections */
. = ALIGN(4); . = ALIGN(4);
_edata = .; _edata = .;
} >ROM } >FWRAM AT>ROM
_sidata = LOADADDR(.data);
/* Uninitialized data section */ /* Uninitialized data section */
.bss : .bss :
@ -64,8 +76,12 @@ SECTIONS
*(.sbss) *(.sbss)
*(.sbss*) *(.sbss*)
*(COMMON) *(COMMON)
. = ALIGN(4); . = ALIGN(4);
_ebss = .; _ebss = .;
} >ROM } >FWRAM
} }
_sfwram = ORIGIN(FWRAM);
_efwram = ORIGIN(FWRAM) + LENGTH(FWRAM);
_sresetinfo = ORIGIN(RESETINFO);
_eresetinfo = ORIGIN(RESETINFO) + LENGTH(RESETINFO);

View file

@ -334,8 +334,8 @@ static void run(const struct context *ctx)
// clang-format off // clang-format off
#ifndef S_SPLINT_S #ifndef S_SPLINT_S
asm volatile( asm volatile(
"li a0, 0xd0000000;" // FW_RAM "la a0, _sstack;"
"li a1, 0xd0000800;" // End of 2 KB FW_RAM (just past the end) "la a1, _estack;"
"loop:;" "loop:;"
"sw zero, 0(a0);" "sw zero, 0(a0);"
"addi a0, a0, 4;" "addi a0, a0, 4;"

View file

@ -39,17 +39,24 @@ _start:
li x31,0 li x31,0
/* Clear FW_RAM */ /* Clear FW_RAM */
li a0, 0xd0000000 // TK1_MMIO_FW_RAM_BASE la a0, _sfwram
li a1, 0xd0000800 // TK1_MMIO_FW_RAM_BASE + TK1_MMIO_FW_RAM_SIZE la a1, _efwram
clear: clear:
sw zero, 0(a0) sw zero, 0(a0)
addi a0, a0, 4 addi a0, a0, 4
blt a0, a1, clear blt a0, a1, clear
/* /* Zero-init bss section */
* Init stack at top of fw_ram. la a0, _sbss
*/ la a1, _ebss
li sp, 0xd0000800 // 2 kiB (TK1_MMIO_FW_RAM_SIZE)
loop_init_bss:
sw zero, 0(a0)
addi a0, a0, 4
blt a0, a1, loop_init_bss
/* Init stack */
la sp, _estack
call main call main

View file

@ -54,6 +54,8 @@
*/ */
#define TK1_ROM_BASE 0x00000000 #define TK1_ROM_BASE 0x00000000
#define TK1_ROM_SIZE 0x2000
#define TK1_RAM_BASE 0x40000000 #define TK1_RAM_BASE 0x40000000
#define TK1_RAM_SIZE 0x20000 #define TK1_RAM_SIZE 0x20000
@ -63,8 +65,8 @@
#define TK1_APP_MAX_SIZE 0x20000 #define TK1_APP_MAX_SIZE 0x20000
#define TK1_MMIO_FW_RAM_BASE 0xd0000000 #define TK1_MMIO_FW_RAM_BASE 0xd0000000
// FW_RAM is 2048 bytes // FW_RAM is 4096 bytes
#define TK1_MMIO_FW_RAM_SIZE 0x800 #define TK1_MMIO_FW_RAM_SIZE 0x1000
#define TK1_MMIO_TRNG_BASE 0xc0000000 #define TK1_MMIO_TRNG_BASE 0xc0000000
#define TK1_MMIO_TRNG_STATUS 0xc0000024 #define TK1_MMIO_TRNG_STATUS 0xc0000024

View file

@ -89,7 +89,7 @@ module application_fpga (
wire [31 : 0] cpu_wdata; wire [31 : 0] cpu_wdata;
reg rom_cs; reg rom_cs;
reg [11 : 0] rom_address; reg [10 : 0] rom_address;
wire [31 : 0] rom_read_data; wire [31 : 0] rom_read_data;
wire rom_ready; wire rom_ready;
@ -128,7 +128,7 @@ module application_fpga (
reg fw_ram_cs; reg fw_ram_cs;
reg [ 3 : 0] fw_ram_we; reg [ 3 : 0] fw_ram_we;
reg [ 8 : 0] fw_ram_address; reg [ 9 : 0] fw_ram_address;
reg [31 : 0] fw_ram_write_data; reg [31 : 0] fw_ram_write_data;
wire [31 : 0] fw_ram_read_data; wire [31 : 0] fw_ram_read_data;
wire fw_ram_ready; wire fw_ram_ready;
@ -394,7 +394,7 @@ module application_fpga (
muxed_rdata_new = 32'h0; muxed_rdata_new = 32'h0;
rom_cs = 1'h0; rom_cs = 1'h0;
rom_address = cpu_addr[13 : 2]; rom_address = cpu_addr[12 : 2];
ram_cs = 1'h0; ram_cs = 1'h0;
ram_we = 4'h0; ram_we = 4'h0;
@ -403,7 +403,7 @@ module application_fpga (
fw_ram_cs = 1'h0; fw_ram_cs = 1'h0;
fw_ram_we = cpu_wstrb; fw_ram_we = cpu_wstrb;
fw_ram_address = cpu_addr[10 : 2]; fw_ram_address = cpu_addr[11 : 2];
fw_ram_write_data = cpu_wdata; fw_ram_write_data = cpu_wdata;
trng_cs = 1'h0; trng_cs = 1'h0;

View file

@ -101,7 +101,7 @@ module application_fpga_sim (
wire [31 : 0] cpu_wdata; wire [31 : 0] cpu_wdata;
reg rom_cs; reg rom_cs;
reg [11 : 0] rom_address; reg [10 : 0] rom_address;
wire [31 : 0] rom_read_data; wire [31 : 0] rom_read_data;
wire rom_ready; wire rom_ready;
@ -140,7 +140,7 @@ module application_fpga_sim (
reg fw_ram_cs; reg fw_ram_cs;
reg [ 3 : 0] fw_ram_we; reg [ 3 : 0] fw_ram_we;
reg [ 8 : 0] fw_ram_address; reg [ 9 : 0] fw_ram_address;
reg [31 : 0] fw_ram_write_data; reg [31 : 0] fw_ram_write_data;
wire [31 : 0] fw_ram_read_data; wire [31 : 0] fw_ram_read_data;
wire fw_ram_ready; wire fw_ram_ready;
@ -408,7 +408,7 @@ module application_fpga_sim (
muxed_rdata_new = 32'h0; muxed_rdata_new = 32'h0;
rom_cs = 1'h0; rom_cs = 1'h0;
rom_address = cpu_addr[13 : 2]; rom_address = cpu_addr[12 : 2];
ram_cs = 1'h0; ram_cs = 1'h0;
ram_we = 4'h0; ram_we = 4'h0;
@ -417,7 +417,7 @@ module application_fpga_sim (
fw_ram_cs = 1'h0; fw_ram_cs = 1'h0;
fw_ram_we = cpu_wstrb; fw_ram_we = cpu_wstrb;
fw_ram_address = cpu_addr[10 : 2]; fw_ram_address = cpu_addr[11 : 2];
fw_ram_write_data = cpu_wdata; fw_ram_write_data = cpu_wdata;
trng_cs = 1'h0; trng_cs = 1'h0;