flash erase method change

This commit is contained in:
Polprzewodnikowy 2022-09-30 01:36:53 +02:00
parent 2ce73c03bf
commit fa561b4728
13 changed files with 164 additions and 71 deletions

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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;
}
@ -512,13 +530,26 @@ void cfg_process (void) {
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;

View File

@ -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);

View File

@ -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();
}

View File

@ -8,6 +8,7 @@
#define FLASH_ERASE_BLOCK_SIZE (128 * 1024)
void flash_wait_busy (void);
void flash_erase_block (uint32_t offset);

View File

@ -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)

View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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
@ -343,16 +342,24 @@ class SC64:
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: