[SC64][FW][SW] SD card byte swap on reads support

This commit is contained in:
Mateusz Faderewski 2023-05-01 16:33:25 +02:00
parent 8c7f97b433
commit 647aa5cfc9
9 changed files with 66 additions and 8 deletions

View File

@ -364,6 +364,7 @@ module mcu_top (
logic bootloader_skip; logic bootloader_skip;
assign n64_scb.cfg_identifier = 32'h53437632; assign n64_scb.cfg_identifier = 32'h53437632;
assign usb_dma_scb.byte_swap = 1'b0;
logic dd_bm_ack; logic dd_bm_ack;
@ -577,7 +578,8 @@ module mcu_top (
REG_SD_DMA_SCR: begin REG_SD_DMA_SCR: begin
reg_rdata <= { reg_rdata <= {
28'd0, 27'd0,
sd_dma_scb.byte_swap,
sd_dma_scb.busy, sd_dma_scb.busy,
sd_dma_scb.direction, sd_dma_scb.direction,
2'b00 2'b00
@ -855,11 +857,10 @@ module mcu_top (
end end
REG_SD_DMA_SCR: begin REG_SD_DMA_SCR: begin
{ sd_dma_scb.byte_swap <= reg_wdata[4];
sd_dma_scb.direction, sd_dma_scb.direction <= reg_wdata[2];
sd_dma_scb.stop, sd_dma_scb.stop <= reg_wdata[1];
sd_dma_scb.start sd_dma_scb.start <= reg_wdata[0];
} <= reg_wdata[2:0];
end end
REG_DD_SCR: begin REG_DD_SCR: begin

View File

@ -4,6 +4,7 @@ interface dma_scb ();
logic stop; logic stop;
logic busy; logic busy;
logic direction; logic direction;
logic byte_swap;
logic [26:0] starting_address; logic [26:0] starting_address;
logic [26:0] transfer_length; logic [26:0] transfer_length;
@ -12,6 +13,7 @@ interface dma_scb ();
output stop, output stop,
input busy, input busy,
output direction, output direction,
output byte_swap,
output starting_address, output starting_address,
output transfer_length output transfer_length
); );
@ -21,6 +23,7 @@ interface dma_scb ();
input stop, input stop,
output busy, output busy,
input direction, input direction,
input byte_swap,
input starting_address, input starting_address,
input transfer_length input transfer_length
); );
@ -209,8 +212,12 @@ module memory_dma (
if (mem_bus.write) begin if (mem_bus.write) begin
if (rx_buffer_valid) begin if (rx_buffer_valid) begin
mem_bus.request <= 1'b1; mem_bus.request <= 1'b1;
if (dma_scb.byte_swap) begin
mem_bus.wdata <= {rx_buffer[7:0], rx_buffer[15:8]};
end else begin
mem_bus.wdata <= rx_buffer; mem_bus.wdata <= rx_buffer;
end end
end
end else begin end else begin
if (tx_buffer_ready) begin if (tx_buffer_ready) begin
mem_bus.request <= 1'b1; mem_bus.request <= 1'b1;

View File

@ -52,6 +52,8 @@ typedef enum {
SD_CARD_OP_INIT = 1, SD_CARD_OP_INIT = 1,
SD_CARD_OP_GET_STATUS = 2, SD_CARD_OP_GET_STATUS = 2,
SD_CARD_OP_GET_INFO = 3, SD_CARD_OP_GET_INFO = 3,
SD_CARD_OP_BYTE_SWAP_ON = 4,
SD_CARD_OP_BYTE_SWAP_OFF = 5,
} sd_card_op_t; } sd_card_op_t;
@ -235,6 +237,14 @@ bool sc64_sd_card_get_info (void *address) {
return false; return false;
} }
bool sc64_sd_set_byte_swap (bool enabled) {
uint32_t args[2] = { (uint32_t) (NULL), enabled ? SD_CARD_OP_BYTE_SWAP_ON : SD_CARD_OP_BYTE_SWAP_OFF };
if (sc64_execute_cmd(SC64_CMD_SD_CARD_OP, args, NULL)) {
return true;
}
return false;
}
bool sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count) { bool sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count) {
uint32_t sector_set_args[2] = { sector, 0 }; uint32_t sector_set_args[2] = { sector, 0 };
uint32_t read_args[2] = { (uint32_t) (address), count }; uint32_t read_args[2] = { (uint32_t) (address), count };

View File

@ -86,6 +86,7 @@ typedef enum {
SD_CARD_STATUS_INITIALIZED = (1 << 1), SD_CARD_STATUS_INITIALIZED = (1 << 1),
SD_CARD_STATUS_TYPE_BLOCK = (1 << 2), SD_CARD_STATUS_TYPE_BLOCK = (1 << 2),
SD_CARD_STATUS_50MHZ_MODE = (1 << 3), SD_CARD_STATUS_50MHZ_MODE = (1 << 3),
SD_CARD_STATUS_BYTE_SWAP = (1 << 4),
} sc64_sd_card_status_t; } sc64_sd_card_status_t;
typedef struct { typedef struct {
@ -143,6 +144,7 @@ bool sc64_sd_card_init (void);
bool sc64_sd_card_deinit (void); bool sc64_sd_card_deinit (void);
sc64_sd_card_status_t sc64_sd_card_get_status (void); sc64_sd_card_status_t sc64_sd_card_get_status (void);
bool sc64_sd_card_get_info (void *address); bool sc64_sd_card_get_info (void *address);
bool sc64_sd_set_byte_swap (bool enabled);
bool sc64_sd_write_sectors (void *address, uint32_t sector, uint32_t count); bool sc64_sd_write_sectors (void *address, uint32_t sector, uint32_t count);
bool sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count); bool sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count);
bool sc64_dd_set_sd_disk_info (void *address, uint32_t length); bool sc64_dd_set_sd_disk_info (void *address, uint32_t length);

