[SC64][SW] Save writeback SD card optimizations

This commit is contained in:
Mateusz Faderewski 2023-01-04 23:18:55 +01:00
parent 908fc04ebb
commit 170bf28553
6 changed files with 95 additions and 57 deletions

View File

@ -42,15 +42,6 @@ typedef enum {
BOOT_MODE_DIRECT = 3 BOOT_MODE_DIRECT = 3
} boot_mode_t; } boot_mode_t;
typedef enum {
SAVE_TYPE_NONE = 0,
SAVE_TYPE_EEPROM_4K = 1,
SAVE_TYPE_EEPROM_16K = 2,
SAVE_TYPE_SRAM = 3,
SAVE_TYPE_FLASHRAM = 4,
SAVE_TYPE_SRAM_BANKED = 5
} save_type_t;
typedef enum { typedef enum {
CIC_SEED_UNKNOWN = 0xFFFF CIC_SEED_UNKNOWN = 0xFFFF
} cic_seed_t; } cic_seed_t;
@ -359,6 +350,10 @@ bool cfg_update (uint32_t *args) {
return false; return false;
} }
save_type_t cfg_get_save_type (void) {
return p.save_type;
}
void cfg_get_time (uint32_t *args) { void cfg_get_time (uint32_t *args) {
rtc_time_t t; rtc_time_t t;
rtc_get_time(&t); rtc_get_time(&t);

View File

@ -6,9 +6,20 @@
#include <stdint.h> #include <stdint.h>
typedef enum {
SAVE_TYPE_NONE = 0,
SAVE_TYPE_EEPROM_4K = 1,
SAVE_TYPE_EEPROM_16K = 2,
SAVE_TYPE_SRAM = 3,
SAVE_TYPE_FLASHRAM = 4,
SAVE_TYPE_SRAM_BANKED = 5
} save_type_t;
uint32_t cfg_get_version (void); uint32_t cfg_get_version (void);
bool cfg_query (uint32_t *args); bool cfg_query (uint32_t *args);
bool cfg_update (uint32_t *args); bool cfg_update (uint32_t *args);
save_type_t cfg_get_save_type (void);
void cfg_get_time (uint32_t *args); void cfg_get_time (uint32_t *args);
void cfg_set_time (uint32_t *args); void cfg_set_time (uint32_t *args);
void cfg_reset_state (void); void cfg_reset_state (void);

View File

@ -125,41 +125,14 @@ static uint32_t dd_fill_sd_sector_table (uint32_t index, uint32_t *sector_table)
return sectors; return sectors;
} }
static void dd_process_sd_request (uint16_t index, uint32_t buffer_address, bool write) {
uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE];
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table);
dd_set_block_ready(false);
if (sectors == 0) {
return;
}
uint32_t starting_sector = 0;
uint32_t sectors_to_process = 0;
for (uint32_t i = 0; i < sectors; i++) {
sectors_to_process += 1;
if ((i < (sectors - 1)) && ((sector_table[i] + 1) == sector_table[i + 1])) {
continue;
}
if (write) {
if (sd_write_sectors(buffer_address, sector_table[starting_sector], sectors_to_process)) {
return;
}
} else {
if (sd_read_sectors(buffer_address, sector_table[starting_sector], sectors_to_process)) {
return;
}
}
buffer_address += (sectors_to_process * SD_SECTOR_SIZE);
starting_sector += sectors_to_process;
sectors_to_process = 0;
}
dd_set_block_ready(true);
}
static bool dd_block_read_request (void) { static bool dd_block_read_request (void) {
uint16_t index = dd_track_head_block(); uint16_t index = dd_track_head_block();
uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS; uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS;
if (p.sd_mode) { if (p.sd_mode) {
dd_process_sd_request(index, buffer_address, false); uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE];
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table);
bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_read_sectors);
dd_set_block_ready(!error);
} else { } else {
usb_tx_info_t packet_info; usb_tx_info_t packet_info;
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST); usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);
@ -178,7 +151,10 @@ static bool dd_block_write_request (void) {
uint32_t index = dd_track_head_block(); uint32_t index = dd_track_head_block();
uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS; uint32_t buffer_address = DD_BLOCK_BUFFER_ADDRESS;
if (p.sd_mode) { if (p.sd_mode) {
dd_process_sd_request(index, buffer_address, true); uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE];
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table);
bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_write_sectors);
dd_set_block_ready(!error);
} else { } else {
usb_tx_info_t packet_info; usb_tx_info_t packet_info;
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST); usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);

View File

