[SC64][SW] Added automatic save writeback implementation

This commit is contained in:
Mateusz Faderewski 2022-11-26 18:54:29 +01:00
parent 76ad09cf4a
commit ed25ef16e9
13 changed files with 184 additions and 9 deletions

View File

@ -7,7 +7,7 @@
- 8 kB on-chip buffer for general use
- 25 MB/s peak transfer rate USB interface for data upload/download and debug functionality
- 25 MB/s peak transfer rate SD card interface
- EEPROM, SRAM and FlashRAM save types ~~with automatic writeback to SD card~~ (_not implemented yet_)
- EEPROM, SRAM and FlashRAM save types with automatic writeback to SD card
- Battery backed real time clock (RTC)
- Status LED and button for general use
- 64DD add-on emulation

View File

@ -19,7 +19,8 @@ typedef enum {
SC64_CMD_SD_SECTOR_SET = 'I',
SC64_CMD_SD_WRITE = 'S',
SC64_CMD_SD_READ = 's',
SC64_CMD_DD_SD_DISK_INFO = 'D',
SC64_CMD_DD_SD_INFO = 'D',
SC64_CMD_WRITEBACK_SD_INFO = 'W',
SC64_CMD_FLASH_ERASE_BLOCK = 'P',
SC64_CMD_FLASH_WAIT_BUSY = 'p',
} cmd_id_t;
@ -203,9 +204,17 @@ bool sc64_sd_read_sectors (uint32_t *address, uint32_t sector, uint32_t count) {
return sc64_execute_cmd(SC64_CMD_SD_READ, read_args, NULL);
}
bool sc64_dd_set_sd_disk_info (uint32_t *address, uint32_t length) {
bool sc64_dd_set_sd_info (uint32_t *address, uint32_t length) {
uint32_t args[2] = { (uint32_t) (address), length };
if (sc64_execute_cmd(SC64_CMD_DD_SD_DISK_INFO, args, NULL)) {
if (sc64_execute_cmd(SC64_CMD_DD_SD_INFO, args, NULL)) {
return true;
}
return false;
}
bool sc64_writeback_set_sd_info (uint32_t *address, bool enabled) {
uint32_t args[2] = { (uint32_t) (address), (uint32_t) (enabled) };
if (sc64_execute_cmd(SC64_CMD_WRITEBACK_SD_INFO, args, NULL)) {
return true;
}
return false;

View File

@ -117,6 +117,7 @@ bool sc64_sd_card_get_info (uint32_t *address);
bool sc64_sd_write_sectors (uint32_t *address, uint32_t sector, uint32_t count);
bool sc64_sd_read_sectors (uint32_t *address, uint32_t sector, uint32_t count);
bool sc64_dd_set_sd_disk_info (uint32_t *address, uint32_t length);
bool sc64_writeback_set_sd_info (uint32_t *address, bool enabled);
#endif

View File

@ -20,8 +20,10 @@ SRC_FILES = \
rtc.c \
sd.c \
task.c \
timer.c \
update.c \
usb.c
usb.c \
writeback.c
PAD_TO = 0x08008000
include common.mk

View File

@ -7,6 +7,7 @@
#include "rtc.h"
#include "sd.h"
#include "usb.h"
#include "writeback.h"
typedef enum {
@ -552,7 +553,15 @@ void cfg_process (void) {
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
return;
}
dd_set_sd_disk_info(args[0], args[1]);
dd_set_sd_info(args[0], args[1]);
break;
case 'W':
if (cfg_translate_address(&args[0], 1024, (SDRAM | BRAM))) {
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
return;
}
writeback_set_sd_info(args[0], args[1]);
break;
case 'p':

View File

@ -268,7 +268,7 @@ void dd_set_sd_mode (bool value) {
p.sd_mode = value;
}
void dd_set_sd_disk_info (uint32_t address, uint32_t length) {
void dd_set_sd_info (uint32_t address, uint32_t length) {
sd_disk_info_t info;
length /= sizeof(info);
p.sd_current_disk = 0;
@ -313,7 +313,7 @@ void dd_init (void) {
p.drive_type = DD_DRIVE_TYPE_RETAIL;
p.sd_mode = false;
p.sd_current_disk = 0;
dd_set_sd_disk_info(0, 0);
dd_set_sd_info(0, 0);
}
void dd_process (void) {

View File

@ -25,7 +25,7 @@ dd_disk_state_t dd_get_disk_state (void);
bool dd_set_disk_state (dd_disk_state_t state);
bool dd_get_sd_mode (void);
void dd_set_sd_mode (bool value);
void dd_set_sd_disk_info (uint32_t address, uint32_t length);
void dd_set_sd_info (uint32_t address, uint32_t length);
void dd_handle_button (void);
void dd_init (void);
void dd_process (void);

View File

@ -7,6 +7,7 @@
#include "rtc.h"
#include "sd.h"
#include "usb.h"
#include "writeback.h"
void gvr_task (void) {
@ -19,6 +20,7 @@ void gvr_task (void) {
isv_init();
sd_init();
usb_init();
writeback_init();
while (1) {
button_process();
@ -29,5 +31,6 @@ void gvr_task (void) {
rtc_process();
sd_process();
usb_process();
writeback_process();
}
}

View File

@ -2,6 +2,7 @@
#include "hw.h"
#include "led.h"
#include "task.h"
#include "timer.h"
#define LED_MS_PER_TICK (10)
@ -113,6 +114,8 @@ void led_blink_act (void) {
}
void led_task (void) {
timer_init();
while (1) {
hw_tim_setup(TIM_ID_LED, LED_MS_PER_TICK, led_task_resume);
@ -124,6 +127,8 @@ void led_task (void) {
led_process_act();
}
timer_update();
task_yield();
}
}

30
sw/controller/src/timer.c Normal file
View File

@ -0,0 +1,30 @@
#include "hw.h"
#include "timer.h"
static volatile uint32_t timer[__TIMER_ID_COUNT];
uint32_t timer_get (timer_id_t id) {
return (uint32_t) (timer[id]);
}
void timer_set (timer_id_t id, uint32_t ticks) {
hw_tim_disable_irq(TIM_ID_LED);
timer[id] = ticks;
hw_tim_enable_irq(TIM_ID_LED);
}
void timer_init (void) {
for (timer_id_t id = 0; id < __TIMER_ID_COUNT; id++) {
timer[id] = 0;
}
}
void timer_update (void) {
for (timer_id_t id = 0; id < __TIMER_ID_COUNT; id++) {
if (timer[id] > 0) {
timer[id] -= 1;
}
}
}

20
sw/controller/src/timer.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef TIMER_H__
#define TIMER_H__
#include <stdint.h>
typedef enum {
TIMER_ID_WRITEBACK,
__TIMER_ID_COUNT
} timer_id_t;
uint32_t timer_get (timer_id_t id);
void timer_set (timer_id_t id, uint32_t ticks);
void timer_init (void);
void timer_update (void);
#endif

View File

@ -0,0 +1,82 @@
#include "fpga.h"
#include "sd.h"
#include "timer.h"
#include "writeback.h"
#include "led.h"
#define SAVE_MAX_SECTOR_COUNT (256)
#define SRAM_FLASHRAM_ADDRESS (0x03FE0000)
#define EEPROM_ADDRESS (0x05002000)
#define WRITEBACK_DELAY_TICKS (100)
struct process {
bool enabled;
bool pending;
uint16_t last_save_count;
uint32_t sectors[SAVE_MAX_SECTOR_COUNT];
};
static struct process p;
static void writeback_save_to_sd (void) {
uint32_t save_address = SRAM_FLASHRAM_ADDRESS;
if (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_EEPROM_ENABLED) {
save_address = EEPROM_ADDRESS;
}
for (int i = 0; i < SAVE_MAX_SECTOR_COUNT; i++) {
uint32_t sector = p.sectors[i];
if (sector == 0) {
break;
}
if (sd_write_sectors(save_address, sector, 1)) {
break;
}
save_address += SD_SECTOR_SIZE;
}
}
void writeback_set_sd_info (uint32_t address, bool enabled) {
p.enabled = enabled;
p.pending = false;
p.last_save_count = fpga_reg_get(REG_SAVE_COUNT);
if (p.enabled) {
fpga_mem_read(address, sizeof(p.sectors), (uint8_t *) (p.sectors));
for (int i = 0; i < SAVE_MAX_SECTOR_COUNT; i++) {
p.sectors[i] = SWAP32(p.sectors[i]);
}
} else {
for (int i = 0; i < SAVE_MAX_SECTOR_COUNT; i++) {
p.sectors[i] = 0;
}
}
}
void writeback_init (void) {
p.enabled = false;
p.pending = false;
for (int i = 0; i < SAVE_MAX_SECTOR_COUNT; i++) {
p.sectors[i] = 0;
}
}
void writeback_process (void) {
if (p.enabled) {
uint16_t save_count = fpga_reg_get(REG_SAVE_COUNT);
if (save_count != p.last_save_count) {
p.pending = true;
timer_set(TIMER_ID_WRITEBACK, WRITEBACK_DELAY_TICKS);
p.last_save_count = save_count;
}
}
if (p.pending) {
if (timer_get(TIMER_ID_WRITEBACK) == 0) {
p.pending = false;
writeback_save_to_sd();
}
}
}

View File

@ -0,0 +1,14 @@
#ifndef WRITEBACK_H__
#define WRITEBACK_H__
#include <stdbool.h>
#include <stdint.h>
void writeback_set_sd_info (uint32_t address, bool enabled);
void writeback_init (void);
void writeback_process (void);
#endif