From ea4470eaaac99c893c53f71e74d6a8962ee0b086 Mon Sep 17 00:00:00 2001 From: Polprzewodnikowy Date: Fri, 29 Jul 2022 19:44:05 +0200 Subject: [PATCH] added usb read functionality, general cleanup --- fw/rtl/mcu/mcu_top.sv | 3 +- sw/bootloader/src/exception.c | 2 +- sw/bootloader/src/fatfs/diskio.c | 44 +++---- sw/bootloader/src/io.h | 18 ++- sw/bootloader/src/main.c | 19 +-- sw/bootloader/src/sc64.c | 200 +++++++++++-------------------- sw/bootloader/src/sc64.h | 77 ++++++------ sw/controller/.gitattributes | 1 + sw/controller/src/cfg.c | 118 ++++++++++++++---- sw/controller/src/cic.c | 21 ++-- sw/controller/src/cic.h | 5 +- sw/controller/src/dd.c | 24 +++- sw/controller/src/dd.h | 2 + sw/controller/src/flashram.c | 5 +- sw/controller/src/fpga.h | 2 + sw/controller/src/hw.c | 10 +- sw/controller/src/isv.c | 6 +- sw/controller/src/rtc.c | 5 +- sw/controller/src/task.c | 3 + sw/controller/src/usb.c | 82 ++++++++++++- sw/controller/src/usb.h | 5 + 21 files changed, 397 insertions(+), 255 deletions(-) create mode 100644 sw/controller/.gitattributes diff --git a/fw/rtl/mcu/mcu_top.sv b/fw/rtl/mcu/mcu_top.sv index 9de3de0..f313406 100644 --- a/fw/rtl/mcu/mcu_top.sv +++ b/fw/rtl/mcu/mcu_top.sv @@ -485,7 +485,8 @@ module mcu_top ( REG_RTC_SCR: begin reg_rdata <= { - 31'd0, + 24'h525443, + 7'd0, n64_scb.rtc_pending }; end diff --git a/sw/bootloader/src/exception.c b/sw/bootloader/src/exception.c index af678af..0c40225 100644 --- a/sw/bootloader/src/exception.c +++ b/sw/bootloader/src/exception.c @@ -180,7 +180,7 @@ static const char *exception_get_description (uint8_t exception_code) { void exception_fatal_handler (uint32_t exception_code, uint32_t interrupt_mask, exception_t *e) { version_t *version = version_get(); - uint32_t sc64_version = pi_io_read(&SC64->VERSION); + uint32_t sc64_version = pi_io_read(&SC64_REGS->VERSION); uint32_t *instruction_address = (((uint32_t *) (e->epc.u32)) + ((e->cr & C0_CR_BD) ? 1 : 0)); exception_init_screen(); diff --git a/sw/bootloader/src/fatfs/diskio.c b/sw/bootloader/src/fatfs/diskio.c index 32bee80..2a442c1 100644 --- a/sw/bootloader/src/fatfs/diskio.c +++ b/sw/bootloader/src/fatfs/diskio.c @@ -3,45 +3,45 @@ #include "../sc64.h" -DSTATUS status[__DRIVE_COUNT] = { STA_NOINIT, STA_NOINIT }; +// DSTATUS status[__DRIVE_COUNT] = { STA_NOINIT, STA_NOINIT }; DSTATUS disk_status (BYTE pdrv) { - if (pdrv >= __DRIVE_COUNT) { + // if (pdrv >= __DRIVE_COUNT) { return STA_NODISK; - } - return status[pdrv]; + // } + // return status[pdrv]; } DSTATUS disk_initialize (BYTE pdrv) { - if (pdrv >= __DRIVE_COUNT) { + // if (pdrv >= __DRIVE_COUNT) { return STA_NODISK; - } - if (!sc64_storage_init((drive_id_t) (pdrv))) { - status[pdrv] &= ~(STA_NOINIT); - } - return status[pdrv]; + // } + // if (!sc64_storage_init((drive_id_t) (pdrv))) { + // status[pdrv] &= ~(STA_NOINIT); + // } + // return status[pdrv]; } DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) { - if (pdrv >= __DRIVE_COUNT) { - return RES_PARERR; - } - if (sc64_storage_read((drive_id_t) (pdrv), buff, sector, count)) { + // if (pdrv >= __DRIVE_COUNT) { + // return RES_PARERR; + // } + // if (sc64_storage_read((drive_id_t) (pdrv), buff, sector, count)) { return RES_ERROR; - } - return RES_OK; + // } + // return RES_OK; } #if !FF_FS_READONLY DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) { - if (pdrv >= __DRIVE_COUNT) { - return RES_PARERR; - } - if (sc64_storage_write((drive_id_t) (pdrv), buff, sector, count)) { + // if (pdrv >= __DRIVE_COUNT) { + // return RES_PARERR; + // } + // if (sc64_storage_write((drive_id_t) (pdrv), buff, sector, count)) { return RES_ERROR; - } - return RES_OK; + // } + // return RES_OK; } #endif diff --git a/sw/bootloader/src/io.h b/sw/bootloader/src/io.h index 1f08762..762265e 100644 --- a/sw/bootloader/src/io.h +++ b/sw/bootloader/src/io.h @@ -225,14 +225,28 @@ typedef struct { #define PIFRAM ((io8_t *) PIFRAM_BASE) +typedef struct { + io8_t BUFFER[8192]; + io8_t EEPROM[2048]; + io8_t __unused_1[8192 - 2048]; + io8_t FLASHRAM[128]; + io8_t __unused_2[8192 - 128]; + io8_t DD_SECTOR[2048]; + io8_t __unused_3[8192 - 2048]; +} sc64_buffers_t; + +#define SC64_BUFFERS_BASE (0x1FFE0000UL) +#define SC64_BUFFERS ((sc64_buffers_t *) SC64_BUFFERS_BASE) + + typedef struct { io32_t SR_CMD; io32_t DATA[2]; io32_t VERSION; } sc64_regs_t; -#define SC64_BASE (0x1FFF0000UL) -#define SC64 ((sc64_regs_t *) SC64_BASE) +#define SC64_REGS_BASE (0x1FFF0000UL) +#define SC64_REGS ((sc64_regs_t *) SC64_REGS_BASE) #define SC64_SR_CMD_ERROR (1 << 30) #define SC64_SR_CPU_BUSY (1 << 31) diff --git a/sw/bootloader/src/main.c b/sw/bootloader/src/main.c index 2461ac7..1b791f8 100644 --- a/sw/bootloader/src/main.c +++ b/sw/bootloader/src/main.c @@ -1,17 +1,18 @@ #include "boot.h" #include "error.h" #include "init.h" +#include "io.h" #include "sc64.h" #include "storage.h" void main (void) { boot_info_t boot_info; - sc64_info_t sc64_info; + sc64_boot_info_t sc64_boot_info; - sc64_get_info(&sc64_info); + sc64_get_boot_info(&sc64_boot_info); - switch (sc64_info.boot_mode) { + switch (sc64_boot_info.boot_mode) { case BOOT_MODE_MENU_SD: storage_run_menu(STORAGE_BACKEND_SD); break; @@ -29,23 +30,23 @@ void main (void) { break; default: - error_display("Unknown boot mode selected [%d]\n", sc64_info.boot_mode); + error_display("Unknown boot mode selected [%d]\n", sc64_boot_info.boot_mode); break; } boot_info.reset_type = OS_INFO->reset_type; - if (sc64_info.tv_type != TV_TYPE_UNKNOWN) { - boot_info.tv_type = sc64_info.tv_type; + if (sc64_boot_info.tv_type != TV_TYPE_UNKNOWN) { + boot_info.tv_type = sc64_boot_info.tv_type; } else { if (!boot_get_tv_type(&boot_info)) { boot_info.tv_type = OS_INFO->tv_type; } } - if (sc64_info.cic_seed != CIC_SEED_UNKNOWN) { - boot_info.cic_seed = sc64_info.cic_seed & 0xFF; - boot_info.version = (sc64_info.cic_seed >> 8) & 0x01; + if (sc64_boot_info.cic_seed != CIC_SEED_UNKNOWN) { + boot_info.cic_seed = sc64_boot_info.cic_seed & 0xFF; + boot_info.version = (sc64_boot_info.cic_seed >> 8) & 0x01; } else { if (!boot_get_cic_seed_version(&boot_info)) { boot_info.cic_seed = 0x3F; diff --git a/sw/bootloader/src/sc64.c b/sw/bootloader/src/sc64.c index 20103d9..b398bb2 100644 --- a/sw/bootloader/src/sc64.c +++ b/sw/bootloader/src/sc64.c @@ -1,61 +1,75 @@ +#include "io.h" #include "sc64.h" -#define SECTOR_SIZE (512) +#define SC64_VERSION_2 (0x53437632) -bool sc64_check_presence (void) { - uint32_t version = pi_io_read(&SC64->VERSION); - return (version == SC64_VERSION_2); -} +typedef enum { + SC64_CMD_GET_VERSION = 'v', + SC64_CMD_CONFIG_QUERY = 'c', + SC64_CMD_CONFIG_CHANGE = 'C', + SC64_CMD_TIME_GET = 't', + SC64_CMD_TIME_SET = 'T', + SC64_CMD_USB_READ = 'm', + SC64_CMD_USB_WRITE = 'M', + SC64_CMD_USB_READ_STATUS = 'u', + SC64_CMD_USB_WRITE_STATUS = 'U', +} cmd_id_t; + static bool sc64_wait_cpu_busy (void) { uint32_t sr; do { - sr = pi_io_read(&SC64->SR_CMD); + sr = pi_io_read(&SC64_REGS->SR_CMD); } while (sr & SC64_SR_CPU_BUSY); return sr & SC64_SR_CMD_ERROR; } -static bool sc64_perform_cmd (uint8_t cmd, uint32_t *args, uint32_t *result) { +static bool sc64_execute_cmd (uint8_t cmd, uint32_t *args, uint32_t *result) { if (args != NULL) { - pi_io_write(&SC64->DATA[0], args[0]); - pi_io_write(&SC64->DATA[1], args[1]); + pi_io_write(&SC64_REGS->DATA[0], args[0]); + pi_io_write(&SC64_REGS->DATA[1], args[1]); } - pi_io_write(&SC64->SR_CMD, ((uint32_t) (cmd)) & 0xFF); + pi_io_write(&SC64_REGS->SR_CMD, ((uint32_t) (cmd)) & 0xFF); bool error = sc64_wait_cpu_busy(); if (result != NULL) { - result[0] = pi_io_read(&SC64->DATA[0]); - result[1] = pi_io_read(&SC64->DATA[1]); + result[0] = pi_io_read(&SC64_REGS->DATA[0]); + result[1] = pi_io_read(&SC64_REGS->DATA[1]); } return error; } -uint32_t sc64_query_config (cfg_id_t id) { - uint32_t args[2] = { id, 0 }; - uint32_t result[2]; - sc64_perform_cmd(SC64_CMD_QUERY, args, result); - return result[1]; -} - -void sc64_change_config (cfg_id_t id, uint32_t value) { - uint32_t args[2] = { id, value }; - sc64_perform_cmd(SC64_CMD_CONFIG, args, NULL); -} - -void sc64_get_info (sc64_info_t *info) { - info->cic_seed = (uint16_t) sc64_query_config(CFG_ID_CIC_SEED); - info->tv_type = (tv_type_t) sc64_query_config(CFG_ID_TV_TYPE); - info->boot_mode = (boot_mode_t) sc64_query_config(CFG_ID_BOOT_MODE); +bool sc64_check_presence (void) { + uint32_t version = pi_io_read(&SC64_REGS->VERSION); + return (version == SC64_VERSION_2); } void sc64_init (void) { sc64_change_config(CFG_ID_BOOTLOADER_SWITCH, false); } +uint32_t sc64_query_config (cfg_id_t id) { + uint32_t args[2] = { id, 0 }; + uint32_t result[2]; + sc64_execute_cmd(SC64_CMD_CONFIG_QUERY, args, result); + return result[1]; +} + +void sc64_change_config (cfg_id_t id, uint32_t value) { + uint32_t args[2] = { id, value }; + sc64_execute_cmd(SC64_CMD_CONFIG_CHANGE, args, NULL); +} + +void sc64_get_boot_info (sc64_boot_info_t *info) { + info->cic_seed = (uint16_t) sc64_query_config(CFG_ID_CIC_SEED); + info->tv_type = (tv_type_t) sc64_query_config(CFG_ID_TV_TYPE); + info->boot_mode = (boot_mode_t) sc64_query_config(CFG_ID_BOOT_MODE); +} + void sc64_get_time (rtc_time_t *t) { uint32_t result[2]; - sc64_perform_cmd(SC64_CMD_GET_TIME, NULL, result); + sc64_execute_cmd(SC64_CMD_TIME_GET, NULL, result); t->second = (result[0] & 0xFF); t->minute = ((result[0] >> 8) & 0xFF); t->hour = ((result[0] >> 16) & 0xFF); @@ -70,106 +84,38 @@ void sc64_set_time (rtc_time_t *t) { ((t->hour << 16) | (t->minute << 8) | t->second), ((t->weekday << 24) | (t->year << 16) | (t->month << 8) | t->day), }; - sc64_perform_cmd(SC64_CMD_SET_TIME, args, NULL); + sc64_execute_cmd(SC64_CMD_TIME_SET, args, NULL); } -static uint32_t sc64_wait_drive_ready (drive_id_t drive) { - uint32_t args[2] = { ((drive & 0x01) << 31), 0 }; +bool sc64_usb_write_ready (void) { uint32_t result[2]; + sc64_execute_cmd(SC64_CMD_USB_WRITE_STATUS, NULL, result); + return result[0]; +} + +void sc64_usb_write (uint32_t *address, uint32_t length) { + while (!sc64_usb_write_ready()); + uint32_t args[2] = { (uint32_t) (address), length }; + sc64_execute_cmd(SC64_CMD_USB_WRITE, args, NULL); +} + +bool sc64_usb_read_ready (uint8_t *type, uint32_t *length) { + uint32_t result[2]; + sc64_execute_cmd(SC64_CMD_USB_READ_STATUS, NULL, result); + if (type != NULL) { + *type = result[0] & 0xFF; + } + if (length != NULL) { + *length = result[1]; + } + return result[1] > 0; +} + +void sc64_usb_read (uint32_t *address, uint32_t length) { + uint32_t args[2] = { (uint32_t) (address), length }; + uint32_t result[2]; + sc64_execute_cmd(SC64_CMD_USB_READ, args, NULL); do { - sc64_perform_cmd(SC64_CMD_DRIVE_BUSY, args, result); - } while (result[0]); - return result[1]; -} - -bool sc64_storage_init (drive_id_t drive) { - uint32_t args[2] = { ((drive & 0x01) << 31), 0 }; - if (sc64_perform_cmd(SC64_CMD_DRIVE_INIT, args, NULL)) { - return true; - } - if (sc64_wait_drive_ready(drive)) { - return true; - } - return false; -} - -static bool sc64_drive_start_rw (drive_id_t drive, bool write, uint32_t sector, uint32_t offset) { - uint32_t args[2] = { (((drive & 0x01) << 31) | (offset & 0x7FFFFFFF)), sector }; - if (sc64_perform_cmd(write ? SC64_CMD_DRIVE_WRITE : SC64_CMD_DRIVE_READ, args, NULL)) { - return true; - } - return false; -} - -bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_t count) { - io32_t *src; - uint8_t *dst = (uint8_t *) (buffer); - uint32_t current_offset = 0; - uint32_t next_offset = SECTOR_SIZE; - - if (sc64_drive_start_rw(drive, false, sector++, 0x03FF0000UL)) { - return true; - } - while (count > 0) { - if (sc64_wait_drive_ready(drive)) { - return true; - } - if (count > 1) { - if (sc64_drive_start_rw(drive, false, sector++, 0x03FF0000UL + next_offset)) { - return true; - } - next_offset = next_offset ? 0 : SECTOR_SIZE; - } - src = (io32_t *) (0x13FF0000UL + current_offset); - for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) { - uint32_t data = pi_io_read(src + i); - *dst++ = ((data >> 24) & 0xFF); - *dst++ = ((data >> 16) & 0xFF); - *dst++ = ((data >> 8) & 0xFF); - *dst++ = ((data >> 0) & 0xFF); - } - current_offset = current_offset ? 0 : SECTOR_SIZE; - count -= 1; - } - - return false; -} - -bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count) { - uint8_t *src = (uint8_t *) (buffer); - io32_t *dst = (io32_t *) (0x13FF0000UL); - - while (count > 0) { - for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) { - uint32_t data = 0; - data |= ((*src++) << 24); - data |= ((*src++) << 16); - data |= ((*src++) << 8); - data |= ((*src++) << 0); - pi_io_write((dst + i), data); - } - if (sc64_drive_start_rw(drive, true, sector, 0x03FF0000UL)) { - return true; - } - if (sc64_wait_drive_ready(drive)) { - return true; - } - sector += 1; - count -= 1; - } - - return false; -} - -static void sc64_uart_put_char (char c) { -#ifdef DEBUG - uint32_t args[2] = { (uint32_t) (c), 0 }; - sc64_perform_cmd(SC64_CMD_UART_PUT, args, NULL); -#endif -} - -void sc64_uart_print_string (const char *text) { - while (*text != '\0') { - sc64_uart_put_char (*text++); - } + sc64_execute_cmd(SC64_CMD_USB_READ_STATUS, NULL, result); + } while(result[0] & (1 << 24)); } diff --git a/sw/bootloader/src/sc64.h b/sw/bootloader/src/sc64.h index 3f73405..682b090 100644 --- a/sw/bootloader/src/sc64.h +++ b/sw/bootloader/src/sc64.h @@ -4,61 +4,64 @@ #include #include -#include "io.h" - - -#define SC64_CMD_QUERY ('c') -#define SC64_CMD_CONFIG ('C') -#define SC64_CMD_GET_TIME ('t') -#define SC64_CMD_SET_TIME ('T') -#define SC64_CMD_DRIVE_INIT (0xF0) -#define SC64_CMD_DRIVE_BUSY (0xF1) -#define SC64_CMD_DRIVE_READ (0xF2) -#define SC64_CMD_DRIVE_WRITE (0xF3) -#define SC64_CMD_DRIVE_LOAD (0xF4) -#define SC64_CMD_DRIVE_STORE (0xF5) -#define SC64_CMD_UART_PUT ('U') - -#define SC64_VERSION_2 (0x53437632) typedef enum { CFG_ID_BOOTLOADER_SWITCH, CFG_ID_ROM_WRITE_ENABLE, CFG_ID_ROM_SHADOW_ENABLE, - CFG_ID_DD_ENABLE, + CFG_ID_DD_MODE, CFG_ID_ISV_ENABLE, CFG_ID_BOOT_MODE, CFG_ID_SAVE_TYPE, CFG_ID_CIC_SEED, CFG_ID_TV_TYPE, CFG_ID_FLASH_ERASE_BLOCK, + CFG_ID_DD_DRIVE_TYPE, + CFG_ID_DD_DISK_STATE, } cfg_id_t; typedef enum { - CIC_SEED_UNKNOWN = 0xFFFF, -} cic_seed_t; - -typedef enum { - TV_TYPE_PAL = 0, - TV_TYPE_NTSC = 1, - TV_TYPE_MPAL = 2, - TV_TYPE_UNKNOWN = 3, -} tv_type_t; + DD_MODE_DISABLED = 0, + DD_MODE_REGS = 1, + DD_MODE_IPL = 2, + DD_MODE_FULL = 3 +} dd_mode_t; typedef enum { BOOT_MODE_MENU_SD = 0, BOOT_MODE_MENU_USB = 1, BOOT_MODE_ROM = 2, BOOT_MODE_DDIPL = 3, - BOOT_MODE_DIRECT = 4, + BOOT_MODE_DIRECT = 4 } 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 { + CIC_SEED_UNKNOWN = 0xFFFF +} cic_seed_t; + +typedef enum { + TV_TYPE_PAL = 0, + TV_TYPE_NTSC = 1, + TV_TYPE_MPAL = 2, + TV_TYPE_UNKNOWN = 3 +} tv_type_t; + + typedef struct { boot_mode_t boot_mode; uint16_t cic_seed; tv_type_t tv_type; -} sc64_info_t; +} sc64_boot_info_t; typedef struct { uint8_t second; @@ -70,24 +73,18 @@ typedef struct { uint8_t year; } rtc_time_t; -typedef enum { - DRIVE_SD = 0, - DRIVE_USB = 1, - __DRIVE_COUNT = 2 -} drive_id_t; - bool sc64_check_presence (void); +void sc64_init (void); uint32_t sc64_query_config (cfg_id_t id); void sc64_change_config (cfg_id_t id, uint32_t value); -void sc64_get_info (sc64_info_t *info); -void sc64_init (void); +void sc64_get_boot_info (sc64_boot_info_t *info); void sc64_get_time (rtc_time_t *t); void sc64_set_time (rtc_time_t *t); -bool sc64_storage_init (drive_id_t drive); -bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_t count); -bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count); -void sc64_uart_print_string (const char *text); +bool sc64_write_usb_ready (void); +void sc64_write_usb (uint32_t *address, uint32_t length); +bool sc64_usb_read_ready (uint8_t *type, uint32_t *length); +void sc64_usb_read (uint32_t *address, uint32_t length); #endif diff --git a/sw/controller/.gitattributes b/sw/controller/.gitattributes new file mode 100644 index 0000000..18d0af0 --- /dev/null +++ b/sw/controller/.gitattributes @@ -0,0 +1 @@ +lib/** linguist-vendored diff --git a/sw/controller/src/cfg.c b/sw/controller/src/cfg.c index d838797..655c34f 100644 --- a/sw/controller/src/cfg.c +++ b/sw/controller/src/cfg.c @@ -5,13 +5,14 @@ #include "fpga.h" #include "isv.h" #include "rtc.h" +#include "usb.h" typedef enum { CFG_ID_BOOTLOADER_SWITCH, CFG_ID_ROM_WRITE_ENABLE, CFG_ID_ROM_SHADOW_ENABLE, - CFG_ID_DD_ENABLE, + CFG_ID_DD_MODE, CFG_ID_ISV_ENABLE, CFG_ID_BOOT_MODE, CFG_ID_SAVE_TYPE, @@ -23,13 +24,11 @@ typedef enum { } cfg_id_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; + DD_MODE_DISABLED = 0, + DD_MODE_REGS = 1, + DD_MODE_IPL = 2, + DD_MODE_FULL = 3 +} dd_mode_t; typedef enum { BOOT_MODE_MENU_SD = 0, @@ -39,17 +38,43 @@ typedef enum { BOOT_MODE_DIRECT = 4 } 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 { + CIC_SEED_UNKNOWN = 0xFFFF +} cic_seed_t; + +typedef enum { + TV_TYPE_PAL = 0, + TV_TYPE_NTSC = 1, + TV_TYPE_MPAL = 2, + TV_TYPE_UNKNOWN = 3 +} tv_type_t; + struct process { boot_mode_t boot_mode; save_type_t save_type; - uint16_t cic_seed; - uint8_t tv_type; + cic_seed_t cic_seed; + tv_type_t tv_type; + bool usb_output_ready; }; + static struct process p; +static void cfg_set_usb_output_ready (void) { + p.usb_output_ready = true; +} + static void change_scr_bits (uint32_t mask, bool value) { if (value) { fpga_reg_set(REG_CFG_SCR, fpga_reg_get(REG_CFG_SCR) | mask); @@ -101,18 +126,26 @@ uint32_t cfg_get_version (void) { } void cfg_query (uint32_t *args) { + uint32_t scr = fpga_reg_get(REG_CFG_SCR); + switch (args[0]) { case CFG_ID_BOOTLOADER_SWITCH: - args[1] = (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_BOOTLOADER_ENABLED); + args[1] = (scr & CFG_SCR_BOOTLOADER_ENABLED); break; case CFG_ID_ROM_WRITE_ENABLE: - args[1] = (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_ROM_WRITE_ENABLED); + args[1] = (scr & CFG_SCR_ROM_WRITE_ENABLED); break; case CFG_ID_ROM_SHADOW_ENABLE: - args[1] = (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_ROM_SHADOW_ENABLED); + args[1] = (scr & CFG_SCR_ROM_SHADOW_ENABLED); break; - case CFG_ID_DD_ENABLE: - args[1] = (fpga_reg_get(REG_CFG_SCR) & CFG_SCR_DD_ENABLED); + case CFG_ID_DD_MODE: + args[1] = DD_MODE_DISABLED; + if (scr & CFG_SCR_DDIPL_ENABLED) { + args[1] |= DD_MODE_IPL; + } + if (scr & CFG_SCR_DD_ENABLED) { + args[1] |= DD_MODE_REGS; + } break; case CFG_ID_ISV_ENABLE: args[1] = isv_get_enabled(); @@ -130,10 +163,13 @@ void cfg_query (uint32_t *args) { args[1] = p.tv_type; break; case CFG_ID_FLASH_ERASE_BLOCK: + args[1] = 0xFFFFFFFF; break; case CFG_ID_DD_DRIVE_TYPE: + args[1] = dd_get_drive_type(); break; case CFG_ID_DD_DISK_STATE: + args[1] = dd_get_disk_state(); break; } } @@ -149,8 +185,18 @@ void cfg_update (uint32_t *args) { case CFG_ID_ROM_SHADOW_ENABLE: change_scr_bits(CFG_SCR_ROM_SHADOW_ENABLED, args[1]); break; - case CFG_ID_DD_ENABLE: - change_scr_bits(CFG_SCR_DD_ENABLED | CFG_SCR_DDIPL_ENABLED, args[1]); + case CFG_ID_DD_MODE: + if (args[1] == DD_MODE_DISABLED) { + change_scr_bits(CFG_SCR_DD_ENABLED | CFG_SCR_DDIPL_ENABLED, false); + } else if (args[1] == DD_MODE_REGS) { + change_scr_bits(CFG_SCR_DD_ENABLED, true); + change_scr_bits(CFG_SCR_DDIPL_ENABLED, false); + } else if (args[1] == DD_MODE_IPL) { + change_scr_bits(CFG_SCR_DD_ENABLED, false); + change_scr_bits(CFG_SCR_DDIPL_ENABLED, true); + } else { + change_scr_bits(CFG_SCR_DD_ENABLED | CFG_SCR_DDIPL_ENABLED, true); + } break; case CFG_ID_ISV_ENABLE: isv_set_enabled(args[1]); @@ -163,10 +209,10 @@ void cfg_update (uint32_t *args) { set_save_type((save_type_t) (args[1])); break; case CFG_ID_CIC_SEED: - p.cic_seed = (uint16_t) (args[1] & 0xFFFF); + p.cic_seed = (cic_seed_t) (args[1] & 0xFFFF); break; case CFG_ID_TV_TYPE: - p.tv_type = (uint8_t) (args[1] & 0x03); + p.tv_type = (tv_type_t) (args[1] & 0x03); break; case CFG_ID_FLASH_ERASE_BLOCK: flash_erase_block(args[1]); @@ -199,19 +245,19 @@ void cfg_set_time (uint32_t *args) { rtc_set_time(&t); } - void cfg_init (void) { fpga_reg_set(REG_CFG_SCR, 0); set_save_type(SAVE_TYPE_NONE); - p.cic_seed = 0xFFFF; - p.tv_type = 0x03; + p.cic_seed = CIC_SEED_UNKNOWN; + p.tv_type = TV_TYPE_UNKNOWN; p.boot_mode = BOOT_MODE_MENU_SD; + p.usb_output_ready = true; } - void cfg_process (void) { uint32_t args[2]; + usb_tx_info_t packet_info; if (fpga_reg_get(REG_STATUS) & STATUS_CFG_PENDING) { args[0] = fpga_reg_get(REG_CFG_DATA_0); @@ -239,6 +285,32 @@ void cfg_process (void) { cfg_set_time(args); break; + case 'm': + if (!usb_prepare_read(args)) { + return; + } + break; + + case 'M': + usb_create_packet(&packet_info, PACKET_CMD_USB_OUTPUT); + packet_info.dma_length = args[1]; + packet_info.dma_address = args[0]; + packet_info.done_callback = cfg_set_usb_output_ready; + if (usb_enqueue_packet(&packet_info)) { + p.usb_output_ready = false; + } else { + return; + } + break; + + case 'u': + usb_get_read_info(args); + break; + + case 'U': + args[0] = p.usb_output_ready ? 1 : 0; + break; + default: fpga_reg_set(REG_CFG_CMD, CFG_CMD_ERROR | CFG_CMD_DONE); return; diff --git a/sw/controller/src/cic.c b/sw/controller/src/cic.c index 2eb696b..a7b92ec 100644 --- a/sw/controller/src/cic.c +++ b/sw/controller/src/cic.c @@ -1,3 +1,4 @@ +#include #include "cic.h" #include "hw.h" #include "rtc.h" @@ -290,18 +291,16 @@ static void cic_soft_reset (void) { task_yield(); } -void cic_set_dd_mode (bool enabled) { - cic_dd_mode = enabled; -} -void cic_set_seed (uint8_t seed) { - cic_seed = seed; -} - -void cic_set_checksum (uint8_t *checksum) { - for (int i = 0; i < 6; i++) { - cic_checksum[i] = checksum[i]; - } +void cic_set_parameters (uint32_t *args) { + cic_dd_mode = (args[0] >> 24) & 0x01; + cic_seed = (args[0] >> 16) & 0xFF; + cic_checksum[0] = (args[0] >> 8) & 0xFF; + cic_checksum[1] = args[0] & 0xFF; + cic_checksum[2] = (args[1] >> 24) & 0xFF; + cic_checksum[3] = (args[1] >> 16) & 0xFF; + cic_checksum[4] = (args[1] >> 8) & 0xFF; + cic_checksum[5] = args[1] & 0xFF; } void cic_hw_init (void) { diff --git a/sw/controller/src/cic.h b/sw/controller/src/cic.h index 66031f8..0a0cb11 100644 --- a/sw/controller/src/cic.h +++ b/sw/controller/src/cic.h @@ -2,13 +2,10 @@ #define CIC_H__ -#include #include -void cic_set_dd_mode (bool enabled); -void cic_set_seed (uint8_t seed); -void cic_set_checksum (uint8_t *checksum); +void cic_set_parameters (uint32_t *args); void cic_hw_init (void); void cic_task (void); diff --git a/sw/controller/src/dd.c b/sw/controller/src/dd.c index 2f0d5fc..8f3e71e 100644 --- a/sw/controller/src/dd.c +++ b/sw/controller/src/dd.c @@ -75,6 +75,7 @@ struct process { sector_info_t sector_info; bool block_ready; bool block_valid; + dd_drive_type_t drive_type; }; @@ -90,19 +91,18 @@ static uint16_t dd_track_head_block (void) { static bool dd_block_read_request (void) { usb_tx_info_t packet_info; - packet_info.cmd = PACKET_CMD_DD_REQUEST; + usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST); packet_info.data_length = 12; packet_info.data[0] = 1; packet_info.data[1] = DD_BLOCK_BUFFER_ADDRESS; packet_info.data[2] = dd_track_head_block(); - packet_info.dma_length = 0; p.block_ready = false; return usb_enqueue_packet(&packet_info); } static bool dd_block_write_request (void) { usb_tx_info_t packet_info; - packet_info.cmd = PACKET_CMD_DD_REQUEST; + usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST); packet_info.data_length = 12; packet_info.data[0] = 2; packet_info.data[1] = DD_BLOCK_BUFFER_ADDRESS; @@ -123,18 +123,35 @@ void dd_set_block_ready (bool valid) { p.block_valid = valid; } +dd_drive_type_t dd_get_drive_type (void) { + return p.drive_type; +} + void dd_set_drive_type (dd_drive_type_t type) { switch (type) { case DD_DRIVE_TYPE_RETAIL: fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_RETAIL); + p.drive_type = type; break; case DD_DRIVE_TYPE_DEVELOPMENT: fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_DEVELOPMENT); + p.drive_type = type; break; } } +dd_disk_state_t dd_get_disk_state (void) { + uint32_t scr = fpga_reg_get(REG_DD_SCR); + if (scr & DD_SCR_DISK_CHANGED) { + return DD_DISK_STATE_CHANGED; + } + if (scr & DD_SCR_DISK_INSERTED) { + return DD_DISK_STATE_INSERTED; + } + return DD_DISK_STATE_EJECTED; +} + void dd_set_disk_state (dd_disk_state_t state) { uint32_t scr = fpga_reg_get(REG_DD_SCR); scr &= ~(DD_SCR_DISK_CHANGED | DD_SCR_DISK_INSERTED); @@ -162,6 +179,7 @@ void dd_init (void) { p.cmd_response_ready = false; p.disk_spinning = false; p.bm_running = false; + p.drive_type = DD_DRIVE_TYPE_RETAIL; } void dd_process (void) { diff --git a/sw/controller/src/dd.h b/sw/controller/src/dd.h index 57e731c..ab0f624 100644 --- a/sw/controller/src/dd.h +++ b/sw/controller/src/dd.h @@ -17,7 +17,9 @@ typedef enum { } dd_disk_state_t; +dd_drive_type_t dd_get_drive_type (void); void dd_set_drive_type (dd_drive_type_t type); +dd_disk_state_t dd_get_disk_state (void); void dd_set_disk_state (dd_disk_state_t state); void dd_set_block_ready (bool valid); void dd_init (void); diff --git a/sw/controller/src/flashram.c b/sw/controller/src/flashram.c index df3cb8e..24cd792 100644 --- a/sw/controller/src/flashram.c +++ b/sw/controller/src/flashram.c @@ -6,9 +6,9 @@ #define FLASHRAM_SIZE (128 * 1024) #define FLASHRAM_SECTOR_SIZE (16 * 1024) #define FLASHRAM_PAGE_SIZE (128) +#define FLASHRAM_OFFSET (0x03FE0000UL) +#define FLASHRAM_BUFFER_OFFSET (0x06004000UL) -#define FLASHRAM_OFFSET ((64 * 1024 * 1024) - (128 * 1024)) -#define FLASHRAM_BUFFER_OFFSET (((64 + 32) * 1024 * 1024) + ((8 + 8) * 1024)) enum operation { OP_NONE, @@ -39,7 +39,6 @@ void flashram_init (void) { fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE); } - void flashram_process (void) { uint32_t scr = fpga_reg_get(REG_FLASHRAM_SCR); enum operation op = flashram_operation_type(scr); diff --git a/sw/controller/src/fpga.h b/sw/controller/src/fpga.h index 134da8a..ae9fa41 100644 --- a/sw/controller/src/fpga.h +++ b/sw/controller/src/fpga.h @@ -114,6 +114,8 @@ typedef enum { #define RTC_SCR_PENDING (1 << 0) #define RTC_SCR_DONE (1 << 1) +#define RTC_SCR_MAGIC (0x52544300) +#define RTC_SCR_MAGIC_MASK (0xFFFFFF00) #define SD_SCR_CLOCK_MODE_OFF (0 << 0) #define SD_SCR_CLOCK_MODE_400KHZ (1 << 0) diff --git a/sw/controller/src/hw.c b/sw/controller/src/hw.c index 113016e..db03ebf 100644 --- a/sw/controller/src/hw.c +++ b/sw/controller/src/hw.c @@ -38,6 +38,7 @@ typedef enum { GPIO_AF_7 = 0x07 } gpio_af_t; + typedef struct { void (*volatile falling)(void); void (*volatile rising)(void); @@ -46,12 +47,10 @@ typedef struct { static const GPIO_TypeDef *gpios[] = { GPIOA, GPIOB }; static gpio_irq_callback_t gpio_irq_callbacks[16]; - static volatile uint8_t *i2c_data_txptr; static volatile uint8_t *i2c_data_rxptr; static volatile uint32_t i2c_next_cr2; static void (*volatile i2c_callback)(void); - static const TIM_TypeDef *tims[] = { TIM14, TIM16, TIM17, TIM3 }; static void (*volatile tim_callbacks[4])(void); @@ -198,6 +197,12 @@ void hw_i2c_enable_irq (void) { } void hw_tim_setup (tim_id_t id, uint16_t delay, void (*callback)(void)) { + if (delay == 0) { + if (callback) { + callback(); + } + return; + } TIM_TypeDef *tim = ((TIM_TypeDef *) (tims[id])); tim->CR1 = (TIM_CR1_OPM | TIM_CR1_URS); tim->PSC = (64000 - 1); @@ -362,6 +367,7 @@ void hw_init (void) { NVIC_EnableIRQ(TIM3_IRQn); } + void EXTI0_1_IRQHandler (void) { for (int i = 0; i <= 1; i++) { if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) { diff --git a/sw/controller/src/isv.c b/sw/controller/src/isv.c index 99f6910..feefc95 100644 --- a/sw/controller/src/isv.c +++ b/sw/controller/src/isv.c @@ -13,6 +13,7 @@ struct process { uint32_t current_read_pointer; }; + static struct process p; @@ -29,9 +30,11 @@ static uint32_t isv_get_read_pointer (void) { void isv_set_enabled (bool enabled) { + uint32_t read_pointer = 0; if (enabled) { p.enabled = true; p.current_read_pointer = 0; + fpga_mem_write(ISV_READ_POINTER_ADDRESS, 4, (uint8_t *) (&read_pointer)); } else { p.enabled = false; } @@ -55,8 +58,7 @@ void isv_process (void) { uint32_t offset = ISV_BUFFER_ADDRESS + p.current_read_pointer; usb_tx_info_t packet_info; - packet_info.cmd = PACKET_CMD_ISV_OUTPUT; - packet_info.data_length = 0; + usb_create_packet(&packet_info, PACKET_CMD_ISV_OUTPUT); packet_info.dma_length = length; packet_info.dma_address = offset; if (usb_enqueue_packet(&packet_info)) { diff --git a/sw/controller/src/rtc.c b/sw/controller/src/rtc.c index 5f3fecc..6d2d7b9 100644 --- a/sw/controller/src/rtc.c +++ b/sw/controller/src/rtc.c @@ -26,7 +26,6 @@ static uint8_t rtc_region = 0xFF; static volatile bool rtc_region_pending = false; - static rtc_time_t rtc_time = { .second = 0x00, .minute = 0x00, @@ -174,6 +173,7 @@ static void rtc_init (void) { } } + bool rtc_get_time (rtc_time_t *time) { bool vaild; @@ -248,8 +248,9 @@ void rtc_task (void) { void rtc_process (void) { rtc_time_t time; uint32_t data[2]; + uint32_t scr = fpga_reg_get(REG_RTC_SCR); - if (fpga_reg_get(REG_RTC_SCR) & RTC_SCR_PENDING) { + if ((scr & RTC_SCR_PENDING) && ((scr & RTC_SCR_MAGIC_MASK) == RTC_SCR_MAGIC)) { data[0] = fpga_reg_get(REG_RTC_TIME_0); data[1] = fpga_reg_get(REG_RTC_TIME_1); diff --git a/sw/controller/src/task.c b/sw/controller/src/task.c index 3c5aa6c..92dd743 100644 --- a/sw/controller/src/task.c +++ b/sw/controller/src/task.c @@ -12,6 +12,7 @@ typedef enum { TASK_FLAG_RESET = (1 << 1), } task_flags_t; + typedef struct { uint32_t initial_pc; uint32_t initial_sp; @@ -62,6 +63,7 @@ static uint32_t task_switch_context (uint32_t sp) { return task_table[task_current].sp; } + void task_create (task_id_t id, void (*code)(void), void *stack, size_t stack_size) { if (id < __TASK_ID_MAX) { task_t *task = &task_table[id]; @@ -110,6 +112,7 @@ __attribute__((naked)) void task_scheduler_start (void) { while (1); } + __attribute__((naked)) void PendSV_Handler (void) { asm volatile ( "mrs r1, psp \n" diff --git a/sw/controller/src/usb.c b/sw/controller/src/usb.c index ea25f1c..5f4f1b1 100644 --- a/sw/controller/src/usb.c +++ b/sw/controller/src/usb.c @@ -1,5 +1,6 @@ #include #include +#include "cic.h" #include "dd.h" #include "cfg.h" #include "fpga.h" @@ -42,6 +43,10 @@ struct process { bool packet_pending; usb_tx_info_t packet_info; + + bool read_ready; + uint32_t read_length; + uint32_t read_address; }; @@ -54,6 +59,10 @@ static const uint32_t ERR_TOKEN = (0x45525200UL); static const uint32_t PKT_TOKEN = (0x504B5400UL); +static bool usb_dma_ready (void) { + return !((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY)); +} + static bool usb_rx_byte (uint8_t *data) { if (fpga_usb_status_get() & USB_STATUS_RXNE) { *data = fpga_usb_pop(); @@ -119,7 +128,6 @@ static bool usb_rx_cmd (uint8_t *cmd) { return false; } - static void usb_rx_process (void) { if (p.rx_state == RX_STATE_IDLE) { if (!p.response_pending && usb_rx_cmd(&p.rx_cmd)) { @@ -130,6 +138,7 @@ static void usb_rx_process (void) { p.response_info.cmd = p.rx_cmd; p.response_info.data_length = 0; p.response_info.dma_length = 0; + p.response_info.done_callback = NULL; } } @@ -153,6 +162,12 @@ static void usb_rx_process (void) { p.response_info.data[0] = cfg_get_version(); break; + case 'B': + cic_set_parameters(p.rx_args); + p.rx_state = RX_STATE_IDLE; + p.response_pending = true; + break; + case 'c': cfg_query(p.rx_args); p.rx_state = RX_STATE_IDLE; @@ -197,7 +212,7 @@ static void usb_rx_process (void) { case 'M': case 'D': - if (!((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY))) { + if (usb_dma_ready()) { if (!p.rx_dma_running) { fpga_reg_set(REG_USB_DMA_ADDRESS, p.rx_args[0]); fpga_reg_set(REG_USB_DMA_LENGTH, p.rx_args[1]); @@ -213,6 +228,27 @@ static void usb_rx_process (void) { } break; + case 'U': + if ((p.read_length > 0) && usb_dma_ready()) { + uint32_t length = (p.read_length > p.rx_args[1]) ? p.rx_args[1] : p.read_length; + if (!p.rx_dma_running) { + fpga_reg_set(REG_USB_DMA_ADDRESS, p.read_address); + fpga_reg_set(REG_USB_DMA_LENGTH, length); + fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_DIRECTION | DMA_SCR_START); + p.rx_dma_running = true; + p.read_ready = false; + } else { + p.rx_args[1] -= length; + p.read_length -= length; + p.read_address += length; + p.read_ready = true; + if (p.rx_args[1] == 0) { + p.rx_state = RX_STATE_IDLE; + } + } + } + break; + default: p.rx_state = RX_STATE_IDLE; p.response_pending = true; @@ -273,7 +309,7 @@ static void usb_tx_process (void) { if (p.tx_state == TX_STATE_DMA) { if (p.tx_info.dma_length > 0) { - if (!((fpga_reg_get(REG_USB_DMA_SCR) & DMA_SCR_BUSY))) { + if (usb_dma_ready()) { if (!p.tx_dma_running) { p.tx_dma_running = true; fpga_reg_set(REG_USB_DMA_ADDRESS, p.tx_info.dma_address); @@ -290,11 +326,25 @@ static void usb_tx_process (void) { if (p.tx_state == TX_STATE_FLUSH) { fpga_reg_set(REG_USB_SCR, USB_SCR_WRITE_FLUSH); + if (p.tx_info.done_callback) { + p.tx_info.done_callback(); + } p.tx_state = TX_STATE_IDLE; } } +void usb_create_packet (usb_tx_info_t *info, uint8_t cmd) { + info->cmd = cmd; + info->data_length = 0; + for (int i = 0; i < 4; i++) { + info->data[i] = 0; + } + info->dma_length = 0; + info->dma_address = 0; + info->done_callback = NULL; +} + bool usb_enqueue_packet (usb_tx_info_t *info) { if (p.packet_pending) { return false; @@ -306,6 +356,25 @@ bool usb_enqueue_packet (usb_tx_info_t *info) { return true; } +bool usb_prepare_read (uint32_t *args) { + if (!p.read_ready) { + return false; + } + p.read_length = args[1]; + p.read_address = args[0]; + return true; +} + +void usb_get_read_info (uint32_t *args) { + args[0] = 0; + args[1] = 0; + if (p.rx_state == RX_STATE_DATA && p.rx_cmd == 'U') { + args[0] = p.rx_args[0] & 0xFF; + args[1] = p.rx_args[1]; + } + args[0] |= (p.read_length > 0) ? (1 << 24) : 0; +} + void usb_init (void) { fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_STOP); fpga_reg_set(REG_USB_SCR, USB_SCR_FIFO_FLUSH); @@ -316,6 +385,10 @@ void usb_init (void) { p.response_pending = false; p.packet_pending = false; + p.read_ready = true; + p.read_length = 0; + p.read_address = 0; + usb_rx_word_counter = 0; usb_rx_word_buffer = 0; usb_tx_word_counter = 0; @@ -324,6 +397,9 @@ void usb_init (void) { void usb_process (void) { if (fpga_reg_get(REG_USB_SCR) & USB_SCR_RESET_PENDING) { + if (p.tx_state != TX_STATE_IDLE && p.tx_info.done_callback) { + p.tx_info.done_callback(); + } usb_init(); fpga_reg_set(REG_USB_SCR, USB_SCR_RESET_ACK); } else { diff --git a/sw/controller/src/usb.h b/sw/controller/src/usb.h index 8765624..33bf286 100644 --- a/sw/controller/src/usb.h +++ b/sw/controller/src/usb.h @@ -9,6 +9,7 @@ typedef enum packet_cmd { PACKET_CMD_DD_REQUEST = 'D', PACKET_CMD_ISV_OUTPUT = 'I', + PACKET_CMD_USB_OUTPUT = 'U', } usb_packet_cmd_e; @@ -18,10 +19,14 @@ typedef struct usb_tx_info { uint32_t data[4]; uint32_t dma_length; uint32_t dma_address; + void (*done_callback)(void); } usb_tx_info_t; +void usb_create_packet (usb_tx_info_t *info, uint8_t cmd); bool usb_enqueue_packet (usb_tx_info_t *info); +bool usb_prepare_read (uint32_t *args); +void usb_get_read_info (uint32_t *args); void usb_init (void); void usb_process (void);