sd card writing is working

This commit is contained in:
Polprzewodnikowy 2022-09-13 02:19:26 +02:00
parent 4e18dffaa0
commit ceed43c324
9 changed files with 211 additions and 12 deletions

View File

@ -15,7 +15,7 @@ module sd_dat (
// Input and output data sampling // Input and output data sampling
logic sd_dat_oe; logic sd_dat_oe;
logic sd_dat_out; logic [3:0] sd_dat_out;
logic [3:0] sd_dat_in; logic [3:0] sd_dat_in;
logic sd_dat_oe_data; logic sd_dat_oe_data;
logic [3:0] sd_dat_data; logic [3:0] sd_dat_data;
@ -82,10 +82,14 @@ module sd_dat (
// DAT state // DAT state
typedef enum bit [1:0] { typedef enum bit [2:0] {
STATE_IDLE, STATE_IDLE,
STATE_RX_WAIT, STATE_RX_WAIT,
STATE_RX STATE_RX,
STATE_TX_WAIT,
STATE_TX,
STATE_TX_STATUS_WAIT,
STATE_TX_STATUS
} e_state; } e_state;
e_state state; e_state state;
@ -113,6 +117,7 @@ module sd_dat (
next_state = STATE_RX_WAIT; next_state = STATE_RX_WAIT;
end end
if (sd_scb.dat_start_write) begin if (sd_scb.dat_start_write) begin
next_state = STATE_TX_WAIT;
end end
end end
@ -135,6 +140,46 @@ module sd_dat (
end end
end end
end end
STATE_TX_WAIT: begin
if (sd_clk_falling) begin
if (sd_scb.tx_count >= 11'd512) begin
next_state = STATE_TX;
end
end
end
STATE_TX: begin
if (sd_clk_falling) begin
if (counter == 11'd1042) begin
next_state = STATE_TX_STATUS_WAIT;
end
end
end
STATE_TX_STATUS_WAIT: begin
if (sd_clk_rising) begin
if (counter == 11'd8) begin
next_state = STATE_IDLE;
end else if (!sd_dat_in[0]) begin
next_state = STATE_TX_STATUS;
end
end
end
STATE_TX_STATUS: begin
if (sd_clk_rising) begin
if (counter == 11'd5) begin
if (sd_dat_in[0]) begin
if (blocks_remaining == 8'd0) begin
next_state = STATE_IDLE;
end else begin
next_state = STATE_TX_WAIT;
end
end
end
end
end
endcase endcase
end end
@ -186,10 +231,18 @@ module sd_dat (
// Data shifting // Data shifting
assign crc_data = rx_wdata[3:0]; logic [7:0] data_shift;
logic tx_rdata_valid;
assign crc_data = (state == STATE_RX) ? rx_wdata[3:0] : sd_dat_data;
always_comb begin
tx_read = (state == STATE_TX) && sd_clk_falling && (counter < 11'd1024) && (!counter[0]);
end
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
rx_write <= 1'b0; rx_write <= 1'b0;
tx_rdata_valid <= tx_read;
crc_reset <= 1'b0; crc_reset <= 1'b0;
crc_enable <= 1'b0; crc_enable <= 1'b0;
crc_shift <= 1'b0; crc_shift <= 1'b0;
@ -209,7 +262,7 @@ module sd_dat (
STATE_RX_WAIT: begin STATE_RX_WAIT: begin
if (sd_clk_rising) begin if (sd_clk_rising) begin
if (!sd_dat_in[0]) begin if (!sd_dat_in[0]) begin
counter <= 8'd1; counter <= 11'd1;
crc_reset <= 1'b1; crc_reset <= 1'b1;
end end
end end
@ -239,8 +292,75 @@ module sd_dat (
end end
end end
end end
STATE_TX_WAIT: begin
if (sd_clk_falling) begin
if (sd_scb.tx_count >= 11'd512) begin
counter <= 11'd0;
end
end
end
STATE_TX: begin
if (sd_clk_falling) begin
counter <= counter + 1'd1;
if (counter == 11'd0) begin
crc_reset <= 1'b1;
sd_dat_oe_data <= 1'b1;
sd_dat_data <= 4'h0;
end else if (counter <= 11'd1024) begin
crc_enable <= 1'b1;
{sd_dat_data, data_shift} <= {data_shift, 4'h0};
end else begin
crc_shift <= 1'b1;
sd_dat_data <= {crc_result[3][15], crc_result[2][15], crc_result[1][15], crc_result[0][15]};
end
if (counter == 11'd1042) begin
sd_dat_oe_data <= 1'b0;
counter <= 11'd0;
end
end
end
STATE_TX_STATUS_WAIT: begin
if (sd_clk_rising) begin
counter <= counter + 1'd1;
if (counter == 11'd8) begin
sd_scb.dat_error <= 1'b1;
end else if (!sd_dat_in[0]) begin
counter <= 11'd1;
end
end
end
STATE_TX_STATUS: begin
if (sd_clk_rising) begin
if (counter < 11'd5) begin
counter <= counter + 1'd1;
end
if ((counter == 11'd1) && (sd_dat_in[0] != 1'b0)) begin
sd_scb.dat_error <= 1'b1;
end
if ((counter == 11'd2) && (sd_dat_in[0] != 1'b1)) begin
sd_scb.dat_error <= 1'b1;
end
if ((counter == 11'd3) && (sd_dat_in[0] != 1'b0)) begin
sd_scb.dat_error <= 1'b1;
end
if ((counter == 11'd4) && (sd_dat_in[0] != 1'b1)) begin
sd_scb.dat_error <= 1'b1;
end
if ((counter == 11'd5) && (sd_dat_in[0] == 1'b1)) begin
blocks_remaining <= blocks_remaining - 1'd1;
end
end
end
endcase endcase
end end
if (tx_rdata_valid) begin
data_shift <= tx_rdata;
end
end end
endmodule endmodule

View File

@ -69,9 +69,34 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
if (pdrv > 0) { if (pdrv > 0) {
return RES_PARERR; return RES_PARERR;
} }
// TODO: write uint32_t *physical_address = (uint32_t *) (PHYSICAL(buff));
if (physical_address < (uint32_t *) (N64_RAM_SIZE)) {
uint8_t aligned_buffer[BUFFER_BLOCKS_MAX * SD_BLOCK_SIZE] __attribute__((aligned(8)));
while (count > 0) {
uint32_t blocks = ((count > BUFFER_BLOCKS_MAX) ? BUFFER_BLOCKS_MAX : count);
size_t length = (blocks * SD_BLOCK_SIZE);
if (((uint32_t) (buff) % 8) == 0) {
cache_data_hit_writeback((void *) (buff), length);
pi_dma_write((io32_t *) (SC64_BUFFERS->BUFFER), (void *) (buff), length);
} else {
memcpy(aligned_buffer, buff, length);
cache_data_hit_writeback(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)) {
return RES_ERROR; return RES_ERROR;
} }
buff += length;
sector += blocks;
count -= blocks;
}
} else {
if (sc64_sd_write_sectors(physical_address, sector, count)) {
return RES_ERROR;
}
}
return RES_OK;
}
#endif #endif
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void *buff) { DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void *buff) {

View File

@ -166,7 +166,7 @@
/ Drive/Volume Configurations / Drive/Volume Configurations
/---------------------------------------------------------------------------*/ /---------------------------------------------------------------------------*/
#define FF_VOLUMES 2 #define FF_VOLUMES 1
/* Number of volumes (logical drives) to be used. (1-10) */ /* Number of volumes (logical drives) to be used. (1-10) */

View File

@ -60,7 +60,7 @@ void menu_load_and_run (void) {
} }
FF_CHECK(f_read(&fil, menu, size, &br), "Couldn't read menu file"); FF_CHECK(f_read(&fil, menu, size, &br), "Couldn't read menu file");
FF_CHECK(br != size, "Read size is different than expected"); FF_CHECK(br != size, "Read size is different than expected");
// TODO: delete this // TODO: delete this, do not touch SDRAM when loading menu
FF_CHECK(f_lseek(&fil, 0), "Couldn't seek to the beginning of file"); FF_CHECK(f_lseek(&fil, 0), "Couldn't seek to the beginning of file");
FF_CHECK(f_read(&fil, (void *) (0xB0000000UL), f_size(&fil), &br), "Couldn't read file contents to SDRAM"); FF_CHECK(f_read(&fil, (void *) (0xB0000000UL), f_size(&fil), &br), "Couldn't read file contents to SDRAM");
// TODO: ^ // TODO: ^

View File

@ -17,8 +17,8 @@ typedef enum {
SC64_CMD_USB_READ = 'm', SC64_CMD_USB_READ = 'm',
SC64_CMD_SD_CARD_INIT = 'i', SC64_CMD_SD_CARD_INIT = 'i',
SC64_CMD_SD_SECTOR_SET = 'I', SC64_CMD_SD_SECTOR_SET = 'I',
SC64_CMD_SD_READ = 's',
SC64_CMD_SD_WRITE = 'S', SC64_CMD_SD_WRITE = 'S',
SC64_CMD_SD_READ = 's',
} cmd_id_t; } cmd_id_t;
@ -157,6 +157,15 @@ bool sc64_sd_card_deinit (void) {
return false; return false;
} }
bool sc64_sd_write_sectors (uint32_t *address, uint32_t sector, uint32_t count) {
uint32_t sector_set_args[2] = { sector, 0 };
uint32_t write_args[2] = { (uint32_t) (address), count };
if (sc64_execute_cmd(SC64_CMD_SD_SECTOR_SET, sector_set_args, NULL)) {
return true;
}
return sc64_execute_cmd(SC64_CMD_SD_WRITE, write_args, NULL);
}
bool sc64_sd_read_sectors (uint32_t *address, uint32_t sector, uint32_t count) { bool sc64_sd_read_sectors (uint32_t *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

@ -105,6 +105,7 @@ bool sc64_usb_read_ready (uint8_t *type, uint32_t *length);
bool sc64_usb_read (uint32_t *address, uint32_t length); bool sc64_usb_read (uint32_t *address, uint32_t length);
bool sc64_sd_card_init (void); bool sc64_sd_card_init (void);
bool sc64_sd_card_deinit (void); bool sc64_sd_card_deinit (void);
bool sc64_sd_write_sectors (uint32_t *address, uint32_t sector, uint32_t count);
bool sc64_sd_read_sectors (uint32_t *address, uint32_t sector, uint32_t count); bool sc64_sd_read_sectors (uint32_t *address, uint32_t sector, uint32_t count);

View File

@ -415,6 +415,16 @@ void cfg_process (void) {
} }
break; break;
case 'S':
if (cfg_translate_address(args)) {
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
return;
}
if (sd_write_sectors(args[0], p.sd_card_sector, args[1])) {
cfg_set_error(CFG_ERROR_SD);
}
break;
default: default:
cfg_set_error(CFG_ERROR_UNKNOWN_CMD); cfg_set_error(CFG_ERROR_UNKNOWN_CMD);
return; return;

View File

@ -235,6 +235,39 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
return false; return false;
} }
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
if (!p.card_initialized || (count == 0)) {
return true;
}
if (!p.card_type_block) {
sector *= SD_BLOCK_SIZE;
}
while (count > 0) {
uint32_t blocks = ((count > DAT_BLOCK_MAX_COUNT) ? DAT_BLOCK_MAX_COUNT : count);
led_blink_act();
if (sd_cmd(23, blocks, RSP_R1, NULL)) {
return true;
}
if (sd_cmd(25, sector, RSP_R1, NULL)) {
return true;
}
sd_dat_prepare(address, blocks, DAT_WRITE);
bool error = sd_dat_wait(1000);
sd_cmd(12, 0, RSP_R1b, NULL);
if (error) {
sd_dat_abort();
return true;
}
address += (blocks * SD_BLOCK_SIZE);
sector += (blocks * (p.card_type_block ? 1 : SD_BLOCK_SIZE));
count -= blocks;
}
return false;
}
bool sd_card_init (void) { bool sd_card_init (void) {
uint32_t arg; uint32_t arg;
uint32_t rsp; uint32_t rsp;

View File

@ -6,6 +6,7 @@
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_write_sectors (uint32_t address, uint32_t sector, uint32_t count);
bool sd_card_init (void); bool sd_card_init (void);
void sd_card_deinit (void); void sd_card_deinit (void);
void sd_init (void); void sd_init (void);