mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-12-25 12:31:57 +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
|
||||
- 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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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':
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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
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