mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-22 14:09:16 +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
|
// 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
|
||||||
|
@ -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) {
|
||||||
|
@ -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) */
|
||||||
|
|
||||||
|
|
||||||
|
@ -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: ^
|
||||||
|
@ -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 };
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user