mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 07:06:52 +01:00
[SC64][FW][SW] Load CPU software directly from embedded flash in FPGA (#9)
This commit is contained in:
parent
c02494855e
commit
adff845460
10
build.sh
10
build.sh
@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
PACKAGE_FILE_NAME="SummerCart64"
|
PACKAGE_FILE_NAME="SummerCart64"
|
||||||
FILES=(
|
FILES=(
|
||||||
"./fw/output_files/SummerCart64.pof"
|
"./fw/output_files/SC64_update.bin"
|
||||||
"./hw/v1/ftdi-template.xml"
|
"./fw/output_files/SC64_update.pof"
|
||||||
|
"./hw/ftdi-template.xml"
|
||||||
"./sw/cic/UltraCIC-III.hex"
|
"./sw/cic/UltraCIC-III.hex"
|
||||||
"./sw/riscv/build/controller.rom"
|
|
||||||
"./LICENSE"
|
"./LICENSE"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,6 +35,10 @@ popd
|
|||||||
pushd fw
|
pushd fw
|
||||||
echo "Building FPGA firmware"
|
echo "Building FPGA firmware"
|
||||||
quartus_sh --flow compile ./SummerCart64.qpf
|
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
|
popd
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/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"
|
||||||
|
42
fw/SummerCart64.cof
Normal file
42
fw/SummerCart64.cof
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="US-ASCII" standalone="yes"?>
|
||||||
|
<cof>
|
||||||
|
<output_filename>output_files/SC64_firmware.pof</output_filename>
|
||||||
|
<n_pages>1</n_pages>
|
||||||
|
<width>1</width>
|
||||||
|
<mode>14</mode>
|
||||||
|
<sof_data>
|
||||||
|
<user_name>Page_0</user_name>
|
||||||
|
<page_flags>1</page_flags>
|
||||||
|
<bit0>
|
||||||
|
<sof_filename>output_files/SummerCart64.sof<compress_bitstream>1</compress_bitstream></sof_filename>
|
||||||
|
</bit0>
|
||||||
|
</sof_data>
|
||||||
|
<version>10</version>
|
||||||
|
<create_cvp_file>0</create_cvp_file>
|
||||||
|
<create_hps_iocsr>0</create_hps_iocsr>
|
||||||
|
<auto_create_rpd>1</auto_create_rpd>
|
||||||
|
<rpd_little_endian>0</rpd_little_endian>
|
||||||
|
<options>
|
||||||
|
<map_file>1</map_file>
|
||||||
|
</options>
|
||||||
|
<MAX10_device_options>
|
||||||
|
<por>0</por>
|
||||||
|
<io_pullup>1</io_pullup>
|
||||||
|
<config_from_cfm0_only>0</config_from_cfm0_only>
|
||||||
|
<isp_source>0</isp_source>
|
||||||
|
<verify_protect>0</verify_protect>
|
||||||
|
<epof>0</epof>
|
||||||
|
<ufm_source>2</ufm_source>
|
||||||
|
<ufm_filepath>../sw/n64/build/SummerLoader64.hex</ufm_filepath>
|
||||||
|
<cfm0_filepath>../sw/riscv/build/controller.hex</cfm0_filepath>
|
||||||
|
<cfm0_file_start_addr>305152</cfm0_file_start_addr>
|
||||||
|
</MAX10_device_options>
|
||||||
|
<advanced_options>
|
||||||
|
<ignore_epcs_id_check>1</ignore_epcs_id_check>
|
||||||
|
<ignore_condone_check>2</ignore_condone_check>
|
||||||
|
<plc_adjustment>0</plc_adjustment>
|
||||||
|
<post_chain_bitstream_pad_bytes>-1</post_chain_bitstream_pad_bytes>
|
||||||
|
<post_device_bitstream_pad_bytes>-1</post_device_bitstream_pad_bytes>
|
||||||
|
<bitslice_pre_padding>1</bitslice_pre_padding>
|
||||||
|
</advanced_options>
|
||||||
|
</cof>
|
@ -19,7 +19,7 @@
|
|||||||
#
|
#
|
||||||
# Quartus Prime
|
# Quartus Prime
|
||||||
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
|
# 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_bus.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.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_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_flashram.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.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_uart.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.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/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/memory/memory_sdram.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.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/system/system.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/usb/usb_ft1248.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 SIGNALTAP_FILE output_files/signaltap.stp
|
||||||
set_global_assignment -name SLD_FILE db/signaltap_auto_stripped.stp
|
|
||||||
|
|
||||||
# Pin & Location Assignments
|
# Pin & Location Assignments
|
||||||
# ==========================
|
# ==========================
|
||||||
@ -225,7 +224,6 @@ set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
|
|||||||
# Signal Tap Assignments
|
# Signal Tap Assignments
|
||||||
# ======================
|
# ======================
|
||||||
set_global_assignment -name ENABLE_SIGNALTAP ON
|
set_global_assignment -name ENABLE_SIGNALTAP ON
|
||||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/signaltap.stp
|
|
||||||
|
|
||||||
# Power Estimation Assignments
|
# 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_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_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
||||||
set_global_assignment -name PARTITION_COLOR 16764057 -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)
|
# end DESIGN_PARTITION(Top)
|
||||||
# -------------------------
|
# -------------------------
|
||||||
|
12
fw/build.sh
12
fw/build.sh
@ -1,3 +1,13 @@
|
|||||||
#!/bin/bash
|
#!/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
|
||||||
|
"
|
||||||
|
@ -64,6 +64,8 @@ module SummerCart64 (
|
|||||||
|
|
||||||
if_si si ();
|
if_si si ();
|
||||||
|
|
||||||
|
if_flash flash ();
|
||||||
|
|
||||||
system system_inst (
|
system system_inst (
|
||||||
.sys(sys)
|
.sys(sys)
|
||||||
);
|
);
|
||||||
@ -81,6 +83,7 @@ module SummerCart64 (
|
|||||||
.sdram(sdram),
|
.sdram(sdram),
|
||||||
.flashram(flashram),
|
.flashram(flashram),
|
||||||
.si(si),
|
.si(si),
|
||||||
|
.flash(flash),
|
||||||
|
|
||||||
.n64_pi_alel(i_n64_pi_alel),
|
.n64_pi_alel(i_n64_pi_alel),
|
||||||
.n64_pi_aleh(i_n64_pi_aleh),
|
.n64_pi_aleh(i_n64_pi_aleh),
|
||||||
@ -107,6 +110,7 @@ module SummerCart64 (
|
|||||||
.sdram(sdram),
|
.sdram(sdram),
|
||||||
.flashram(flashram),
|
.flashram(flashram),
|
||||||
.si(si),
|
.si(si),
|
||||||
|
.flash(flash),
|
||||||
|
|
||||||
.gpio_o(gpio_o),
|
.gpio_o(gpio_o),
|
||||||
.gpio_i(gpio_i),
|
.gpio_i(gpio_i),
|
||||||
|
@ -30,7 +30,7 @@ module cpu_cfg (
|
|||||||
R_SCR: bus.rdata = {
|
R_SCR: bus.rdata = {
|
||||||
cfg.cpu_ready,
|
cfg.cpu_ready,
|
||||||
cfg.cpu_busy,
|
cfg.cpu_busy,
|
||||||
cfg.usb_waiting,
|
1'b0,
|
||||||
cfg.cmd_error,
|
cfg.cmd_error,
|
||||||
21'd0,
|
21'd0,
|
||||||
skip_bootloader,
|
skip_bootloader,
|
||||||
@ -65,7 +65,6 @@ module cpu_cfg (
|
|||||||
if (sys.reset) begin
|
if (sys.reset) begin
|
||||||
cfg.cpu_ready <= 1'b0;
|
cfg.cpu_ready <= 1'b0;
|
||||||
cfg.cpu_busy <= 1'b0;
|
cfg.cpu_busy <= 1'b0;
|
||||||
cfg.usb_waiting <= 1'b0;
|
|
||||||
cfg.cmd_error <= 1'b0;
|
cfg.cmd_error <= 1'b0;
|
||||||
cfg.sdram_switch <= 1'b0;
|
cfg.sdram_switch <= 1'b0;
|
||||||
cfg.sdram_writable <= 1'b0;
|
cfg.sdram_writable <= 1'b0;
|
||||||
@ -91,9 +90,8 @@ module cpu_cfg (
|
|||||||
{
|
{
|
||||||
cfg.cpu_ready,
|
cfg.cpu_ready,
|
||||||
cfg.cpu_busy,
|
cfg.cpu_busy,
|
||||||
cfg.usb_waiting,
|
|
||||||
cfg.cmd_error
|
cfg.cmd_error
|
||||||
} <= bus.wdata[31:28];
|
} <= {bus.wdata[31:30], bus.wdata[28]};
|
||||||
end
|
end
|
||||||
if (bus.wmask[0]) begin
|
if (bus.wmask[0]) begin
|
||||||
{
|
{
|
||||||
|
61
fw/rtl/cpu/cpu_flash.sv
Normal file
61
fw/rtl/cpu/cpu_flash.sv
Normal file
@ -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
|
@ -5,6 +5,7 @@ module cpu_soc (
|
|||||||
if_sdram.cpu sdram,
|
if_sdram.cpu sdram,
|
||||||
if_flashram.cpu flashram,
|
if_flashram.cpu flashram,
|
||||||
if_si.cpu si,
|
if_si.cpu si,
|
||||||
|
if_flash.cpu flash,
|
||||||
|
|
||||||
input [7:0] gpio_i,
|
input [7:0] gpio_i,
|
||||||
output [7:0] gpio_o,
|
output [7:0] gpio_o,
|
||||||
@ -111,4 +112,10 @@ module cpu_soc (
|
|||||||
.si(si)
|
.si(si)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cpu_flash cpu_flash_inst (
|
||||||
|
.sys(sys),
|
||||||
|
.bus(bus.at[sc64::ID_CPU_FLASH].device),
|
||||||
|
.flash(flash)
|
||||||
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -41,10 +41,18 @@
|
|||||||
<interface name="clk" internal="onchip_flash_0.clk" type="clock" dir="end">
|
<interface name="clk" internal="onchip_flash_0.clk" type="clock" dir="end">
|
||||||
<port name="clock" internal="clock" />
|
<port name="clock" internal="clock" />
|
||||||
</interface>
|
</interface>
|
||||||
<interface name="csr" internal="onchip_flash_0.csr" />
|
<interface name="csr" internal="onchip_flash_0.csr" type="avalon" dir="end">
|
||||||
|
<port name="avmm_csr_addr" internal="avmm_csr_addr" />
|
||||||
|
<port name="avmm_csr_read" internal="avmm_csr_read" />
|
||||||
|
<port name="avmm_csr_writedata" internal="avmm_csr_writedata" />
|
||||||
|
<port name="avmm_csr_write" internal="avmm_csr_write" />
|
||||||
|
<port name="avmm_csr_readdata" internal="avmm_csr_readdata" />
|
||||||
|
</interface>
|
||||||
<interface name="data" internal="onchip_flash_0.data" type="avalon" dir="end">
|
<interface name="data" internal="onchip_flash_0.data" type="avalon" dir="end">
|
||||||
<port name="avmm_data_addr" internal="avmm_data_addr" />
|
<port name="avmm_data_addr" internal="avmm_data_addr" />
|
||||||
<port name="avmm_data_read" internal="avmm_data_read" />
|
<port name="avmm_data_read" internal="avmm_data_read" />
|
||||||
|
<port name="avmm_data_writedata" internal="avmm_data_writedata" />
|
||||||
|
<port name="avmm_data_write" internal="avmm_data_write" />
|
||||||
<port name="avmm_data_readdata" internal="avmm_data_readdata" />
|
<port name="avmm_data_readdata" internal="avmm_data_readdata" />
|
||||||
<port name="avmm_data_waitrequest" internal="avmm_data_waitrequest" />
|
<port name="avmm_data_waitrequest" internal="avmm_data_waitrequest" />
|
||||||
<port name="avmm_data_readdatavalid" internal="avmm_data_readdatavalid" />
|
<port name="avmm_data_readdatavalid" internal="avmm_data_readdatavalid" />
|
||||||
@ -68,7 +76,7 @@
|
|||||||
<parameter name="PART_NAME" value="10M08SCE144C8G" />
|
<parameter name="PART_NAME" value="10M08SCE144C8G" />
|
||||||
<parameter name="READ_BURST_COUNT" value="2" />
|
<parameter name="READ_BURST_COUNT" value="2" />
|
||||||
<parameter name="READ_BURST_MODE" value="Incrementing" />
|
<parameter name="READ_BURST_MODE" value="Incrementing" />
|
||||||
<parameter name="SECTOR_ACCESS_MODE">Read only,Read only,Hidden,Read only,Read only</parameter>
|
<parameter name="SECTOR_ACCESS_MODE">Read and write,Read and write,Hidden,Read and write,Read and write</parameter>
|
||||||
<parameter name="autoInitializationFileName">$${FILENAME}_onchip_flash_0</parameter>
|
<parameter name="autoInitializationFileName">$${FILENAME}_onchip_flash_0</parameter>
|
||||||
<parameter name="initFlashContent" value="true" />
|
<parameter name="initFlashContent" value="true" />
|
||||||
<parameter name="initializationFileName">../sw/n64/build/SummerLoader64.hex</parameter>
|
<parameter name="initializationFileName">../sw/n64/build/SummerLoader64.hex</parameter>
|
||||||
|
@ -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
|
|
@ -1,14 +1,124 @@
|
|||||||
module n64_bootloader (
|
module n64_bootloader (
|
||||||
if_system.sys sys,
|
if_system.sys sys,
|
||||||
if_n64_bus bus
|
if_n64_bus bus,
|
||||||
|
if_flash.memory flash
|
||||||
);
|
);
|
||||||
|
|
||||||
memory_flash memory_flash_inst (
|
logic mem_request;
|
||||||
.sys(sys),
|
logic csr_ack;
|
||||||
.request(bus.request),
|
logic data_ack;
|
||||||
.ack(bus.ack),
|
logic write_ack;
|
||||||
.address(bus.address),
|
logic data_busy;
|
||||||
.rdata(bus.rdata)
|
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
|
endmodule
|
||||||
|
@ -29,7 +29,7 @@ module n64_cfg (
|
|||||||
R_SR: bus.rdata = {
|
R_SR: bus.rdata = {
|
||||||
cfg.cpu_ready,
|
cfg.cpu_ready,
|
||||||
cfg.cpu_busy,
|
cfg.cpu_busy,
|
||||||
cfg.usb_waiting,
|
1'b0,
|
||||||
cfg.cmd_error,
|
cfg.cmd_error,
|
||||||
12'd0
|
12'd0
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@ module n64_soc (
|
|||||||
if_sdram.memory sdram,
|
if_sdram.memory sdram,
|
||||||
if_flashram.flashram flashram,
|
if_flashram.flashram flashram,
|
||||||
if_si.si si,
|
if_si.si si,
|
||||||
|
if_flash.memory flash,
|
||||||
|
|
||||||
input n64_pi_alel,
|
input n64_pi_alel,
|
||||||
input n64_pi_aleh,
|
input n64_pi_aleh,
|
||||||
@ -63,7 +64,8 @@ module n64_soc (
|
|||||||
|
|
||||||
n64_bootloader n64_bootloader_inst (
|
n64_bootloader n64_bootloader_inst (
|
||||||
.sys(sys),
|
.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 (
|
n64_flashram n64_flashram_inst (
|
||||||
|
@ -2,7 +2,6 @@ interface if_config ();
|
|||||||
|
|
||||||
logic cpu_ready;
|
logic cpu_ready;
|
||||||
logic cpu_busy;
|
logic cpu_busy;
|
||||||
logic usb_waiting;
|
|
||||||
logic cmd_error;
|
logic cmd_error;
|
||||||
logic cmd_request;
|
logic cmd_request;
|
||||||
logic [7:0] cmd;
|
logic [7:0] cmd;
|
||||||
@ -38,7 +37,6 @@ interface if_config ();
|
|||||||
modport n64 (
|
modport n64 (
|
||||||
input cpu_ready,
|
input cpu_ready,
|
||||||
input cpu_busy,
|
input cpu_busy,
|
||||||
input usb_waiting,
|
|
||||||
input cmd_error,
|
input cmd_error,
|
||||||
output cmd_request,
|
output cmd_request,
|
||||||
output cmd,
|
output cmd,
|
||||||
@ -50,7 +48,6 @@ interface if_config ();
|
|||||||
modport cpu (
|
modport cpu (
|
||||||
output cpu_ready,
|
output cpu_ready,
|
||||||
output cpu_busy,
|
output cpu_busy,
|
||||||
output usb_waiting,
|
|
||||||
output cmd_error,
|
output cmd_error,
|
||||||
input cmd_request,
|
input cmd_request,
|
||||||
input cmd,
|
input cmd,
|
||||||
|
@ -21,6 +21,7 @@ package sc64;
|
|||||||
ID_CPU_SDRAM,
|
ID_CPU_SDRAM,
|
||||||
ID_CPU_FLASHRAM,
|
ID_CPU_FLASHRAM,
|
||||||
ID_CPU_SI,
|
ID_CPU_SI,
|
||||||
|
ID_CPU_FLASH,
|
||||||
__ID_CPU_END
|
__ID_CPU_END
|
||||||
} e_cpu_id;
|
} e_cpu_id;
|
||||||
|
|
||||||
|
2
sw/n64/.gitignore
vendored
2
sw/n64/.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
/build
|
/build
|
||||||
/what
|
*.z64
|
||||||
|
@ -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
|
BUILD_DIR = build
|
||||||
|
SOURCE_DIR = src
|
||||||
|
PROGRAM_NAME = SummerLoader64
|
||||||
|
|
||||||
SRC_DIRS = $(SOURCE_DIR) $(sort $(dir $(wildcard $(SOURCE_DIR)/*/.)))
|
include $(N64_INST)/include/n64.mk
|
||||||
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)))
|
|
||||||
|
|
||||||
VPATH = $(SRC_DIRS)
|
src = main.c sc64.c boot.c crc32.c
|
||||||
|
|
||||||
COMMONFLAGS = -march=vr4300 -mtune=vr4300
|
all: $(BUILD_DIR)/$(PROGRAM_NAME).hex
|
||||||
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: 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
|
$(BUILD_DIR)/$(PROGRAM_NAME).hex: $(PROGRAM_NAME).z64
|
||||||
$(OBJCOPY) $(BUILD_DIR)/$(PROG_NAME).elf $(BUILD_DIR)/$(PROG_NAME).bin -O binary
|
sed '$$ s/\x00*$$//' $(PROGRAM_NAME).z64 > $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64
|
||||||
$(OBJDUMP) -S $(BUILD_DIR)/$(PROG_NAME).elf > $(BUILD_DIR)/$(PROG_NAME).lst
|
@if [ $$(stat -L -c %s $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64) -gt 92160 ]; then\
|
||||||
$(N64TOOL) $(N64_FLAGS) -t $(PROG_NAME) $(BUILD_DIR)/$(PROG_NAME).bin
|
echo "\n Error: stripped file size is larger than 90kB thus cannot fit inside FPGA flash.\n"; exit 1;\
|
||||||
$(CHKSUM64) $(BUILD_DIR)/$(PROG_NAME).z64
|
fi
|
||||||
truncate --size=90k $(BUILD_DIR)/$(PROG_NAME).z64
|
truncate --size=90k $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64
|
||||||
$(OBJCOPY) $(BUILD_DIR)/$(PROG_NAME).z64 $(BUILD_DIR)/$(PROG_NAME).hex -I binary -O ihex
|
$(N64_OBJCOPY) -I binary -O ihex $(BUILD_DIR)/$(PROGRAM_NAME)_stripped.z64 $(BUILD_DIR)/$(PROGRAM_NAME).hex
|
||||||
|
|
||||||
$(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)
|
|
||||||
|
|
||||||
clean:
|
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
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/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"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "sc64.h"
|
#include "sc64.h"
|
||||||
#include "boot/boot.h"
|
#include "boot.h"
|
||||||
|
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
|
@ -29,6 +29,7 @@ $(BUILD_DIR)/uc.elf: $(OBJS) SC64.ld
|
|||||||
$(BUILD_DIR)/controller.rom: $(BUILD_DIR)/uc.elf
|
$(BUILD_DIR)/controller.rom: $(BUILD_DIR)/uc.elf
|
||||||
$(OBJCOPY) -R .bootloader $(BUILD_DIR)/uc.elf $(BUILD_DIR)/controller.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) -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
|
python3 tools/bin2rom.py $@ < $(BUILD_DIR)/controller.bin
|
||||||
@echo 'Size of controller modules:'
|
@echo 'Size of controller modules:'
|
||||||
@$(SIZE) -B -t --common $(OBJS)
|
@$(SIZE) -B -t --common $(OBJS)
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/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"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
|
#include "flash.h"
|
||||||
#include "joybus.h"
|
#include "joybus.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ enum cfg_id {
|
|||||||
CFG_ID_SAVE_OFFEST,
|
CFG_ID_SAVE_OFFEST,
|
||||||
CFG_ID_DD_OFFEST,
|
CFG_ID_DD_OFFEST,
|
||||||
CFG_ID_SKIP_BOOTLOADER,
|
CFG_ID_SKIP_BOOTLOADER,
|
||||||
|
CFG_ID_FLASH_OPERATION,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum save_type {
|
enum save_type {
|
||||||
@ -132,6 +134,9 @@ void cfg_update (uint32_t *args) {
|
|||||||
case CFG_ID_SKIP_BOOTLOADER:
|
case CFG_ID_SKIP_BOOTLOADER:
|
||||||
change_scr_bits(CFG_SCR_SKIP_BOOTLOADER, args[1]);
|
change_scr_bits(CFG_SCR_SKIP_BOOTLOADER, args[1]);
|
||||||
break;
|
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:
|
case CFG_ID_SKIP_BOOTLOADER:
|
||||||
args[1] = CFG->SCR & CFG_SCR_SKIP_BOOTLOADER;
|
args[1] = CFG->SCR & CFG_SCR_SKIP_BOOTLOADER;
|
||||||
break;
|
break;
|
||||||
|
case CFG_ID_FLASH_OPERATION:
|
||||||
|
args[1] = flash_read(args[1]);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
60
sw/riscv/src/flash.c
Normal file
60
sw/riscv/src/flash.c
Normal file
@ -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;
|
||||||
|
}
|
12
sw/riscv/src/flash.h
Normal file
12
sw/riscv/src/flash.h
Normal file
@ -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
|
@ -2,43 +2,18 @@
|
|||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
|
||||||
|
|
||||||
#define BOOT_UART
|
|
||||||
|
|
||||||
|
|
||||||
__attribute__ ((naked, section(".bootloader"))) void reset_handler (void) {
|
__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)
|
for (int i = 0; i < RAM_SIZE; i += 4) {
|
||||||
volatile uint8_t *pointer = (volatile uint8_t *) &RAM;
|
*ram++ = *flash++;
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
while (!(UART->SCR & UART_SCR_RXNE));
|
|
||||||
length |= (UART->DR << (i * 8));
|
|
||||||
}
|
}
|
||||||
#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 (
|
__asm__ volatile (
|
||||||
"la t0, app_handler \n"
|
"la t0, app_handler \n"
|
||||||
"jalr zero, t0 \n"
|
"jalr zero, t0 \n"
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ typedef volatile uint32_t io32_t;
|
|||||||
|
|
||||||
#define RAM_BASE (0x00000000UL)
|
#define RAM_BASE (0x00000000UL)
|
||||||
#define RAM (*((io32_t *) RAM_BASE))
|
#define RAM (*((io32_t *) RAM_BASE))
|
||||||
|
#define RAM_SIZE (16 * 1024)
|
||||||
|
|
||||||
|
|
||||||
#define BOOTLOADER_BASE (0x10000000UL)
|
#define BOOTLOADER_BASE (0x10000000UL)
|
||||||
@ -153,6 +154,38 @@ typedef volatile struct joybus_regs {
|
|||||||
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
|
#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 reset_handler (void);
|
||||||
void app_handler (void);
|
void app_handler (void);
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ void uart_print_08hex (uint32_t number) {
|
|||||||
|
|
||||||
void uart_init (void) {
|
void uart_init (void) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
uart_print("App ready!\n");
|
uart_print("App ready from flash!\n");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,8 @@ void process_uart (void) {
|
|||||||
uart_print_02hex(((uint8_t *) (time))[i]);
|
uart_print_02hex(((uint8_t *) (time))[i]);
|
||||||
uart_print(" ");
|
uart_print(" ");
|
||||||
}
|
}
|
||||||
uart_print("\r\n");
|
uart_print("\n");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -77,6 +77,7 @@ struct process {
|
|||||||
uint32_t args[2];
|
uint32_t args[2];
|
||||||
bool error;
|
bool error;
|
||||||
bool dma_in_progress;
|
bool dma_in_progress;
|
||||||
|
bool queried;
|
||||||
|
|
||||||
bool debug_rx_busy;
|
bool debug_rx_busy;
|
||||||
uint32_t debug_rx_address;
|
uint32_t debug_rx_address;
|
||||||
@ -173,6 +174,7 @@ void process_usb (void) {
|
|||||||
p.counter = 0;
|
p.counter = 0;
|
||||||
p.error = false;
|
p.error = false;
|
||||||
p.dma_in_progress = false;
|
p.dma_in_progress = false;
|
||||||
|
p.queried = false;
|
||||||
p.state = STATE_ARGS;
|
p.state = STATE_ARGS;
|
||||||
} else {
|
} else {
|
||||||
p.cmd = '!';
|
p.cmd = '!';
|
||||||
@ -199,7 +201,10 @@ void process_usb (void) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'Q':
|
case 'Q':
|
||||||
|
if (!p.queried) {
|
||||||
cfg_query(p.args);
|
cfg_query(p.args);
|
||||||
|
p.queried = true;
|
||||||
|
}
|
||||||
if (tx_word(p.args[1])) {
|
if (tx_word(p.args[1])) {
|
||||||
p.state = STATE_RESPONSE;
|
p.state = STATE_RESPONSE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user