mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-29 00:44:13 +01:00
save writeback on reset fully working
This commit is contained in:
parent
3200919328
commit
aa74831511
@ -19,7 +19,7 @@
|
|||||||
#
|
#
|
||||||
# Quartus Prime
|
# Quartus Prime
|
||||||
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
|
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
|
||||||
# Date created = 00:33:20 February 17, 2021
|
# Date created = 01:35:54 February 19, 2021
|
||||||
#
|
#
|
||||||
# -------------------------------------------------------------------------- #
|
# -------------------------------------------------------------------------- #
|
||||||
#
|
#
|
||||||
@ -77,6 +77,7 @@ set_global_assignment -name VERILOG_FILE rtl/top.v
|
|||||||
set_global_assignment -name VERILOG_FILE rtl/usb/usb_ftdi_fsi.v
|
set_global_assignment -name VERILOG_FILE rtl/usb/usb_ftdi_fsi.v
|
||||||
set_global_assignment -name VERILOG_FILE rtl/usb/usb_pc.v
|
set_global_assignment -name VERILOG_FILE rtl/usb/usb_pc.v
|
||||||
set_global_assignment -name VERILOG_INCLUDE_FILE rtl/constants.vh
|
set_global_assignment -name VERILOG_INCLUDE_FILE rtl/constants.vh
|
||||||
|
set_global_assignment -name SLD_FILE db/signal_tap_logic_analyzer_auto_stripped.stp
|
||||||
|
|
||||||
# Pin & Location Assignments
|
# Pin & Location Assignments
|
||||||
# ==========================
|
# ==========================
|
||||||
@ -272,11 +273,10 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
|||||||
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
|
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
|
||||||
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
||||||
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||||
|
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||||
|
|
||||||
# end DESIGN_PARTITION(Top)
|
# end DESIGN_PARTITION(Top)
|
||||||
# -------------------------
|
# -------------------------
|
||||||
|
|
||||||
# end ENTITY(top)
|
# end ENTITY(top)
|
||||||
# ---------------
|
# ---------------
|
||||||
set_global_assignment -name SLD_FILE db/signal_tap_logic_analyzer_auto_stripped.stp
|
|
||||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
|
@ -43,14 +43,13 @@ set_false_path -from [get_ports {i_ftdi_so i_ftdi_cts}]
|
|||||||
set_output_delay -clock [get_clocks {sd_clk}] -max 6.0 [get_ports {io_sd_cmd io_sd_dat[*]}]
|
set_output_delay -clock [get_clocks {sd_clk}] -max 6.0 [get_ports {io_sd_cmd io_sd_dat[*]}]
|
||||||
set_output_delay -clock [get_clocks {sd_clk}] -min -2.0 [get_ports {io_sd_cmd io_sd_dat[*]}]
|
set_output_delay -clock [get_clocks {sd_clk}] -min -2.0 [get_ports {io_sd_cmd io_sd_dat[*]}]
|
||||||
|
|
||||||
set_input_delay -clock [get_clocks {sd_clk}] -max 14.0 [get_ports {io_sd_cmd io_sd_dat[*]}]
|
set_input_delay -clock [get_clocks {sd_clk}] -max 15.0 [get_ports {io_sd_cmd io_sd_dat[*]}]
|
||||||
set_input_delay -clock [get_clocks {sd_clk}] -min 2.5 [get_ports {io_sd_cmd io_sd_dat[*]}]
|
set_input_delay -clock [get_clocks {sd_clk}] -min 6.5 [get_ports {io_sd_cmd io_sd_dat[*]}]
|
||||||
|
|
||||||
set_multicycle_path -setup -start 1 -from [get_clocks $sys_clk] -to [get_clocks {sd_clk}]
|
|
||||||
set_multicycle_path -hold -start 1 -from [get_clocks $sys_clk] -to [get_clocks {sd_clk}]
|
set_multicycle_path -hold -start 1 -from [get_clocks $sys_clk] -to [get_clocks {sd_clk}]
|
||||||
|
|
||||||
set_multicycle_path -setup -end 3 -from [get_clocks {sd_clk}] -to [get_clocks $sys_clk]
|
set_multicycle_path -setup -end 3 -from [get_clocks {sd_clk}] -to [get_clocks $sys_clk]
|
||||||
set_multicycle_path -hold -end 2 -from [get_clocks {sd_clk}] -to [get_clocks $sys_clk]
|
set_multicycle_path -hold -end 1 -from [get_clocks {sd_clk}] -to [get_clocks $sys_clk]
|
||||||
|
|
||||||
|
|
||||||
# N64, PI and SI timings
|
# N64, PI and SI timings
|
||||||
|
@ -17,6 +17,7 @@ module sd_dat (
|
|||||||
output o_dat_write_busy,
|
output o_dat_write_busy,
|
||||||
output reg o_dat_crc_error,
|
output reg o_dat_crc_error,
|
||||||
output reg o_dat_write_error,
|
output reg o_dat_write_error,
|
||||||
|
output reg o_dat_write_ok,
|
||||||
|
|
||||||
input i_rx_fifo_overrun,
|
input i_rx_fifo_overrun,
|
||||||
output reg o_rx_fifo_push,
|
output reg o_rx_fifo_push,
|
||||||
@ -41,7 +42,7 @@ module sd_dat (
|
|||||||
reg [6:0] r_state;
|
reg [6:0] r_state;
|
||||||
|
|
||||||
assign o_dat_busy = !r_state[STATE_IDLE];
|
assign o_dat_busy = !r_state[STATE_IDLE];
|
||||||
assign o_dat_write_busy = r_state[STATE_SENDING] || r_state[STATE_STATUS] || r_state[STATE_BUSY];
|
assign o_dat_write_busy = !io_sd_dat[0];
|
||||||
|
|
||||||
|
|
||||||
// Bit counter logic
|
// Bit counter logic
|
||||||
@ -50,13 +51,13 @@ module sd_dat (
|
|||||||
reg r_bit_counter_done;
|
reg r_bit_counter_done;
|
||||||
|
|
||||||
wire w_read_start = r_state[STATE_READ_WAIT] && !io_sd_dat[0] && i_sd_clk_strobe_rising;
|
wire w_read_start = r_state[STATE_READ_WAIT] && !io_sd_dat[0] && i_sd_clk_strobe_rising;
|
||||||
wire w_write_start = r_state[STATE_WRITE_WAIT] && (i_tx_fifo_items == ({1'b0, i_dat_block_size} + 1)) && i_sd_clk_strobe_falling;
|
wire w_write_start = r_state[STATE_WRITE_WAIT] && (i_tx_fifo_items >= ({1'b0, i_dat_block_size} + 1)) && i_sd_clk_strobe_falling;
|
||||||
wire w_status_start = r_state[STATE_SENDING] && r_bit_counter_done;
|
wire w_status_start = r_state[STATE_SENDING] && r_bit_counter_done;
|
||||||
wire w_status_done = r_state[STATE_STATUS] && r_bit_counter_done;
|
wire w_status_done = r_state[STATE_STATUS] && r_bit_counter_done;
|
||||||
wire w_block_read_done = r_state[STATE_RECEIVING] && r_bit_counter_done;
|
wire w_block_read_done = r_state[STATE_RECEIVING] && r_bit_counter_done;
|
||||||
wire w_block_write_done = r_state[STATE_SENDING] && r_bit_counter_done;
|
wire w_block_write_done = r_state[STATE_SENDING] && r_bit_counter_done;
|
||||||
wire w_block_done = w_block_read_done || w_block_write_done;
|
|
||||||
wire w_block_write_busy_done = r_state[STATE_BUSY] && io_sd_dat[0];
|
wire w_block_write_busy_done = r_state[STATE_BUSY] && io_sd_dat[0];
|
||||||
|
wire w_block_done = w_block_read_done || w_block_write_busy_done;
|
||||||
|
|
||||||
wire [12:0] w_block_bit_length = i_dat_width ? ({2'b00, {1'b0, i_dat_block_size} + 1'd1, 3'b000}) : ({{1'b0, i_dat_block_size} + 1'd1, 5'b00000});
|
wire [12:0] w_block_bit_length = i_dat_width ? ({2'b00, {1'b0, i_dat_block_size} + 1'd1, 3'b000}) : ({{1'b0, i_dat_block_size} + 1'd1, 5'b00000});
|
||||||
|
|
||||||
@ -138,12 +139,14 @@ module sd_dat (
|
|||||||
|
|
||||||
reg [4:0] r_status;
|
reg [4:0] r_status;
|
||||||
|
|
||||||
|
wire w_no_write_error = r_status == STATUS_NO_ERROR;
|
||||||
wire w_crc_write_error = r_status == STATUS_CRC_ERROR;
|
wire w_crc_write_error = r_status == STATUS_CRC_ERROR;
|
||||||
wire w_data_write_error = r_status == STATUS_WRITE_ERROR;
|
wire w_data_write_error = r_status == STATUS_WRITE_ERROR;
|
||||||
|
|
||||||
always @(posedge i_clk) begin
|
always @(posedge i_clk) begin
|
||||||
if (i_reset) begin
|
if (i_reset || w_block_start) begin
|
||||||
o_dat_crc_error <= 1'b0;
|
o_dat_crc_error <= 1'b0;
|
||||||
|
o_dat_write_error <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
if (w_block_read_done) begin
|
if (w_block_read_done) begin
|
||||||
o_dat_crc_error <= w_crc_read_error;
|
o_dat_crc_error <= w_crc_read_error;
|
||||||
@ -151,6 +154,7 @@ module sd_dat (
|
|||||||
if (w_status_done) begin
|
if (w_status_done) begin
|
||||||
o_dat_crc_error <= w_crc_write_error;
|
o_dat_crc_error <= w_crc_write_error;
|
||||||
o_dat_write_error <= w_data_write_error;
|
o_dat_write_error <= w_data_write_error;
|
||||||
|
o_dat_write_ok <= w_no_write_error;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -230,7 +234,7 @@ module sd_dat (
|
|||||||
|
|
||||||
r_state[STATE_BUSY]: begin
|
r_state[STATE_BUSY]: begin
|
||||||
if (w_block_write_busy_done) begin
|
if (w_block_write_busy_done) begin
|
||||||
if (w_block_stop) begin
|
if (w_block_stop || !w_no_write_error) begin
|
||||||
r_state[STATE_IDLE] <= 1'b1;
|
r_state[STATE_IDLE] <= 1'b1;
|
||||||
end else begin
|
end else begin
|
||||||
r_state[STATE_WRITE_WAIT] <= 1'b1;
|
r_state[STATE_WRITE_WAIT] <= 1'b1;
|
||||||
@ -274,7 +278,7 @@ module sd_dat (
|
|||||||
wire w_tx_latch = r_state[STATE_SENDING] && i_sd_clk_strobe_falling;
|
wire w_tx_latch = r_state[STATE_SENDING] && i_sd_clk_strobe_falling;
|
||||||
wire w_tx_data_phase = r_bit_counter >= 13'd17;
|
wire w_tx_data_phase = r_bit_counter >= 13'd17;
|
||||||
wire w_tx_crc_phase = r_bit_counter >= 13'd1;
|
wire w_tx_crc_phase = r_bit_counter >= 13'd1;
|
||||||
wire w_tx_fifo_pop = i_dat_width ? (r_bit_counter[2:0] == 3'd0) : (r_bit_counter[4:0] == 5'd16);
|
wire w_tx_fifo_pop = i_dat_width ? (r_bit_counter[2:0] == 3'd0) : (r_bit_counter[4:0] == 5'd17);
|
||||||
wire w_tx_shift_load = r_bit_counter[2:0] == 3'd0;
|
wire w_tx_shift_load = r_bit_counter[2:0] == 3'd0;
|
||||||
|
|
||||||
reg [7:0] r_tx_shift [0:3];
|
reg [7:0] r_tx_shift [0:3];
|
||||||
@ -309,7 +313,12 @@ module sd_dat (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
r_tx_shift[0] <= i_tx_fifo_data[{3'b000, r_bit_counter[4:3]} +: 8];
|
case (r_bit_counter[4:3])
|
||||||
|
2'b10: r_tx_shift[0] <= i_tx_fifo_data[31:24];
|
||||||
|
2'b01: r_tx_shift[0] <= i_tx_fifo_data[23:16];
|
||||||
|
2'b00: r_tx_shift[0] <= i_tx_fifo_data[15:8];
|
||||||
|
2'b11: r_tx_shift[0] <= i_tx_fifo_data[7:0];
|
||||||
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end else if (w_tx_crc_phase) begin
|
end else if (w_tx_crc_phase) begin
|
||||||
|
@ -159,6 +159,7 @@ module sd_interface (
|
|||||||
wire w_dat_write_busy;
|
wire w_dat_write_busy;
|
||||||
wire w_dat_crc_error;
|
wire w_dat_crc_error;
|
||||||
wire w_dat_write_error;
|
wire w_dat_write_error;
|
||||||
|
wire w_dat_write_ok;
|
||||||
|
|
||||||
sd_dat sd_dat_inst (
|
sd_dat sd_dat_inst (
|
||||||
.i_clk(i_clk),
|
.i_clk(i_clk),
|
||||||
@ -179,6 +180,7 @@ module sd_interface (
|
|||||||
.o_dat_write_busy(w_dat_write_busy),
|
.o_dat_write_busy(w_dat_write_busy),
|
||||||
.o_dat_crc_error(w_dat_crc_error),
|
.o_dat_crc_error(w_dat_crc_error),
|
||||||
.o_dat_write_error(w_dat_write_error),
|
.o_dat_write_error(w_dat_write_error),
|
||||||
|
.o_dat_write_ok(w_dat_write_ok),
|
||||||
|
|
||||||
.i_rx_fifo_overrun(w_rx_fifo_overrun),
|
.i_rx_fifo_overrun(w_rx_fifo_overrun),
|
||||||
.o_rx_fifo_push(w_rx_fifo_push),
|
.o_rx_fifo_push(w_rx_fifo_push),
|
||||||
@ -267,6 +269,7 @@ module sd_interface (
|
|||||||
.i_dat_write_busy(w_dat_write_busy),
|
.i_dat_write_busy(w_dat_write_busy),
|
||||||
.i_dat_crc_error(w_dat_crc_error),
|
.i_dat_crc_error(w_dat_crc_error),
|
||||||
.i_dat_write_error(w_dat_write_error),
|
.i_dat_write_error(w_dat_write_error),
|
||||||
|
.i_dat_write_ok(w_dat_write_ok),
|
||||||
|
|
||||||
.o_rx_fifo_flush(w_rx_fifo_flush),
|
.o_rx_fifo_flush(w_rx_fifo_flush),
|
||||||
.o_rx_fifo_pop(w_rx_fifo_regs_pop),
|
.o_rx_fifo_pop(w_rx_fifo_regs_pop),
|
||||||
|
@ -25,6 +25,7 @@ module sd_regs (
|
|||||||
input i_dat_write_busy,
|
input i_dat_write_busy,
|
||||||
input i_dat_crc_error,
|
input i_dat_crc_error,
|
||||||
input i_dat_write_error,
|
input i_dat_write_error,
|
||||||
|
input i_dat_write_ok,
|
||||||
|
|
||||||
output reg o_rx_fifo_flush,
|
output reg o_rx_fifo_flush,
|
||||||
output reg o_rx_fifo_pop,
|
output reg o_rx_fifo_pop,
|
||||||
@ -204,7 +205,8 @@ module sd_regs (
|
|||||||
|
|
||||||
SD_REG_DAT: begin
|
SD_REG_DAT: begin
|
||||||
o_data <= {
|
o_data <= {
|
||||||
4'd0,
|
3'd0,
|
||||||
|
i_dat_write_ok,
|
||||||
i_dat_write_error,
|
i_dat_write_error,
|
||||||
i_dat_write_busy,
|
i_dat_write_busy,
|
||||||
i_tx_fifo_items,
|
i_tx_fifo_items,
|
||||||
|
@ -539,7 +539,7 @@ module top (
|
|||||||
|
|
||||||
// LED
|
// LED
|
||||||
|
|
||||||
wire w_led_trigger = (w_n64_request && !w_n64_busy) || (w_pc_request && !w_pc_busy);
|
wire w_led_trigger = (w_n64_request && !w_n64_busy) || (w_pc_request && !w_pc_busy) || (w_sd_dma_request && !w_sd_dma_busy);
|
||||||
|
|
||||||
cart_led cart_led_inst (
|
cart_led cart_led_inst (
|
||||||
.i_clk(w_sys_clk),
|
.i_clk(w_sys_clk),
|
||||||
|
@ -53,7 +53,7 @@ DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
|||||||
|
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
|
|
||||||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
DRESULT disk_write(BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
||||||
sc64_sd_err_t error;
|
sc64_sd_err_t error;
|
||||||
|
|
||||||
if (pdrv > 0) {
|
if (pdrv > 0) {
|
||||||
@ -79,5 +79,15 @@ DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
|
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
|
||||||
return RES_PARERR;
|
switch (cmd) {
|
||||||
|
case CTRL_SYNC: {
|
||||||
|
sc64_sd_err_t error = sc64_sd_dat_busy_wait();
|
||||||
|
if (error != E_OK) {
|
||||||
|
return RES_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
@ -97,24 +97,6 @@ void loader_display_logo(void) {
|
|||||||
display_show(display);
|
display_show(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loader_display_message(const char *message) {
|
|
||||||
if (!loader_initialized) {
|
|
||||||
loader_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
display_context_t display;
|
|
||||||
|
|
||||||
display = loader_get_display(true);
|
|
||||||
|
|
||||||
graphics_fill_screen(display, 0);
|
|
||||||
|
|
||||||
loader_draw_version_and_logo(display);
|
|
||||||
|
|
||||||
graphics_draw_text(display, x_offset, y_offset, message);
|
|
||||||
|
|
||||||
display_show(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
void loader_display_error_and_halt(menu_load_error_t error, const char *message) {
|
void loader_display_error_and_halt(menu_load_error_t error, const char *message) {
|
||||||
if (!loader_initialized) {
|
if (!loader_initialized) {
|
||||||
loader_init();
|
loader_init();
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
void loader_cleanup(void);
|
void loader_cleanup(void);
|
||||||
void loader_display_logo(void);
|
void loader_display_logo(void);
|
||||||
void loader_display_message(const char *message);
|
|
||||||
void loader_display_error_and_halt(menu_load_error_t error, const char *message);
|
void loader_display_error_and_halt(menu_load_error_t error, const char *message);
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,6 +146,9 @@ typedef struct sc64_sd_registers_s {
|
|||||||
#define SC64_SD_CMD_INDEX(i) ((i) & 0x3F)
|
#define SC64_SD_CMD_INDEX(i) ((i) & 0x3F)
|
||||||
|
|
||||||
|
|
||||||
|
#define SC64_SD_DAT_WRITE_OK (1 << 28)
|
||||||
|
#define SC64_SD_DAT_WRITE_ERROR (1 << 27)
|
||||||
|
#define SC64_SD_DAT_WRITE_BUSY (1 << 26)
|
||||||
#define SC64_SD_DAT_TX_FIFO_ITEMS_GET(dat) (((dat) >> 17) & 0x1FF)
|
#define SC64_SD_DAT_TX_FIFO_ITEMS_GET(dat) (((dat) >> 17) & 0x1FF)
|
||||||
#define SC64_SD_DAT_TX_FIFO_BYTES_GET(dat) (SC64_SD_DAT_TX_FIFO_ITEMS_GET(dat) * 4)
|
#define SC64_SD_DAT_TX_FIFO_BYTES_GET(dat) (SC64_SD_DAT_TX_FIFO_ITEMS_GET(dat) * 4)
|
||||||
#define SC64_SD_DAT_TX_FIFO_FULL (1 << 16)
|
#define SC64_SD_DAT_TX_FIFO_FULL (1 << 16)
|
||||||
@ -184,6 +187,7 @@ typedef struct sc64_sd_registers_s {
|
|||||||
|
|
||||||
#define SC64_SD_DMA_BANK_ADDR(b, a) ((((b) & 0xF) << 28) | ((a) & 0x3FFFFFC))
|
#define SC64_SD_DMA_BANK_ADDR(b, a) ((((b) & 0xF) << 28) | ((a) & 0x3FFFFFC))
|
||||||
|
|
||||||
|
|
||||||
#define SC64_SD_DMA_LEN_GET(len) (((len) & 0x7FFF) * 4)
|
#define SC64_SD_DMA_LEN_GET(len) (((len) & 0x7FFF) * 4)
|
||||||
|
|
||||||
#define SC64_SD_DMA_LEN(l) ((((l) / 4) - 1) & 0x7FFF)
|
#define SC64_SD_DMA_LEN(l) ((((l) / 4) - 1) & 0x7FFF)
|
||||||
|
@ -157,20 +157,24 @@ static sc64_sd_err_t sc64_sd_cmd_send(uint8_t index, uint32_t arg, sc64_sd_cmd_f
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sc64_sd_dat_prepare(size_t num_blocks, size_t block_size, sc64_sd_dat_direction_t direction) {
|
static void sc64_sd_dat_prepare(size_t num_blocks, size_t block_size, sc64_sd_dat_direction_t direction) {
|
||||||
platform_pi_io_write(&SC64_SD->DAT, (
|
uint32_t reg = (
|
||||||
SC64_SD_DAT_NUM_BLOCKS(num_blocks) |
|
SC64_SD_DAT_NUM_BLOCKS(num_blocks) |
|
||||||
SC64_SD_DAT_BLOCK_SIZE(block_size) |
|
SC64_SD_DAT_BLOCK_SIZE(block_size) |
|
||||||
((direction == DAT_DIR_TX) ? SC64_SD_DAT_DIRECTION : 0) |
|
((direction == DAT_DIR_TX) ? SC64_SD_DAT_DIRECTION : 0) |
|
||||||
SC64_SD_DAT_START
|
SC64_SD_DAT_START
|
||||||
));
|
);
|
||||||
|
|
||||||
|
platform_pi_io_write(&SC64_SD->DAT, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sc64_sd_dat_abort(void) {
|
static void sc64_sd_dat_abort(void) {
|
||||||
platform_pi_io_write(&SC64_SD->DAT, (
|
uint32_t reg = (
|
||||||
SC64_SD_DAT_TX_FIFO_FLUSH |
|
SC64_SD_DAT_TX_FIFO_FLUSH |
|
||||||
SC64_SD_DAT_RX_FIFO_FLUSH |
|
SC64_SD_DAT_RX_FIFO_FLUSH |
|
||||||
SC64_SD_DAT_STOP
|
SC64_SD_DAT_STOP
|
||||||
));
|
);
|
||||||
|
|
||||||
|
platform_pi_io_write(&SC64_SD->DAT, reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sc64_sd_err_t sc64_sd_dat_read(size_t block_size, void *buffer) {
|
static sc64_sd_err_t sc64_sd_dat_read(size_t block_size, void *buffer) {
|
||||||
@ -212,7 +216,7 @@ static sc64_sd_err_t sc64_sd_dat_read(size_t block_size, void *buffer) {
|
|||||||
static sc64_sd_err_t sc64_sd_dat_write(size_t block_size, void *buffer) {
|
static sc64_sd_err_t sc64_sd_dat_write(size_t block_size, void *buffer) {
|
||||||
int timeout;
|
int timeout;
|
||||||
uint32_t reg;
|
uint32_t reg;
|
||||||
|
|
||||||
timeout = 1000000;
|
timeout = 1000000;
|
||||||
do {
|
do {
|
||||||
reg = platform_pi_io_read(&SC64_SD->DAT);
|
reg = platform_pi_io_read(&SC64_SD->DAT);
|
||||||
@ -221,11 +225,21 @@ static sc64_sd_err_t sc64_sd_dat_write(size_t block_size, void *buffer) {
|
|||||||
}
|
}
|
||||||
} while ((reg & SC64_SD_DAT_BUSY) && (--timeout));
|
} while ((reg & SC64_SD_DAT_BUSY) && (--timeout));
|
||||||
|
|
||||||
|
if (timeout == 0) {
|
||||||
|
sc64_sd_dat_abort();
|
||||||
|
|
||||||
|
return E_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(reg & SC64_SD_DAT_BUSY)) {
|
if (!(reg & SC64_SD_DAT_BUSY)) {
|
||||||
if (reg & SC64_SD_DAT_CRC_ERROR) {
|
if (reg & SC64_SD_DAT_CRC_ERROR) {
|
||||||
return E_CRC_ERROR;
|
return E_CRC_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (reg & SC64_SD_DAT_WRITE_ERROR) {
|
||||||
|
return E_WRITE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (reg & SC64_SD_DAT_TX_FIFO_UNDERRUN) {
|
if (reg & SC64_SD_DAT_TX_FIFO_UNDERRUN) {
|
||||||
platform_pi_io_write(&SC64_SD->DAT, SC64_SD_DAT_TX_FIFO_FLUSH);
|
platform_pi_io_write(&SC64_SD->DAT, SC64_SD_DAT_TX_FIFO_FLUSH);
|
||||||
|
|
||||||
@ -233,14 +247,8 @@ static sc64_sd_err_t sc64_sd_dat_write(size_t block_size, void *buffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeout == 0) {
|
platform_cache_writeback(buffer, block_size);
|
||||||
sc64_sd_dat_abort();
|
|
||||||
|
|
||||||
return E_TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
platform_pi_dma_write(buffer, &SC64_SD->FIFO, block_size);
|
platform_pi_dma_write(buffer, &SC64_SD->FIFO, block_size);
|
||||||
platform_cache_invalidate(buffer, block_size);
|
|
||||||
|
|
||||||
return E_OK;
|
return E_OK;
|
||||||
}
|
}
|
||||||
@ -420,8 +428,11 @@ sc64_sd_err_t sc64_sd_sectors_read(uint32_t starting_sector, size_t count, uint8
|
|||||||
|
|
||||||
sc64_sd_err_t sc64_sd_sectors_write(uint32_t starting_sector, size_t count, uint8_t *buffer) {
|
sc64_sd_err_t sc64_sd_sectors_write(uint32_t starting_sector, size_t count, uint8_t *buffer) {
|
||||||
sc64_sd_err_t error;
|
sc64_sd_err_t error;
|
||||||
|
sc64_sd_err_t write_error;
|
||||||
uint32_t response;
|
uint32_t response;
|
||||||
uint32_t current_sector;
|
uint32_t current_sector;
|
||||||
|
size_t sectors_remaining;
|
||||||
|
size_t num_blocks;
|
||||||
|
|
||||||
error = sc64_sd_sectors_parameters_check(count, buffer, true);
|
error = sc64_sd_sectors_parameters_check(count, buffer, true);
|
||||||
if (error != E_OK) {
|
if (error != E_OK) {
|
||||||
@ -433,23 +444,51 @@ sc64_sd_err_t sc64_sd_sectors_write(uint32_t starting_sector, size_t count, uint
|
|||||||
current_sector *= SD_BLOCK_SIZE;
|
current_sector *= SD_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
sectors_remaining = count;
|
||||||
sc64_sd_dat_prepare(1, SD_BLOCK_SIZE, DAT_DIR_TX);
|
|
||||||
|
|
||||||
error = sc64_sd_cmd_send(24, current_sector, NO_FLAGS, &response);
|
while (sectors_remaining) {
|
||||||
|
num_blocks = (sectors_remaining > SC64_SD_DAT_NUM_BLOCKS_MAX) ? SC64_SD_DAT_NUM_BLOCKS_MAX : sectors_remaining;
|
||||||
|
|
||||||
|
sc64_sd_dat_prepare(num_blocks, SD_BLOCK_SIZE, DAT_DIR_TX);
|
||||||
|
|
||||||
|
error = sc64_sd_cmd_send(25, current_sector, NO_FLAGS, &response);
|
||||||
if (error != E_OK) {
|
if (error != E_OK) {
|
||||||
sc64_sd_dat_abort();
|
sc64_sd_dat_abort();
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = sc64_sd_dat_write(SD_BLOCK_SIZE, buffer);
|
for (size_t i = 0; i < num_blocks; i++) {
|
||||||
|
write_error = sc64_sd_dat_write(SD_BLOCK_SIZE, buffer);
|
||||||
|
if (write_error != E_OK) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer += SD_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = sc64_sd_dat_busy_wait();
|
||||||
|
if (error != E_OK) {
|
||||||
|
sc64_sd_dat_abort();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = sc64_sd_cmd_send(12, 0, NO_FLAGS, &response);
|
||||||
if (error != E_OK) {
|
if (error != E_OK) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer += SD_BLOCK_SIZE;
|
error = sc64_sd_dat_busy_wait();
|
||||||
current_sector += sd_card_type_block ? 1 : SD_BLOCK_SIZE;
|
if (error != E_OK) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_error != E_OK) {
|
||||||
|
return write_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_sector += num_blocks * (sd_card_type_block ? 1 : SD_BLOCK_SIZE);
|
||||||
|
sectors_remaining -= num_blocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
return E_OK;
|
return E_OK;
|
||||||
@ -534,79 +573,95 @@ sc64_sd_err_t sc64_sd_sectors_read_dma(uint32_t starting_sector, size_t count, u
|
|||||||
return E_OK;
|
return E_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
sc64_sd_err_t sc64_sd_sectors_write_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address) {
|
// sc64_sd_err_t sc64_sd_sectors_write_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address) {
|
||||||
size_t sectors_left;
|
// size_t sectors_left;
|
||||||
uint32_t current_sector;
|
// uint32_t current_sector;
|
||||||
uint32_t current_address;
|
// uint32_t current_address;
|
||||||
uint32_t num_blocks;
|
// uint32_t num_blocks;
|
||||||
uint32_t reg;
|
// uint32_t reg;
|
||||||
sc64_sd_err_t error;
|
// sc64_sd_err_t error;
|
||||||
uint32_t response;
|
// uint32_t response;
|
||||||
|
// int timeout;
|
||||||
|
|
||||||
|
// error = sc64_sd_sectors_parameters_check(count, NULL, false);
|
||||||
|
// if (error != E_OK) {
|
||||||
|
// return error;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// sectors_left = count;
|
||||||
|
// current_sector = starting_sector;
|
||||||
|
// if (!sd_card_type_block) {
|
||||||
|
// current_sector *= SD_BLOCK_SIZE;
|
||||||
|
// }
|
||||||
|
// current_address = address;
|
||||||
|
|
||||||
|
// do {
|
||||||
|
// num_blocks = (sectors_left > SC64_SD_DAT_NUM_BLOCKS_MAX) ? SC64_SD_DAT_NUM_BLOCKS_MAX : sectors_left;
|
||||||
|
|
||||||
|
// sc64_sd_dat_prepare(num_blocks, SD_BLOCK_SIZE, DAT_DIR_TX);
|
||||||
|
// sc64_sd_dma_prepare(num_blocks, SD_BLOCK_SIZE, DMA_DIR_CARD, bank, current_address);
|
||||||
|
|
||||||
|
// error = sc64_sd_cmd_send(25, current_sector, NO_FLAGS, &response);
|
||||||
|
// if (error != E_OK) {
|
||||||
|
// sc64_sd_dma_abort();
|
||||||
|
// sc64_sd_dat_abort();
|
||||||
|
|
||||||
|
// return error;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// timeout = 1000000;
|
||||||
|
// do {
|
||||||
|
// reg = platform_pi_io_read(&SC64_SD->DAT);
|
||||||
|
// } while ((reg & SC64_SD_DAT_BUSY) && (--timeout));
|
||||||
|
|
||||||
|
// error = sc64_sd_cmd_send(12, 0, NO_FLAGS, &response);
|
||||||
|
// if (error != E_OK) {
|
||||||
|
// sc64_sd_dma_abort();
|
||||||
|
// sc64_sd_dat_abort();
|
||||||
|
|
||||||
|
// return error;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (reg & SC64_SD_DAT_CRC_ERROR) {
|
||||||
|
// sc64_sd_dma_abort();
|
||||||
|
|
||||||
|
// return E_CRC_ERROR;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (reg & SC64_SD_DAT_TX_FIFO_UNDERRUN) {
|
||||||
|
// sc64_sd_dma_abort();
|
||||||
|
// platform_pi_io_write(&SC64_SD->DAT, SC64_SD_DAT_TX_FIFO_FLUSH);
|
||||||
|
|
||||||
|
// return E_FIFO_ERROR;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (timeout == 0) {
|
||||||
|
// sc64_sd_dma_abort();
|
||||||
|
// sc64_sd_dat_abort();
|
||||||
|
|
||||||
|
// return E_TIMEOUT;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// sectors_left -= num_blocks;
|
||||||
|
// current_sector += num_blocks * (sd_card_type_block ? 1 : SD_BLOCK_SIZE);
|
||||||
|
// current_address += num_blocks * SD_BLOCK_SIZE;
|
||||||
|
// } while (sectors_left > 0);
|
||||||
|
|
||||||
|
// return E_OK;
|
||||||
|
// }
|
||||||
|
|
||||||
|
sc64_sd_err_t sc64_sd_dat_busy_wait(void) {
|
||||||
int timeout;
|
int timeout;
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
error = sc64_sd_sectors_parameters_check(count, NULL, false);
|
timeout = 1000000;
|
||||||
if (error != E_OK) {
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
sectors_left = count;
|
|
||||||
current_sector = starting_sector;
|
|
||||||
if (!sd_card_type_block) {
|
|
||||||
current_sector *= SD_BLOCK_SIZE;
|
|
||||||
}
|
|
||||||
current_address = address;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
num_blocks = (sectors_left > SC64_SD_DAT_NUM_BLOCKS_MAX) ? SC64_SD_DAT_NUM_BLOCKS_MAX : sectors_left;
|
reg = platform_pi_io_read(&SC64_SD->DAT);
|
||||||
|
} while ((reg & (SC64_SD_DAT_WRITE_BUSY | SC64_SD_DAT_BUSY)) && (--timeout));
|
||||||
|
|
||||||
sc64_sd_dat_prepare(num_blocks, SD_BLOCK_SIZE, DAT_DIR_TX);
|
if (timeout == 0) {
|
||||||
sc64_sd_dma_prepare(num_blocks, SD_BLOCK_SIZE, DMA_DIR_CARD, bank, current_address);
|
return E_TIMEOUT;
|
||||||
|
}
|
||||||
error = sc64_sd_cmd_send(25, current_sector, NO_FLAGS, &response);
|
|
||||||
if (error != E_OK) {
|
|
||||||
sc64_sd_dma_abort();
|
|
||||||
sc64_sd_dat_abort();
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout = 1000000;
|
|
||||||
do {
|
|
||||||
reg = platform_pi_io_read(&SC64_SD->DAT);
|
|
||||||
} while ((reg & SC64_SD_DAT_BUSY) && (--timeout));
|
|
||||||
|
|
||||||
error = sc64_sd_cmd_send(12, 0, NO_FLAGS, &response);
|
|
||||||
if (error != E_OK) {
|
|
||||||
sc64_sd_dma_abort();
|
|
||||||
sc64_sd_dat_abort();
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reg & SC64_SD_DAT_CRC_ERROR) {
|
|
||||||
sc64_sd_dma_abort();
|
|
||||||
|
|
||||||
return E_CRC_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reg & SC64_SD_DAT_TX_FIFO_UNDERRUN) {
|
|
||||||
sc64_sd_dma_abort();
|
|
||||||
platform_pi_io_write(&SC64_SD->DAT, SC64_SD_DAT_TX_FIFO_FLUSH);
|
|
||||||
|
|
||||||
return E_FIFO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeout == 0) {
|
|
||||||
sc64_sd_dma_abort();
|
|
||||||
sc64_sd_dat_abort();
|
|
||||||
|
|
||||||
return E_TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
sectors_left -= num_blocks;
|
|
||||||
current_sector += num_blocks * (sd_card_type_block ? 1 : SD_BLOCK_SIZE);
|
|
||||||
current_address += num_blocks * SD_BLOCK_SIZE;
|
|
||||||
} while (sectors_left > 0);
|
|
||||||
|
|
||||||
return E_OK;
|
return E_OK;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ typedef enum sc64_sd_err_e {
|
|||||||
E_BAD_INDEX,
|
E_BAD_INDEX,
|
||||||
E_PAR_ERROR,
|
E_PAR_ERROR,
|
||||||
E_FIFO_ERROR,
|
E_FIFO_ERROR,
|
||||||
|
E_WRITE_ERROR,
|
||||||
E_NO_INIT,
|
E_NO_INIT,
|
||||||
} sc64_sd_err_t;
|
} sc64_sd_err_t;
|
||||||
|
|
||||||
@ -22,7 +23,8 @@ bool sc64_sd_status_get(void);
|
|||||||
sc64_sd_err_t sc64_sd_sectors_read(uint32_t starting_sector, size_t count, uint8_t *buffer);
|
sc64_sd_err_t sc64_sd_sectors_read(uint32_t starting_sector, size_t count, uint8_t *buffer);
|
||||||
sc64_sd_err_t sc64_sd_sectors_write(uint32_t starting_sector, size_t count, uint8_t *buffer);
|
sc64_sd_err_t sc64_sd_sectors_write(uint32_t starting_sector, size_t count, uint8_t *buffer);
|
||||||
sc64_sd_err_t sc64_sd_sectors_read_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address);
|
sc64_sd_err_t sc64_sd_sectors_read_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address);
|
||||||
sc64_sd_err_t sc64_sd_sectors_write_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address);
|
// sc64_sd_err_t sc64_sd_sectors_write_dma(uint32_t starting_sector, size_t count, uint8_t bank, uint32_t address);
|
||||||
|
sc64_sd_err_t sc64_sd_dat_busy_wait(void);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
static uint8_t current_bank = SC64_BANK_INVALID;
|
static uint8_t current_bank = SC64_BANK_INVALID;
|
||||||
static uint32_t current_offset = 0;
|
static uint32_t current_offset = 0;
|
||||||
static uint8_t save_buffer[128 * 1024] __attribute__((aligned(16)));
|
static uint8_t save_buffer[128 * 1024] __attribute__((aligned(16)));
|
||||||
|
static bool fs_initialized = false;
|
||||||
|
static FATFS fatfs;
|
||||||
|
|
||||||
|
|
||||||
static DRESULT sc64_sd_fs_load_with_dma(BYTE pdrv, FSIZE_t offset, LBA_t sector, UINT count) {
|
static DRESULT sc64_sd_fs_load_with_dma(BYTE pdrv, FSIZE_t offset, LBA_t sector, UINT count) {
|
||||||
@ -38,13 +40,9 @@ static DRESULT sc64_sd_fs_load_with_dma(BYTE pdrv, FSIZE_t offset, LBA_t sector,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool fs_initialized = false;
|
|
||||||
static FATFS fatfs;
|
|
||||||
|
|
||||||
|
|
||||||
sc64_sd_fs_error_t sc64_sd_fs_init(void) {
|
sc64_sd_fs_error_t sc64_sd_fs_init(void) {
|
||||||
FRESULT fresult;
|
FRESULT fresult;
|
||||||
|
|
||||||
fresult = f_mount(&fatfs, "", 1);
|
fresult = f_mount(&fatfs, "", 1);
|
||||||
if (fresult != FR_OK) {
|
if (fresult != FR_OK) {
|
||||||
switch (fresult) {
|
switch (fresult) {
|
||||||
|
Loading…
Reference in New Issue
Block a user