mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-22 05:59:15 +01:00
[SC64][SW] Added automatic save writeback implementation
This commit is contained in:
parent
76ad09cf4a
commit
ed25ef16e9
@ -7,7 +7,7 @@
|
|||||||
- 8 kB on-chip buffer for general use
|
- 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 USB interface for data upload/download and debug functionality
|
||||||
- 25 MB/s peak transfer rate SD card interface
|
- 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)
|
- Battery backed real time clock (RTC)
|
||||||
- Status LED and button for general use
|
- Status LED and button for general use
|
||||||
- 64DD add-on emulation
|
- 64DD add-on emulation
|
||||||
|
@ -19,7 +19,8 @@ typedef enum {
|
|||||||
SC64_CMD_SD_SECTOR_SET = 'I',
|
SC64_CMD_SD_SECTOR_SET = 'I',
|
||||||
SC64_CMD_SD_WRITE = 'S',
|
SC64_CMD_SD_WRITE = 'S',
|
||||||
SC64_CMD_SD_READ = '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_ERASE_BLOCK = 'P',
|
||||||
SC64_CMD_FLASH_WAIT_BUSY = 'p',
|
SC64_CMD_FLASH_WAIT_BUSY = 'p',
|
||||||
} cmd_id_t;
|
} 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);
|
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 };
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -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_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_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_dd_set_sd_disk_info (uint32_t *address, uint32_t length);
|
||||||
|
bool sc64_writeback_set_sd_info (uint32_t *address, bool enabled);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,8 +20,10 @@ SRC_FILES = \
|
|||||||
rtc.c \
|
rtc.c \
|
||||||
sd.c \
|
sd.c \
|
||||||
task.c \
|
task.c \
|
||||||
|
timer.c \
|
||||||
update.c \
|
update.c \
|
||||||
usb.c
|
usb.c \
|
||||||
|
writeback.c
|
||||||
PAD_TO = 0x08008000
|
PAD_TO = 0x08008000
|
||||||
|
|
||||||
include common.mk
|
include common.mk
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
#include "sd.h"
|
#include "sd.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
#include "writeback.h"
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -552,7 +553,15 @@ void cfg_process (void) {
|
|||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
||||||
return;
|
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;
|
break;
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
|
@ -268,7 +268,7 @@ void dd_set_sd_mode (bool value) {
|
|||||||
p.sd_mode = 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;
|
sd_disk_info_t info;
|
||||||
length /= sizeof(info);
|
length /= sizeof(info);
|
||||||
p.sd_current_disk = 0;
|
p.sd_current_disk = 0;
|
||||||
@ -313,7 +313,7 @@ void dd_init (void) {
|
|||||||
p.drive_type = DD_DRIVE_TYPE_RETAIL;
|
p.drive_type = DD_DRIVE_TYPE_RETAIL;
|
||||||
p.sd_mode = false;
|
p.sd_mode = false;
|
||||||
p.sd_current_disk = 0;
|
p.sd_current_disk = 0;
|
||||||
dd_set_sd_disk_info(0, 0);
|
dd_set_sd_info(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dd_process (void) {
|
void dd_process (void) {
|
||||||
|
@ -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_set_disk_state (dd_disk_state_t state);
|
||||||
bool dd_get_sd_mode (void);
|
bool dd_get_sd_mode (void);
|
||||||
void dd_set_sd_mode (bool value);
|
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_handle_button (void);
|
||||||
void dd_init (void);
|
void dd_init (void);
|
||||||
void dd_process (void);
|
void dd_process (void);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
#include "sd.h"
|
#include "sd.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
#include "writeback.h"
|
||||||
|
|
||||||
|
|
||||||
void gvr_task (void) {
|
void gvr_task (void) {
|
||||||
@ -19,6 +20,7 @@ void gvr_task (void) {
|
|||||||
isv_init();
|
isv_init();
|
||||||
sd_init();
|
sd_init();
|
||||||
usb_init();
|
usb_init();
|
||||||
|
writeback_init();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
button_process();
|
button_process();
|
||||||
@ -29,5 +31,6 @@ void gvr_task (void) {
|
|||||||
rtc_process();
|
rtc_process();
|
||||||
sd_process();
|
sd_process();
|
||||||
usb_process();
|
usb_process();
|
||||||
|
writeback_process();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "led.h"
|
#include "led.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
|
||||||
#define LED_MS_PER_TICK (10)
|
#define LED_MS_PER_TICK (10)
|
||||||
@ -113,6 +114,8 @@ void led_blink_act (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void led_task (void) {
|
void led_task (void) {
|
||||||
|
timer_init();
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
hw_tim_setup(TIM_ID_LED, LED_MS_PER_TICK, led_task_resume);
|
hw_tim_setup(TIM_ID_LED, LED_MS_PER_TICK, led_task_resume);
|
||||||
|
|
||||||
@ -124,6 +127,8 @@ void led_task (void) {
|
|||||||
led_process_act();
|
led_process_act();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timer_update();
|
||||||
|
|
||||||
task_yield();
|
task_yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
30
sw/controller/src/timer.c
Normal file
30
sw/controller/src/timer.c
Normal 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
20
sw/controller/src/timer.h
Normal 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
|
82
sw/controller/src/writeback.c
Normal file
82
sw/controller/src/writeback.c
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
sw/controller/src/writeback.h
Normal file
14
sw/controller/src/writeback.h
Normal 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
|
Loading…
Reference in New Issue
Block a user