@ -197,6 +197,7 @@ static bool sd_dat_wait (uint16_t timeout) {
do { do {
uint32_t sd_dat = fpga_reg_get(REG_SD_DAT); uint32_t sd_dat = fpga_reg_get(REG_SD_DAT);
uint32_t sd_dma_scr = fpga_reg_get(REG_SD_DMA_SCR); uint32_t sd_dma_scr = fpga_reg_get(REG_SD_DMA_SCR);
led_blink_act();
if ((!(sd_dat & SD_DAT_BUSY)) && (!(sd_dma_scr & DMA_SCR_BUSY))) { if ((!(sd_dat & SD_DAT_BUSY)) && (!(sd_dma_scr & DMA_SCR_BUSY))) {
sd_clear_timeout(); sd_clear_timeout();
return (sd_dat & SD_DAT_ERROR); return (sd_dat & SD_DAT_ERROR);
@ -430,6 +431,34 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
return false; return false;
} }
bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors) {
uint32_t starting_sector = 0;
uint32_t sectors_to_process = 0;
if (count == 0) {
return true;
}
for (uint32_t i = 0; i < count; i++) {
if (sector_table[i] == 0) {
return true;
}
sectors_to_process += 1;
if ((i < (count - 1)) && ((sector_table[i] + 1) == sector_table[i + 1])) {
continue;
}
bool error = sd_process_sectors(address, sector_table[starting_sector], sectors_to_process);
if (error) {
return true;
}
address += (sectors_to_process * SD_SECTOR_SIZE);
starting_sector += sectors_to_process;
sectors_to_process = 0;
}
return false;
}
void sd_init (void) { void sd_init (void) {
p.card_initialized = false; p.card_initialized = false;
sd_set_clock(CLOCK_STOP); sd_set_clock(CLOCK_STOP);

View File

@ -8,12 +8,16 @@
#define SD_SECTOR_SIZE (512) #define SD_SECTOR_SIZE (512)
typedef bool sd_process_sectors_t (uint32_t address, uint32_t sector, uint32_t count);
bool sd_card_init (void); bool sd_card_init (void);
void sd_card_deinit (void); void sd_card_deinit (void);
uint32_t sd_card_get_status (void); uint32_t sd_card_get_status (void);
bool sd_card_get_info (uint32_t address); bool sd_card_get_info (uint32_t address);
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count); bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count);
bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count); bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count);
bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors);
void sd_init (void); void sd_init (void);
void sd_process (void); void sd_process (void);

View File

@ -1,3 +1,4 @@
#include "cfg.h"
#include "fpga.h" #include "fpga.h"
#include "sd.h" #include "sd.h"
#include "timer.h" #include "timer.h"
@ -7,6 +8,11 @@
#define SAVE_MAX_SECTOR_COUNT (256) #define SAVE_MAX_SECTOR_COUNT (256)
#define SRAM_FLASHRAM_ADDRESS (0x03FE0000) #define SRAM_FLASHRAM_ADDRESS (0x03FE0000)
#define EEPROM_ADDRESS (0x05002000) #define EEPROM_ADDRESS (0x05002000)
#define EEPROM_4K_SECTOR_COUNT (1)
#define EEPROM_16K_SECTOR_COUNT (4)
#define SRAM_SECTOR_COUNT (64)
#define FLASHRAM_SECTOR_COUNT (256)
#define SRAM_BANKED_SECTOR_COUNT (192)
#define WRITEBACK_DELAY_TICKS (100) #define WRITEBACK_DELAY_TICKS (100)
@ -22,20 +28,37 @@ static struct process p;
static void writeback_save_to_sd (void) { static void writeback_save_to_sd (void) {
uint32_t save_address = SRAM_FLASHRAM_ADDRESS; uint32_t address;
if (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_EEPROM_ENABLED) { uint32_t count;
save_address = EEPROM_ADDRESS;
} switch (cfg_get_save_type()) {
for (int i = 0; i < SAVE_MAX_SECTOR_COUNT; i++) { case SAVE_TYPE_EEPROM_4K:
uint32_t sector = p.sectors[i]; address = EEPROM_ADDRESS;
if (sector == 0) { count = EEPROM_4K_SECTOR_COUNT;
break; break;
} case SAVE_TYPE_EEPROM_16K:
if (sd_write_sectors(save_address, sector, 1)) { address = EEPROM_ADDRESS;
count = EEPROM_16K_SECTOR_COUNT;
break;
case SAVE_TYPE_SRAM:
address = SRAM_FLASHRAM_ADDRESS;
count = SRAM_SECTOR_COUNT;
break;
case SAVE_TYPE_FLASHRAM:
address = SRAM_FLASHRAM_ADDRESS;
count = FLASHRAM_SECTOR_COUNT;
break;
case SAVE_TYPE_SRAM_BANKED:
address = SRAM_FLASHRAM_ADDRESS;
count = SRAM_BANKED_SECTOR_COUNT;
break;
default:
p.enabled = false; p.enabled = false;
break; return;
} }
save_address += SD_SECTOR_SIZE;
if(sd_optimize_sectors(address, p.sectors, count, sd_write_sectors)) {
p.enabled = false;
} }
} }