Skip to content

Commit

Permalink
[SC64][SW] Fix SD deinit error when the card is not locked + SD modul…
Browse files Browse the repository at this point in the history
…e refactor
  • Loading branch information
Polprzewodnikowy committed Nov 16, 2024
1 parent e2c100a commit 6eef811
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 81 deletions.
8 changes: 4 additions & 4 deletions sw/bootloader/src/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
23 changes: 7 additions & 16 deletions sw/controller/src/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
Expand All @@ -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);
}
Expand All @@ -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);
Expand Down
148 changes: 94 additions & 54 deletions sw/controller/src/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand All @@ -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,
Expand Down Expand Up @@ -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) {
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);

}

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;
}
if (dat & SD_DAT_ERROR) {
return DAT_ERROR_IO;
}
return DAT_OK;
}

static void sd_dat_abort (void) {
fpga_reg_set(REG_SD_DAT, SD_DAT_STOP | SD_DAT_FIFO_FLUSH);
}

static void sd_dma_start_write (uint32_t address, uint32_t count) {
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;

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;
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_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);
fpga_reg_set(REG_SD_DMA_SCR, scr);
}

static void sd_dat_abort (void) {
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);
fpga_reg_set(REG_SD_DAT, SD_DAT_STOP | SD_DAT_FIFO_FLUSH);
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_error_t sd_dat_wait (uint16_t timeout_ms) {
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) {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions sw/controller/src/sd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
14 changes: 7 additions & 7 deletions sw/controller/src/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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 {
Expand All @@ -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);
Expand Down

0 comments on commit 6eef811

Please sign in to comment.