mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-28 08:24:14 +01:00
[SC64][SW] bootloader/controller: added more meaningful errors in the SD card module
Also added manual CRC16 check in the software for data blocks smaller than 512 bytes
This commit is contained in:
parent
92838da349
commit
e6751c262d
@ -10,6 +10,9 @@
|
|||||||
#define BUFFER_BLOCKS_MAX (sizeof(SC64_BUFFERS->BUFFER) / SD_SECTOR_SIZE)
|
#define BUFFER_BLOCKS_MAX (sizeof(SC64_BUFFERS->BUFFER) / SD_SECTOR_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
sc64_error_t sc64_error_fatfs;
|
||||||
|
|
||||||
|
|
||||||
DSTATUS disk_status (BYTE pdrv) {
|
DSTATUS disk_status (BYTE pdrv) {
|
||||||
if (pdrv > 0) {
|
if (pdrv > 0) {
|
||||||
return STA_NODISK;
|
return STA_NODISK;
|
||||||
@ -20,7 +23,7 @@ DSTATUS disk_status (BYTE pdrv) {
|
|||||||
sc64_sd_card_status_t sd_card_status;
|
sc64_sd_card_status_t sd_card_status;
|
||||||
|
|
||||||
if ((error = sc64_sd_card_get_status(&sd_card_status)) != SC64_OK) {
|
if ((error = sc64_sd_card_get_status(&sd_card_status)) != SC64_OK) {
|
||||||
error_display("Could not get SD card status: %d", error);
|
error_display("Could not get SD card status\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sd_card_status & SD_CARD_STATUS_INSERTED)) {
|
if (!(sd_card_status & SD_CARD_STATUS_INSERTED)) {
|
||||||
@ -38,7 +41,7 @@ DSTATUS disk_initialize (BYTE pdrv) {
|
|||||||
return STA_NODISK;
|
return STA_NODISK;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc64_sd_card_init();
|
sc64_error_fatfs = sc64_sd_card_init();
|
||||||
|
|
||||||
return disk_status(pdrv);
|
return disk_status(pdrv);
|
||||||
}
|
}
|
||||||
@ -53,7 +56,7 @@ DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
|||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
uint32_t blocks = ((count > BUFFER_BLOCKS_MAX) ? BUFFER_BLOCKS_MAX : count);
|
uint32_t blocks = ((count > BUFFER_BLOCKS_MAX) ? BUFFER_BLOCKS_MAX : count);
|
||||||
size_t length = (blocks * SD_SECTOR_SIZE);
|
size_t length = (blocks * SD_SECTOR_SIZE);
|
||||||
if (sc64_sd_read_sectors((uint32_t *) (SC64_BUFFERS->BUFFER), sector, blocks) != SC64_OK) {
|
if ((sc64_error_fatfs = sc64_sd_read_sectors((uint32_t *) (SC64_BUFFERS->BUFFER), sector, blocks)) != SC64_OK) {
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
if (((uint32_t) (buff) % 8) == 0) {
|
if (((uint32_t) (buff) % 8) == 0) {
|
||||||
@ -67,7 +70,7 @@ DRESULT disk_read (BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
|||||||
count -= blocks;
|
count -= blocks;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sc64_sd_read_sectors(physical_address, sector, count) != SC64_OK) {
|
if ((sc64_error_fatfs = sc64_sd_read_sectors(physical_address, sector, count)) != SC64_OK) {
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +94,7 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
|||||||
memcpy(aligned_buffer, buff, length);
|
memcpy(aligned_buffer, buff, length);
|
||||||
pi_dma_write((io32_t *) (SC64_BUFFERS->BUFFER), aligned_buffer, length);
|
pi_dma_write((io32_t *) (SC64_BUFFERS->BUFFER), aligned_buffer, length);
|
||||||
}
|
}
|
||||||
if (sc64_sd_write_sectors((uint32_t *) (SC64_BUFFERS->BUFFER), sector, blocks) != SC64_OK) {
|
if ((sc64_error_fatfs = sc64_sd_write_sectors((uint32_t *) (SC64_BUFFERS->BUFFER), sector, blocks)) != SC64_OK) {
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
buff += length;
|
buff += length;
|
||||||
@ -99,7 +102,7 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
|||||||
count -= blocks;
|
count -= blocks;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (sc64_sd_write_sectors(physical_address, sector, count) != SC64_OK) {
|
if ((sc64_error_fatfs = sc64_sd_write_sectors(physical_address, sector, count)) != SC64_OK) {
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +125,7 @@ DWORD get_fattime(void) {
|
|||||||
sc64_rtc_time_t t;
|
sc64_rtc_time_t t;
|
||||||
|
|
||||||
if ((error = sc64_get_time(&t)) != SC64_OK) {
|
if ((error = sc64_get_time(&t)) != SC64_OK) {
|
||||||
error_display("Command TIME_GET failed: %d", error);
|
error_display("Command TIME_GET failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -28,7 +28,7 @@ void init (init_tv_type_t tv_type, init_reset_type_t reset_type, uint32_t entrop
|
|||||||
exception_enable_interrupts();
|
exception_enable_interrupts();
|
||||||
|
|
||||||
if ((error = sc64_set_config(CFG_ID_BOOTLOADER_SWITCH, false)) != SC64_OK) {
|
if ((error = sc64_set_config(CFG_ID_BOOTLOADER_SWITCH, false)) != SC64_OK) {
|
||||||
error_display("Command CONFIG_SET [BOOTLOADER_SWITCH] failed: %d", error);
|
error_display("Command CONFIG_SET [BOOTLOADER_SWITCH] failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test_check()) {
|
if (test_check()) {
|
||||||
|
@ -12,7 +12,7 @@ void main (void) {
|
|||||||
sc64_boot_params_t sc64_boot_params;
|
sc64_boot_params_t sc64_boot_params;
|
||||||
|
|
||||||
if ((error = sc64_get_boot_params(&sc64_boot_params)) != SC64_OK) {
|
if ((error = sc64_get_boot_params(&sc64_boot_params)) != SC64_OK) {
|
||||||
error_display("Could not obtain boot info: %d", error);
|
error_display("Could not obtain boot info\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
boot_params_t boot_params;
|
boot_params_t boot_params;
|
||||||
@ -40,7 +40,7 @@ void main (void) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error_display("Unknown boot mode selected [%d]\n", sc64_boot_params.boot_mode);
|
error_display("Unknown boot mode selected (%d)\n", sc64_boot_params.boot_mode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,11 @@
|
|||||||
#define ROM_ADDRESS (0x10000000)
|
#define ROM_ADDRESS (0x10000000)
|
||||||
|
|
||||||
|
|
||||||
|
extern sc64_error_t sc64_error_fatfs;
|
||||||
|
|
||||||
|
|
||||||
static const char *fatfs_error_codes[] = {
|
static const char *fatfs_error_codes[] = {
|
||||||
"Succeeded",
|
"No error",
|
||||||
"A hard error occurred in the low level disk I/O layer",
|
"A hard error occurred in the low level disk I/O layer",
|
||||||
"Assertion failed",
|
"Assertion failed",
|
||||||
"The physical drive cannot work",
|
"The physical drive cannot work",
|
||||||
@ -35,7 +38,14 @@ static const char *fatfs_error_codes[] = {
|
|||||||
#define FF_CHECK(x, message, ...) { \
|
#define FF_CHECK(x, message, ...) { \
|
||||||
fresult = x; \
|
fresult = x; \
|
||||||
if (fresult != FR_OK) { \
|
if (fresult != FR_OK) { \
|
||||||
error_display(message ".\nReason: %s", __VA_ARGS__ __VA_OPT__(,) fatfs_error_codes[fresult]); \
|
error_display( \
|
||||||
|
message "\n" \
|
||||||
|
" > FatFs error: %s\n" \
|
||||||
|
" > SD card error: %s (%08X)", \
|
||||||
|
__VA_ARGS__ __VA_OPT__(,) \
|
||||||
|
fatfs_error_codes[fresult], \
|
||||||
|
sc64_error_description(sc64_error_fatfs), sc64_error_fatfs \
|
||||||
|
); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,15 +65,15 @@ void menu_load (void) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if ((error = sc64_writeback_pending(&writeback_pending)) != SC64_OK) {
|
if ((error = sc64_writeback_pending(&writeback_pending)) != SC64_OK) {
|
||||||
error_display("Command WRITEBACK_PENDING failed: %d", error);
|
error_display("Command WRITEBACK_PENDING failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
} while (writeback_pending);
|
} while (writeback_pending);
|
||||||
|
|
||||||
if ((error = sc64_writeback_disable()) != SC64_OK) {
|
if ((error = sc64_writeback_disable()) != SC64_OK) {
|
||||||
error_display("Could not disable writeback: %d", error);
|
error_display("Could not disable save writeback\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
FF_CHECK(f_mount(&fs, "", 1), "SD card initialize error. No SD card or invalid partition table");
|
FF_CHECK(f_mount(&fs, "", 1), "SD card initialize error");
|
||||||
FF_CHECK(f_open(&fil, "sc64menu.n64", FA_READ), "Could not open menu executable (sc64menu.n64)");
|
FF_CHECK(f_open(&fil, "sc64menu.n64", FA_READ), "Could not open menu executable (sc64menu.n64)");
|
||||||
fix_menu_file_size(&fil);
|
fix_menu_file_size(&fil);
|
||||||
FF_CHECK(f_read(&fil, (void *) (ROM_ADDRESS), f_size(&fil), &bytes_read), "Could not read menu file");
|
FF_CHECK(f_read(&fil, (void *) (ROM_ADDRESS), f_size(&fil), &bytes_read), "Could not read menu file");
|
||||||
|
@ -89,6 +89,61 @@ static sc64_error_t sc64_execute_cmd (sc64_cmd_t *cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *sc64_error_description (sc64_error_t error) {
|
||||||
|
sc64_error_type_t type = (sc64_error_type_t) ((error >> 24) & 0xFF);
|
||||||
|
error &= 0xFFFFFF;
|
||||||
|
|
||||||
|
if (type == ERROR_TYPE_CFG) {
|
||||||
|
switch ((sc64_cfg_error_t) (error)) {
|
||||||
|
case SC64_OK: return "No error";
|
||||||
|
case CFG_ERROR_UNKNOWN_COMMAND: return "Unknown command";
|
||||||
|
case CFG_ERROR_INVALID_ARGUMENT: return "Invalid argument";
|
||||||
|
case CFG_ERROR_INVALID_ADDRESS: return "Invalid address";
|
||||||
|
case CFG_ERROR_INVALID_ID: return "Invalid ID";
|
||||||
|
default: return "Unknown error (CFG)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == ERROR_TYPE_SD_CARD) {
|
||||||
|
switch ((sc64_sd_error_t) (error)) {
|
||||||
|
case SD_OK: return "No error (SD)";
|
||||||
|
case SD_ERROR_NO_CARD_IN_SLOT: return "No SD card in the slot";
|
||||||
|
case SD_ERROR_NOT_INITIALIZED: return "SD card is not initialized";
|
||||||
|
case SD_ERROR_INVALID_ARGUMENT: return "Invalid argument (SD)";
|
||||||
|
case SD_ERROR_INVALID_ADDRESS: return "Invalid address (SD)";
|
||||||
|
case SD_ERROR_INVALID_OPERATION: return "Invalid operation (SD)";
|
||||||
|
case SD_ERROR_CMD2_IO: return "CMD2 I/O";
|
||||||
|
case SD_ERROR_CMD3_IO: return "CMD3 I/O";
|
||||||
|
case SD_ERROR_CMD6_CHECK_IO: return "CMD6 I/O (check)";
|
||||||
|
case SD_ERROR_CMD6_CHECK_CRC: return "CMD6 CRC (check)";
|
||||||
|
case SD_ERROR_CMD6_CHECK_TIMEOUT: return "CMD6 timeout (check)";
|
||||||
|
case SD_ERROR_CMD6_CHECK_RESPONSE: return "CMD6 invalid response (check)";
|
||||||
|
case SD_ERROR_CMD6_SWITCH_IO: return "CMD6 I/O (switch)";
|
||||||
|
case SD_ERROR_CMD6_SWITCH_CRC: return "CMD6 CRC (switch)";
|
||||||
|
case SD_ERROR_CMD6_SWITCH_TIMEOUT: return "CMD6 timeout (switch)";
|
||||||
|
case SD_ERROR_CMD6_SWITCH_RESPONSE: return "CMD6 invalid response (switch)";
|
||||||
|
case SD_ERROR_CMD7_IO: return "CMD7 I/O";
|
||||||
|
case SD_ERROR_CMD8_IO: return "CMD8 I/O";
|
||||||
|
case SD_ERROR_CMD9_IO: return "CMD9 I/O";
|
||||||
|
case SD_ERROR_CMD10_IO: return "CMD10 I/O";
|
||||||
|
case SD_ERROR_CMD18_IO: return "CMD18 I/O";
|
||||||
|
case SD_ERROR_CMD18_CRC: return "CMD18 CRC";
|
||||||
|
case SD_ERROR_CMD18_TIMEOUT: return "CMD18 timeout";
|
||||||
|
case SD_ERROR_CMD25_IO: return "CMD25 I/O";
|
||||||
|
case SD_ERROR_CMD25_CRC: return "CMD25 CRC";
|
||||||
|
case SD_ERROR_CMD25_TIMEOUT: return "CMD25 timeout";
|
||||||
|
case SD_ERROR_ACMD6_IO: return "ACMD6 I/O";
|
||||||
|
case SD_ERROR_ACMD41_IO: return "ACMD41 I/O";
|
||||||
|
case SD_ERROR_ACMD41_OCR: return "ACMD41 OCR";
|
||||||
|
case SD_ERROR_ACMD41_TIMEOUT: return "ACMD41 timeout";
|
||||||
|
default: return "Unknown error (SD)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown error (type)";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void sc64_unlock (void) {
|
void sc64_unlock (void) {
|
||||||
pi_io_write(&SC64_REGS->KEY, SC64_KEY_RESET);
|
pi_io_write(&SC64_REGS->KEY, SC64_KEY_RESET);
|
||||||
pi_io_write(&SC64_REGS->KEY, SC64_KEY_UNLOCK_1);
|
pi_io_write(&SC64_REGS->KEY, SC64_KEY_UNLOCK_1);
|
||||||
@ -396,8 +451,7 @@ sc64_error_t sc64_writeback_enable (void *address) {
|
|||||||
sc64_error_t sc64_writeback_disable (void) {
|
sc64_error_t sc64_writeback_disable (void) {
|
||||||
sc64_error_t error;
|
sc64_error_t error;
|
||||||
uint32_t save_type;
|
uint32_t save_type;
|
||||||
error = sc64_get_config(CFG_ID_SAVE_TYPE, &save_type);
|
if ((error = sc64_get_config(CFG_ID_SAVE_TYPE, &save_type)) != SC64_OK) {
|
||||||
if (error != SC64_OK) {
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
return sc64_set_config(CFG_ID_SAVE_TYPE, save_type);
|
return sc64_set_config(CFG_ID_SAVE_TYPE, save_type);
|
||||||
|
@ -8,14 +8,52 @@
|
|||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SC64_OK,
|
ERROR_TYPE_CFG = 0,
|
||||||
SC64_ERROR_BAD_ARGUMENT,
|
ERROR_TYPE_SD_CARD = 1,
|
||||||
SC64_ERROR_BAD_ADDRESS,
|
} sc64_error_type_t;
|
||||||
SC64_ERROR_BAD_CONFIG_ID,
|
|
||||||
SC64_ERROR_TIMEOUT,
|
typedef enum {
|
||||||
SC64_ERROR_SD_CARD,
|
SC64_OK = 0,
|
||||||
SC64_ERROR_UNKNOWN_CMD = -1
|
CFG_ERROR_UNKNOWN_COMMAND = 1,
|
||||||
} sc64_error_t;
|
CFG_ERROR_INVALID_ARGUMENT = 2,
|
||||||
|
CFG_ERROR_INVALID_ADDRESS = 3,
|
||||||
|
CFG_ERROR_INVALID_ID = 4,
|
||||||
|
} sc64_cfg_error_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SD_OK = 0,
|
||||||
|
SD_ERROR_NO_CARD_IN_SLOT = 1,
|
||||||
|
SD_ERROR_NOT_INITIALIZED = 2,
|
||||||
|
SD_ERROR_INVALID_ARGUMENT = 3,
|
||||||
|
SD_ERROR_INVALID_ADDRESS = 4,
|
||||||
|
SD_ERROR_INVALID_OPERATION = 5,
|
||||||
|
SD_ERROR_CMD2_IO = 6,
|
||||||
|
SD_ERROR_CMD3_IO = 7,
|
||||||
|
SD_ERROR_CMD6_CHECK_IO = 8,
|
||||||
|
SD_ERROR_CMD6_CHECK_CRC = 9,
|
||||||
|
SD_ERROR_CMD6_CHECK_TIMEOUT = 10,
|
||||||
|
SD_ERROR_CMD6_CHECK_RESPONSE = 11,
|
||||||
|
SD_ERROR_CMD6_SWITCH_IO = 12,
|
||||||
|
SD_ERROR_CMD6_SWITCH_CRC = 13,
|
||||||
|
SD_ERROR_CMD6_SWITCH_TIMEOUT = 14,
|
||||||
|
SD_ERROR_CMD6_SWITCH_RESPONSE = 15,
|
||||||
|
SD_ERROR_CMD7_IO = 16,
|
||||||
|
SD_ERROR_CMD8_IO = 17,
|
||||||
|
SD_ERROR_CMD9_IO = 18,
|
||||||
|
SD_ERROR_CMD10_IO = 19,
|
||||||
|
SD_ERROR_CMD18_IO = 20,
|
||||||
|
SD_ERROR_CMD18_CRC = 21,
|
||||||
|
SD_ERROR_CMD18_TIMEOUT = 22,
|
||||||
|
SD_ERROR_CMD25_IO = 23,
|
||||||
|
SD_ERROR_CMD25_CRC = 24,
|
||||||
|
SD_ERROR_CMD25_TIMEOUT = 25,
|
||||||
|
SD_ERROR_ACMD6_IO = 26,
|
||||||
|
SD_ERROR_ACMD41_IO = 27,
|
||||||
|
SD_ERROR_ACMD41_OCR = 28,
|
||||||
|
SD_ERROR_ACMD41_TIMEOUT = 29,
|
||||||
|
} sc64_sd_error_t;
|
||||||
|
|
||||||
|
typedef uint32_t sc64_error_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CFG_ID_BOOTLOADER_SWITCH,
|
CFG_ID_BOOTLOADER_SWITCH,
|
||||||
@ -133,6 +171,8 @@ typedef struct {
|
|||||||
#define SC64_BUFFERS ((sc64_buffers_t *) SC64_BUFFERS_BASE)
|
#define SC64_BUFFERS ((sc64_buffers_t *) SC64_BUFFERS_BASE)
|
||||||
|
|
||||||
|
|
||||||
|
const char *sc64_error_description (sc64_error_t error);
|
||||||
|
|
||||||
void sc64_unlock (void);
|
void sc64_unlock (void);
|
||||||
void sc64_lock (void);
|
void sc64_lock (void);
|
||||||
bool sc64_check_presence (void);
|
bool sc64_check_presence (void);
|
||||||
|
@ -63,22 +63,22 @@ static void test_sc64_cfg (void) {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
if ((error = sc64_get_config(CFG_ID_BUTTON_STATE, &button_state)) != SC64_OK) {
|
if ((error = sc64_get_config(CFG_ID_BUTTON_STATE, &button_state)) != SC64_OK) {
|
||||||
error_display("Command CONFIG_GET [BUTTON_STATE] failed: %d", error);
|
error_display("Command CONFIG_GET [BUTTON_STATE] failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
} while (button_state != 0);
|
} while (button_state != 0);
|
||||||
|
|
||||||
display_printf("done\n\n");
|
display_printf("done\n\n");
|
||||||
|
|
||||||
if ((error = sc64_get_identifier(&identifier)) != SC64_OK) {
|
if ((error = sc64_get_identifier(&identifier)) != SC64_OK) {
|
||||||
error_display("Command IDENTIFIER_GET failed: %d", error);
|
error_display("Command IDENTIFIER_GET failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = sc64_get_version(&major, &minor, &revision)) != SC64_OK) {
|
if ((error = sc64_get_version(&major, &minor, &revision)) != SC64_OK) {
|
||||||
error_display("Command VERSION_GET failed: %d", error);
|
error_display("Command VERSION_GET failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = sc64_get_diagnostic(DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE, &tmp)) != SC64_OK) {
|
if ((error = sc64_get_diagnostic(DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE, &tmp)) != SC64_OK) {
|
||||||
error_display("Command DIAGNOSTIC_GET failed: %d", error);
|
error_display("Command DIAGNOSTIC_GET failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t voltage = (uint16_t) (tmp >> 16);
|
uint16_t voltage = (uint16_t) (tmp >> 16);
|
||||||
@ -104,7 +104,7 @@ static void test_sc64_cfg (void) {
|
|||||||
sc64_rtc_time_t t;
|
sc64_rtc_time_t t;
|
||||||
|
|
||||||
if ((error = sc64_get_time(&t)) != SC64_OK) {
|
if ((error = sc64_get_time(&t)) != SC64_OK) {
|
||||||
error_display("Command TIME_GET failed: %d", error);
|
error_display("Command TIME_GET failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
display_printf("RTC current time:\n ");
|
display_printf("RTC current time:\n ");
|
||||||
@ -136,16 +136,14 @@ static void test_pi (void) {
|
|||||||
|
|
||||||
for (int i = 0; i < size / sizeof(uint32_t); i++) {
|
for (int i = 0; i < size / sizeof(uint32_t); i++) {
|
||||||
if (w_buffer[i] != r_buffer[i]) {
|
if (w_buffer[i] != r_buffer[i]) {
|
||||||
display_printf(
|
error_display(
|
||||||
"\n"
|
"PI test failed:\n"
|
||||||
" > Mismatch error at address 0x%08lX\n"
|
" > Mismatch error at address 0x%08lX\n"
|
||||||
" > 0x%08lX (W) != 0x%08lX (R)",
|
" > 0x%08lX (W) != 0x%08lX (R)",
|
||||||
(uint32_t) (SC64_BUFFERS->BUFFER) + (i * sizeof(uint32_t)),
|
(uint32_t) (SC64_BUFFERS->BUFFER) + (i * sizeof(uint32_t)),
|
||||||
w_buffer[i],
|
w_buffer[i],
|
||||||
r_buffer[i]
|
r_buffer[i]
|
||||||
);
|
);
|
||||||
|
|
||||||
while (true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +160,7 @@ static void test_sd_card_io (void) {
|
|||||||
uint8_t sector[512] __attribute__((aligned(8)));
|
uint8_t sector[512] __attribute__((aligned(8)));
|
||||||
|
|
||||||
if ((error = sc64_sd_card_get_status(&card_status)) != SC64_OK) {
|
if ((error = sc64_sd_card_get_status(&card_status)) != SC64_OK) {
|
||||||
error_display("Could not get SD card info: %d", error);
|
error_display("Could not get SD card info\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card_status & SD_CARD_STATUS_INSERTED) {
|
if (card_status & SD_CARD_STATUS_INSERTED) {
|
||||||
@ -172,15 +170,15 @@ static void test_sd_card_io (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((error = sc64_sd_card_deinit()) != SC64_OK) {
|
if ((error = sc64_sd_card_deinit()) != SC64_OK) {
|
||||||
return display_printf("SD card deinit error: %d", error);
|
error_display("SD card deinit error\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = sc64_sd_card_init()) != SC64_OK) {
|
if ((error = sc64_sd_card_init()) != SC64_OK) {
|
||||||
return display_printf("SD card init error: %d\n", error);
|
return display_printf("SD card init error\n (%08X) - %s\n", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = sc64_sd_card_get_status(&card_status)) != SC64_OK) {
|
if ((error = sc64_sd_card_get_status(&card_status)) != SC64_OK) {
|
||||||
error_display("Could not get SD card info: %d", error);
|
error_display("Could not get SD card info\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card_status & SD_CARD_STATUS_INITIALIZED) {
|
if (card_status & SD_CARD_STATUS_INITIALIZED) {
|
||||||
@ -197,7 +195,7 @@ static void test_sd_card_io (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((error = sc64_sd_card_get_info((uint32_t *) (SC64_BUFFERS->BUFFER))) != SC64_OK) {
|
if ((error = sc64_sd_card_get_info((uint32_t *) (SC64_BUFFERS->BUFFER))) != SC64_OK) {
|
||||||
return display_printf("SD card get info error: %d\n", error);
|
error_display("SD card get info error\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), card_info, sizeof(card_info));
|
pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), card_info, sizeof(card_info));
|
||||||
@ -217,7 +215,7 @@ static void test_sd_card_io (void) {
|
|||||||
display_printf("\n");
|
display_printf("\n");
|
||||||
|
|
||||||
if ((error = sc64_sd_read_sectors((void *) (SC64_BUFFERS->BUFFER), 0, 1)) != SC64_OK) {
|
if ((error = sc64_sd_read_sectors((void *) (SC64_BUFFERS->BUFFER), 0, 1)) != SC64_OK) {
|
||||||
return display_printf("SD card read sector 0 error: %d\n", error);
|
return display_printf("SD card read sector 0 error\n (%08X) - %s\n", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), sector, sizeof(sector));
|
pi_dma_read((io32_t *) (SC64_BUFFERS->BUFFER), sector, sizeof(sector));
|
||||||
@ -245,21 +243,21 @@ static void test_sd_card_fatfs (void) {
|
|||||||
UINT bytes;
|
UINT bytes;
|
||||||
|
|
||||||
if ((error = sc64_sd_card_deinit()) != SC64_OK) {
|
if ((error = sc64_sd_card_deinit()) != SC64_OK) {
|
||||||
return display_printf("SD card deinit error: %d", error);
|
error_display("SD card deinit error\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fresult = f_mount(&fs, "", 1)) != FR_OK) {
|
if ((fresult = f_mount(&fs, "", 1)) != FR_OK) {
|
||||||
return display_printf("f_mount error: %d\n", fresult);
|
display_printf("f_mount error: %d\n", fresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fresult = f_getlabel("", label, &vsn)) != FR_OK) {
|
if ((fresult = f_getlabel("", label, &vsn)) != FR_OK) {
|
||||||
return display_printf("f_getlabel error: %d\n", fresult);
|
display_printf("f_getlabel error: %d\n", fresult);
|
||||||
|
} else {
|
||||||
|
display_printf("Volume [%s] / [%08lX]\n\n", label, vsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
display_printf("Volume [%s] / [%08lX]\n\n", label, vsn);
|
|
||||||
|
|
||||||
if ((fresult = f_open(&fil, "sc64test.bin", FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) {
|
if ((fresult = f_open(&fil, "sc64test.bin", FA_CREATE_ALWAYS | FA_WRITE)) != FR_OK) {
|
||||||
return display_printf("f_open (write) error: %d\n", fresult);
|
display_printf("f_open (write) error: %d\n", fresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
srand(random_seed);
|
srand(random_seed);
|
||||||
@ -276,11 +274,13 @@ static void test_sd_card_fatfs (void) {
|
|||||||
fill_random(w_buffer, block_size, 0, 0);
|
fill_random(w_buffer, block_size, 0, 0);
|
||||||
|
|
||||||
if ((fresult = f_write(&fil, w_buffer, block_size, &bytes)) != FR_OK) {
|
if ((fresult = f_write(&fil, w_buffer, block_size, &bytes)) != FR_OK) {
|
||||||
return display_printf("\nf_write error: %d\n", fresult);
|
display_printf("\nf_write error: %d", fresult);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes != block_size) {
|
if (bytes != block_size) {
|
||||||
return display_printf("\nf_write (%ld!=%ld) error: %d\n", bytes, block_size, fresult);
|
display_printf("\nf_write (%ld!=%ld) error: %d", bytes, block_size, fresult);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
left -= block_size;
|
left -= block_size;
|
||||||
@ -289,15 +289,15 @@ static void test_sd_card_fatfs (void) {
|
|||||||
display_printf("\n");
|
display_printf("\n");
|
||||||
|
|
||||||
if ((fresult = f_close(&fil)) != FR_OK) {
|
if ((fresult = f_close(&fil)) != FR_OK) {
|
||||||
return display_printf("f_close (write) error: %d\n", fresult);
|
display_printf("f_close (write) error: %d\n", fresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fresult = f_open(&fil, "sc64test.bin", FA_OPEN_EXISTING | FA_READ)) != FR_OK) {
|
if ((fresult = f_open(&fil, "sc64test.bin", FA_OPEN_EXISTING | FA_READ)) != FR_OK) {
|
||||||
return display_printf("f_open (read) error: %d\n", fresult);
|
display_printf("f_open (read) error: %d\n", fresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f_size(&fil) != SD_TEST_FILE_SIZE) {
|
if (f_size(&fil) != SD_TEST_FILE_SIZE) {
|
||||||
return display_printf("f_size (%d!=%d) error\n", f_size(&fil), SD_TEST_FILE_SIZE);
|
display_printf("f_size (%d!=%d) error\n", f_size(&fil), SD_TEST_FILE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
srand(random_seed);
|
srand(random_seed);
|
||||||
@ -314,25 +314,25 @@ static void test_sd_card_fatfs (void) {
|
|||||||
fill_random(w_buffer, block_size, 0, 0);
|
fill_random(w_buffer, block_size, 0, 0);
|
||||||
|
|
||||||
if ((fresult = f_read(&fil, r_buffer, block_size, &bytes)) != FR_OK) {
|
if ((fresult = f_read(&fil, r_buffer, block_size, &bytes)) != FR_OK) {
|
||||||
return display_printf("\nf_read error: %d\n", fresult);
|
display_printf("\nf_read error: %d", fresult);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes != block_size) {
|
if (bytes != block_size) {
|
||||||
return display_printf("\nf_read (%ld!=%ld) error: %d\n", bytes, block_size, fresult);
|
display_printf("\nf_read (%ld!=%ld) error: %d", bytes, block_size, fresult);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (UINT i = 0; i < (block_size / sizeof(uint32_t)); i++) {
|
for (UINT i = 0; i < (block_size / sizeof(uint32_t)); i++) {
|
||||||
if (w_buffer[i] != r_buffer[i]) {
|
if (w_buffer[i] != r_buffer[i]) {
|
||||||
display_printf(
|
error_display(
|
||||||
"\n"
|
"SD card (FatFs) test failed:\n"
|
||||||
" > Mismatch error at file offset 0x%08lX\n"
|
" > Mismatch error at file offset 0x%08lX\n"
|
||||||
" > 0x%08lX (W) != 0x%08lX (R)",
|
" > 0x%08lX (W) != 0x%08lX (R)",
|
||||||
f_tell(&fil) + (i * sizeof(uint32_t)),
|
f_tell(&fil) + (i * sizeof(uint32_t)),
|
||||||
w_buffer[i],
|
w_buffer[i],
|
||||||
r_buffer[i]
|
r_buffer[i]
|
||||||
);
|
);
|
||||||
|
|
||||||
while (true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,15 +342,15 @@ static void test_sd_card_fatfs (void) {
|
|||||||
display_printf("\n");
|
display_printf("\n");
|
||||||
|
|
||||||
if ((fresult = f_close(&fil)) != FR_OK) {
|
if ((fresult = f_close(&fil)) != FR_OK) {
|
||||||
return display_printf("f_close (read) error: %d\n", fresult);
|
display_printf("f_close (read) error: %d\n", fresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fresult = f_unlink("sc64test.bin")) != FR_OK) {
|
if ((fresult = f_unlink("sc64test.bin")) != FR_OK) {
|
||||||
return display_printf("f_unlink error: %d\n", fresult);
|
display_printf("f_unlink error: %d\n", fresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fresult = f_unmount("")) != FR_OK) {
|
if ((fresult = f_unmount("")) != FR_OK) {
|
||||||
return display_printf("f_unmount error: %d\n", fresult);
|
display_printf("f_unmount error: %d\n", fresult);
|
||||||
}
|
}
|
||||||
|
|
||||||
random_seed += c0_count();
|
random_seed += c0_count();
|
||||||
@ -473,16 +473,15 @@ static void test_sdram (void) {
|
|||||||
|
|
||||||
for (int i = 0; i < TEST_BUFFER_SIZE / sizeof(uint64_t); i++) {
|
for (int i = 0; i < TEST_BUFFER_SIZE / sizeof(uint64_t); i++) {
|
||||||
if (test_data[i] != check_data[i]) {
|
if (test_data[i] != check_data[i]) {
|
||||||
display_printf(
|
error_display(
|
||||||
"\n"
|
"SDRAM test failed, %s\n"
|
||||||
" > Mismatch error at address 0x%08lX\n"
|
" > Mismatch error at address 0x%08lX\n"
|
||||||
" > 0x%016llX (W) != 0x%016llX (R)",
|
" > 0x%016llX (W) != 0x%016llX (R)",
|
||||||
|
test->name,
|
||||||
SDRAM_ADDRESS + offset + (i * sizeof(uint64_t)),
|
SDRAM_ADDRESS + offset + (i * sizeof(uint64_t)),
|
||||||
test_data[i],
|
test_data[i],
|
||||||
check_data[i]
|
check_data[i]
|
||||||
);
|
);
|
||||||
|
|
||||||
while (true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -511,7 +510,7 @@ bool test_check (void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((error = sc64_get_config(CFG_ID_BUTTON_STATE, &button_state)) != SC64_OK) {
|
if ((error = sc64_get_config(CFG_ID_BUTTON_STATE, &button_state)) != SC64_OK) {
|
||||||
error_display("Command CONFIG_GET [BUTTON_STATE] failed: %d", error);
|
error_display("Command CONFIG_GET [BUTTON_STATE] failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (button_state != 0);
|
return (button_state != 0);
|
||||||
@ -538,12 +537,12 @@ void test_execute (void) {
|
|||||||
|
|
||||||
pi_io_config(0x0F, 0x05, 0x0C, 0x02);
|
pi_io_config(0x0F, 0x05, 0x0C, 0x02);
|
||||||
|
|
||||||
if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, true))) {
|
if ((error = sc64_set_config(CFG_ID_ROM_WRITE_ENABLE, true)) != SC64_OK) {
|
||||||
error_display("Command CONFIG_SET [ROM_WRITE_ENABLE] failed: %d", error);
|
error_display("Command CONFIG_SET [ROM_WRITE_ENABLE] failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = sc64_set_config(CFG_ID_ROM_SHADOW_ENABLE, false))) {
|
if ((error = sc64_set_config(CFG_ID_ROM_SHADOW_ENABLE, false)) != SC64_OK) {
|
||||||
error_display("Command CONFIG_SET [ROM_SHADOW_ENABLE] failed: %d", error);
|
error_display("Command CONFIG_SET [ROM_SHADOW_ENABLE] failed\n (%08X) - %s", error, sc64_error_description(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
random_seed = __entropy + c0_count();
|
random_seed = __entropy + c0_count();
|
||||||
|
@ -66,16 +66,6 @@ typedef enum {
|
|||||||
TV_TYPE_PASSTHROUGH = 3
|
TV_TYPE_PASSTHROUGH = 3
|
||||||
} tv_type_t;
|
} tv_type_t;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
CFG_ERROR_OK = 0,
|
|
||||||
CFG_ERROR_BAD_ARGUMENT = 1,
|
|
||||||
CFG_ERROR_BAD_ADDRESS = 2,
|
|
||||||
CFG_ERROR_BAD_CONFIG_ID = 3,
|
|
||||||
CFG_ERROR_TIMEOUT = 4,
|
|
||||||
CFG_ERROR_SD_CARD = 5,
|
|
||||||
CFG_ERROR_UNKNOWN_CMD = -1,
|
|
||||||
} cfg_error_t;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SD_CARD_OP_DEINIT = 0,
|
SD_CARD_OP_DEINIT = 0,
|
||||||
SD_CARD_OP_INIT = 1,
|
SD_CARD_OP_INIT = 1,
|
||||||
@ -95,6 +85,18 @@ typedef enum {
|
|||||||
BRAM = (1 << 2),
|
BRAM = (1 << 2),
|
||||||
} translate_type_t;
|
} translate_type_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ERROR_TYPE_CFG = 0,
|
||||||
|
ERROR_TYPE_SD_CARD = 1,
|
||||||
|
} error_type_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CFG_OK = 0,
|
||||||
|
CFG_ERROR_UNKNOWN_COMMAND = 1,
|
||||||
|
CFG_ERROR_INVALID_ARGUMENT = 2,
|
||||||
|
CFG_ERROR_INVALID_ADDRESS = 3,
|
||||||
|
CFG_ERROR_INVALID_ID = 4,
|
||||||
|
} cfg_error_t;
|
||||||
|
|
||||||
struct process {
|
struct process {
|
||||||
boot_mode_t boot_mode;
|
boot_mode_t boot_mode;
|
||||||
@ -169,8 +171,8 @@ static bool cfg_translate_address (uint32_t *address, uint32_t length, translate
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cfg_set_error (cfg_error_t error) {
|
static void cfg_set_error (error_type_t type, uint32_t error) {
|
||||||
fpga_reg_set(REG_CFG_DATA_0, error);
|
fpga_reg_set(REG_CFG_DATA_0, ((type & 0xFF) << 24) | (error & 0xFFFFFF));
|
||||||
fpga_reg_set(REG_CFG_DATA_1, 0);
|
fpga_reg_set(REG_CFG_DATA_1, 0);
|
||||||
fpga_reg_set(REG_CFG_CMD, CFG_CMD_ERROR | CFG_CMD_DONE);
|
fpga_reg_set(REG_CFG_CMD, CFG_CMD_ERROR | CFG_CMD_DONE);
|
||||||
}
|
}
|
||||||
@ -504,7 +506,7 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
if (cfg_query(args)) {
|
if (cfg_query(args)) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_CONFIG_ID);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -513,7 +515,7 @@ void cfg_process (void) {
|
|||||||
prev_cfg[0] = args[0];
|
prev_cfg[0] = args[0];
|
||||||
cfg_query(prev_cfg);
|
cfg_query(prev_cfg);
|
||||||
if (cfg_update(args)) {
|
if (cfg_update(args)) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_CONFIG_ID);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
args[1] = prev_cfg[1];
|
args[1] = prev_cfg[1];
|
||||||
@ -521,14 +523,14 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 'a':
|
case 'a':
|
||||||
if (cfg_query_setting(args)) {
|
if (cfg_query_setting(args)) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_CONFIG_ID);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'A':
|
case 'A':
|
||||||
if (cfg_update_setting(args)) {
|
if (cfg_update_setting(args)) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_CONFIG_ID);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -543,7 +545,7 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
if (cfg_translate_address(&args[0], args[1], (SDRAM | BRAM))) {
|
if (cfg_translate_address(&args[0], args[1], (SDRAM | BRAM))) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!usb_prepare_read(args)) {
|
if (!usb_prepare_read(args)) {
|
||||||
@ -553,7 +555,7 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 'M':
|
case 'M':
|
||||||
if (cfg_translate_address(&args[0], args[1] & 0xFFFFFF, (SDRAM | BRAM))) {
|
if (cfg_translate_address(&args[0], args[1] & 0xFFFFFF, (SDRAM | BRAM))) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
usb_create_packet(&packet_info, PACKET_CMD_DEBUG_OUTPUT);
|
usb_create_packet(&packet_info, PACKET_CMD_DEBUG_OUTPUT);
|
||||||
@ -584,10 +586,10 @@ void cfg_process (void) {
|
|||||||
break;
|
break;
|
||||||
case SD_CARD_OP_INIT: {
|
case SD_CARD_OP_INIT: {
|
||||||
led_activity_on();
|
led_activity_on();
|
||||||
bool error = sd_card_init();
|
sd_error_t error = sd_card_init();
|
||||||
led_activity_off();
|
led_activity_off();
|
||||||
if (error) {
|
if (error != SD_OK) {
|
||||||
cfg_set_error(CFG_ERROR_SD_CARD);
|
cfg_set_error(ERROR_TYPE_SD_CARD, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -595,30 +597,36 @@ void cfg_process (void) {
|
|||||||
case SD_CARD_OP_GET_STATUS:
|
case SD_CARD_OP_GET_STATUS:
|
||||||
args[1] = sd_card_get_status();
|
args[1] = sd_card_get_status();
|
||||||
break;
|
break;
|
||||||
case SD_CARD_OP_GET_INFO:
|
case SD_CARD_OP_GET_INFO: {
|
||||||
if (cfg_translate_address(&args[0], SD_CARD_INFO_SIZE, (SDRAM | BRAM))) {
|
if (cfg_translate_address(&args[0], SD_CARD_INFO_SIZE, (SDRAM | BRAM))) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(ERROR_TYPE_SD_CARD, SD_ERROR_INVALID_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sd_card_get_info(args[0])) {
|
sd_error_t error = sd_card_get_info(args[0]);
|
||||||
cfg_set_error(CFG_ERROR_SD_CARD);
|
if (error != SD_OK) {
|
||||||
|
cfg_set_error(ERROR_TYPE_SD_CARD, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SD_CARD_OP_BYTE_SWAP_ON:
|
}
|
||||||
if (sd_set_byte_swap(true)) {
|
case SD_CARD_OP_BYTE_SWAP_ON: {
|
||||||
cfg_set_error(CFG_ERROR_SD_CARD);
|
sd_error_t error = sd_set_byte_swap(true);
|
||||||
|
if (error != SD_OK) {
|
||||||
|
cfg_set_error(ERROR_TYPE_SD_CARD, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SD_CARD_OP_BYTE_SWAP_OFF:
|
}
|
||||||
if (sd_set_byte_swap(false)) {
|
case SD_CARD_OP_BYTE_SWAP_OFF: {
|
||||||
cfg_set_error(CFG_ERROR_SD_CARD);
|
sd_error_t error = sd_set_byte_swap(false);
|
||||||
|
if (error != SD_OK) {
|
||||||
|
cfg_set_error(ERROR_TYPE_SD_CARD, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
|
cfg_set_error(ERROR_TYPE_SD_CARD, SD_ERROR_INVALID_OPERATION);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -629,18 +637,18 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 's': {
|
case 's': {
|
||||||
if (args[1] >= 0x800000) {
|
if (args[1] >= 0x800000) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
|
cfg_set_error(ERROR_TYPE_SD_CARD, SD_ERROR_INVALID_ARGUMENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cfg_translate_address(&args[0], args[1] * SD_SECTOR_SIZE, (SDRAM | FLASH | BRAM))) {
|
if (cfg_translate_address(&args[0], args[1] * SD_SECTOR_SIZE, (SDRAM | FLASH | BRAM))) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(ERROR_TYPE_SD_CARD, SD_ERROR_INVALID_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
led_activity_on();
|
led_activity_on();
|
||||||
bool error = sd_read_sectors(args[0], p.sd_card_sector, args[1]);
|
sd_error_t error = sd_read_sectors(args[0], p.sd_card_sector, args[1]);
|
||||||
led_activity_off();
|
led_activity_off();
|
||||||
if (error) {
|
if (error != SD_OK) {
|
||||||
cfg_set_error(CFG_ERROR_SD_CARD);
|
cfg_set_error(ERROR_TYPE_SD_CARD, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p.sd_card_sector += args[1];
|
p.sd_card_sector += args[1];
|
||||||
@ -649,18 +657,18 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 'S': {
|
case 'S': {
|
||||||
if (args[1] >= 0x800000) {
|
if (args[1] >= 0x800000) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
|
cfg_set_error(ERROR_TYPE_SD_CARD, SD_ERROR_INVALID_ARGUMENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cfg_translate_address(&args[0], args[1] * SD_SECTOR_SIZE, (SDRAM | FLASH | BRAM))) {
|
if (cfg_translate_address(&args[0], args[1] * SD_SECTOR_SIZE, (SDRAM | FLASH | BRAM))) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(ERROR_TYPE_SD_CARD, SD_ERROR_INVALID_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
led_activity_on();
|
led_activity_on();
|
||||||
bool error = sd_write_sectors(args[0], p.sd_card_sector, args[1]);
|
sd_error_t error = sd_write_sectors(args[0], p.sd_card_sector, args[1]);
|
||||||
led_activity_off();
|
led_activity_off();
|
||||||
if (error) {
|
if (error != SD_OK) {
|
||||||
cfg_set_error(CFG_ERROR_SD_CARD);
|
cfg_set_error(ERROR_TYPE_SD_CARD, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p.sd_card_sector += args[1];
|
p.sd_card_sector += args[1];
|
||||||
@ -669,7 +677,7 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
if (cfg_translate_address(&args[0], args[1], (SDRAM | BRAM))) {
|
if (cfg_translate_address(&args[0], args[1], (SDRAM | BRAM))) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dd_set_disk_mapping(args[0], args[1]);
|
dd_set_disk_mapping(args[0], args[1]);
|
||||||
@ -681,7 +689,7 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 'W':
|
case 'W':
|
||||||
if (cfg_translate_address(&args[0], WRITEBACK_SECTOR_TABLE_SIZE, (SDRAM | BRAM))) {
|
if (cfg_translate_address(&args[0], WRITEBACK_SECTOR_TABLE_SIZE, (SDRAM | BRAM))) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
writeback_load_sector_table(args[0]);
|
writeback_load_sector_table(args[0]);
|
||||||
@ -690,15 +698,15 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 'K':
|
case 'K':
|
||||||
if (args[1] >= DATA_BUFFER_SIZE) {
|
if (args[1] >= DATA_BUFFER_SIZE) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ARGUMENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cfg_translate_address(&args[0], args[1], FLASH)) {
|
if (cfg_translate_address(&args[0], args[1], FLASH)) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (flash_program(DATA_BUFFER_ADDRESS, args[0], args[1])) {
|
if (flash_program(DATA_BUFFER_ADDRESS, args[0], args[1])) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ARGUMENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -712,24 +720,24 @@ void cfg_process (void) {
|
|||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
if (cfg_translate_address(&args[0], FLASH_ERASE_BLOCK_SIZE, FLASH)) {
|
if (cfg_translate_address(&args[0], FLASH_ERASE_BLOCK_SIZE, FLASH)) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ADDRESS);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (flash_erase_block(args[0])) {
|
if (flash_erase_block(args[0])) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ARGUMENT);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
if (cfg_read_diagnostic_data(args)) {
|
if (cfg_read_diagnostic_data(args)) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_CONFIG_ID);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_INVALID_ID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cfg_set_error(CFG_ERROR_UNKNOWN_CMD);
|
cfg_set_error(ERROR_TYPE_CFG, CFG_ERROR_UNKNOWN_COMMAND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,9 +137,9 @@ static bool dd_block_read_request (void) {
|
|||||||
uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE];
|
uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE];
|
||||||
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, false);
|
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, false);
|
||||||
led_activity_on();
|
led_activity_on();
|
||||||
bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_read_sectors);
|
sd_error_t error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_read_sectors);
|
||||||
led_activity_off();
|
led_activity_off();
|
||||||
dd_set_block_ready(!error);
|
dd_set_block_ready(error == SD_OK);
|
||||||
} else {
|
} else {
|
||||||
usb_tx_info_t packet_info;
|
usb_tx_info_t packet_info;
|
||||||
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);
|
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);
|
||||||
@ -161,9 +161,9 @@ static bool dd_block_write_request (void) {
|
|||||||
uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE];
|
uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE];
|
||||||
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, true);
|
uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, true);
|
||||||
led_activity_on();
|
led_activity_on();
|
||||||
bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_write_sectors);
|
sd_error_t error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_write_sectors);
|
||||||
led_activity_off();
|
led_activity_off();
|
||||||
dd_set_block_ready(!error);
|
dd_set_block_ready(error == SD_OK);
|
||||||
} else {
|
} else {
|
||||||
usb_tx_info_t packet_info;
|
usb_tx_info_t packet_info;
|
||||||
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);
|
usb_create_packet(&packet_info, PACKET_CMD_DD_REQUEST);
|
||||||
|
@ -61,7 +61,6 @@ typedef enum {
|
|||||||
|
|
||||||
|
|
||||||
#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1))
|
#define ALIGN(value, align) (((value) + ((typeof(value))(align) - 1)) & ~((typeof(value))(align) - 1))
|
||||||
#define SWAP16(x) ((((x) & 0xFF) << 8) | (((x) & 0xFF00) >> 8))
|
|
||||||
#define SWAP32(x) (((x) & 0xFF) << 24 | ((x) & 0xFF00) << 8 | ((x) & 0xFF0000) >> 8 | ((x) & 0xFF000000) >> 24)
|
#define SWAP32(x) (((x) & 0xFF) << 24 | ((x) & 0xFF00) << 8 | ((x) & 0xFF0000) >> 8 | ((x) & 0xFF000000) >> 24)
|
||||||
|
|
||||||
#define FPGA_ID (0x64)
|
#define FPGA_ID (0x64)
|
||||||
|
@ -339,12 +339,12 @@ static void hw_i2c_init (void) {
|
|||||||
I2C1->CR1 |= I2C_CR1_PE;
|
I2C1->CR1 |= I2C_CR1_PE;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length) {
|
i2c_error_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length) {
|
||||||
hw_timeout_start();
|
hw_timeout_start();
|
||||||
|
|
||||||
while (I2C1->ISR & I2C_ISR_BUSY) {
|
while (I2C1->ISR & I2C_ISR_BUSY) {
|
||||||
if (hw_timeout_elapsed(I2C_TIMEOUT_US_BUSY)) {
|
if (hw_timeout_elapsed(I2C_TIMEOUT_US_BUSY)) {
|
||||||
return I2C_ERR_BUSY;
|
return I2C_ERROR_BUSY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,11 +372,11 @@ i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isr & I2C_ISR_NACKF) {
|
if (isr & I2C_ISR_NACKF) {
|
||||||
return I2C_ERR_NACK;
|
return I2C_ERROR_NACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hw_timeout_elapsed(tx_timeout)) {
|
if (hw_timeout_elapsed(tx_timeout)) {
|
||||||
return I2C_ERR_TIMEOUT;
|
return I2C_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,7 +386,7 @@ i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint
|
|||||||
|
|
||||||
while (!(I2C1->ISR & I2C_ISR_TC)) {
|
while (!(I2C1->ISR & I2C_ISR_TC)) {
|
||||||
if (hw_timeout_elapsed(tx_timeout)) {
|
if (hw_timeout_elapsed(tx_timeout)) {
|
||||||
return I2C_ERR_TIMEOUT;
|
return I2C_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,7 +415,7 @@ i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hw_timeout_elapsed(rx_timeout)) {
|
if (hw_timeout_elapsed(rx_timeout)) {
|
||||||
return I2C_ERR_TIMEOUT;
|
return I2C_ERROR_TIMEOUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,10 @@ typedef enum {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
I2C_OK,
|
I2C_OK,
|
||||||
I2C_ERR_BUSY,
|
I2C_ERROR_BUSY,
|
||||||
I2C_ERR_TIMEOUT,
|
I2C_ERROR_TIMEOUT,
|
||||||
I2C_ERR_NACK,
|
I2C_ERROR_NACK,
|
||||||
} i2c_err_t;
|
} i2c_error_t;
|
||||||
|
|
||||||
typedef uint64_t hw_flash_t;
|
typedef uint64_t hw_flash_t;
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ void hw_spi_stop (void);
|
|||||||
void hw_spi_rx (uint8_t *data, int length);
|
void hw_spi_rx (uint8_t *data, int length);
|
||||||
void hw_spi_tx (uint8_t *data, int length);
|
void hw_spi_tx (uint8_t *data, int length);
|
||||||
|
|
||||||
i2c_err_t hw_i2c_trx (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length);
|
i2c_error_t hw_i2c_trx (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length);
|
||||||
|
|
||||||
void hw_crc32_reset (void);
|
void hw_crc32_reset (void);
|
||||||
uint32_t hw_crc32_calculate (uint8_t *data, uint32_t length);
|
uint32_t hw_crc32_calculate (uint8_t *data, uint32_t length);
|
||||||
|
@ -133,9 +133,9 @@ static bool lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint
|
|||||||
packet_length += length;
|
packet_length += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c_err_t err = hw_i2c_trx(LCMXO2_I2C_ADDR_CFG, packet, packet_length, buffer, (write ? 0 : length));
|
i2c_error_t error = hw_i2c_trx(LCMXO2_I2C_ADDR_CFG, packet, packet_length, buffer, (write ? 0 : length));
|
||||||
|
|
||||||
return (err != I2C_OK);
|
return (error != I2C_OK);
|
||||||
#else
|
#else
|
||||||
lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_WBCE);
|
lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_WBCE);
|
||||||
|
|
||||||
|
@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
#define CMD6_ARG_CHECK_HS (0x00FFFFF1UL)
|
#define CMD6_ARG_CHECK_HS (0x00FFFFF1UL)
|
||||||
#define CMD6_ARG_SWITCH_HS (0x80FFFFF1UL)
|
#define CMD6_ARG_SWITCH_HS (0x80FFFFF1UL)
|
||||||
|
#define CMD6_DATA_LENGTH (64)
|
||||||
|
#define CMD6_INVALID_CURRENT_LIMIT(b) ((((b)[0] << 8) | (b)[1]) == 0)
|
||||||
|
#define CMD6_HS_SUPPORTED(b) ((b)[13] & (1 << 1))
|
||||||
|
#define CMD6_HS_ENABLED(b) (((b)[16] & 0x0F) == 0x01)
|
||||||
|
|
||||||
#define CMD8_ARG_SUPPLY_VOLTAGE_27_36_V (1 << 8)
|
#define CMD8_ARG_SUPPLY_VOLTAGE_27_36_V (1 << 8)
|
||||||
#define CMD8_ARG_CHECK_PATTERN (0xAA << 0)
|
#define CMD8_ARG_CHECK_PATTERN (0xAA << 0)
|
||||||
@ -18,6 +22,9 @@
|
|||||||
#define ACMD41_ARG_OCR (0x300000 << 0)
|
#define ACMD41_ARG_OCR (0x300000 << 0)
|
||||||
#define ACMD41_ARG_HCS (1 << 30)
|
#define ACMD41_ARG_HCS (1 << 30)
|
||||||
|
|
||||||
|
#define R1_APP_CMD (1 << 5)
|
||||||
|
#define R1_ILLEGAL_COMMAND (1 << 22)
|
||||||
|
|
||||||
#define R3_OCR (0x300000 << 0)
|
#define R3_OCR (0x300000 << 0)
|
||||||
#define R3_CCS (1 << 30)
|
#define R3_CCS (1 << 30)
|
||||||
#define R3_BUSY (1 << 31)
|
#define R3_BUSY (1 << 31)
|
||||||
@ -27,12 +34,9 @@
|
|||||||
#define R7_SUPPLY_VOLTAGE_27_36_V (1 << 8)
|
#define R7_SUPPLY_VOLTAGE_27_36_V (1 << 8)
|
||||||
#define R7_CHECK_PATTERN (0xAA << 0)
|
#define R7_CHECK_PATTERN (0xAA << 0)
|
||||||
|
|
||||||
#define SWITCH_FUNCTION_CURRENT_LIMIT (SD_INIT_BUFFER_ADDRESS + 0)
|
|
||||||
#define SWITCH_FUNCTION_GROUP_1 (SD_INIT_BUFFER_ADDRESS + 12)
|
|
||||||
#define SWITCH_FUNCTION_GROUP_1_HS (1 << 1)
|
|
||||||
|
|
||||||
#define TIMEOUT_INIT_MS (1000)
|
#define TIMEOUT_INIT_MS (1000)
|
||||||
|
|
||||||
|
#define DAT_CRC16_LENGTH (8)
|
||||||
#define DAT_BLOCK_MAX_COUNT (256)
|
#define DAT_BLOCK_MAX_COUNT (256)
|
||||||
#define DAT_TIMEOUT_INIT_MS (2000)
|
#define DAT_TIMEOUT_INIT_MS (2000)
|
||||||
#define DAT_TIMEOUT_DATA_MS (5000)
|
#define DAT_TIMEOUT_DATA_MS (5000)
|
||||||
@ -62,9 +66,17 @@ typedef enum {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DAT_OK,
|
DAT_OK,
|
||||||
DAT_ERR_IO,
|
DAT_ERROR_IO,
|
||||||
DAT_ERR_TIMEOUT,
|
DAT_ERROR_TIMEOUT,
|
||||||
} dat_err_t;
|
} dat_error_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CMD6_OK,
|
||||||
|
CMD6_ERROR_ILLEGAL_CMD,
|
||||||
|
CMD6_ERROR_IO,
|
||||||
|
CMD6_ERROR_CRC,
|
||||||
|
CMD6_ERROR_TIMEOUT,
|
||||||
|
} cmd6_error_t;
|
||||||
|
|
||||||
|
|
||||||
struct process {
|
struct process {
|
||||||
@ -150,7 +162,11 @@ static bool sd_cmd (uint8_t cmd, uint32_t arg, rsp_type_t rsp_type, void *rsp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool sd_acmd (uint8_t acmd, uint32_t arg, rsp_type_t rsp_type, void *rsp) {
|
static bool sd_acmd (uint8_t acmd, uint32_t arg, rsp_type_t rsp_type, void *rsp) {
|
||||||
if (sd_cmd(55, p.rca, RSP_R1, NULL)) {
|
uint32_t acmd_rsp;
|
||||||
|
if (sd_cmd(55, p.rca, RSP_R1, &acmd_rsp)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(acmd_rsp & R1_APP_CMD)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (sd_cmd(acmd, arg, rsp_type, rsp)) {
|
if (sd_cmd(acmd, arg, rsp_type, rsp)) {
|
||||||
@ -185,7 +201,7 @@ static void sd_dat_abort (void) {
|
|||||||
fpga_reg_set(REG_SD_DAT, SD_DAT_STOP | SD_DAT_FIFO_FLUSH);
|
fpga_reg_set(REG_SD_DAT, SD_DAT_STOP | SD_DAT_FIFO_FLUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
static dat_err_t sd_dat_wait (uint16_t timeout_ms) {
|
static dat_error_t sd_dat_wait (uint16_t timeout_ms) {
|
||||||
timer_countdown_start(TIMER_ID_SD, timeout_ms);
|
timer_countdown_start(TIMER_ID_SD, timeout_ms);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@ -194,7 +210,7 @@ static dat_err_t sd_dat_wait (uint16_t timeout_ms) {
|
|||||||
if ((!(sd_dat & SD_DAT_BUSY)) && (!(sd_dma_scr & DMA_SCR_BUSY))) {
|
if ((!(sd_dat & SD_DAT_BUSY)) && (!(sd_dma_scr & DMA_SCR_BUSY))) {
|
||||||
if (sd_dat & SD_DAT_ERROR) {
|
if (sd_dat & SD_DAT_ERROR) {
|
||||||
sd_dat_abort();
|
sd_dat_abort();
|
||||||
return DAT_ERR_IO;
|
return DAT_ERROR_IO;
|
||||||
}
|
}
|
||||||
return DAT_OK;
|
return DAT_OK;
|
||||||
}
|
}
|
||||||
@ -202,19 +218,87 @@ static dat_err_t sd_dat_wait (uint16_t timeout_ms) {
|
|||||||
|
|
||||||
sd_dat_abort();
|
sd_dat_abort();
|
||||||
|
|
||||||
return DAT_ERR_TIMEOUT;
|
return DAT_ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool sd_dat_check_crc16 (uint8_t *data, uint32_t length) {
|
||||||
|
uint16_t device_crc[4];
|
||||||
|
uint16_t controller_crc[4];
|
||||||
|
|
||||||
|
for (int crc = 0; crc < 4; crc++) {
|
||||||
|
device_crc[crc] = 0;
|
||||||
|
controller_crc[crc] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t index = length; index < (length + DAT_CRC16_LENGTH); index++) {
|
||||||
|
uint8_t byte = data[index];
|
||||||
|
for (int nibble = 0; nibble < 2; nibble++) {
|
||||||
|
for (int crc = 0; crc < 4; crc++) {
|
||||||
|
device_crc[crc] <<= 1;
|
||||||
|
device_crc[crc] |= (byte >> (7 - crc)) & (1 << 0);
|
||||||
|
}
|
||||||
|
byte <<= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t index = 0; index < length; index++) {
|
||||||
|
uint8_t byte = data[index];
|
||||||
|
for (int nibble = 0; nibble < 2; nibble++) {
|
||||||
|
for (int crc = 0; crc < 4; crc++) {
|
||||||
|
uint8_t inv = ((controller_crc[crc] >> 15) ^ (byte >> (7 - crc))) & (1 << 0);
|
||||||
|
controller_crc[crc] ^= (inv << 11) | (inv << 4);
|
||||||
|
controller_crc[crc] <<= 1;
|
||||||
|
controller_crc[crc] |= inv;
|
||||||
|
}
|
||||||
|
byte <<= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int crc = 0; crc < 4; crc++) {
|
||||||
|
if (controller_crc[crc] != device_crc[crc]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cmd6_error_t sd_cmd6 (uint32_t arg, uint8_t *buffer) {
|
||||||
|
uint32_t rsp;
|
||||||
|
sd_dat_prepare(SD_INIT_BUFFER_ADDRESS, 1, DAT_READ);
|
||||||
|
if (sd_cmd(6, arg, RSP_R1, &rsp)) {
|
||||||
|
sd_dat_abort();
|
||||||
|
return CMD6_ERROR_IO;
|
||||||
|
}
|
||||||
|
if (rsp & R1_ILLEGAL_COMMAND) {
|
||||||
|
sd_dat_abort();
|
||||||
|
return CMD6_ERROR_ILLEGAL_CMD;
|
||||||
|
}
|
||||||
|
if (sd_dat_wait(DAT_TIMEOUT_INIT_MS) == DAT_ERROR_TIMEOUT) {
|
||||||
|
return CMD6_ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
fpga_mem_read(SD_INIT_BUFFER_ADDRESS, CMD6_DATA_LENGTH + DAT_CRC16_LENGTH, buffer);
|
||||||
|
if (sd_dat_check_crc16(buffer, CMD6_DATA_LENGTH)) {
|
||||||
|
return CMD6_ERROR_CRC;
|
||||||
|
}
|
||||||
|
return SD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool sd_card_init (void) {
|
sd_error_t sd_card_init (void) {
|
||||||
uint32_t arg;
|
uint32_t arg;
|
||||||
uint32_t rsp;
|
uint32_t rsp;
|
||||||
uint16_t tmp;
|
cmd6_error_t cmd6_error;
|
||||||
|
uint8_t cmd6_buffer[CMD6_DATA_LENGTH + DAT_CRC16_LENGTH];
|
||||||
|
|
||||||
p.byte_swap = false;
|
p.byte_swap = false;
|
||||||
|
|
||||||
if (p.card_initialized) {
|
if (p.card_initialized) {
|
||||||
return false;
|
return SD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sd_card_is_inserted()) {
|
||||||
|
return SD_ERROR_NO_CARD_IN_SLOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
p.card_initialized = true;
|
p.card_initialized = true;
|
||||||
@ -230,7 +314,7 @@ bool sd_card_init (void) {
|
|||||||
} else {
|
} else {
|
||||||
if (rsp != (R7_SUPPLY_VOLTAGE_27_36_V | R7_CHECK_PATTERN)) {
|
if (rsp != (R7_SUPPLY_VOLTAGE_27_36_V | R7_CHECK_PATTERN)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_CMD8_IO;
|
||||||
}
|
}
|
||||||
arg = (ACMD41_ARG_HCS | ACMD41_ARG_OCR);
|
arg = (ACMD41_ARG_HCS | ACMD41_ARG_OCR);
|
||||||
}
|
}
|
||||||
@ -239,16 +323,16 @@ bool sd_card_init (void) {
|
|||||||
do {
|
do {
|
||||||
if (timer_countdown_elapsed(TIMER_ID_SD)) {
|
if (timer_countdown_elapsed(TIMER_ID_SD)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_ACMD41_TIMEOUT;
|
||||||
}
|
}
|
||||||
if (sd_acmd(41, arg, RSP_R3, &rsp)) {
|
if (sd_acmd(41, arg, RSP_R3, &rsp)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_ACMD41_IO;
|
||||||
}
|
}
|
||||||
if (rsp & R3_BUSY) {
|
if (rsp & R3_BUSY) {
|
||||||
if ((rsp & R3_OCR) == 0) {
|
if ((rsp & R3_OCR) == 0) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_ACMD41_OCR;
|
||||||
}
|
}
|
||||||
p.card_type_block = (rsp & R3_CCS);
|
p.card_type_block = (rsp & R3_CCS);
|
||||||
break;
|
break;
|
||||||
@ -257,71 +341,78 @@ bool sd_card_init (void) {
|
|||||||
|
|
||||||
if (sd_cmd(2, 0, RSP_R2, NULL)) {
|
if (sd_cmd(2, 0, RSP_R2, NULL)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_CMD2_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sd_cmd(3, 0, RSP_R6, &rsp)) {
|
if (sd_cmd(3, 0, RSP_R6, &rsp)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_CMD3_IO;
|
||||||
}
|
}
|
||||||
p.rca = (rsp & R6_RCA_MASK);
|
p.rca = (rsp & R6_RCA_MASK);
|
||||||
|
|
||||||
if (sd_cmd(9, p.rca, RSP_R2, p.csd)) {
|
if (sd_cmd(9, p.rca, RSP_R2, p.csd)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_CMD9_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sd_cmd(10, p.rca, RSP_R2, p.cid)) {
|
if (sd_cmd(10, p.rca, RSP_R2, p.cid)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_CMD10_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sd_cmd(7, p.rca, RSP_R1b, NULL)) {
|
if (sd_cmd(7, p.rca, RSP_R1b, NULL)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_CMD7_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
sd_set_clock(CLOCK_25MHZ);
|
sd_set_clock(CLOCK_25MHZ);
|
||||||
|
|
||||||
if (sd_acmd(6, ACMD6_ARG_BUS_WIDTH_4BIT, RSP_R1, NULL)) {
|
if (sd_acmd(6, ACMD6_ARG_BUS_WIDTH_4BIT, RSP_R1, NULL)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_ACMD6_IO;
|
||||||
}
|
}
|
||||||
|
|
||||||
sd_dat_prepare(SD_INIT_BUFFER_ADDRESS, 1, DAT_READ);
|
if ((cmd6_error = sd_cmd6(CMD6_ARG_CHECK_HS, cmd6_buffer)) == CMD6_ERROR_ILLEGAL_CMD) {
|
||||||
if (sd_cmd(6, CMD6_ARG_CHECK_HS, RSP_R1, NULL)) {
|
return SD_OK;
|
||||||
sd_dat_abort();
|
|
||||||
sd_card_deinit();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if (sd_dat_wait(DAT_TIMEOUT_INIT_MS) == DAT_ERR_TIMEOUT) {
|
|
||||||
|
if (cmd6_error != CMD6_OK) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
switch (cmd6_error) {
|
||||||
|
case CMD6_ERROR_IO: return SD_ERROR_CMD6_CHECK_IO;
|
||||||
|
case CMD6_ERROR_CRC: return SD_ERROR_CMD6_CHECK_CRC;
|
||||||
|
case CMD6_ERROR_TIMEOUT: return SD_ERROR_CMD6_CHECK_TIMEOUT;
|
||||||
|
default: return SD_ERROR_CMD6_CHECK_IO;
|
||||||
}
|
}
|
||||||
fpga_mem_read(SWITCH_FUNCTION_CURRENT_LIMIT, 2, (uint8_t *) (&tmp));
|
}
|
||||||
if (SWAP16(tmp) == 0) {
|
|
||||||
|
if (CMD6_INVALID_CURRENT_LIMIT(cmd6_buffer)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_CMD6_CHECK_RESPONSE;
|
||||||
}
|
}
|
||||||
fpga_mem_read(SWITCH_FUNCTION_GROUP_1, 2, (uint8_t *) (&tmp));
|
|
||||||
if (SWAP16(tmp) & SWITCH_FUNCTION_GROUP_1_HS) {
|
if (CMD6_HS_SUPPORTED(cmd6_buffer)) {
|
||||||
sd_dat_prepare(SD_INIT_BUFFER_ADDRESS, 1, DAT_READ);
|
if ((cmd6_error = sd_cmd6(CMD6_ARG_SWITCH_HS, cmd6_buffer)) != CMD6_OK) {
|
||||||
if (sd_cmd(6, CMD6_ARG_SWITCH_HS, RSP_R1, NULL)) {
|
|
||||||
sd_dat_abort();
|
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
switch (cmd6_error) {
|
||||||
|
case CMD6_ERROR_IO: return SD_ERROR_CMD6_SWITCH_IO;
|
||||||
|
case CMD6_ERROR_CRC: return SD_ERROR_CMD6_SWITCH_CRC;
|
||||||
|
case CMD6_ERROR_TIMEOUT: return SD_ERROR_CMD6_SWITCH_TIMEOUT;
|
||||||
|
default: return SD_ERROR_CMD6_SWITCH_IO;
|
||||||
}
|
}
|
||||||
if (sd_dat_wait(DAT_TIMEOUT_INIT_MS) == DAT_ERR_TIMEOUT) {
|
}
|
||||||
|
|
||||||
|
if (CMD6_INVALID_CURRENT_LIMIT(cmd6_buffer)) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
return true;
|
return SD_ERROR_CMD6_SWITCH_RESPONSE;
|
||||||
}
|
}
|
||||||
fpga_mem_read(SWITCH_FUNCTION_GROUP_1, 2, (uint8_t *) (&tmp));
|
|
||||||
if (SWAP16(tmp) & SWITCH_FUNCTION_GROUP_1_HS) {
|
if (CMD6_HS_ENABLED(cmd6_buffer)) {
|
||||||
sd_set_clock(CLOCK_50MHZ);
|
sd_set_clock(CLOCK_50MHZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return SD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sd_card_deinit (void) {
|
void sd_card_deinit (void) {
|
||||||
@ -354,29 +445,33 @@ uint32_t sd_card_get_status (void) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sd_card_get_info (uint32_t address) {
|
sd_error_t sd_card_get_info (uint32_t address) {
|
||||||
if (!p.card_initialized) {
|
if (!p.card_initialized) {
|
||||||
return true;
|
return SD_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
fpga_mem_write(address, sizeof(p.csd), p.csd);
|
fpga_mem_write(address, sizeof(p.csd), p.csd);
|
||||||
address += sizeof(p.csd);
|
address += sizeof(p.csd);
|
||||||
fpga_mem_write(address, sizeof(p.cid), p.cid);
|
fpga_mem_write(address, sizeof(p.cid), p.cid);
|
||||||
address += sizeof(p.cid);
|
address += sizeof(p.cid);
|
||||||
return false;
|
return SD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sd_set_byte_swap (bool enabled) {
|
sd_error_t sd_set_byte_swap (bool enabled) {
|
||||||
if (!p.card_initialized) {
|
if (!p.card_initialized) {
|
||||||
return true;
|
return SD_ERROR_NOT_INITIALIZED;
|
||||||
}
|
}
|
||||||
p.byte_swap = enabled;
|
p.byte_swap = enabled;
|
||||||
return false;
|
return SD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
sd_error_t sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
||||||
if (!p.card_initialized || (count == 0)) {
|
if (!p.card_initialized) {
|
||||||
return true;
|
return SD_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
return SD_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p.card_type_block) {
|
if (!p.card_type_block) {
|
||||||
@ -386,12 +481,13 @@ bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
|||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
uint32_t blocks = ((count > DAT_BLOCK_MAX_COUNT) ? DAT_BLOCK_MAX_COUNT : count);
|
uint32_t blocks = ((count > DAT_BLOCK_MAX_COUNT) ? DAT_BLOCK_MAX_COUNT : count);
|
||||||
if (sd_cmd(25, sector, RSP_R1, NULL)) {
|
if (sd_cmd(25, sector, RSP_R1, NULL)) {
|
||||||
return true;
|
return SD_ERROR_CMD25_IO;
|
||||||
}
|
}
|
||||||
sd_dat_prepare(address, blocks, DAT_WRITE);
|
sd_dat_prepare(address, blocks, DAT_WRITE);
|
||||||
if (sd_dat_wait(DAT_TIMEOUT_DATA_MS) != DAT_OK) {
|
dat_error_t error = sd_dat_wait(DAT_TIMEOUT_DATA_MS);
|
||||||
|
if (error != DAT_OK) {
|
||||||
sd_cmd(12, 0, RSP_R1b, NULL);
|
sd_cmd(12, 0, RSP_R1b, NULL);
|
||||||
return true;
|
return (error == DAT_ERROR_IO) ? SD_ERROR_CMD25_CRC : SD_ERROR_CMD25_TIMEOUT;
|
||||||
}
|
}
|
||||||
sd_cmd(12, 0, RSP_R1b, NULL);
|
sd_cmd(12, 0, RSP_R1b, NULL);
|
||||||
address += (blocks * SD_SECTOR_SIZE);
|
address += (blocks * SD_SECTOR_SIZE);
|
||||||
@ -402,13 +498,17 @@ bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
sd_error_t sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
||||||
if (!p.card_initialized || (count == 0)) {
|
if (!p.card_initialized) {
|
||||||
return true;
|
return SD_ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
return SD_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.byte_swap && ((address % 2) != 0)) {
|
if (p.byte_swap && ((address % 2) != 0)) {
|
||||||
return true;
|
return SD_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p.card_type_block) {
|
if (!p.card_type_block) {
|
||||||
@ -420,11 +520,12 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
|||||||
sd_dat_prepare(address, blocks, DAT_READ);
|
sd_dat_prepare(address, blocks, DAT_READ);
|
||||||
if (sd_cmd(18, sector, RSP_R1, NULL)) {
|
if (sd_cmd(18, sector, RSP_R1, NULL)) {
|
||||||
sd_dat_abort();
|
sd_dat_abort();
|
||||||
return true;
|
return SD_ERROR_CMD18_IO;
|
||||||
}
|
}
|
||||||
if (sd_dat_wait(DAT_TIMEOUT_DATA_MS) != DAT_OK) {
|
dat_error_t error = sd_dat_wait(DAT_TIMEOUT_DATA_MS);
|
||||||
|
if (error != DAT_OK) {
|
||||||
sd_cmd(12, 0, RSP_R1b, NULL);
|
sd_cmd(12, 0, RSP_R1b, NULL);
|
||||||
return true;
|
return (error == DAT_ERROR_IO) ? SD_ERROR_CMD18_CRC : SD_ERROR_CMD18_TIMEOUT;
|
||||||
}
|
}
|
||||||
sd_cmd(12, 0, RSP_R1b, NULL);
|
sd_cmd(12, 0, RSP_R1b, NULL);
|
||||||
address += (blocks * SD_SECTOR_SIZE);
|
address += (blocks * SD_SECTOR_SIZE);
|
||||||
@ -432,21 +533,21 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
|||||||
count -= blocks;
|
count -= blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return SD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors) {
|
sd_error_t sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors) {
|
||||||
uint32_t starting_sector = 0;
|
uint32_t starting_sector = 0;
|
||||||
uint32_t sectors_to_process = 0;
|
uint32_t sectors_to_process = 0;
|
||||||
|
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
return true;
|
return SD_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i = 0; i < count; i++) {
|
for (uint32_t i = 0; i < count; i++) {
|
||||||
if (sector_table[i] == 0) {
|
if (sector_table[i] == 0) {
|
||||||
return true;
|
return SD_ERROR_INVALID_ARGUMENT;
|
||||||
}
|
}
|
||||||
sectors_to_process += 1;
|
sectors_to_process += 1;
|
||||||
if ((i < (count - 1)) && ((sector_table[i] + 1) == sector_table[i + 1])) {
|
if ((i < (count - 1)) && ((sector_table[i] + 1) == sector_table[i + 1])) {
|
||||||
@ -454,14 +555,14 @@ bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t cou
|
|||||||
}
|
}
|
||||||
bool error = sd_process_sectors(address, sector_table[starting_sector], sectors_to_process);
|
bool error = sd_process_sectors(address, sector_table[starting_sector], sectors_to_process);
|
||||||
if (error) {
|
if (error) {
|
||||||
return true;
|
return error;
|
||||||
}
|
}
|
||||||
address += (sectors_to_process * SD_SECTOR_SIZE);
|
address += (sectors_to_process * SD_SECTOR_SIZE);
|
||||||
starting_sector += sectors_to_process;
|
starting_sector += sectors_to_process;
|
||||||
sectors_to_process = 0;
|
sectors_to_process = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return SD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,20 +10,53 @@
|
|||||||
#define SD_CARD_INFO_SIZE (32)
|
#define SD_CARD_INFO_SIZE (32)
|
||||||
|
|
||||||
|
|
||||||
typedef bool sd_process_sectors_t (uint32_t address, uint32_t sector, uint32_t count);
|
typedef enum {
|
||||||
|
SD_OK = 0,
|
||||||
|
SD_ERROR_NO_CARD_IN_SLOT = 1,
|
||||||
|
SD_ERROR_NOT_INITIALIZED = 2,
|
||||||
|
SD_ERROR_INVALID_ARGUMENT = 3,
|
||||||
|
SD_ERROR_INVALID_ADDRESS = 4,
|
||||||
|
SD_ERROR_INVALID_OPERATION = 5,
|
||||||
|
SD_ERROR_CMD2_IO = 6,
|
||||||
|
SD_ERROR_CMD3_IO = 7,
|
||||||
|
SD_ERROR_CMD6_CHECK_IO = 8,
|
||||||
|
SD_ERROR_CMD6_CHECK_CRC = 9,
|
||||||
|
SD_ERROR_CMD6_CHECK_TIMEOUT = 10,
|
||||||
|
SD_ERROR_CMD6_CHECK_RESPONSE = 11,
|
||||||
|
SD_ERROR_CMD6_SWITCH_IO = 12,
|
||||||
|
SD_ERROR_CMD6_SWITCH_CRC = 13,
|
||||||
|
SD_ERROR_CMD6_SWITCH_TIMEOUT = 14,
|
||||||
|
SD_ERROR_CMD6_SWITCH_RESPONSE = 15,
|
||||||
|
SD_ERROR_CMD7_IO = 16,
|
||||||
|
SD_ERROR_CMD8_IO = 17,
|
||||||
|
SD_ERROR_CMD9_IO = 18,
|
||||||
|
SD_ERROR_CMD10_IO = 19,
|
||||||
|
SD_ERROR_CMD18_IO = 20,
|
||||||
|
SD_ERROR_CMD18_CRC = 21,
|
||||||
|
SD_ERROR_CMD18_TIMEOUT = 22,
|
||||||
|
SD_ERROR_CMD25_IO = 23,
|
||||||
|
SD_ERROR_CMD25_CRC = 24,
|
||||||
|
SD_ERROR_CMD25_TIMEOUT = 25,
|
||||||
|
SD_ERROR_ACMD6_IO = 26,
|
||||||
|
SD_ERROR_ACMD41_IO = 27,
|
||||||
|
SD_ERROR_ACMD41_OCR = 28,
|
||||||
|
SD_ERROR_ACMD41_TIMEOUT = 29,
|
||||||
|
} sd_error_t;
|
||||||
|
|
||||||
|
typedef sd_error_t sd_process_sectors_t (uint32_t address, uint32_t sector, uint32_t count);
|
||||||
|
|
||||||
|
|
||||||
bool sd_card_init (void);
|
sd_error_t sd_card_init (void);
|
||||||
void sd_card_deinit (void);
|
void sd_card_deinit (void);
|
||||||
bool sd_card_is_inserted (void);
|
bool sd_card_is_inserted (void);
|
||||||
uint32_t sd_card_get_status (void);
|
uint32_t sd_card_get_status (void);
|
||||||
bool sd_card_get_info (uint32_t address);
|
sd_error_t sd_card_get_info (uint32_t address);
|
||||||
bool sd_set_byte_swap (bool enabled);
|
sd_error_t sd_set_byte_swap (bool enabled);
|
||||||
|
|
||||||
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count);
|
sd_error_t 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);
|
sd_error_t sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count);
|
||||||
|
|
||||||
bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors);
|
sd_error_t sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors);
|
||||||
|
|
||||||
void sd_init (void);
|
void sd_init (void);
|
||||||
|
|
||||||
|
@ -82,9 +82,9 @@ static void writeback_save_to_sd (void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool error = sd_optimize_sectors(address, p.sectors, (length / SD_SECTOR_SIZE), sd_write_sectors);
|
sd_error_t error = sd_optimize_sectors(address, p.sectors, (length / SD_SECTOR_SIZE), sd_write_sectors);
|
||||||
|
|
||||||
if (error) {
|
if (error != SD_OK) {
|
||||||
writeback_disable();
|
writeback_disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user