diff --git a/sw/bootloader/src/test.c b/sw/bootloader/src/test.c index 81b4c10..d223336 100644 --- a/sw/bootloader/src/test.c +++ b/sw/bootloader/src/test.c @@ -178,7 +178,7 @@ static void test_sd_card_io (void) { uint8_t sector[512] __attribute__((aligned(8))); if ((error = sc64_sd_card_get_status(&card_status)) != SC64_OK) { - error_display("Could not get SD card info\n (%08X) - %s", error, sc64_error_description(error)); + error_display("Could not get SD card status\n (%08X) - %s", error, sc64_error_description(error)); } if (card_status & SD_CARD_STATUS_INSERTED) { @@ -188,11 +188,11 @@ static void test_sd_card_io (void) { } if ((error = sc64_sd_card_deinit()) != SC64_OK) { - error_display("SD card deinit error\n (%08X) - %s", error, sc64_error_description(error)); + return display_printf("SD card deinit error, skipping test\n (%08X) - %s", error, sc64_error_description(error)); } if ((error = sc64_sd_card_init()) != SC64_OK) { - return display_printf("SD card init error\n (%08X) - %s\n", error, sc64_error_description(error)); + return display_printf("SD card init error, skipping test\n (%08X) - %s\n", error, sc64_error_description(error)); } if ((error = sc64_sd_card_get_status(&card_status)) != SC64_OK) { @@ -261,7 +261,7 @@ static void test_sd_card_fatfs (void) { UINT bytes; if ((error = sc64_sd_card_deinit()) != SC64_OK) { - error_display("SD card deinit error\n (%08X) - %s", error, sc64_error_description(error)); + return display_printf("SD card deinit error, skipping test\n (%08X) - %s", error, sc64_error_description(error)); } if ((fresult = f_mount(&fs, "", 1)) != FR_OK) { diff --git a/sw/controller/src/cfg.c b/sw/controller/src/cfg.c index 29cec9e..b3f5224 100644 --- a/sw/controller/src/cfg.c +++ b/sw/controller/src/cfg.c @@ -92,15 +92,6 @@ typedef enum { TV_TYPE_PASSTHROUGH = 3 } tv_type_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_BYTE_SWAP_ON = 4, - SD_CARD_OP_BYTE_SWAP_OFF = 5, -} sd_card_op_t; - typedef enum { DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE = 0, } diagnostic_id_t; @@ -641,15 +632,15 @@ void cfg_process (void) { case CMD_ID_SD_CARD_OP: { sd_error_t error = SD_OK; switch (p.data[1]) { - case SD_CARD_OP_DEINIT: - error = sd_get_lock(SD_LOCK_N64); + case SD_OP_DEINIT: + error = sd_try_lock(SD_LOCK_N64); if (error == SD_OK) { sd_card_deinit(); sd_release_lock(SD_LOCK_N64); } break; - case SD_CARD_OP_INIT: + case SD_OP_INIT: error = sd_try_lock(SD_LOCK_N64); if (error == SD_OK) { led_activity_on(); @@ -661,11 +652,11 @@ void cfg_process (void) { } break; - case SD_CARD_OP_GET_STATUS: + case SD_OP_GET_STATUS: p.data[1] = sd_card_get_status(); break; - case SD_CARD_OP_GET_INFO: + case SD_OP_GET_INFO: if (cfg_translate_address(&p.data[0], SD_CARD_INFO_SIZE, (SDRAM | BRAM))) { return cfg_cmd_reply_error(ERROR_TYPE_SD_CARD, SD_ERROR_INVALID_ADDRESS); } @@ -675,14 +666,14 @@ void cfg_process (void) { } break; - case SD_CARD_OP_BYTE_SWAP_ON: + case SD_OP_BYTE_SWAP_ON: error = sd_get_lock(SD_LOCK_N64); if (error == SD_OK) { error = sd_set_byte_swap(true); } break; - case SD_CARD_OP_BYTE_SWAP_OFF: + case SD_OP_BYTE_SWAP_OFF: error = sd_get_lock(SD_LOCK_N64); if (error == SD_OK) { error = sd_set_byte_swap(false); diff --git a/sw/controller/src/sd.c b/sw/controller/src/sd.c index 72d0411..a324c83 100644 --- a/sw/controller/src/sd.c +++ b/sw/controller/src/sd.c @@ -4,7 +4,7 @@ #include "timer.h" -#define SD_INIT_BUFFER_ADDRESS (0x05002BB8UL) +#define SD_INIT_BUFFER_ADDRESS (0x05002A00UL) #define BYTE_SWAP_ADDRESS_END (0x05000000UL) #define CMD6_ARG_CHECK_HS (0x00FFFFF1UL) @@ -35,11 +35,10 @@ #define R7_CHECK_PATTERN (0xAA << 0) #define TIMEOUT_INIT_MS (1000) +#define TIMEOUT_DATA_MS (5000) #define DAT_CRC16_LENGTH (8) #define DAT_BLOCK_MAX_COUNT (256) -#define DAT_TIMEOUT_INIT_MS (2000) -#define DAT_TIMEOUT_DATA_MS (5000) typedef enum { @@ -59,16 +58,12 @@ typedef enum { RSP_R7, } rsp_type_t; -typedef enum { - DAT_READ, - DAT_WRITE, -} dat_mode_t; - typedef enum { DAT_OK, + DAT_BUSY, DAT_ERROR_IO, DAT_ERROR_TIMEOUT, -} dat_error_t; +} dat_status_t; typedef enum { CMD6_OK, @@ -176,50 +171,97 @@ static bool sd_acmd (uint8_t acmd, uint32_t arg, rsp_type_t rsp_type, void *rsp) return false; } -static void sd_dat_prepare (uint32_t address, uint32_t count, dat_mode_t mode) { - uint32_t length = (count * SD_SECTOR_SIZE); - uint32_t sd_dat = (((count - 1) << SD_DAT_BLOCKS_BIT) | SD_DAT_FIFO_FLUSH); - uint32_t sd_dma_scr = DMA_SCR_START; +static void sd_dat_start_write (uint32_t count) { + uint32_t dat = (((count - 1) << SD_DAT_BLOCKS_BIT) | SD_DAT_START_WRITE | SD_DAT_FIFO_FLUSH); + fpga_reg_set(REG_SD_DAT, dat); - if (mode == DAT_READ) { - sd_dat |= SD_DAT_START_READ; - sd_dma_scr |= DMA_SCR_DIRECTION; - if (p.byte_swap && (address < BYTE_SWAP_ADDRESS_END)) { - sd_dma_scr |= DMA_SCR_BYTE_SWAP; - } - } else { - sd_dat |= SD_DAT_START_WRITE; +} + +static void sd_dat_start_read (uint32_t count) { + uint32_t dat = (((count - 1) << SD_DAT_BLOCKS_BIT) | SD_DAT_START_READ | SD_DAT_FIFO_FLUSH); + fpga_reg_set(REG_SD_DAT, dat); + +} + +static dat_status_t sd_dat_status (void) { + uint32_t dat = fpga_reg_get(REG_SD_DAT); + if (dat & SD_DAT_BUSY) { + return DAT_BUSY; } - - fpga_reg_set(REG_SD_DAT, sd_dat); - fpga_reg_set(REG_SD_DMA_ADDRESS, address); - fpga_reg_set(REG_SD_DMA_LENGTH, length); - fpga_reg_set(REG_SD_DMA_SCR, sd_dma_scr); + if (dat & SD_DAT_ERROR) { + return DAT_ERROR_IO; + } + return DAT_OK; } static void sd_dat_abort (void) { - fpga_reg_set(REG_SD_DMA_SCR, DMA_SCR_STOP); fpga_reg_set(REG_SD_DAT, SD_DAT_STOP | SD_DAT_FIFO_FLUSH); } -static dat_error_t sd_dat_wait (uint16_t timeout_ms) { +static void sd_dma_start_write (uint32_t address, uint32_t count) { + uint32_t length = (count * SD_SECTOR_SIZE); + uint32_t scr = DMA_SCR_START; + + fpga_reg_set(REG_SD_DMA_ADDRESS, address); + fpga_reg_set(REG_SD_DMA_LENGTH, length); + fpga_reg_set(REG_SD_DMA_SCR, scr); +} + +static void sd_dma_start_read (uint32_t address, uint32_t count) { + uint32_t length = (count * SD_SECTOR_SIZE); + uint32_t scr = (DMA_SCR_DIRECTION | DMA_SCR_START); + + if (p.byte_swap && (address < BYTE_SWAP_ADDRESS_END)) { + scr |= DMA_SCR_BYTE_SWAP; + } + + fpga_reg_set(REG_SD_DMA_ADDRESS, address); + fpga_reg_set(REG_SD_DMA_LENGTH, length); + fpga_reg_set(REG_SD_DMA_SCR, scr); +} + +static void sd_dma_wait_busy (void) { + while (fpga_reg_get(REG_SD_DMA_SCR) & DMA_SCR_BUSY); +} + +static void sd_dma_abort (void) { + fpga_reg_set(REG_SD_DMA_SCR, DMA_SCR_STOP); + sd_dma_wait_busy(); +} + +static void sd_start_write (uint32_t address, uint32_t count) { + sd_dat_start_write(count); + sd_dma_start_write(address, count); +} + +static void sd_start_read (uint32_t address, uint32_t count) { + sd_dat_start_read(count); + sd_dma_start_read(address, count); +} + +static void sd_abort (void) { + sd_dma_abort(); + sd_dat_abort(); +} + +static dat_status_t sd_sync (uint16_t timeout_ms) { timer_countdown_start(TIMER_ID_SD, timeout_ms); - do { - uint32_t sd_dat = fpga_reg_get(REG_SD_DAT); - uint32_t sd_dma_scr = fpga_reg_get(REG_SD_DMA_SCR); - if ((!(sd_dat & SD_DAT_BUSY)) && (!(sd_dma_scr & DMA_SCR_BUSY))) { - if (sd_dat & SD_DAT_ERROR) { - sd_dat_abort(); - return DAT_ERROR_IO; + while (true) { + dat_status_t status = sd_dat_status(); + + if (status != DAT_BUSY) { + if (status != DAT_OK) { + sd_abort(); } - return DAT_OK; + return status; } - } while (!timer_countdown_elapsed(TIMER_ID_SD)); - sd_dat_abort(); - - return DAT_ERROR_TIMEOUT; + if (timer_countdown_elapsed(TIMER_ID_SD)) { + sd_abort(); + return DAT_ERROR_TIMEOUT; + } + } } static bool sd_dat_check_crc16 (uint8_t *data, uint32_t length) { @@ -266,15 +308,15 @@ static bool sd_dat_check_crc16 (uint8_t *data, uint32_t length) { 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); + sd_start_read(SD_INIT_BUFFER_ADDRESS, 1); if (sd_cmd(6, arg, RSP_R1, NULL)) { - sd_dat_abort(); + sd_abort(); if ((!sd_cmd(13, p.rca, RSP_R1, &rsp)) && (rsp & R1_ILLEGAL_COMMAND)) { return CMD6_ERROR_ILLEGAL_CMD; } return CMD6_ERROR_IO; } - if (sd_dat_wait(DAT_TIMEOUT_INIT_MS) == DAT_ERROR_TIMEOUT) { + if (sd_sync(TIMEOUT_DATA_MS) == DAT_ERROR_TIMEOUT) { return CMD6_ERROR_TIMEOUT; } fpga_mem_read(SD_INIT_BUFFER_ADDRESS, CMD6_DATA_LENGTH + DAT_CRC16_LENGTH, buffer); @@ -495,13 +537,12 @@ sd_error_t sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) if (sd_cmd(25, sector, RSP_R1, NULL)) { return SD_ERROR_CMD25_IO; } - sd_dat_prepare(address, blocks, DAT_WRITE); - dat_error_t error = sd_dat_wait(DAT_TIMEOUT_DATA_MS); - if (error != DAT_OK) { - sd_cmd(12, 0, RSP_R1b, NULL); - return (error == DAT_ERROR_IO) ? SD_ERROR_CMD25_CRC : SD_ERROR_CMD25_TIMEOUT; - } + sd_start_write(address, blocks); + dat_status_t status = sd_sync(TIMEOUT_DATA_MS); sd_cmd(12, 0, RSP_R1b, NULL); + if (status != DAT_OK) { + return (status == DAT_ERROR_IO) ? SD_ERROR_CMD25_CRC : SD_ERROR_CMD25_TIMEOUT; + } address += (blocks * SD_SECTOR_SIZE); sector += (blocks * (p.card_type_block ? 1 : SD_SECTOR_SIZE)); count -= blocks; @@ -529,17 +570,16 @@ sd_error_t sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) { while (count > 0) { uint32_t blocks = ((count > DAT_BLOCK_MAX_COUNT) ? DAT_BLOCK_MAX_COUNT : count); - sd_dat_prepare(address, blocks, DAT_READ); + sd_start_read(address, blocks); if (sd_cmd(18, sector, RSP_R1, NULL)) { - sd_dat_abort(); + sd_abort(); return SD_ERROR_CMD18_IO; } - dat_error_t error = sd_dat_wait(DAT_TIMEOUT_DATA_MS); - if (error != DAT_OK) { - sd_cmd(12, 0, RSP_R1b, NULL); - return (error == DAT_ERROR_IO) ? SD_ERROR_CMD18_CRC : SD_ERROR_CMD18_TIMEOUT; - } + dat_status_t status = sd_sync(TIMEOUT_DATA_MS); sd_cmd(12, 0, RSP_R1b, NULL); + if (status != DAT_OK) { + return (status == DAT_ERROR_IO) ? SD_ERROR_CMD18_CRC : SD_ERROR_CMD18_TIMEOUT; + } address += (blocks * SD_SECTOR_SIZE); sector += (blocks * (p.card_type_block ? 1 : SD_SECTOR_SIZE)); count -= blocks; diff --git a/sw/controller/src/sd.h b/sw/controller/src/sd.h index a6c8b03..f7f3af9 100644 --- a/sw/controller/src/sd.h +++ b/sw/controller/src/sd.h @@ -52,6 +52,15 @@ typedef enum { SD_LOCK_USB, } sd_lock_t; +typedef enum { + SD_OP_DEINIT = 0, + SD_OP_INIT = 1, + SD_OP_GET_STATUS = 2, + SD_OP_GET_INFO = 3, + SD_OP_BYTE_SWAP_ON = 4, + SD_OP_BYTE_SWAP_OFF = 5, +} sd_op_t; + sd_error_t sd_card_init (void); void sd_card_deinit (void); diff --git a/sw/controller/src/usb.c b/sw/controller/src/usb.c index 99f9a0b..9935b54 100644 --- a/sw/controller/src/usb.c +++ b/sw/controller/src/usb.c @@ -390,15 +390,15 @@ static void usb_rx_process (void) { case 'i': { sd_error_t error = SD_OK; switch (p.rx_args[1]) { - case 0: - error = sd_get_lock(SD_LOCK_USB); + case SD_OP_DEINIT: + error = sd_try_lock(SD_LOCK_USB); if (error == SD_OK) { sd_card_deinit(); sd_release_lock(SD_LOCK_USB); } break; - case 1: + case SD_OP_INIT: error = sd_try_lock(SD_LOCK_USB); if (error == SD_OK) { led_activity_on(); @@ -410,10 +410,10 @@ static void usb_rx_process (void) { } break; - case 2: + case SD_OP_GET_STATUS: break; - case 3: + case SD_OP_GET_INFO: if (usb_validate_address_length(p.rx_args[0], SD_CARD_INFO_SIZE, true)) { error = SD_ERROR_INVALID_ADDRESS; } else { @@ -424,14 +424,14 @@ static void usb_rx_process (void) { } break; - case 4: + case SD_OP_BYTE_SWAP_ON: error = sd_get_lock(SD_LOCK_USB); if (error == SD_OK) { error = sd_set_byte_swap(true); } break; - case 5: + case SD_OP_BYTE_SWAP_OFF: error = sd_get_lock(SD_LOCK_USB); if (error == SD_OK) { error = sd_set_byte_swap(false);