View File

@ -57,6 +57,9 @@ static void test_sd_card (void) {
if (card_status & SD_CARD_STATUS_50MHZ_MODE) { if (card_status & SD_CARD_STATUS_50MHZ_MODE) {
display_printf("SD card runs at 50 MHz clock speed\n"); display_printf("SD card runs at 50 MHz clock speed\n");
} }
if (card_status & SD_CARD_STATUS_BYTE_SWAP) {
display_printf("SD card read byte swap is enabled\n");
}
if (sc64_sd_card_get_info((uint32_t *) (SC64_BUFFERS->BUFFER))) { if (sc64_sd_card_get_info((uint32_t *) (SC64_BUFFERS->BUFFER))) {
display_printf("SD card get info error!\n"); display_printf("SD card get info error!\n");

View File

@ -79,6 +79,8 @@ typedef enum {
SD_CARD_OP_INIT = 1, SD_CARD_OP_INIT = 1,
SD_CARD_OP_GET_STATUS = 2, SD_CARD_OP_GET_STATUS = 2,
SD_CARD_OP_GET_INFO = 3, SD_CARD_OP_GET_INFO = 3,
SD_CARD_OP_BYTE_SWAP_ON = 4,
SD_CARD_OP_BYTE_SWAP_OFF = 5,
} sd_card_op_t; } sd_card_op_t;
typedef enum { typedef enum {
@ -575,6 +577,18 @@ void cfg_process (void) {
return; return;
} }
break; break;
case SD_CARD_OP_BYTE_SWAP_ON:
if (sd_set_byte_swap(true)) {
cfg_set_error(CFG_ERROR_SD_CARD);
return;
}
break;
case SD_CARD_OP_BYTE_SWAP_OFF:
if (sd_set_byte_swap(false)) {
cfg_set_error(CFG_ERROR_SD_CARD);
return;
}
break;
default: default:
cfg_set_error(CFG_ERROR_BAD_ARGUMENT); cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
return; return;

View File

@ -92,6 +92,7 @@ typedef enum {
#define DMA_SCR_STOP (1 << 1) #define DMA_SCR_STOP (1 << 1)
#define DMA_SCR_DIRECTION (1 << 2) #define DMA_SCR_DIRECTION (1 << 2)
#define DMA_SCR_BUSY (1 << 3) #define DMA_SCR_BUSY (1 << 3)
#define DMA_SCR_BYTE_SWAP (1 << 4)
#define CFG_SCR_BOOTLOADER_ENABLED (1 << 0) #define CFG_SCR_BOOTLOADER_ENABLED (1 << 0)
#define CFG_SCR_BOOTLOADER_SKIP (1 << 1) #define CFG_SCR_BOOTLOADER_SKIP (1 << 1)

View File

@ -7,6 +7,7 @@
#define SD_INIT_BUFFER_ADDRESS (0x05002800UL) #define SD_INIT_BUFFER_ADDRESS (0x05002800UL)
#define BYTE_SWAP_ADDRESS_END (0x05000000UL)
#define CMD6_ARG_CHECK_HS (0x00FFFFF1UL) #define CMD6_ARG_CHECK_HS (0x00FFFFF1UL)
#define CMD6_ARG_SWITCH_HS (0x80FFFFF1UL) #define CMD6_ARG_SWITCH_HS (0x80FFFFF1UL)
@ -67,6 +68,7 @@ struct process {
uint8_t csd[16]; uint8_t csd[16];
uint8_t cid[16]; uint8_t cid[16];
volatile bool timeout; volatile bool timeout;
bool byte_swap;
}; };
@ -178,6 +180,9 @@ static void sd_dat_prepare (uint32_t address, uint32_t count, dat_mode_t mode) {
if (mode == DAT_READ) { if (mode == DAT_READ) {
sd_dat |= SD_DAT_START_READ; sd_dat |= SD_DAT_START_READ;
sd_dma_scr |= DMA_SCR_DIRECTION; sd_dma_scr |= DMA_SCR_DIRECTION;
if (p.byte_swap && (address < BYTE_SWAP_ADDRESS_END)) {
sd_dma_scr |= DMA_SCR_BYTE_SWAP;
}
} else { } else {
sd_dat |= SD_DAT_START_WRITE; sd_dat |= SD_DAT_START_WRITE;
} }
@ -217,6 +222,8 @@ bool sd_card_init (void) {
uint32_t rsp; uint32_t rsp;
uint16_t tmp; uint16_t tmp;
p.byte_swap = false;
if (p.card_initialized) { if (p.card_initialized) {
return false; return false;
} }
@ -336,6 +343,7 @@ bool sd_card_init (void) {
void sd_card_deinit (void) { void sd_card_deinit (void) {
if (p.card_initialized) { if (p.card_initialized) {
p.card_initialized = false; p.card_initialized = false;
p.byte_swap = false;
sd_set_clock(CLOCK_400KHZ); sd_set_clock(CLOCK_400KHZ);
sd_cmd(0, 0, RSP_NONE, NULL); sd_cmd(0, 0, RSP_NONE, NULL);
sd_set_clock(CLOCK_STOP); sd_set_clock(CLOCK_STOP);
@ -348,11 +356,13 @@ bool sd_card_is_inserted (void) {
uint32_t sd_card_get_status (void) { uint32_t sd_card_get_status (void) {
uint32_t scr = fpga_reg_get(REG_SD_SCR); uint32_t scr = fpga_reg_get(REG_SD_SCR);
uint32_t byte_swap = p.byte_swap ? 1 : 0;
uint32_t clock_mode_50mhz = ((scr & SD_SCR_CLOCK_MODE_MASK) == SD_SCR_CLOCK_MODE_50MHZ) ? 1 : 0; uint32_t clock_mode_50mhz = ((scr & SD_SCR_CLOCK_MODE_MASK) == SD_SCR_CLOCK_MODE_50MHZ) ? 1 : 0;
uint32_t card_type_block = p.card_type_block ? 1 : 0; uint32_t card_type_block = p.card_type_block ? 1 : 0;
uint32_t card_initialized = p.card_initialized ? 1 : 0; uint32_t card_initialized = p.card_initialized ? 1 : 0;
uint32_t card_inserted = (scr & SD_SCR_CARD_INSERTED) ? 1 : 0; uint32_t card_inserted = (scr & SD_SCR_CARD_INSERTED) ? 1 : 0;
return ( return (
(byte_swap << 4) |
(clock_mode_50mhz << 3) | (clock_mode_50mhz << 3) |
(card_type_block << 2) | (card_type_block << 2) |
(card_initialized << 1) | (card_initialized << 1) |
@ -371,6 +381,14 @@ bool sd_card_get_info (uint32_t address) {
return false; return false;
} }
bool sd_set_byte_swap (bool enabled) {
if (!p.card_initialized) {
return true;
}
p.byte_swap = enabled;
return false;
}
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) { bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
if (!p.card_initialized || (count == 0)) { if (!p.card_initialized || (count == 0)) {
return true; return true;
@ -463,11 +481,12 @@ bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t cou
void sd_init (void) { void sd_init (void) {
p.card_initialized = false; p.card_initialized = false;
p.byte_swap = false;
sd_set_clock(CLOCK_STOP); sd_set_clock(CLOCK_STOP);
} }
void sd_process (void) { void sd_process (void) {
if (!sd_card_is_inserted()) { if (p.card_initialized && !sd_card_is_inserted()) {
sd_card_deinit(); sd_card_deinit();
} }
} }

View File

@ -17,6 +17,7 @@ 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); bool sd_card_get_info (uint32_t address);
bool sd_set_byte_swap (bool enabled);
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count); bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count);
bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count); bool 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); bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors);