diff --git a/build.sh b/build.sh
index d5c8053..cc036aa 100755
--- a/build.sh
+++ b/build.sh
@@ -3,10 +3,10 @@
PACKAGE_FILE_NAME="SummerCart64"
FILES=(
- "./fw/output_files/SummerCart64.pof"
- "./hw/v1/ftdi-template.xml"
+ "./fw/output_files/SC64_update.bin"
+ "./fw/output_files/SC64_update.pof"
+ "./hw/ftdi-template.xml"
"./sw/cic/UltraCIC-III.hex"
- "./sw/riscv/build/controller.rom"
"./LICENSE"
)
@@ -35,6 +35,10 @@ popd
pushd fw
echo "Building FPGA firmware"
quartus_sh --flow compile ./SummerCart64.qpf
+quartus_cpf -c ./SummerCart64.cof
+cp output_files/SC64_firmware.pof output_files/SC64_update.pof
+cat output_files/sc64_firmware_ufm_auto.rpd output_files/sc64_firmware_cfm0_auto.rpd > output_files/SC64_update_LE.bin
+riscv32-unknown-elf-objcopy -I binary -O binary --reverse-bytes=4 output_files/SC64_update_LE.bin output_files/SC64_update.bin
popd
diff --git a/build_in_docker.sh b/build_in_docker.sh
index 7405b54..dded6f2 100755
--- a/build_in_docker.sh
+++ b/build_in_docker.sh
@@ -1,3 +1,6 @@
#!/bin/bash
-docker run --mount type=bind,src="$(pwd)",target="/workdir" ghcr.io/polprzewodnikowy/sc64env:v1.0 /bin/bash ./build.sh
+docker run \
+ --mount type=bind,src="$(pwd)",target="/workdir" \
+ ghcr.io/polprzewodnikowy/sc64env:v1.0 \
+ /bin/bash -c "./build.sh"
diff --git a/fw/SummerCart64.cof b/fw/SummerCart64.cof
new file mode 100644
index 0000000..bf1be85
--- /dev/null
+++ b/fw/SummerCart64.cof
@@ -0,0 +1,42 @@
+
+
+ output_files/SC64_firmware.pof
+ 1
+ 1
+ 14
+
+ Page_0
+ 1
+
+ output_files/SummerCart64.sof1
+
+
+ 10
+ 0
+ 0
+ 1
+ 0
+
+ 1
+
+
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 2
+ ../sw/n64/build/SummerLoader64.hex
+ ../sw/riscv/build/controller.hex
+ 305152
+
+
+ 1
+ 2
+ 0
+ -1
+ -1
+ 1
+
+
\ No newline at end of file
diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf
index 1987b3c..4c1f698 100644
--- a/fw/SummerCart64.qsf
+++ b/fw/SummerCart64.qsf
@@ -19,7 +19,7 @@
#
# Quartus Prime
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
-# Date created = 21:23:28 September 18, 2021
+# Date created = 22:44:04 October 26, 2021
#
# -------------------------------------------------------------------------- #
#
@@ -58,6 +58,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE ../sw/riscv/build/cpu_bootloader.
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv
+set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flash.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv
@@ -68,7 +69,6 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_soc.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_uart.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_wrapper.sv
-set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_flash.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv
@@ -86,7 +86,6 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/sc64.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/system.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/usb/usb_ft1248.sv
set_global_assignment -name SIGNALTAP_FILE output_files/signaltap.stp
-set_global_assignment -name SLD_FILE db/signaltap_auto_stripped.stp
# Pin & Location Assignments
# ==========================
@@ -225,7 +224,6 @@ set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
# Signal Tap Assignments
# ======================
set_global_assignment -name ENABLE_SIGNALTAP ON
-set_global_assignment -name USE_SIGNALTAP_FILE output_files/signaltap.stp
# Power Estimation Assignments
# ============================
@@ -305,7 +303,6 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
- set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
diff --git a/fw/build.sh b/fw/build.sh
index 4c1b7c8..c30bed2 100755
--- a/fw/build.sh
+++ b/fw/build.sh
@@ -1,3 +1,13 @@
#!/bin/bash
-docker run --mount type=bind,src="$(pwd)/..",target="/workdir" ghcr.io/polprzewodnikowy/sc64env:v1.0 /bin/bash -c "cd fw && quartus_sh --flow compile ./SummerCart64.qpf"
+docker run \
+ --mount type=bind,src="$(pwd)/..",target="/workdir" \
+ ghcr.io/polprzewodnikowy/sc64env:v1.0 \
+ /bin/bash -c " \
+ cd fw && \
+ quartus_sh --flow compile ./SummerCart64.qpf && \
+ quartus_cpf -c ./SummerCart64.cof && \
+ cp output_files/SC64_firmware.pof output_files/SC64_update.pof && \
+ cat output_files/sc64_firmware_ufm_auto.rpd output_files/sc64_firmware_cfm0_auto.rpd > output_files/SC64_update_LE.bin && \
+ riscv32-unknown-elf-objcopy -I binary -O binary --reverse-bytes=4 output_files/SC64_update_LE.bin output_files/SC64_update.bin
+ "
diff --git a/fw/rtl/SummerCart64.sv b/fw/rtl/SummerCart64.sv
index 0474b97..48eea35 100644
--- a/fw/rtl/SummerCart64.sv
+++ b/fw/rtl/SummerCart64.sv
@@ -64,6 +64,8 @@ module SummerCart64 (
if_si si ();
+ if_flash flash ();
+
system system_inst (
.sys(sys)
);
@@ -81,6 +83,7 @@ module SummerCart64 (
.sdram(sdram),
.flashram(flashram),
.si(si),
+ .flash(flash),
.n64_pi_alel(i_n64_pi_alel),
.n64_pi_aleh(i_n64_pi_aleh),
@@ -107,6 +110,7 @@ module SummerCart64 (
.sdram(sdram),
.flashram(flashram),
.si(si),
+ .flash(flash),
.gpio_o(gpio_o),
.gpio_i(gpio_i),
diff --git a/fw/rtl/cpu/cpu_cfg.sv b/fw/rtl/cpu/cpu_cfg.sv
index 426b1b9..275ab66 100644
--- a/fw/rtl/cpu/cpu_cfg.sv
+++ b/fw/rtl/cpu/cpu_cfg.sv
@@ -30,7 +30,7 @@ module cpu_cfg (
R_SCR: bus.rdata = {
cfg.cpu_ready,
cfg.cpu_busy,
- cfg.usb_waiting,
+ 1'b0,
cfg.cmd_error,
21'd0,
skip_bootloader,
@@ -65,7 +65,6 @@ module cpu_cfg (
if (sys.reset) begin
cfg.cpu_ready <= 1'b0;
cfg.cpu_busy <= 1'b0;
- cfg.usb_waiting <= 1'b0;
cfg.cmd_error <= 1'b0;
cfg.sdram_switch <= 1'b0;
cfg.sdram_writable <= 1'b0;
@@ -91,9 +90,8 @@ module cpu_cfg (
{
cfg.cpu_ready,
cfg.cpu_busy,
- cfg.usb_waiting,
cfg.cmd_error
- } <= bus.wdata[31:28];
+ } <= {bus.wdata[31:30], bus.wdata[28]};
end
if (bus.wmask[0]) begin
{
diff --git a/fw/rtl/cpu/cpu_flash.sv b/fw/rtl/cpu/cpu_flash.sv
new file mode 100644
index 0000000..a7c3b6f
--- /dev/null
+++ b/fw/rtl/cpu/cpu_flash.sv
@@ -0,0 +1,61 @@
+interface if_flash ();
+
+ logic request;
+ logic ack;
+ logic write;
+ logic [31:0] address;
+ logic [31:0] rdata;
+ logic [31:0] wdata;
+
+ modport cpu (
+ output request,
+ input ack,
+ output write,
+ output address,
+ input rdata,
+ output wdata
+ );
+
+ modport memory (
+ input request,
+ output ack,
+ input write,
+ input address,
+ output rdata,
+ input wdata
+ );
+
+endinterface
+
+
+module cpu_flash (
+ if_system.sys sys,
+ if_cpu_bus bus,
+ if_flash.cpu flash
+);
+
+ logic request;
+
+ always_comb begin
+ bus.ack = flash.ack;
+ bus.rdata = flash.rdata;
+ flash.request = bus.request || request;
+ flash.write = &bus.wmask;
+ flash.address = bus.address;
+ flash.wdata = bus.wdata;
+ end
+
+ always_ff @(posedge sys.clk) begin
+ if (sys.reset) begin
+ request <= 1'b0;
+ end else begin
+ if (bus.request) begin
+ request <= 1'b1;
+ end
+ if (flash.ack) begin
+ request <= 1'b0;
+ end
+ end
+ end
+
+endmodule
diff --git a/fw/rtl/cpu/cpu_soc.sv b/fw/rtl/cpu/cpu_soc.sv
index 5a9303a..69b4050 100644
--- a/fw/rtl/cpu/cpu_soc.sv
+++ b/fw/rtl/cpu/cpu_soc.sv
@@ -5,6 +5,7 @@ module cpu_soc (
if_sdram.cpu sdram,
if_flashram.cpu flashram,
if_si.cpu si,
+ if_flash.cpu flash,
input [7:0] gpio_i,
output [7:0] gpio_o,
@@ -111,4 +112,10 @@ module cpu_soc (
.si(si)
);
+ cpu_flash cpu_flash_inst (
+ .sys(sys),
+ .bus(bus.at[sc64::ID_CPU_FLASH].device),
+ .flash(flash)
+ );
+
endmodule
diff --git a/fw/rtl/intel/flash/intel_flash.qsys b/fw/rtl/intel/flash/intel_flash.qsys
index 9aca588..ffe595d 100644
--- a/fw/rtl/intel/flash/intel_flash.qsys
+++ b/fw/rtl/intel/flash/intel_flash.qsys
@@ -7,17 +7,17 @@
description=""
tags="INTERNAL_COMPONENT=true"
categories="System" />
-
@@ -41,10 +41,18 @@
-
+
+
+
+
+
+
+
+
+
@@ -68,7 +76,7 @@
- Read only,Read only,Hidden,Read only,Read only
+ Read and write,Read and write,Hidden,Read and write,Read and write
$${FILENAME}_onchip_flash_0
../sw/n64/build/SummerLoader64.hex
diff --git a/fw/rtl/memory/memory_flash.sv b/fw/rtl/memory/memory_flash.sv
deleted file mode 100644
index 2aefc25..0000000
--- a/fw/rtl/memory/memory_flash.sv
+++ /dev/null
@@ -1,76 +0,0 @@
-module memory_flash (
- if_system.sys sys,
-
- input request,
- output ack,
- input [31:0] address,
- output [15:0] rdata
-);
-
- logic flash_enable;
- logic flash_request;
- logic flash_busy;
- logic flash_ack;
- logic [31:0] flash_rdata;
-
- logic dummy_ack;
-
- always_comb begin
- flash_enable = address < 32'h10016800;
-
- ack = flash_ack | dummy_ack;
-
- rdata = 16'd0;
- if (ack && flash_enable) begin
- if (address[1]) rdata = {flash_rdata[23:16], flash_rdata[31:24]};
- else rdata = {flash_rdata[7:0], flash_rdata[15:8]};
- end
- end
-
- typedef enum bit [0:0] {
- S_IDLE,
- S_WAIT
- } e_state;
-
- e_state state;
-
- always_ff @(posedge sys.clk) begin
- dummy_ack <= 1'b0;
-
- if (sys.reset) begin
- state <= S_IDLE;
- flash_request <= 1'b0;
- end else begin
- case (state)
- S_IDLE: begin
- if (request) begin
- state <= S_WAIT;
- flash_request <= flash_enable;
- dummy_ack <= !flash_enable;
- end
- end
-
- S_WAIT: begin
- if (!flash_busy) begin
- flash_request <= 1'b0;
- end
- if (ack) begin
- state <= S_IDLE;
- end
- end
- endcase
- end
- end
-
- intel_flash intel_flash_inst (
- .clock(sys.clk),
- .reset_n(~sys.reset),
- .avmm_data_addr(address[31:2]),
- .avmm_data_read(flash_request),
- .avmm_data_readdata(flash_rdata),
- .avmm_data_waitrequest(flash_busy),
- .avmm_data_readdatavalid(flash_ack),
- .avmm_data_burstcount(2'd1)
- );
-
-endmodule
diff --git a/fw/rtl/n64/n64_bootloader.sv b/fw/rtl/n64/n64_bootloader.sv
index 2967a31..0f5942e 100644
--- a/fw/rtl/n64/n64_bootloader.sv
+++ b/fw/rtl/n64/n64_bootloader.sv
@@ -1,14 +1,124 @@
module n64_bootloader (
if_system.sys sys,
- if_n64_bus bus
+ if_n64_bus bus,
+ if_flash.memory flash
);
- memory_flash memory_flash_inst (
- .sys(sys),
- .request(bus.request),
- .ack(bus.ack),
- .address(bus.address),
- .rdata(bus.rdata)
+ logic mem_request;
+ logic csr_ack;
+ logic data_ack;
+ logic write_ack;
+ logic data_busy;
+ logic mem_write;
+ logic [31:0] mem_address;
+ logic [31:0] csr_rdata;
+ logic [31:0] data_rdata;
+ logic [31:0] mem_wdata;
+
+ typedef enum bit [0:0] {
+ S_IDLE,
+ S_WAIT
+ } e_state;
+
+ typedef enum bit [0:0] {
+ T_N64,
+ T_CPU
+ } e_source_request;
+
+ e_state state;
+ e_source_request source_request;
+
+ always_ff @(posedge sys.clk) begin
+ csr_ack <= 1'b0;
+ write_ack <= 1'b0;
+
+ if (sys.reset) begin
+ state <= S_IDLE;
+ mem_request <= 1'b0;
+ end else begin
+ case (state)
+ S_IDLE: begin
+ if (bus.request || flash.request) begin
+ state <= S_WAIT;
+ mem_request <= 1'b1;
+ if (bus.request) begin
+ mem_write <= 1'b0;
+ mem_address <= bus.address;
+ mem_wdata <= bus.wdata;
+ source_request <= T_N64;
+ end else if (flash.request) begin
+ mem_write <= flash.write;
+ mem_address <= flash.address;
+ mem_wdata <= flash.wdata;
+ source_request <= T_CPU;
+ end
+ end
+ end
+
+ S_WAIT: begin
+ if (mem_address[27] && source_request != T_N64 && !csr_ack) begin
+ mem_request <= 1'b0;
+ csr_ack <= 1'b1;
+ end
+ if ((!mem_address[27] || source_request == T_N64) && !data_busy) begin
+ mem_request <= 1'b0;
+ end
+ if (!mem_address[27] && mem_write && !data_busy && !write_ack) begin
+ write_ack <= 1'b1;
+ end
+ if (csr_ack || data_ack || write_ack) begin
+ state <= S_IDLE;
+ end
+ end
+ endcase
+ end
+ end
+
+ logic csr_or_data;
+ logic csr_read;
+ logic csr_write;
+ logic data_read;
+ logic data_write;
+
+ always_comb begin
+ csr_or_data = mem_address[27] && source_request == T_CPU;
+ csr_read = csr_or_data && mem_request && !mem_write;
+ csr_write = csr_or_data && mem_request && mem_write;
+ data_read = !csr_or_data && mem_request && !mem_write;
+ data_write = !csr_or_data && mem_request && mem_write;
+
+ bus.ack = source_request == T_N64 && data_ack;
+ bus.rdata = 16'd0;
+ if (bus.ack && bus.address >= 32'h10000000 && bus.address < 32'h10016800) begin
+ if (bus.address[1]) bus.rdata = {data_rdata[23:16], data_rdata[31:24]};
+ else bus.rdata = {data_rdata[7:0], data_rdata[15:8]};
+ end
+
+ flash.ack = source_request == T_CPU && (csr_ack || data_ack || write_ack);
+ flash.rdata = 32'd0;
+ if (flash.ack) begin
+ flash.rdata = csr_or_data ? csr_rdata : data_rdata;
+ end
+ end
+
+ intel_flash intel_flash_inst (
+ .clock(sys.clk),
+ .reset_n(~sys.reset),
+
+ .avmm_csr_addr(mem_address[2]),
+ .avmm_csr_read(csr_read),
+ .avmm_csr_writedata(mem_wdata),
+ .avmm_csr_write(csr_write),
+ .avmm_csr_readdata(csr_rdata),
+
+ .avmm_data_addr(mem_address[31:2]),
+ .avmm_data_read(data_read),
+ .avmm_data_writedata(mem_wdata),
+ .avmm_data_write(data_write),
+ .avmm_data_readdata(data_rdata),
+ .avmm_data_waitrequest(data_busy),
+ .avmm_data_readdatavalid(data_ack),
+ .avmm_data_burstcount(2'd1)
);
endmodule
diff --git a/fw/rtl/n64/n64_cfg.sv b/fw/rtl/n64/n64_cfg.sv
index 49d6023..486d343 100644
--- a/fw/rtl/n64/n64_cfg.sv
+++ b/fw/rtl/n64/n64_cfg.sv
@@ -29,7 +29,7 @@ module n64_cfg (
R_SR: bus.rdata = {
cfg.cpu_ready,
cfg.cpu_busy,
- cfg.usb_waiting,
+ 1'b0,
cfg.cmd_error,
12'd0
};
diff --git a/fw/rtl/n64/n64_soc.sv b/fw/rtl/n64/n64_soc.sv
index 1f38904..4e6c5a3 100644
--- a/fw/rtl/n64/n64_soc.sv
+++ b/fw/rtl/n64/n64_soc.sv
@@ -5,6 +5,7 @@ module n64_soc (
if_sdram.memory sdram,
if_flashram.flashram flashram,
if_si.si si,
+ if_flash.memory flash,
input n64_pi_alel,
input n64_pi_aleh,
@@ -63,7 +64,8 @@ module n64_soc (
n64_bootloader n64_bootloader_inst (
.sys(sys),
- .bus(bus.at[sc64::ID_N64_BOOTLOADER].device)
+ .bus(bus.at[sc64::ID_N64_BOOTLOADER].device),
+ .flash(flash)
);
n64_flashram n64_flashram_inst (
diff --git a/fw/rtl/system/config.sv b/fw/rtl/system/config.sv
index fa4b8e3..42e4820 100644
--- a/fw/rtl/system/config.sv
+++ b/fw/rtl/system/config.sv
@@ -2,7 +2,6 @@ interface if_config ();
logic cpu_ready;
logic cpu_busy;
- logic usb_waiting;
logic cmd_error;
logic cmd_request;
logic [7:0] cmd;
@@ -38,7 +37,6 @@ interface if_config ();
modport n64 (
input cpu_ready,
input cpu_busy,
- input usb_waiting,
input cmd_error,
output cmd_request,
output cmd,
@@ -50,7 +48,6 @@ interface if_config ();
modport cpu (
output cpu_ready,
output cpu_busy,
- output usb_waiting,
output cmd_error,
input cmd_request,
input cmd,
diff --git a/fw/rtl/system/sc64.sv b/fw/rtl/system/sc64.sv
index 9044d52..e8ddb03 100644
--- a/fw/rtl/system/sc64.sv
+++ b/fw/rtl/system/sc64.sv
@@ -21,6 +21,7 @@ package sc64;
ID_CPU_SDRAM,
ID_CPU_FLASHRAM,
ID_CPU_SI,
+ ID_CPU_FLASH,
__ID_CPU_END
} e_cpu_id;
diff --git a/sw/n64/.gitignore b/sw/n64/.gitignore
index e53d106..23dcf96 100644
--- a/sw/n64/.gitignore
+++ b/sw/n64/.gitignore
@@ -1,2 +1,2 @@
/build
-/what
\ No newline at end of file
+*.z64
diff --git a/sw/n64/Makefile b/sw/n64/Makefile
index f835a6f..8b384cc 100644
--- a/sw/n64/Makefile
+++ b/sw/n64/Makefile
@@ -1,69 +1,28 @@
-ROOTDIR = $(N64_INST)
-
-GCCN64PREFIX = $(ROOTDIR)/bin/mips64-elf-
-CC = $(GCCN64PREFIX)gcc
-AS = $(GCCN64PREFIX)as
-LD = $(GCCN64PREFIX)ld
-OBJCOPY = $(GCCN64PREFIX)objcopy
-OBJDUMP = $(GCCN64PREFIX)objdump
-
-CHKSUM64 = $(ROOTDIR)/bin/chksum64
-MKSPRITE = $(ROOTDIR)/bin/mksprite
-N64TOOL = $(ROOTDIR)/bin/n64tool
-
-HEADER_PATH = $(ROOTDIR)/mips64-elf/lib
-HEADER_NAME = header
-
-PROG_NAME = SummerLoader64
-
-ROM_SIZE = 1028k
-
-SOURCE_DIR = src
BUILD_DIR = build
+SOURCE_DIR = src
+PROGRAM_NAME = SummerLoader64
-SRC_DIRS = $(SOURCE_DIR) $(sort $(dir $(wildcard $(SOURCE_DIR)/*/.)))
-INC_DIRS = $(addprefix -I, . $(SRC_DIRS)) -I./libsc64/inc
-SRC_FILES = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIRS)))
-# IMG_FILES = $(wildcard $(patsubst %, %/*.png, . $(SRC_DIRS)))
-OBJ_FILES = $(addprefix $(BUILD_DIR)/, $(notdir $(IMG_FILES:.png=.o) $(SRC_FILES:.c=.o)))
+include $(N64_INST)/include/n64.mk
-VPATH = $(SRC_DIRS)
+src = main.c sc64.c boot.c crc32.c
-COMMONFLAGS = -march=vr4300 -mtune=vr4300
-ASFLAGS = $(COMMONFLAGS)
-CFLAGS = $(COMMONFLAGS) -std=gnu11 -Os -Wall -I$(ROOTDIR)/mips64-elf/include $(INC_DIRS) -ffunction-sections -fdata-sections -Wl,--gc-sections
-LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld
-#-L./libsc64/lib -lsc64_libdragon
-N64_FLAGS = -l $(ROM_SIZE) -h $(HEADER_PATH)/$(HEADER_NAME) -o $(BUILD_DIR)/$(PROG_NAME).z64
+all: $(BUILD_DIR)/$(PROGRAM_NAME).hex
-all: make_output_dir $(BUILD_DIR)/$(PROG_NAME).z64
+$(BUILD_DIR)/$(PROGRAM_NAME).elf: $(src:%.c=$(BUILD_DIR)/%.o)
-$(OBJ_FILES): Makefile
+$(PROGRAM_NAME).z64: N64_ROM_TITLE="$(PROGRAM_NAME)"
-$(BUILD_DIR)/$(PROG_NAME).z64: $(BUILD_DIR)/$(PROG_NAME).elf
- $(OBJCOPY) $(BUILD_DIR)/$(PROG_NAME).elf $(BUILD_DIR)/$(PROG_NAME).bin -O binary
- $(OBJDUMP) -S $(BUILD_DIR)/$(PROG_NAME).elf > $(BUILD_DIR)/$(PROG_NAME).lst
- $(N64TOOL) $(N64_FLAGS) -t $(PROG_NAME) $(BUILD_DIR)/$(PROG_NAME).bin
- $(CHKSUM64) $(BUILD_DIR)/$(PROG_NAME).z64
- truncate --size=90k $(BUILD_DIR)/$(PROG_NAME).z64
- $(OBJCOPY) $(BUILD_DIR)/$(PROG_NAME).z64 $(BUILD_DIR)/$(PROG_NAME).hex -I binary -O ihex
-
-$(BUILD_DIR)/$(PROG_NAME).elf: $(OBJ_FILES)
- $(LD) -o $(BUILD_DIR)/$(PROG_NAME).elf $(OBJ_FILES) $(LINK_FLAGS)
-
-$(BUILD_DIR)/%.o: %.c
- $(COMPILE.c) $(OUTPUT_OPTION) $<
-
-# $(BUILD_DIR)/%.sprite: $(IMG_FILES)
-# $(MKSPRITE) 32 $< $@
-
-# $(BUILD_DIR)/%.o: $(BUILD_DIR)/%.sprite
-# $(OBJCOPY) -I binary -O elf32-bigmips -B mips:4000 --rename-section .data=.rodata $< $@
-
-make_output_dir:
- $(shell mkdir ./$(BUILD_DIR) 2> /dev/null)
+$(BUILD_DIR)/$(PROGRAM_NAME).hex: $(PROGRAM_NAME).z64
+ sed '$$ s/\x00*$$//' $(PROGRAM_NAME).z64 > $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64
+ @if [ $$(stat -L -c %s $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64) -gt 92160 ]; then\
+ echo "\n Error: stripped file size is larger than 90kB thus cannot fit inside FPGA flash.\n"; exit 1;\
+ fi
+ truncate --size=90k $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64
+ $(N64_OBJCOPY) -I binary -O ihex $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64 $(BUILD_DIR)/$(PROGRAM_NAME).hex
clean:
- $(shell rm -rf ./$(BUILD_DIR) 2> /dev/null)
+ rm -rf ./$(BUILD_DIR) ./$(PROGRAM_NAME).z64
-.PHONY: all clean make_output_dir
+-include $(wildcard $(BUILD_DIR)/*.d)
+
+.PHONY: all clean
diff --git a/sw/n64/build.sh b/sw/n64/build.sh
index faeb3d6..a048919 100755
--- a/sw/n64/build.sh
+++ b/sw/n64/build.sh
@@ -1,3 +1,6 @@
#!/bin/bash
-docker run --mount type=bind,src="$(pwd)",target="/workdir" ghcr.io/polprzewodnikowy/sc64env:v1.0 /bin/bash -c "make clean all"
+docker run \
+ --mount type=bind,src="$(pwd)",target="/workdir" \
+ ghcr.io/polprzewodnikowy/sc64env:v1.0 \
+ /bin/bash -c "make clean all"
diff --git a/sw/n64/src/boot/boot.c b/sw/n64/src/boot.c
similarity index 100%
rename from sw/n64/src/boot/boot.c
rename to sw/n64/src/boot.c
diff --git a/sw/n64/src/boot/boot.h b/sw/n64/src/boot.h
similarity index 100%
rename from sw/n64/src/boot/boot.h
rename to sw/n64/src/boot.h
diff --git a/sw/n64/src/boot/crc32.c b/sw/n64/src/crc32.c
similarity index 100%
rename from sw/n64/src/boot/crc32.c
rename to sw/n64/src/crc32.c
diff --git a/sw/n64/src/boot/crc32.h b/sw/n64/src/crc32.h
similarity index 100%
rename from sw/n64/src/boot/crc32.h
rename to sw/n64/src/crc32.h
diff --git a/sw/n64/src/main.c b/sw/n64/src/main.c
index 1e0aac6..3535426 100644
--- a/sw/n64/src/main.c
+++ b/sw/n64/src/main.c
@@ -1,5 +1,5 @@
#include "sc64.h"
-#include "boot/boot.h"
+#include "boot.h"
int main(void) {
diff --git a/sw/n64/src/boot/n64_regs.h b/sw/n64/src/n64_regs.h
similarity index 100%
rename from sw/n64/src/boot/n64_regs.h
rename to sw/n64/src/n64_regs.h
diff --git a/sw/riscv/Makefile b/sw/riscv/Makefile
index d4db2a9..897e6c5 100644
--- a/sw/riscv/Makefile
+++ b/sw/riscv/Makefile
@@ -29,6 +29,7 @@ $(BUILD_DIR)/uc.elf: $(OBJS) SC64.ld
$(BUILD_DIR)/controller.rom: $(BUILD_DIR)/uc.elf
$(OBJCOPY) -R .bootloader $(BUILD_DIR)/uc.elf $(BUILD_DIR)/controller.elf
$(OBJCOPY) -O binary --set-section-flags .bss=alloc,contents $(BUILD_DIR)/controller.elf $(BUILD_DIR)/controller.bin
+ $(OBJCOPY) -I binary -O ihex $(BUILD_DIR)/controller.bin $(BUILD_DIR)/controller.hex
python3 tools/bin2rom.py $@ < $(BUILD_DIR)/controller.bin
@echo 'Size of controller modules:'
@$(SIZE) -B -t --common $(OBJS)
diff --git a/sw/riscv/build.sh b/sw/riscv/build.sh
index 1c0ceb8..024bdf7 100755
--- a/sw/riscv/build.sh
+++ b/sw/riscv/build.sh
@@ -1,3 +1,6 @@
#!/bin/bash
-docker run --mount type=bind,src="$(pwd)",target="/workdir" ghcr.io/polprzewodnikowy/sc64env:v1.0 /bin/bash -c "USER_FLAGS=\"-DDEBUG\" make clean all"
+docker run \
+ --mount type=bind,src="$(pwd)",target="/workdir" \
+ ghcr.io/polprzewodnikowy/sc64env:v1.0 \
+ /bin/bash -c "USER_FLAGS=\"-DDEBUG\" make clean all"
diff --git a/sw/riscv/src/cfg.c b/sw/riscv/src/cfg.c
index 3b405da..cc5d8d8 100644
--- a/sw/riscv/src/cfg.c
+++ b/sw/riscv/src/cfg.c
@@ -1,4 +1,5 @@
#include "cfg.h"
+#include "flash.h"
#include "joybus.h"
#include "usb.h"
@@ -26,6 +27,7 @@ enum cfg_id {
CFG_ID_SAVE_OFFEST,
CFG_ID_DD_OFFEST,
CFG_ID_SKIP_BOOTLOADER,
+ CFG_ID_FLASH_OPERATION,
};
enum save_type {
@@ -132,6 +134,9 @@ void cfg_update (uint32_t *args) {
case CFG_ID_SKIP_BOOTLOADER:
change_scr_bits(CFG_SCR_SKIP_BOOTLOADER, args[1]);
break;
+ case CFG_ID_FLASH_OPERATION:
+ flash_program(args[1]);
+ break;
}
}
@@ -167,6 +172,9 @@ void cfg_query (uint32_t *args) {
case CFG_ID_SKIP_BOOTLOADER:
args[1] = CFG->SCR & CFG_SCR_SKIP_BOOTLOADER;
break;
+ case CFG_ID_FLASH_OPERATION:
+ args[1] = flash_read(args[1]);
+ break;
}
}
diff --git a/sw/riscv/src/flash.c b/sw/riscv/src/flash.c
new file mode 100644
index 0000000..bdff2d8
--- /dev/null
+++ b/sw/riscv/src/flash.c
@@ -0,0 +1,60 @@
+#include "flash.h"
+
+
+uint32_t flash_read (uint32_t sdram_offset) {
+ io32_t *flash = (io32_t *) (FLASH_BASE);
+ io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset);
+
+ for (size_t i = 0; i < FLASH_SIZE; i += 4) {
+ *sdram++ = *flash++;
+ }
+
+ return FLASH_SIZE;
+}
+
+void flash_program (uint32_t sdram_offset) {
+ uint32_t cr;
+
+ io32_t *flash = (io32_t *) (FLASH_BASE);
+ io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset);
+
+ cr = FLASH_CONFIG->CR;
+ for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
+ cr &= ~(1 << (FLASH_CR_WRITE_PROTECT_BIT + sector));
+ }
+ FLASH_CONFIG->CR = cr;
+
+ while ((FLASH_CONFIG->SR & FLASH_SR_STATUS_MASK) != FLASH_SR_STATUS_IDLE);
+
+ for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
+ cr = FLASH_CONFIG->CR;
+ cr &= ~(FLASH_CR_SECTOR_ERASE_MASK);
+ cr |= ((sector + 1) << FLASH_CR_SECTOR_ERASE_BIT);
+ FLASH_CONFIG->CR = cr;
+
+ while ((FLASH_CONFIG->SR & FLASH_SR_STATUS_MASK) == FLASH_SR_STATUS_BUSY_ERASE);
+
+ if (!(FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL)) {
+ break;
+ }
+ }
+
+ if (FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL) {
+ for (size_t word = 0; word < FLASH_SIZE; word += 4) {
+ *flash++ = *sdram++;
+
+ if (!(FLASH_CONFIG->SR & FLASH_SR_WRITE_SUCCESSFUL)) {
+ break;
+ }
+ }
+ }
+
+ cr = FLASH_CONFIG->CR;
+ cr |= FLASH_CR_SECTOR_ERASE_MASK;
+ for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
+ cr |= (1 << (FLASH_CR_WRITE_PROTECT_BIT + sector));
+ }
+ FLASH_CONFIG->CR = cr;
+
+ return;
+}
diff --git a/sw/riscv/src/flash.h b/sw/riscv/src/flash.h
new file mode 100644
index 0000000..26916c5
--- /dev/null
+++ b/sw/riscv/src/flash.h
@@ -0,0 +1,12 @@
+#ifndef FLASH_H__
+#define FLASH_H__
+
+
+#include "sys.h"
+
+
+uint32_t flash_read (uint32_t sdram_offset);
+void flash_program (uint32_t sdram_offset);
+
+
+#endif
diff --git a/sw/riscv/src/handlers.c b/sw/riscv/src/handlers.c
index a5f2895..dfc69de 100644
--- a/sw/riscv/src/handlers.c
+++ b/sw/riscv/src/handlers.c
@@ -2,43 +2,18 @@
#include "sys.h"
-#define BOOT_UART
-
-
__attribute__ ((naked, section(".bootloader"))) void reset_handler (void) {
- register uint32_t length = 0;
+ io32_t *ram = (io32_t *) &RAM;
+ io32_t *flash = (io32_t *) (FLASH_BASE + FLASH_CPU_IMAGE_OFFSET);
-#if defined(BOOT_UART)
- volatile uint8_t *pointer = (volatile uint8_t *) &RAM;
- for (int i = 0; i < 4; i++) {
- while (!(UART->SCR & UART_SCR_RXNE));
- length |= (UART->DR << (i * 8));
+ for (int i = 0; i < RAM_SIZE; i += 4) {
+ *ram++ = *flash++;
}
-#elif defined(BOOT_N64)
- volatile uint32_t *pointer = (volatile uint32_t *) &RAM;
- while (!(CFG->SCR & CFG_SCR_CPU_BUSY));
- length = CFG->DATA[0];
- CFG->SCR &= ~(CFG_SCR_CPU_READY);
-#endif
- while (1) {
-#if defined(BOOT_UART)
- while (!(UART->SCR & UART_SCR_RXNE));
- *pointer++ = UART->DR;
- length = length - 1;
-#elif defined(BOOT_N64)
- while (!(CFG->SCR & CFG_SCR_CPU_BUSY));
- *pointer++ = CFG->DATA[0];
- CFG->SCR &= ~(CFG_SCR_CPU_READY);
- length = length - 4;
-#endif
- if (length == 0) {
- __asm__ volatile (
- "la t0, app_handler \n"
- "jalr zero, t0 \n"
- );
- }
- }
+ __asm__ volatile (
+ "la t0, app_handler \n"
+ "jalr zero, t0 \n"
+ );
}
diff --git a/sw/riscv/src/sys.h b/sw/riscv/src/sys.h
index 8fb9343..4d1e7e6 100644
--- a/sw/riscv/src/sys.h
+++ b/sw/riscv/src/sys.h
@@ -13,6 +13,7 @@ typedef volatile uint32_t io32_t;
#define RAM_BASE (0x00000000UL)
#define RAM (*((io32_t *) RAM_BASE))
+#define RAM_SIZE (16 * 1024)
#define BOOTLOADER_BASE (0x10000000UL)
@@ -153,6 +154,38 @@ typedef volatile struct joybus_regs {
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
+#define FLASH_BASE (0xB0000000UL)
+#define FLASH (*((io32_t *) FLASH_BASE))
+
+#define FLASH_CPU_IMAGE_OFFSET (0x35800)
+#define FLASH_SIZE (0x39800)
+#define FLASH_NUM_SECTORS (4)
+
+
+typedef volatile struct flash_config_regs {
+ io32_t SR;
+ io32_t CR;
+} flash_config_regs_t;
+
+#define FLASH_CONFIG_BASE (0xB8000000UL)
+#define FLASH_CONFIG ((flash_config_regs_t *) FLASH_CONFIG_BASE)
+
+#define FLASH_SR_STATUS_MASK (3 << 0)
+#define FLASH_SR_STATUS_IDLE (0)
+#define FLASH_SR_STATUS_BUSY_ERASE (1)
+#define FLASH_SR_STATUS_BUSY_WRITE (2)
+#define FLASH_SR_STATUS_BUSY_READ (3)
+#define FLASH_SR_READ_SUCCESSFUL (1 << 2)
+#define FLASH_SR_WRITE_SUCCESSFUL (1 << 3)
+#define FLASH_SR_ERASE_SUCCESSFUL (1 << 4)
+#define FLASH_SR_WRITE_PROTECT_BIT (5)
+
+#define FLASH_CR_PAGE_ERASE_BIT (0)
+#define FLASH_CR_SECTOR_ERASE_BIT (20)
+#define FLASH_CR_SECTOR_ERASE_MASK (7 << FLASH_CR_SECTOR_ERASE_BIT)
+#define FLASH_CR_WRITE_PROTECT_BIT (23)
+
+
void reset_handler (void);
void app_handler (void);
diff --git a/sw/riscv/src/uart.c b/sw/riscv/src/uart.c
index b33d00a..47c1b70 100644
--- a/sw/riscv/src/uart.c
+++ b/sw/riscv/src/uart.c
@@ -38,7 +38,7 @@ void uart_print_08hex (uint32_t number) {
void uart_init (void) {
#ifdef DEBUG
- uart_print("App ready!\n");
+ uart_print("App ready from flash!\n");
#endif
}
@@ -72,7 +72,8 @@ void process_uart (void) {
uart_print_02hex(((uint8_t *) (time))[i]);
uart_print(" ");
}
- uart_print("\r\n");
+ uart_print("\n");
+ break;
}
}
#endif
diff --git a/sw/riscv/src/usb.c b/sw/riscv/src/usb.c
index 4bf8f8d..49f1730 100644
--- a/sw/riscv/src/usb.c
+++ b/sw/riscv/src/usb.c
@@ -77,6 +77,7 @@ struct process {
uint32_t args[2];
bool error;
bool dma_in_progress;
+ bool queried;
bool debug_rx_busy;
uint32_t debug_rx_address;
@@ -173,6 +174,7 @@ void process_usb (void) {
p.counter = 0;
p.error = false;
p.dma_in_progress = false;
+ p.queried = false;
p.state = STATE_ARGS;
} else {
p.cmd = '!';
@@ -199,7 +201,10 @@ void process_usb (void) {
break;
case 'Q':
- cfg_query(p.args);
+ if (!p.queried) {
+ cfg_query(p.args);
+ p.queried = true;
+ }
if (tx_word(p.args[1])) {
p.state = STATE_RESPONSE;
}