From c4036a65cf3532cac77c264f4b2b3b57d961b931 Mon Sep 17 00:00:00 2001 From: Polprzewodnikowy Date: Tue, 26 Oct 2021 22:44:49 +0200 Subject: [PATCH] flashing works --- fw/SummerCart64.qsf | 3 +- fw/rtl/n64/n64_bootloader.sv | 9 ++++-- sw/riscv/src/cfg.c | 8 +++++ sw/riscv/src/flash.c | 60 ++++++++++++++++++++++++++++++++++++ sw/riscv/src/flash.h | 12 ++++++++ sw/riscv/src/handlers.c | 2 +- sw/riscv/src/sys.h | 27 +++++++++++++--- sw/riscv/src/usb.c | 7 ++++- 8 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 sw/riscv/src/flash.c create mode 100644 sw/riscv/src/flash.h diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index 8f8edbf..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 = 00:50:07 October 26, 2021 +# Date created = 22:44:04 October 26, 2021 # # -------------------------------------------------------------------------- # # @@ -303,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/rtl/n64/n64_bootloader.sv b/fw/rtl/n64/n64_bootloader.sv index 8773928..0f5942e 100644 --- a/fw/rtl/n64/n64_bootloader.sv +++ b/fw/rtl/n64/n64_bootloader.sv @@ -7,6 +7,7 @@ module n64_bootloader ( logic mem_request; logic csr_ack; logic data_ack; + logic write_ack; logic data_busy; logic mem_write; logic [31:0] mem_address; @@ -29,6 +30,7 @@ module n64_bootloader ( always_ff @(posedge sys.clk) begin csr_ack <= 1'b0; + write_ack <= 1'b0; if (sys.reset) begin state <= S_IDLE; @@ -61,7 +63,10 @@ module n64_bootloader ( if ((!mem_address[27] || source_request == T_N64) && !data_busy) begin mem_request <= 1'b0; end - if (csr_ack || data_ack) begin + 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 @@ -89,7 +94,7 @@ module n64_bootloader ( else bus.rdata = {data_rdata[7:0], data_rdata[15:8]}; end - flash.ack = source_request == T_CPU && (csr_ack || data_ack); + 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; 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 9a757f0..dfc69de 100644 --- a/sw/riscv/src/handlers.c +++ b/sw/riscv/src/handlers.c @@ -4,7 +4,7 @@ __attribute__ ((naked, section(".bootloader"))) void reset_handler (void) { io32_t *ram = (io32_t *) &RAM; - io32_t *flash = (io32_t *) (FLASH_BASE + FLASH_IMAGE_OFFSET); + io32_t *flash = (io32_t *) (FLASH_BASE + FLASH_CPU_IMAGE_OFFSET); for (int i = 0; i < RAM_SIZE; i += 4) { *ram++ = *flash++; diff --git a/sw/riscv/src/sys.h b/sw/riscv/src/sys.h index 87c356e..4d1e7e6 100644 --- a/sw/riscv/src/sys.h +++ b/sw/riscv/src/sys.h @@ -157,16 +157,33 @@ typedef volatile struct joybus_regs { #define FLASH_BASE (0xB0000000UL) #define FLASH (*((io32_t *) FLASH_BASE)) -#define FLASH_IMAGE_OFFSET (0x35800) +#define FLASH_CPU_IMAGE_OFFSET (0x35800) +#define FLASH_SIZE (0x39800) +#define FLASH_NUM_SECTORS (4) -typedef volatile struct flash_regs { +typedef volatile struct flash_config_regs { io32_t SR; io32_t CR; -} flash_regs_t; +} flash_config_regs_t; -#define FLASH_SCR_BASE (0xB8000000UL) -#define FLASH_SCR ((flash_regs_t *) FLASH_SCR_BASE) +#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); 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; }