diff --git a/fw/rtl/n64/n64_pi.sv b/fw/rtl/n64/n64_pi.sv index 8a2b6f1..e268c41 100644 --- a/fw/rtl/n64/n64_pi.sv +++ b/fw/rtl/n64/n64_pi.sv @@ -236,6 +236,13 @@ module n64_pi ( end if (n64_scb.cfg_unlock) begin + if (n64_pi_dq_in >= 16'h1FFC && n64_pi_dq_in < 16'h1FFE) begin + read_port <= PORT_MEM; + write_port <= PORT_NONE; + mem_offset <= (-32'h1FFC_0000) + SHADOW_OFFSET; + n64_scb.pi_flash_active <= 1'b1; + end + if (n64_pi_dq_in >= 16'h1FFE && n64_pi_dq_in < 16'h1FFF) begin read_port <= PORT_MEM; write_port <= PORT_MEM; diff --git a/sw/bootloader/src/sc64.c b/sw/bootloader/src/sc64.c index d8b1994..b452878 100644 --- a/sw/bootloader/src/sc64.c +++ b/sw/bootloader/src/sc64.c @@ -20,6 +20,8 @@ typedef enum { SC64_CMD_SD_WRITE = 'S', SC64_CMD_SD_READ = 's', SC64_CMD_DD_SD_DISK_INFO = 'D', + SC64_CMD_FLASH_ERASE_BLOCK = 'P', + SC64_CMD_FLASH_WAIT_BUSY = 'p', } cmd_id_t; typedef enum { @@ -166,13 +168,13 @@ bool sc64_sd_card_deinit (void) { return false; } -bool sc64_sd_card_get_status (void) { +sd_card_status_t sc64_sd_card_get_status (void) { uint32_t args[2] = { 0, SD_CARD_OP_GET_STATUS }; uint32_t result[2]; if (sc64_execute_cmd(SC64_CMD_SD_CARD_OP, args, result)) { return false; } - return result[1]; + return (sd_card_status_t) (result[1]); } bool sc64_sd_card_get_info (uint32_t *address) { diff --git a/sw/bootloader/src/sc64.h b/sw/bootloader/src/sc64.h index 311661e..5768ff4 100644 --- a/sw/bootloader/src/sc64.h +++ b/sw/bootloader/src/sc64.h @@ -24,13 +24,12 @@ typedef enum { CFG_ID_SAVE_TYPE, CFG_ID_CIC_SEED, CFG_ID_TV_TYPE, - CFG_ID_FLASH_ERASE_BLOCK, + CFG_ID_DD_SD_MODE, CFG_ID_DD_DRIVE_TYPE, CFG_ID_DD_DISK_STATE, CFG_ID_BUTTON_STATE, CFG_ID_BUTTON_MODE, CFG_ID_ROM_EXTENDED_ENABLE, - CFG_ID_DD_SD_MODE, } cfg_id_t; typedef enum { @@ -74,6 +73,12 @@ typedef enum { BUTTON_MODE_DD_DISK_SWAP, } button_mode_t; +typedef enum { + SD_CARD_STATUS_INITIALIZED = (1 << 0), + SD_CARD_STATUS_TYPE_BLOCK = (1 << 1), + SD_CARD_STATUS_50MHZ_MODE = (1 << 2), +} sd_card_status_t; + typedef struct { boot_mode_t boot_mode; @@ -107,7 +112,7 @@ bool sc64_usb_read_ready (uint8_t *type, uint32_t *length); bool sc64_usb_read (uint32_t *address, uint32_t length); bool sc64_sd_card_init (void); bool sc64_sd_card_deinit (void); -bool sc64_sd_card_get_status (void); +sd_card_status_t sc64_sd_card_get_status (void); 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); diff --git a/sw/bootloader/src/test.c b/sw/bootloader/src/test.c index 277e025..5095ccd 100644 --- a/sw/bootloader/src/test.c +++ b/sw/bootloader/src/test.c @@ -13,6 +13,7 @@ bool test_check (void) { } void test_execute (void) { + sd_card_status_t card_status; uint8_t card_info[32] __attribute__((aligned(8))); display_init(NULL); @@ -24,6 +25,18 @@ void test_execute (void) { while (1); } + card_status = sc64_sd_card_get_status(); + + if (card_status & SD_CARD_STATUS_INITIALIZED) { + display_printf("SD card initialized\n"); + } + if (card_status & SD_CARD_STATUS_TYPE_BLOCK) { + display_printf("SD card type block\n"); + } + if (card_status & SD_CARD_STATUS_50MHZ_MODE) { + display_printf("SD card 50 MHz clock mode\n"); + } + if (sc64_sd_card_get_info((uint32_t *) (SC64_BUFFERS->BUFFER))) { display_printf("SD card get info error!\n"); while (1); diff --git a/sw/controller/src/cfg.c b/sw/controller/src/cfg.c index 559a1b6..bbb5fd3 100644 --- a/sw/controller/src/cfg.c +++ b/sw/controller/src/cfg.c @@ -19,13 +19,12 @@ typedef enum { CFG_ID_SAVE_TYPE, CFG_ID_CIC_SEED, CFG_ID_TV_TYPE, - CFG_ID_FLASH_ERASE_BLOCK, + CFG_ID_DD_SD_MODE, CFG_ID_DD_DRIVE_TYPE, CFG_ID_DD_DISK_STATE, CFG_ID_BUTTON_STATE, CFG_ID_BUTTON_MODE, CFG_ID_ROM_EXTENDED_ENABLE, - CFG_ID_DD_SD_MODE, } cfg_id_t; typedef enum { @@ -72,6 +71,19 @@ typedef enum { CFG_ERROR_UNKNOWN_CMD = -1, } cfg_error_t; +typedef enum { + SD_CARD_OP_DEINIT = 0, + SD_CARD_OP_INIT = 1, + SD_CARD_OP_GET_STATUS = 2, + SD_CARD_OP_GET_INFO = 3, +} sd_card_op_t; + +typedef enum { + SDRAM = (1 << 0), + FLASH = (1 << 1), + BRAM = (1 << 2), +} translate_type_t; + struct process { boot_mode_t boot_mode; @@ -90,45 +102,57 @@ static void cfg_set_usb_output_ready (void) { p.usb_output_ready = true; } -static bool cfg_translate_address (uint32_t *address, uint32_t length, bool with_flash) { +static bool cfg_translate_address (uint32_t *address, uint32_t length, translate_type_t type) { if (length == 0) { return true; } *address &= 0x1FFFFFFF; - if (*address >= 0x06000000 && *address < 0x06400000) { - if ((*address + length) <= 0x06400000) { - *address = *address - 0x06000000 + 0x03BC0000; - return false; + if (type & SDRAM) { + if (*address >= 0x06000000 && *address < 0x06400000) { + if ((*address + length) <= 0x06400000) { + *address = *address - 0x06000000 + 0x03BC0000; + return false; + } + } + if (*address >= 0x08000000 && *address < 0x08020000) { + if ((*address + length) <= 0x08020000) { + *address = *address - 0x08000000 + 0x03FE0000; + return false; + } + } + if (*address >= 0x10000000 && *address < 0x14000000) { + if ((*address + length) <= 0x14000000) { + *address = *address - 0x10000000 + 0x00000000; + return false; + } } } - if (*address >= 0x08000000 && *address < 0x08020000) { - if ((*address + length) <= 0x08020000) { - *address = *address - 0x08000000 + 0x03FE0000; - return false; + if (type & FLASH) { + if (*address >= 0x14000000 && *address < 0x14E00000) { + if ((*address + length) <= 0x14E00000) { + *address = *address - 0x14000000 + 0x04000000; + return false; + } + } + if (*address >= 0x1FFC0000 && *address < 0x1FFE0000) { + if ((*address + length) <= 0x1FFE0000) { + *address = *address - 0x1FFC0000 + 0x04E00000; + return false; + } } } - if (*address >= 0x10000000 && *address < 0x14000000) { - if ((*address + length) <= 0x14000000) { - *address = *address - 0x10000000 + 0x00000000; - return false; + if (type & BRAM) { + if (*address >= 0x1FFE0000 && *address < 0x1FFE2000) { + if ((*address + length) <= 0x1FFE2000) { + *address = *address - 0x1FFE0000 + 0x05000000; + return false; + } } - } - if (with_flash && *address >= 0x14000000 && *address < 0x15000000) { - if ((*address + length) <= 0x15000000) { - *address = *address - 0x14000000 + 0x04000000; - return false; - } - } - if (*address >= 0x1FFE0000 && *address < 0x1FFE2000) { - if ((*address + length) <= 0x1FFE2000) { - *address = *address - 0x1FFE0000 + 0x05000000; - return false; - } - } - if (*address >= 0x1FFE2000 && *address < 0x1FFE2800) { - if ((*address + length) <= 0x1FFE2800) { - *address = *address - 0x1FFE2000 + 0x05002000; - return false; + if (*address >= 0x1FFE2000 && *address < 0x1FFE2800) { + if ((*address + length) <= 0x1FFE2800) { + *address = *address - 0x1FFE2000 + 0x05002000; + return false; + } } } return true; @@ -227,9 +251,6 @@ bool cfg_query (uint32_t *args) { case CFG_ID_TV_TYPE: args[1] = p.tv_type; break; - case CFG_ID_FLASH_ERASE_BLOCK: - args[1] = FLASH_ERASE_BLOCK_SIZE; - break; case CFG_ID_DD_DRIVE_TYPE: args[1] = dd_get_drive_type(); break; @@ -295,9 +316,6 @@ bool cfg_update (uint32_t *args) { case CFG_ID_TV_TYPE: p.tv_type = (tv_type_t) (args[1] & 0x03); break; - case CFG_ID_FLASH_ERASE_BLOCK: - flash_erase_block(args[1]); - break; case CFG_ID_DD_DRIVE_TYPE: dd_set_drive_type(args[1]); break; @@ -341,7 +359,7 @@ void cfg_set_time (uint32_t *args) { rtc_set_time(&t); } -void cfg_reset (void) { +void cfg_reset_state (void) { uint32_t mask = ( CFG_SCR_BOOTLOADER_SKIP | CFG_SCR_ROM_WRITE_ENABLED | @@ -364,7 +382,7 @@ void cfg_reset (void) { void cfg_init (void) { fpga_reg_set(REG_CFG_SCR, CFG_SCR_BOOTLOADER_ENABLED); - cfg_reset(); + cfg_reset_state(); p.usb_output_ready = true; } @@ -412,7 +430,7 @@ void cfg_process (void) { break; case 'm': - if (cfg_translate_address(&args[0], args[1], false)) { + if (cfg_translate_address(&args[0], args[1], (SDRAM | BRAM))) { cfg_set_error(CFG_ERROR_BAD_ADDRESS); return; } @@ -422,7 +440,7 @@ void cfg_process (void) { break; case 'M': - if (cfg_translate_address(&args[0], args[1] & 0xFFFFFF, false)) { + if (cfg_translate_address(&args[0], args[1] & 0xFFFFFF, (SDRAM | BRAM))) { cfg_set_error(CFG_ERROR_BAD_ADDRESS); return; } @@ -449,20 +467,20 @@ void cfg_process (void) { case 'i': switch (args[1]) { - case 0: + case SD_CARD_OP_DEINIT: sd_card_deinit(); break; - case 1: + case SD_CARD_OP_INIT: if (sd_card_init()) { cfg_set_error(CFG_ERROR_SD_CARD); return; } break; - case 2: + case SD_CARD_OP_GET_STATUS: args[1] = sd_card_get_status(); break; - case 3: - if (cfg_translate_address(&args[0], 32, false)) { + case SD_CARD_OP_GET_INFO: + if (cfg_translate_address(&args[0], 32, (SDRAM | BRAM))) { cfg_set_error(CFG_ERROR_BAD_ADDRESS); return; } @@ -486,7 +504,7 @@ void cfg_process (void) { cfg_set_error(CFG_ERROR_BAD_ARGUMENT); return; } - if (cfg_translate_address(&args[0], args[1] * SD_SECTOR_SIZE, true)) { + if (cfg_translate_address(&args[0], args[1] * SD_SECTOR_SIZE, (SDRAM | BRAM | FLASH))) { cfg_set_error(CFG_ERROR_BAD_ADDRESS); return; } @@ -501,7 +519,7 @@ void cfg_process (void) { cfg_set_error(CFG_ERROR_BAD_ARGUMENT); return; } - if (cfg_translate_address(&args[0], args[1] * SD_SECTOR_SIZE, true)) { + if (cfg_translate_address(&args[0], args[1] * SD_SECTOR_SIZE, (SDRAM | BRAM | FLASH))) { cfg_set_error(CFG_ERROR_BAD_ADDRESS); return; } @@ -510,15 +528,28 @@ void cfg_process (void) { return; } break; - + case 'D': - if (cfg_translate_address(&args[0], args[1], false)) { + if (cfg_translate_address(&args[0], args[1], (SDRAM | BRAM))) { cfg_set_error(CFG_ERROR_BAD_ADDRESS); return; } dd_set_sd_disk_info(args[0], args[1]); break; + case 'p': + flash_wait_busy(); + args[0] = FLASH_ERASE_BLOCK_SIZE; + break; + + case 'P': + if (cfg_translate_address(&args[0], FLASH_ERASE_BLOCK_SIZE, FLASH)) { + cfg_set_error(CFG_ERROR_BAD_ADDRESS); + return; + } + flash_erase_block(args[0]); + break; + case '?': args[0] = fpga_reg_get(REG_DEBUG); break; diff --git a/sw/controller/src/cfg.h b/sw/controller/src/cfg.h index 9b58610..8ca463b 100644 --- a/sw/controller/src/cfg.h +++ b/sw/controller/src/cfg.h @@ -11,7 +11,7 @@ bool cfg_query (uint32_t *args); bool cfg_update (uint32_t *args); void cfg_get_time (uint32_t *args); void cfg_set_time (uint32_t *args); -void cfg_reset (void); +void cfg_reset_state (void); void cfg_init (void); void cfg_process (void); diff --git a/sw/controller/src/flash.c b/sw/controller/src/flash.c index 1c0f602..bca24aa 100644 --- a/sw/controller/src/flash.c +++ b/sw/controller/src/flash.c @@ -2,16 +2,20 @@ #include "fpga.h" +#define FLASH_ADDRESS (0x04000000UL) #define ERASE_BLOCK_SIZE (64 * 1024) -void flash_erase_block (uint32_t offset) { +void flash_wait_busy (void) { uint8_t dummy[2]; + fpga_mem_read(FLASH_ADDRESS, 2, dummy); +} - for (int i = 0; i < 2; i++) { - while (fpga_reg_get(REG_FLASH_SCR) & FLASH_SCR_BUSY); +void flash_erase_block (uint32_t offset) { + for (int i = 0; i < (FLASH_ERASE_BLOCK_SIZE / ERASE_BLOCK_SIZE); i++) { fpga_reg_set(REG_FLASH_SCR, offset); - fpga_mem_read(offset, 2, dummy); + while (fpga_reg_get(REG_FLASH_SCR) & FLASH_SCR_BUSY); offset += ERASE_BLOCK_SIZE; } + flash_wait_busy(); } diff --git a/sw/controller/src/flash.h b/sw/controller/src/flash.h index 1b65424..a60d010 100644 --- a/sw/controller/src/flash.h +++ b/sw/controller/src/flash.h @@ -8,6 +8,7 @@ #define FLASH_ERASE_BLOCK_SIZE (128 * 1024) +void flash_wait_busy (void); void flash_erase_block (uint32_t offset); diff --git a/sw/controller/src/fpga.h b/sw/controller/src/fpga.h index 63bdd9c..e9082cd 100644 --- a/sw/controller/src/fpga.h +++ b/sw/controller/src/fpga.h @@ -128,6 +128,8 @@ typedef enum { #define SD_SCR_CLOCK_MODE_400KHZ (1 << 0) #define SD_SCR_CLOCK_MODE_25MHZ (2 << 0) #define SD_SCR_CLOCK_MODE_50MHZ (3 << 0) +#define SD_SCR_CLOCK_MODE_BIT (0) +#define SD_SCR_CLOCK_MODE_MASK (0x3 << SD_SCR_CLOCK_MODE_BIT) #define SD_SCR_CMD_BUSY (1 << 2) #define SD_SCR_CMD_ERROR (1 << 3) #define SD_SCR_CARD_BUSY (1 << 4) diff --git a/sw/controller/src/sd.c b/sw/controller/src/sd.c index 6a82406..5202da5 100644 --- a/sw/controller/src/sd.c +++ b/sw/controller/src/sd.c @@ -339,8 +339,16 @@ void sd_card_deinit (void) { } } -bool sd_card_get_status (void) { - return p.card_initialized; +uint32_t sd_card_get_status (void) { + uint32_t scr = fpga_reg_get(REG_SD_SCR); + uint32_t clock_mode_50mhz = ((scr & SD_SCR_CLOCK_MODE_MASK) == SD_SCR_CLOCK_MODE_50MHZ) ? 1 : 0; + uint32_t card_type_block = p.card_type_block ? 1 : 0; + uint32_t initialized = p.card_initialized ? 1 : 0; + return ( + (clock_mode_50mhz << 2) | + (card_type_block << 1) | + (initialized << 0) + ); } bool sd_card_get_info (uint32_t address) { diff --git a/sw/controller/src/sd.h b/sw/controller/src/sd.h index 54d8dd3..40445a5 100644 --- a/sw/controller/src/sd.h +++ b/sw/controller/src/sd.h @@ -10,7 +10,7 @@ bool sd_card_init (void); void sd_card_deinit (void); -bool sd_card_get_status (void); +uint32_t sd_card_get_status (void); bool sd_card_get_info (uint32_t address); 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); diff --git a/sw/controller/src/usb.c b/sw/controller/src/usb.c index 386505f..08cec3e 100644 --- a/sw/controller/src/usb.c +++ b/sw/controller/src/usb.c @@ -162,7 +162,7 @@ static void usb_rx_process (void) { break; case 'R': - cfg_reset(); + cfg_reset_state(); cic_reset_parameters(); p.rx_state = RX_STATE_IDLE; p.response_pending = true; @@ -275,6 +275,20 @@ static void usb_rx_process (void) { } break; + case 'p': + flash_wait_busy(); + p.rx_state = RX_STATE_IDLE; + p.response_pending = true; + p.response_info.data_length = 4; + p.response_info.data[0] = FLASH_ERASE_BLOCK_SIZE; + break; + + case 'P': + flash_erase_block(p.rx_args[0]); + p.rx_state = RX_STATE_IDLE; + p.response_pending = true; + break; + case '?': p.rx_state = RX_STATE_IDLE; p.response_pending = true; diff --git a/sw/pc/sc64.py b/sw/pc/sc64.py index 7fc56ca..8df32f9 100755 --- a/sw/pc/sc64.py +++ b/sw/pc/sc64.py @@ -235,13 +235,12 @@ class SC64: SAVE_TYPE = 6 CIC_SEED = 7 TV_TYPE = 8 - FLASH_ERASE_BLOCK = 9 + DD_SD_MODE = 9 DD_DRIVE_TYPE = 10 DD_DISK_STATE = 11 BUTTON_STATE = 12 BUTTON_MODE = 13 ROM_EXTENDED_ENABLE = 14 - DD_SD_MODE = 15 class __UpdateError(IntEnum): OK = 0 @@ -342,17 +341,25 @@ class SC64: if (length > 0): return self.__link.execute_cmd(cmd=b'm', args=[address, length], timeout=20.0) return bytes([]) + + def __flash_wait_busy(self) -> int: + data = self.__link.execute_cmd(cmd=b'p') + return self.__get_int(data[0:4]) + + def __flash_erase_block(self, address: int) -> None: + self.__link.execute_cmd(cmd=b'P', args=[address, 0]) def __erase_flash_region(self, address: int, length: int) -> None: if (address < self.__Address.FLASH): raise ValueError('Flash erase address or length outside of possible range') if ((address + length) > (self.__Address.FLASH + self.__Length.FLASH)): raise ValueError('Flash erase address or length outside of possible range') - erase_block_size = self.__get_config(self.__CfgId.FLASH_ERASE_BLOCK) + erase_block_size = self.__flash_wait_busy() if (address % erase_block_size != 0): raise ValueError('Flash erase address not aligned to block size') for offset in range(address, address + length, erase_block_size): - self.__set_config(self.__CfgId.FLASH_ERASE_BLOCK, offset) + self.__flash_erase_block(offset) + self.__flash_wait_busy() def __program_flash(self, address: int, data: bytes): program_chunk_size = (128 * 1024) @@ -377,13 +384,12 @@ class SC64: 'save_type': self.SaveType(self.__get_config(self.__CfgId.SAVE_TYPE)), 'cic_seed': self.CICSeed(self.__get_config(self.__CfgId.CIC_SEED)), 'tv_type': self.TVType(self.__get_config(self.__CfgId.TV_TYPE)), - 'flash_erase_block': self.__get_config(self.__CfgId.FLASH_ERASE_BLOCK), + 'dd_sd_mode': bool(self.__get_config(self.__CfgId.DD_SD_MODE)), 'dd_drive_type': self.__DDDriveType(self.__get_config(self.__CfgId.DD_DRIVE_TYPE)), 'dd_disk_state': self.__DDDiskState(self.__get_config(self.__CfgId.DD_DISK_STATE)), 'button_state': bool(self.__get_config(self.__CfgId.BUTTON_STATE)), 'button_mode': self.__ButtonMode(self.__get_config(self.__CfgId.BUTTON_MODE)), 'rom_extended_enable': bool(self.__get_config(self.__CfgId.ROM_EXTENDED_ENABLE)), - 'dd_sd_mode': bool(self.__get_config(self.__CfgId.DD_SD_MODE)), } def debug_send(self, datatype: __DebugDatatype, data: bytes) -> None: