From f546e5d17d6a1cc7dd49cdd0643a5c420cca0846 Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Fri, 7 Mar 2025 20:51:56 +0100 Subject: [PATCH] [SC64][SW] Implement FlashRAM timings emulation and add a fake variant of FlashRAM --- docs/04_config_options.md | 3 +- sw/bootloader/src/sc64.h | 3 +- sw/controller/src/cfg.c | 3 ++ sw/controller/src/cfg.h | 1 + sw/controller/src/flashram.c | 54 +++++++++++++++++++++++++++++------ sw/controller/src/sd.c | 2 -- sw/controller/src/timer.h | 1 + sw/controller/src/writeback.c | 4 +++ sw/deployer/src/main.rs | 2 ++ sw/deployer/src/sc64/mod.rs | 2 ++ sw/deployer/src/sc64/types.rs | 4 +++ 11 files changed, 67 insertions(+), 12 deletions(-) diff --git a/docs/04_config_options.md b/docs/04_config_options.md index 5254f24..3d84f03 100644 --- a/docs/04_config_options.md +++ b/docs/04_config_options.md @@ -133,9 +133,10 @@ type: *enum* | default: `0` - `4` - FlashRAM 1 Mib save is enabled - `5` - SRAM 768 kib save is enabled - `6` - SRAM 1 Mib save is enabled +- `7` - FakeFlashRAM 1 Mib save is enabled (write/erase timings are not emulated and erase before write is not required) Use this setting for selecting save type that will be emulated. Only one save type can be enabled. -Any successful write to this config will disable automatic save writeback to USB or SD card when previously enabled. +Any successful write to this config will disable automatic save writeback to the USB or SD card if previously enabled. --- diff --git a/sw/bootloader/src/sc64.h b/sw/bootloader/src/sc64.h index 1c684c6..4916f6e 100644 --- a/sw/bootloader/src/sc64.h +++ b/sw/bootloader/src/sc64.h @@ -104,7 +104,8 @@ typedef enum { SAVE_TYPE_SRAM = 3, SAVE_TYPE_FLASHRAM = 4, SAVE_TYPE_SRAM_BANKED = 5, - SAVE_TYPE_SRAM_1M = 6 + SAVE_TYPE_SRAM_1M = 6, + SAVE_TYPE_FLASHRAM_FAKE = 7, } sc64_save_type_t; typedef enum { diff --git a/sw/controller/src/cfg.c b/sw/controller/src/cfg.c index b3f5224..0f29eb1 100644 --- a/sw/controller/src/cfg.c +++ b/sw/controller/src/cfg.c @@ -278,6 +278,9 @@ static bool cfg_set_save_type (save_type_t save_type) { case SAVE_TYPE_SRAM_1M: cfg_change_scr_bits(CFG_SCR_SRAM_ENABLED, true); break; + case SAVE_TYPE_FLASHRAM_FAKE: + cfg_change_scr_bits(CFG_SCR_FLASHRAM_ENABLED, true); + break; default: save_type = SAVE_TYPE_NONE; break; diff --git a/sw/controller/src/cfg.h b/sw/controller/src/cfg.h index 0459fe3..e2c2ee7 100644 --- a/sw/controller/src/cfg.h +++ b/sw/controller/src/cfg.h @@ -14,6 +14,7 @@ typedef enum { SAVE_TYPE_FLASHRAM = 4, SAVE_TYPE_SRAM_BANKED = 5, SAVE_TYPE_SRAM_1M = 6, + SAVE_TYPE_FLASHRAM_FAKE = 7, __SAVE_TYPE_COUNT } save_type_t; diff --git a/sw/controller/src/flashram.c b/sw/controller/src/flashram.c index 4372528..0d92654 100644 --- a/sw/controller/src/flashram.c +++ b/sw/controller/src/flashram.c @@ -1,12 +1,18 @@ #include +#include "cfg.h" #include "fpga.h" +#include "hw.h" +#include "timer.h" -#define FLASHRAM_SIZE (128 * 1024) -#define FLASHRAM_SECTOR_SIZE (16 * 1024) -#define FLASHRAM_PAGE_SIZE (128) -#define FLASHRAM_ADDRESS (0x03FE0000UL) -#define FLASHRAM_BUFFER_ADDRESS (0x05002C00UL) +#define FLASHRAM_SIZE (128 * 1024) +#define FLASHRAM_SECTOR_SIZE (16 * 1024) +#define FLASHRAM_PAGE_SIZE (128) +#define FLASHRAM_ADDRESS (0x03FE0000UL) +#define FLASHRAM_BUFFER_ADDRESS (0x05002C00UL) + +#define FLASHRAM_WRITE_TIMING_MS (3) +#define FLASHRAM_ERASE_TIMING_MS (200) typedef enum { @@ -16,6 +22,13 @@ typedef enum { OP_WRITE_PAGE } flashram_op_t; +struct process { + bool pending; +}; + + +static struct process p; + static flashram_op_t flashram_operation_type (uint32_t scr) { if (!(scr & FLASHRAM_SCR_PENDING)) { @@ -38,6 +51,7 @@ void flashram_init (void) { if (fpga_reg_get(REG_FLASHRAM_SCR) & FLASHRAM_SCR_PENDING) { fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE); } + p.pending = false; } @@ -53,8 +67,15 @@ void flashram_process (void) { uint8_t write_buffer[FLASHRAM_PAGE_SIZE]; uint32_t page = ((scr & FLASHRAM_SCR_PAGE_MASK) >> FLASHRAM_SCR_PAGE_BIT); + const bool full_emulation = (cfg_get_save_type() != SAVE_TYPE_FLASHRAM_FAKE); - if (op == OP_WRITE_PAGE) { + if (p.pending) { + if (timer_countdown_elapsed(TIMER_ID_FLASHRAM)) { + p.pending = false; + } else { + return; + } + } else if (op == OP_WRITE_PAGE) { uint8_t page_buffer[FLASHRAM_PAGE_SIZE]; uint32_t address = (FLASHRAM_ADDRESS + (page * FLASHRAM_PAGE_SIZE)); @@ -63,11 +84,24 @@ void flashram_process (void) { fpga_mem_read(address, FLASHRAM_PAGE_SIZE, write_buffer); for (int i = 0; i < FLASHRAM_PAGE_SIZE; i++) { - write_buffer[i] &= page_buffer[i]; + if (full_emulation) { + write_buffer[i] &= page_buffer[i]; + } else { + write_buffer[i] = page_buffer[i]; + } } fpga_mem_write(address, FLASHRAM_PAGE_SIZE, write_buffer); - } else if ((op == OP_ERASE_SECTOR) || (op == OP_ERASE_ALL)) { + + if (full_emulation) { + hw_delay_ms(FLASHRAM_WRITE_TIMING_MS); + } + } else if ((op == OP_ERASE_SECTOR) || (op == OP_ERASE_ALL)) { + if (full_emulation) { + p.pending = true; + timer_countdown_start(TIMER_ID_FLASHRAM, FLASHRAM_ERASE_TIMING_MS); + } + for (int i = 0; i < FLASHRAM_PAGE_SIZE; i++) { write_buffer[i] = 0xFF; } @@ -80,6 +114,10 @@ void flashram_process (void) { for (uint32_t offset = 0; offset < erase_size; offset += FLASHRAM_PAGE_SIZE) { fpga_mem_write(address + offset, FLASHRAM_PAGE_SIZE, write_buffer); } + + if (full_emulation) { + return; + } } fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE); diff --git a/sw/controller/src/sd.c b/sw/controller/src/sd.c index 0d201fd..796f4cb 100644 --- a/sw/controller/src/sd.c +++ b/sw/controller/src/sd.c @@ -176,13 +176,11 @@ static bool sd_acmd (uint8_t acmd, uint32_t arg, rsp_type_t rsp_type, void *rsp) static void sd_dat_start_write (uint32_t count) { uint32_t dat = (((count - 1) << SD_DAT_BLOCKS_BIT) | SD_DAT_START_WRITE | SD_DAT_FIFO_FLUSH); fpga_reg_set(REG_SD_DAT, dat); - } static void sd_dat_start_read (uint32_t count) { uint32_t dat = (((count - 1) << SD_DAT_BLOCKS_BIT) | SD_DAT_START_READ | SD_DAT_FIFO_FLUSH); fpga_reg_set(REG_SD_DAT, dat); - } static dat_status_t sd_dat_status (void) { diff --git a/sw/controller/src/timer.h b/sw/controller/src/timer.h index 1adb086..00f2f86 100644 --- a/sw/controller/src/timer.h +++ b/sw/controller/src/timer.h @@ -13,6 +13,7 @@ typedef enum { TIMER_ID_SD, TIMER_ID_USB, TIMER_ID_WRITEBACK, + TIMER_ID_FLASHRAM, __TIMER_ID_COUNT } timer_id_t; diff --git a/sw/controller/src/writeback.c b/sw/controller/src/writeback.c index 6c943fc..96305a4 100644 --- a/sw/controller/src/writeback.c +++ b/sw/controller/src/writeback.c @@ -62,6 +62,10 @@ static save_type_t writeback_get_address_length (uint32_t *address, uint32_t *le *address = SRAM_FLASHRAM_ADDRESS; *length = SRAM_1M_LENGTH; break; + case SAVE_TYPE_FLASHRAM_FAKE: + *address = SRAM_FLASHRAM_ADDRESS; + *length = FLASHRAM_LENGTH; + break; default: *address = 0; *length = 0; diff --git a/sw/deployer/src/main.rs b/sw/deployer/src/main.rs index 7ed78e1..f679db6 100644 --- a/sw/deployer/src/main.rs +++ b/sw/deployer/src/main.rs @@ -330,6 +330,7 @@ enum SaveType { SramBanked, Sram1m, Flashram, + FlashramFake, } impl From for SaveType { @@ -356,6 +357,7 @@ impl From for sc64::SaveType { SaveType::SramBanked => Self::SramBanked, SaveType::Sram1m => Self::Sram1m, SaveType::Flashram => Self::Flashram, + SaveType::FlashramFake => Self::FlashramFake, } } } diff --git a/sw/deployer/src/sc64/mod.rs b/sw/deployer/src/sc64/mod.rs index e90dbd3..11189e0 100644 --- a/sw/deployer/src/sc64/mod.rs +++ b/sw/deployer/src/sc64/mod.rs @@ -445,6 +445,7 @@ impl SC64 { SaveType::Flashram => (SAVE_ADDRESS, FLASHRAM_LENGTH), SaveType::SramBanked => (SAVE_ADDRESS, SRAM_BANKED_LENGTH), SaveType::Sram1m => (SAVE_ADDRESS, SRAM_1M_LENGTH), + SaveType::FlashramFake => (SAVE_ADDRESS, FLASHRAM_LENGTH), }; if length != save_length { @@ -469,6 +470,7 @@ impl SC64 { SaveType::Flashram => (SAVE_ADDRESS, FLASHRAM_LENGTH), SaveType::SramBanked => (SAVE_ADDRESS, SRAM_BANKED_LENGTH), SaveType::Sram1m => (SAVE_ADDRESS, SRAM_1M_LENGTH), + SaveType::FlashramFake => (SAVE_ADDRESS, FLASHRAM_LENGTH), }; self.memory_read_chunked(writer, address, save_length) diff --git a/sw/deployer/src/sc64/types.rs b/sw/deployer/src/sc64/types.rs index 541e8de..a20ea8d 100644 --- a/sw/deployer/src/sc64/types.rs +++ b/sw/deployer/src/sc64/types.rs @@ -288,6 +288,7 @@ pub enum SaveType { Flashram, SramBanked, Sram1m, + FlashramFake, } impl Display for SaveType { @@ -300,6 +301,7 @@ impl Display for SaveType { Self::SramBanked => "SRAM 768k", Self::Flashram => "FlashRAM 1M", Self::Sram1m => "SRAM 1M", + Self::FlashramFake => "FakeFlashRAM 1M" }) } } @@ -315,6 +317,7 @@ impl TryFrom for SaveType { 4 => Self::Flashram, 5 => Self::SramBanked, 6 => Self::Sram1m, + 7 => Self::FlashramFake, _ => return Err(Error::new("Unknown save type code")), }) } @@ -330,6 +333,7 @@ impl From for u32 { SaveType::Flashram => 4, SaveType::SramBanked => 5, SaveType::Sram1m => 6, + SaveType::FlashramFake => 7, } } }