mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-22 05:59:15 +01:00
sd card writing is working
This commit is contained in:
parent
4e18dffaa0
commit
ceed43c324
@ -15,7 +15,7 @@ module sd_dat (
|
||||
// Input and output data sampling
|
||||
|
||||
logic sd_dat_oe;
|
||||
logic sd_dat_out;
|
||||
logic [3:0] sd_dat_out;
|
||||
logic [3:0] sd_dat_in;
|
||||
logic sd_dat_oe_data;
|
||||
logic [3:0] sd_dat_data;
|
||||
@ -82,10 +82,14 @@ module sd_dat (
|
||||
|
||||
// DAT state
|
||||
|
||||
typedef enum bit [1:0] {
|
||||
typedef enum bit [2:0] {
|
||||
STATE_IDLE,
|
||||
STATE_RX_WAIT,
|
||||
STATE_RX
|
||||
STATE_RX,
|
||||
STATE_TX_WAIT,
|
||||
STATE_TX,
|
||||
STATE_TX_STATUS_WAIT,
|
||||
STATE_TX_STATUS
|
||||
} e_state;
|
||||
|
||||
e_state state;
|
||||
@ -113,6 +117,7 @@ module sd_dat (
|
||||
next_state = STATE_RX_WAIT;
|
||||
end
|
||||
if (sd_scb.dat_start_write) begin
|
||||
next_state = STATE_TX_WAIT;
|
||||
end
|
||||
end
|
||||
|
||||
@ -135,6 +140,46 @@ module sd_dat (
|
||||
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
|
||||
end
|
||||
|
||||
@ -186,10 +231,18 @@ module sd_dat (
|
||||
|
||||
// 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
|
||||
rx_write <= 1'b0;
|
||||
tx_rdata_valid <= tx_read;
|
||||
crc_reset <= 1'b0;
|
||||
crc_enable <= 1'b0;
|
||||
crc_shift <= 1'b0;
|
||||
@ -209,7 +262,7 @@ module sd_dat (
|
||||
STATE_RX_WAIT: begin
|
||||
if (sd_clk_rising) begin
|
||||
if (!sd_dat_in[0]) begin
|
||||
counter <= 8'd1;
|
||||
counter <= 11'd1;
|
||||
crc_reset <= 1'b1;
|
||||
end
|
||||
end
|
||||
@ -239,8 +292,75 @@ module sd_dat (
|
||||
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
|
||||
end
|
||||
|
||||
if (tx_rdata_valid) begin
|
||||
data_shift <= tx_rdata;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
@ -69,8 +69,33 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
||||
if (pdrv > 0) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
// TODO: write
|
||||
return RES_ERROR;
|
||||
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;
|
||||
}
|
||||
buff += length;
|
||||
sector += blocks;
|
||||
count -= blocks;
|
||||
}
|
||||
} else {
|
||||
if (sc64_sd_write_sectors(physical_address, sector, count)) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
}
|
||||
return RES_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -166,7 +166,7 @@
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_VOLUMES 2
|
||||
#define FF_VOLUMES 1
|
||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||
|
||||
|
||||
|
@ -60,9 +60,9 @@ void menu_load_and_run (void) {
|
||||
}
|
||||
FF_CHECK(f_read(&fil, menu, size, &br), "Couldn't read menu file");
|
||||
FF_CHECK(br != size, "Read size is different than expected");
|
||||
// TODO: delete this
|
||||
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");
|
||||
// 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_read(&fil, (void *) (0xB0000000UL), f_size(&fil), &br), "Couldn't read file contents to SDRAM");
|
||||
// TODO: ^
|
||||
FF_CHECK(f_close(&fil), "Couldn't close menu file");
|
||||
FF_CHECK(f_unmount(""), "Couldn't unmount drive");
|
||||
|
@ -17,8 +17,8 @@ typedef enum {
|
||||
SC64_CMD_USB_READ = 'm',
|
||||
SC64_CMD_SD_CARD_INIT = 'i',
|
||||
SC64_CMD_SD_SECTOR_SET = 'I',
|
||||
SC64_CMD_SD_READ = 's',
|
||||
SC64_CMD_SD_WRITE = 'S',
|
||||
SC64_CMD_SD_READ = 's',
|
||||
} cmd_id_t;
|
||||
|
||||
|
||||
@ -157,6 +157,15 @@ bool sc64_sd_card_deinit (void) {
|
||||
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) {
|
||||
uint32_t sector_set_args[2] = { sector, 0 };
|
||||
uint32_t read_args[2] = { (uint32_t) (address), count };
|
||||
|
@ -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_sd_card_init (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);
|
||||
|
||||
|
||||
|
@ -415,6 +415,16 @@ void cfg_process (void) {
|
||||
}
|
||||
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:
|
||||
cfg_set_error(CFG_ERROR_UNKNOWN_CMD);
|
||||
return;
|
||||
|
@ -235,6 +235,39 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
||||
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) {
|
||||
uint32_t arg;
|
||||
uint32_t rsp;
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
|
||||
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);
|
||||
void sd_card_deinit (void);
|
||||
void sd_init (void);
|
||||
|
Loading…
Reference in New Issue
Block a user