mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 15:16:53 +01:00
boot screen
This commit is contained in:
parent
200f164363
commit
59491be835
@ -178,7 +178,7 @@ set_global_assignment -name TIMING_ANALYZER_DO_REPORT_TIMING ON
|
||||
|
||||
# Compiler Assignments
|
||||
# ====================
|
||||
set_global_assignment -name OPTIMIZATION_MODE "HIGH PERFORMANCE EFFORT"
|
||||
set_global_assignment -name OPTIMIZATION_MODE "AGGRESSIVE PERFORMANCE"
|
||||
|
||||
# Analysis & Synthesis Assignments
|
||||
# ================================
|
||||
|
@ -10,7 +10,7 @@ module sd_dat (
|
||||
input i_dat_width,
|
||||
input i_dat_direction,
|
||||
input [6:0] i_dat_block_size,
|
||||
input [10:0] i_dat_num_blocks,
|
||||
input [7:0] i_dat_num_blocks,
|
||||
input i_dat_start,
|
||||
input i_dat_stop,
|
||||
output o_dat_busy,
|
||||
@ -64,16 +64,16 @@ module sd_dat (
|
||||
|
||||
// Block counter logic
|
||||
|
||||
reg [10:0] r_block_counter;
|
||||
reg [7:0] r_block_counter;
|
||||
|
||||
wire w_read_start = i_dat_start && r_state[STATE_IDLE];
|
||||
wire w_read_stop = r_block_counter == 11'd0;
|
||||
wire w_read_stop = r_block_counter == 8'd0;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (w_read_start) begin
|
||||
r_block_counter <= i_dat_num_blocks;
|
||||
end else if (w_data_end) begin
|
||||
if (r_block_counter > 11'd0) begin
|
||||
if (r_block_counter > 8'd0) begin
|
||||
r_block_counter <= r_block_counter - 1'd1;
|
||||
end
|
||||
end
|
||||
|
@ -4,8 +4,8 @@ module sd_dma (
|
||||
|
||||
input [3:0] i_dma_bank,
|
||||
input [23:0] i_dma_address,
|
||||
input [17:0] i_dma_length,
|
||||
output [17:0] o_dma_left,
|
||||
input [14:0] i_dma_length,
|
||||
output reg [14:0] o_dma_left,
|
||||
input i_dma_load_bank_address,
|
||||
input i_dma_load_length,
|
||||
input i_dma_direction,
|
||||
@ -33,6 +33,58 @@ module sd_dma (
|
||||
|
||||
wire w_request_successful = o_request && !i_busy;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_dma_load_length && !o_dma_busy) begin
|
||||
o_dma_left <= i_dma_length;
|
||||
end else if (w_request_successful && o_dma_left > 15'd0) begin
|
||||
o_dma_left <= o_dma_left - 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
o_dma_busy <= 1'b0;
|
||||
end else begin
|
||||
if (i_dma_start && !o_dma_busy) begin
|
||||
o_dma_busy <= 1'b1;
|
||||
end
|
||||
if (i_dma_stop || (w_request_successful && o_dma_left == 15'd0)) begin
|
||||
o_dma_busy <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign o_rx_fifo_pop = o_dma_busy && o_write && w_request_successful;
|
||||
|
||||
assign o_tx_fifo_push = o_dma_busy && !o_write && i_ack;
|
||||
assign o_tx_fifo_data = i_data;
|
||||
|
||||
reg r_pending_ack;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset || i_dma_stop) begin
|
||||
r_pending_ack <= 1'b0;
|
||||
end else if (o_dma_busy && !o_write) begin
|
||||
if (w_request_successful) begin
|
||||
r_pending_ack <= 1'b1;
|
||||
end else if (i_ack) begin
|
||||
r_pending_ack <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign o_request = o_dma_busy && (o_write ? (
|
||||
!i_rx_fifo_empty
|
||||
) : (
|
||||
!r_pending_ack && !i_tx_fifo_full
|
||||
));
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_dma_start && !o_dma_busy) begin
|
||||
o_write <= i_dma_direction;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_dma_load_bank_address && !o_dma_busy) begin
|
||||
o_bank <= i_dma_bank;
|
||||
@ -47,47 +99,6 @@ module sd_dma (
|
||||
end
|
||||
end
|
||||
|
||||
reg [17:0] r_remaining;
|
||||
|
||||
assign o_dma_left = r_remaining;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_dma_load_length && !o_dma_busy) begin
|
||||
r_remaining <= i_dma_length;
|
||||
end else if (w_request_successful && r_remaining > 18'd0) begin
|
||||
r_remaining <= r_remaining - 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
o_dma_busy <= 1'b0;
|
||||
end else begin
|
||||
if (i_dma_start && !o_dma_busy) begin
|
||||
o_dma_busy <= 1'b1;
|
||||
end
|
||||
if (i_dma_stop || (w_request_successful && r_remaining == 18'd0)) begin
|
||||
o_dma_busy <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
assign o_rx_fifo_pop = o_dma_busy && o_write && w_request_successful;
|
||||
|
||||
assign o_tx_fifo_data = i_data;
|
||||
|
||||
assign o_request = o_dma_busy && (o_write ? (
|
||||
!i_rx_fifo_empty
|
||||
) : (
|
||||
1'b0 // TODO: Reading
|
||||
));
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_dma_start) begin
|
||||
o_write <= i_dma_direction;
|
||||
end
|
||||
end
|
||||
|
||||
assign o_data = i_rx_fifo_data;
|
||||
|
||||
endmodule
|
||||
|
@ -7,22 +7,22 @@ module sd_fifo (
|
||||
input i_fifo_pop,
|
||||
output o_fifo_empty,
|
||||
output o_fifo_full,
|
||||
output [7:0] o_fifo_items,
|
||||
output reg o_fifo_underrun,
|
||||
output reg o_fifo_overrun,
|
||||
output [8:0] o_fifo_items,
|
||||
input [31:0] i_fifo_data,
|
||||
output [31:0] o_fifo_data
|
||||
);
|
||||
|
||||
reg [31:0] r_fifo_mem [0:127];
|
||||
reg [31:0] r_fifo_mem [0:255];
|
||||
|
||||
reg [7:0] r_fifo_wrptr;
|
||||
reg [7:0] r_fifo_rdptr;
|
||||
reg [8:0] r_fifo_wrptr;
|
||||
reg [8:0] r_fifo_rdptr;
|
||||
|
||||
assign o_fifo_data = r_fifo_mem[r_fifo_rdptr[6:0]];
|
||||
assign o_fifo_data = r_fifo_mem[r_fifo_rdptr[7:0]];
|
||||
|
||||
wire w_empty = r_fifo_wrptr[7] == r_fifo_rdptr[7];
|
||||
wire w_full_or_empty = r_fifo_wrptr[6:0] == r_fifo_rdptr[6:0];
|
||||
wire w_empty = r_fifo_wrptr[8] == r_fifo_rdptr[8];
|
||||
wire w_full_or_empty = r_fifo_wrptr[7:0] == r_fifo_rdptr[7:0];
|
||||
|
||||
assign o_fifo_empty = w_empty && w_full_or_empty;
|
||||
assign o_fifo_full = !w_empty && w_full_or_empty;
|
||||
@ -30,20 +30,20 @@ module sd_fifo (
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
r_fifo_wrptr <= 8'd0;
|
||||
r_fifo_rdptr <= 8'd0;
|
||||
r_fifo_wrptr <= 9'd0;
|
||||
r_fifo_rdptr <= 9'd0;
|
||||
o_fifo_underrun <= 1'b0;
|
||||
o_fifo_overrun <= 1'b0;
|
||||
end else begin
|
||||
if (i_fifo_flush) begin
|
||||
r_fifo_wrptr <= 8'd0;
|
||||
r_fifo_rdptr <= 8'd0;
|
||||
r_fifo_wrptr <= 9'd0;
|
||||
r_fifo_rdptr <= 9'd0;
|
||||
o_fifo_underrun <= 1'b0;
|
||||
o_fifo_overrun <= 1'b0;
|
||||
end
|
||||
if (i_fifo_push) begin
|
||||
o_fifo_overrun <= o_fifo_overrun ? 1'b1 : o_fifo_full;
|
||||
r_fifo_mem[r_fifo_wrptr[6:0]] <= i_fifo_data;
|
||||
r_fifo_mem[r_fifo_wrptr[7:0]] <= i_fifo_data;
|
||||
r_fifo_wrptr <= r_fifo_wrptr + 1'd1;
|
||||
end
|
||||
if (i_fifo_pop) begin
|
||||
|
@ -85,8 +85,9 @@ module sd_interface (
|
||||
wire w_rx_fifo_regs_pop;
|
||||
wire w_rx_fifo_dma_pop;
|
||||
wire w_rx_fifo_empty;
|
||||
wire [7:0] w_rx_fifo_items;
|
||||
wire w_rx_fifo_full;
|
||||
wire w_rx_fifo_overrun;
|
||||
wire [8:0] w_rx_fifo_items;
|
||||
wire [31:0] w_rx_fifo_i_data;
|
||||
wire [31:0] w_rx_fifo_o_data;
|
||||
|
||||
@ -98,10 +99,10 @@ module sd_interface (
|
||||
.i_fifo_push(w_rx_fifo_push),
|
||||
.i_fifo_pop(w_rx_fifo_regs_pop || w_rx_fifo_dma_pop),
|
||||
.o_fifo_empty(w_rx_fifo_empty),
|
||||
.o_fifo_full(),
|
||||
.o_fifo_items(w_rx_fifo_items),
|
||||
.o_fifo_full(w_rx_fifo_full),
|
||||
.o_fifo_underrun(),
|
||||
.o_fifo_overrun(w_rx_fifo_overrun),
|
||||
.o_fifo_items(w_rx_fifo_items),
|
||||
.i_fifo_data(w_rx_fifo_i_data),
|
||||
.o_fifo_data(w_rx_fifo_o_data)
|
||||
);
|
||||
@ -115,6 +116,8 @@ module sd_interface (
|
||||
wire w_tx_fifo_pop;
|
||||
wire w_tx_fifo_empty;
|
||||
wire w_tx_fifo_full;
|
||||
wire w_tx_fifo_underrun;
|
||||
wire [8:0] w_tx_fifo_items;
|
||||
reg [31:0] r_tx_fifo_i_data;
|
||||
wire [31:0] w_tx_fifo_o_data;
|
||||
|
||||
@ -136,9 +139,9 @@ module sd_interface (
|
||||
.i_fifo_pop(w_tx_fifo_pop),
|
||||
.o_fifo_empty(w_tx_fifo_empty),
|
||||
.o_fifo_full(w_tx_fifo_full),
|
||||
.o_fifo_items(),
|
||||
.o_fifo_underrun(),
|
||||
.o_fifo_underrun(w_tx_fifo_underrun),
|
||||
.o_fifo_overrun(),
|
||||
.o_fifo_items(w_tx_fifo_items),
|
||||
.i_fifo_data(r_tx_fifo_i_data),
|
||||
.o_fifo_data(w_tx_fifo_o_data)
|
||||
);
|
||||
@ -149,7 +152,7 @@ module sd_interface (
|
||||
wire w_dat_width;
|
||||
wire w_dat_direction;
|
||||
wire [6:0] w_dat_block_size;
|
||||
wire [10:0] w_dat_num_blocks;
|
||||
wire [7:0] w_dat_num_blocks;
|
||||
wire w_dat_start;
|
||||
wire w_dat_stop;
|
||||
wire w_dat_busy;
|
||||
@ -187,8 +190,8 @@ module sd_interface (
|
||||
|
||||
wire [3:0] w_dma_bank;
|
||||
wire [23:0] w_dma_address;
|
||||
wire [17:0] w_dma_length;
|
||||
wire [17:0] w_dma_left;
|
||||
wire [14:0] w_dma_length;
|
||||
wire [14:0] w_dma_left;
|
||||
wire w_dma_load_bank_address;
|
||||
wire w_dma_load_length;
|
||||
wire w_dma_direction;
|
||||
@ -260,14 +263,18 @@ module sd_interface (
|
||||
|
||||
.o_rx_fifo_flush(w_rx_fifo_flush),
|
||||
.o_rx_fifo_pop(w_rx_fifo_regs_pop),
|
||||
.i_rx_fifo_items(w_rx_fifo_items),
|
||||
.i_rx_fifo_empty(w_rx_fifo_empty),
|
||||
.i_rx_fifo_full(w_rx_fifo_full),
|
||||
.i_rx_fifo_overrun(w_rx_fifo_overrun),
|
||||
.i_rx_fifo_items(w_rx_fifo_items),
|
||||
.i_rx_fifo_data(w_rx_fifo_o_data),
|
||||
|
||||
.o_tx_fifo_flush(w_tx_fifo_flush),
|
||||
.o_tx_fifo_push(w_tx_fifo_regs_push),
|
||||
.i_tx_fifo_empty(w_tx_fifo_empty),
|
||||
.i_tx_fifo_full(w_tx_fifo_full),
|
||||
.i_tx_fifo_underrun(w_tx_fifo_underrun),
|
||||
.i_tx_fifo_items(w_tx_fifo_items),
|
||||
.o_tx_fifo_data(w_tx_fifo_i_data_regs),
|
||||
|
||||
.o_dma_bank(w_dma_bank),
|
||||
|
@ -18,7 +18,7 @@ module sd_regs (
|
||||
output reg o_dat_width,
|
||||
output reg o_dat_direction,
|
||||
output reg [6:0] o_dat_block_size,
|
||||
output reg [10:0] o_dat_num_blocks,
|
||||
output reg [7:0] o_dat_num_blocks,
|
||||
output reg o_dat_start,
|
||||
output reg o_dat_stop,
|
||||
input i_dat_busy,
|
||||
@ -26,24 +26,28 @@ module sd_regs (
|
||||
|
||||
output reg o_rx_fifo_flush,
|
||||
output reg o_rx_fifo_pop,
|
||||
input [7:0] i_rx_fifo_items,
|
||||
input i_rx_fifo_empty,
|
||||
input i_rx_fifo_full,
|
||||
input i_rx_fifo_overrun,
|
||||
input [8:0] i_rx_fifo_items,
|
||||
input [31:0] i_rx_fifo_data,
|
||||
|
||||
output reg o_tx_fifo_flush,
|
||||
output reg o_tx_fifo_push,
|
||||
output o_tx_fifo_push,
|
||||
input i_tx_fifo_empty,
|
||||
input i_tx_fifo_full,
|
||||
output reg [31:0] o_tx_fifo_data,
|
||||
input i_tx_fifo_underrun,
|
||||
input [8:0] i_tx_fifo_items,
|
||||
output [31:0] o_tx_fifo_data,
|
||||
|
||||
output reg [3:0] o_dma_bank,
|
||||
output reg [23:0] o_dma_address,
|
||||
output reg [17:0] o_dma_length,
|
||||
output [3:0] o_dma_bank,
|
||||
output [23:0] o_dma_address,
|
||||
output [14:0] o_dma_length,
|
||||
input [3:0] i_dma_bank,
|
||||
input [23:0] i_dma_address,
|
||||
input [17:0] i_dma_left,
|
||||
output reg o_dma_load_bank_address,
|
||||
output reg o_dma_load_length,
|
||||
input [14:0] i_dma_left,
|
||||
output o_dma_load_bank_address,
|
||||
output o_dma_load_length,
|
||||
output reg o_dma_direction,
|
||||
output reg o_dma_start,
|
||||
output reg o_dma_stop,
|
||||
@ -73,9 +77,11 @@ module sd_regs (
|
||||
always @(*) begin
|
||||
o_dma_bank = i_data[31:28];
|
||||
o_dma_address = i_data[25:2];
|
||||
o_dma_length = i_data[17:0];
|
||||
o_dma_length = i_data[14:0];
|
||||
o_dma_load_bank_address = w_write_request && !i_address[3] && (i_address[2:0] == SD_REG_DMA_ADDR);
|
||||
o_dma_load_length = w_write_request && !i_address[3] && (i_address[2:0] == SD_REG_DMA_LEN);
|
||||
o_tx_fifo_data = i_data;
|
||||
o_tx_fifo_push = w_write_request && i_address[3] && !i_tx_fifo_full && !i_dma_busy;
|
||||
o_busy = 1'b0;
|
||||
end
|
||||
|
||||
@ -84,7 +90,6 @@ module sd_regs (
|
||||
o_dat_start <= 1'b0;
|
||||
o_rx_fifo_flush <= 1'b0;
|
||||
o_tx_fifo_flush <= 1'b0;
|
||||
o_tx_fifo_push <= 1'b0;
|
||||
o_dma_start <= 1'b0;
|
||||
o_dat_stop <= 1'b0;
|
||||
o_dma_stop <= 1'b0;
|
||||
@ -94,49 +99,62 @@ module sd_regs (
|
||||
o_dat_width <= 1'b0;
|
||||
o_dat_direction <= 1'b0;
|
||||
o_dat_block_size <= 7'd0;
|
||||
o_dat_num_blocks <= 11'd0;
|
||||
o_dat_num_blocks <= 8'd0;
|
||||
o_dma_direction <= 1'b0;
|
||||
end else if (w_write_request) begin
|
||||
if (!i_address[3]) begin
|
||||
case (i_address[2:0])
|
||||
SD_REG_SCR: begin
|
||||
{o_dat_width, o_sd_clk_config} <= i_data[2:0];
|
||||
if (!i_command_busy && !i_dat_busy) begin
|
||||
o_sd_clk_config <= i_data[1:0];
|
||||
end
|
||||
if (!i_dat_busy) begin
|
||||
o_dat_width <= i_data[2];
|
||||
end
|
||||
end
|
||||
|
||||
SD_REG_ARG: begin
|
||||
o_command_argument <= i_data;
|
||||
if (!i_command_busy) begin
|
||||
o_command_argument <= i_data;
|
||||
end
|
||||
end
|
||||
|
||||
SD_REG_CMD: begin
|
||||
{
|
||||
o_command_skip_response,
|
||||
o_command_long_response,
|
||||
o_command_start,
|
||||
o_command_index
|
||||
} <= i_data[8:0];
|
||||
if (!i_command_busy) begin
|
||||
{
|
||||
o_command_skip_response,
|
||||
o_command_long_response,
|
||||
o_command_start,
|
||||
o_command_index
|
||||
} <= i_data[8:0];
|
||||
end
|
||||
end
|
||||
|
||||
SD_REG_RSP: begin
|
||||
end
|
||||
|
||||
SD_REG_DAT: begin
|
||||
{
|
||||
o_tx_fifo_flush,
|
||||
o_rx_fifo_flush,
|
||||
o_dat_num_blocks,
|
||||
o_dat_block_size,
|
||||
o_dat_direction,
|
||||
o_dat_stop,
|
||||
o_dat_start
|
||||
} <= i_data[22:0];
|
||||
if (!i_dat_busy || i_data[1]) begin
|
||||
{
|
||||
o_tx_fifo_flush,
|
||||
o_rx_fifo_flush,
|
||||
o_dat_num_blocks,
|
||||
o_dat_block_size,
|
||||
o_dat_direction,
|
||||
o_dat_stop,
|
||||
o_dat_start
|
||||
} <= i_data[19:0];
|
||||
end
|
||||
end
|
||||
|
||||
SD_REG_DMA_SCR: begin
|
||||
{
|
||||
o_dma_direction,
|
||||
o_dma_stop,
|
||||
o_dma_start
|
||||
} <= i_data[2:0];
|
||||
if (!i_dma_busy || i_data[1]) begin
|
||||
{
|
||||
o_dma_direction,
|
||||
o_dma_stop,
|
||||
o_dma_start
|
||||
} <= i_data[2:0];
|
||||
end
|
||||
end
|
||||
|
||||
SD_REG_DMA_ADDR: begin
|
||||
@ -145,9 +163,6 @@ module sd_regs (
|
||||
SD_REG_DMA_LEN: begin
|
||||
end
|
||||
endcase
|
||||
end else begin
|
||||
o_tx_fifo_push <= 1'b1;
|
||||
o_tx_fifo_data <= i_data;
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -173,11 +188,9 @@ module sd_regs (
|
||||
|
||||
SD_REG_CMD: begin
|
||||
o_data <= {
|
||||
21'd0,
|
||||
23'd0,
|
||||
i_command_response_crc_error,
|
||||
i_command_timeout,
|
||||
o_command_skip_response,
|
||||
o_command_long_response,
|
||||
i_command_busy,
|
||||
i_command_index
|
||||
};
|
||||
@ -189,13 +202,15 @@ module sd_regs (
|
||||
|
||||
SD_REG_DAT: begin
|
||||
o_data <= {
|
||||
i_rx_fifo_items,
|
||||
6'd0,
|
||||
i_tx_fifo_items,
|
||||
i_tx_fifo_full,
|
||||
i_tx_fifo_empty,
|
||||
i_tx_fifo_underrun,
|
||||
i_rx_fifo_items,
|
||||
i_rx_fifo_full,
|
||||
i_rx_fifo_empty,
|
||||
i_rx_fifo_overrun,
|
||||
o_dat_num_blocks,
|
||||
o_dat_block_size,
|
||||
o_dat_direction,
|
||||
i_dat_crc_error,
|
||||
i_dat_busy
|
||||
};
|
||||
@ -210,11 +225,13 @@ module sd_regs (
|
||||
end
|
||||
|
||||
SD_REG_DMA_LEN: begin
|
||||
o_data <= {14'd0, i_dma_left};
|
||||
o_data <= {17'd0, i_dma_left};
|
||||
end
|
||||
endcase
|
||||
end else begin
|
||||
o_rx_fifo_pop <= 1'b1;
|
||||
if (!i_rx_fifo_empty && !i_dma_busy) begin
|
||||
o_rx_fifo_pop <= 1'b1;
|
||||
end
|
||||
o_data <= i_rx_fifo_data;
|
||||
end
|
||||
end
|
||||
|
@ -1,58 +1,67 @@
|
||||
ROOTDIR = $(N64_INST)
|
||||
|
||||
GCCN64PREFIX = $(ROOTDIR)/bin/mips64-elf-
|
||||
CHKSUM64PATH = $(ROOTDIR)/bin/chksum64
|
||||
MKDFSPATH = $(ROOTDIR)/bin/mkdfs
|
||||
HEADERPATH = $(ROOTDIR)/mips64-elf/lib
|
||||
N64TOOL = $(ROOTDIR)/bin/n64tool
|
||||
HEADERNAME = header
|
||||
LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld
|
||||
CFLAGS = -std=gnu99 -march=vr4300 -mtune=vr4300 -Os -Wall -I./src -I./src/boot -I./src/fatfs -I./src/sc64 -I$(ROOTDIR)/mips64-elf/include
|
||||
ASFLAGS = -mtune=vr4300 -march=vr4300
|
||||
CC = $(GCCN64PREFIX)gcc
|
||||
AS = $(GCCN64PREFIX)as
|
||||
LD = $(GCCN64PREFIX)ld
|
||||
OBJCOPY = $(GCCN64PREFIX)objcopy
|
||||
OBJDUMP = $(GCCN64PREFIX)objdump
|
||||
|
||||
SRC_DIRS = src src/boot src/fatfs src/sc64
|
||||
SRC_FILES = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIRS)))
|
||||
OBJ_FILES = $(addprefix build/, $(notdir $(SRC_FILES:.c=.o)))
|
||||
VPATH = $(SRC_DIRS)
|
||||
CHKSUM64 = $(ROOTDIR)/bin/chksum64
|
||||
MKSPRITE = $(ROOTDIR)/bin/mksprite
|
||||
N64TOOL = $(ROOTDIR)/bin/n64tool
|
||||
|
||||
ROM_SIZE = 90k
|
||||
|
||||
ifeq ($(N64_BYTE_SWAP),true)
|
||||
ROM_EXTENSION = .v64
|
||||
N64_FLAGS = -b -l $(ROM_SIZE) -h $(HEADERPATH)/$(HEADERNAME) -o build/$(PROG_NAME)$(ROM_EXTENSION)
|
||||
else
|
||||
ROM_EXTENSION = .z64
|
||||
N64_FLAGS = -l $(ROM_SIZE) -h $(HEADERPATH)/$(HEADERNAME) -o build/$(PROG_NAME)$(ROM_EXTENSION)
|
||||
endif
|
||||
HEADER_PATH = $(ROOTDIR)/mips64-elf/lib
|
||||
HEADER_NAME = header
|
||||
|
||||
PROG_NAME = SummerLoader64
|
||||
|
||||
all: make_output_dir build/$(PROG_NAME)$(ROM_EXTENSION)
|
||||
ROM_SIZE = 90k
|
||||
|
||||
SOURCE_DIR = src
|
||||
BUILD_DIR = build
|
||||
|
||||
SRC_DIRS = $(SOURCE_DIR) $(sort $(dir $(wildcard $(SOURCE_DIR)/*/.)))
|
||||
INC_DIRS = $(addprefix -I, . $(SRC_DIRS))
|
||||
SRC_FILES = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIRS)))
|
||||
IMG_FILES = $(wildcard $(patsubst %, %/*.png, . $(SRC_DIRS)))
|
||||
OBJ_FILES = $(addprefix $(BUILD_DIR)/, $(notdir $(IMG_FILES:.png=.o) $(SRC_FILES:.c=.o)))
|
||||
|
||||
VPATH = $(SRC_DIRS)
|
||||
|
||||
COMMONFLAGS = -march=vr4300 -mtune=vr4300
|
||||
ASFLAGS = $(COMMONFLAGS)
|
||||
CFLAGS = $(COMMONFLAGS) -std=gnu99 -Os -Wall -I$(ROOTDIR)/mips64-elf/include $(INC_DIRS)
|
||||
LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld
|
||||
N64_FLAGS = -l $(ROM_SIZE) -h $(HEADER_PATH)/$(HEADER_NAME) -o $(BUILD_DIR)/$(PROG_NAME).z64
|
||||
|
||||
all: make_output_dir $(BUILD_DIR)/$(PROG_NAME).z64
|
||||
|
||||
$(OBJ_FILES): Makefile
|
||||
|
||||
build/$(PROG_NAME)$(ROM_EXTENSION): build/$(PROG_NAME).elf
|
||||
$(OBJCOPY) build/$(PROG_NAME).elf build/$(PROG_NAME).bin -O binary
|
||||
$(OBJDUMP) -S build/$(PROG_NAME).elf > build/$(PROG_NAME).lst
|
||||
rm -f build/$(PROG_NAME)$(ROM_EXTENSION)
|
||||
$(N64TOOL) $(N64_FLAGS) -t $(PROG_NAME) build/$(PROG_NAME).bin
|
||||
$(CHKSUM64PATH) build/$(PROG_NAME)$(ROM_EXTENSION)
|
||||
$(OBJCOPY) build/$(PROG_NAME)$(ROM_EXTENSION) build/$(PROG_NAME).hex -I binary -O ihex
|
||||
$(BUILD_DIR)/$(PROG_NAME).z64: $(BUILD_DIR)/$(PROG_NAME).elf
|
||||
$(OBJCOPY) $(BUILD_DIR)/$(PROG_NAME).elf $(BUILD_DIR)/$(PROG_NAME).bin -O binary
|
||||
$(OBJDUMP) -S $(BUILD_DIR)/$(PROG_NAME).elf > $(BUILD_DIR)/$(PROG_NAME).lst
|
||||
$(N64TOOL) $(N64_FLAGS) -t $(PROG_NAME) $(BUILD_DIR)/$(PROG_NAME).bin
|
||||
$(CHKSUM64) $(BUILD_DIR)/$(PROG_NAME).z64
|
||||
$(OBJCOPY) $(BUILD_DIR)/$(PROG_NAME).z64 $(BUILD_DIR)/$(PROG_NAME).hex -I binary -O ihex
|
||||
|
||||
build/$(PROG_NAME).elf: $(OBJ_FILES)
|
||||
$(LD) -o build/$(PROG_NAME).elf $(OBJ_FILES) $(LINK_FLAGS)
|
||||
$(BUILD_DIR)/$(PROG_NAME).elf: $(OBJ_FILES)
|
||||
$(LD) -o $(BUILD_DIR)/$(PROG_NAME).elf $(OBJ_FILES) $(LINK_FLAGS)
|
||||
|
||||
build/%.o: %.c
|
||||
$(BUILD_DIR)/%.o: %.c
|
||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
$(BUILD_DIR)/%.sprite: $(IMG_FILES)
|
||||
$(MKSPRITE) 32 $< $@
|
||||
|
||||
$(BUILD_DIR)/%.o: $(BUILD_DIR)/%.sprite
|
||||
$(OBJCOPY) -I binary -O elf32-bigmips -B mips:4000 --rename-section .data=.rodata $< $@
|
||||
|
||||
make_output_dir:
|
||||
$(shell mkdir ./build 2>/dev/null)
|
||||
$(shell mkdir ./$(BUILD_DIR) 2> /dev/null)
|
||||
|
||||
clean:
|
||||
rm -rf ./build
|
||||
$(shell rm -rf ./$(BUILD_DIR) 2> /dev/null)
|
||||
|
||||
.PHONY: all clean make_output_dir
|
||||
|
@ -1,7 +1,3 @@
|
||||
# SummerLoader64
|
||||
|
||||
A N64 bootloader for SummerCart64. This project is mainly based on work by **`jago85`** contained in [Brutzelkarte_Bootloader repository](https://github.com/jago85/Brutzelkarte_Bootloader) with some modifications that made code a little bit more readable.
|
||||
|
||||
## TODO
|
||||
|
||||
- Expand documentation
|
||||
|
@ -1,3 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker run -t --mount type=bind,src="$(pwd)",target="/libdragon" anacierdem/libdragon:4.1.1 /bin/bash -c "/usr/bin/make clean; /usr/bin/make all N64_BYTE_SWAP=false"
|
||||
LIBDRAGON_DOCKER_VERSION=latest
|
||||
|
||||
docker \
|
||||
run \
|
||||
-t \
|
||||
--mount type=bind,src=`realpath "$(dirname $0)"`,target="/libdragon" \
|
||||
anacierdem/libdragon:$LIBDRAGON_DOCKER_VERSION \
|
||||
/bin/bash -c "make clean && make all"
|
||||
|
12
sw/bootloader/src/assets/assets.h
Normal file
12
sw/bootloader/src/assets/assets.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef ASSETS_H__
|
||||
#define ASSETS_H__
|
||||
|
||||
|
||||
#include <libdragon.h>
|
||||
|
||||
|
||||
extern sprite_t _binary_build_sc64_logo_sprite_start[];
|
||||
extern sprite_t _binary_build_sc64_logo_sprite_end[];
|
||||
|
||||
|
||||
#endif
|
BIN
sw/bootloader/src/assets/sc64_logo.png
Normal file
BIN
sw/bootloader/src/assets/sc64_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
@ -3,7 +3,10 @@
|
||||
#include "n64_regs.h"
|
||||
|
||||
|
||||
static const struct crc32_to_cic_seed crc32_to_cic_seed[] = {
|
||||
static const struct crc32_to_cic_seed {
|
||||
uint32_t ipl3_crc32;
|
||||
uint16_t cic_seed;
|
||||
} crc32_to_cic_seed[] = {
|
||||
{ .ipl3_crc32 = 0x587BD543, .cic_seed = 0x00AC }, // CIC5101
|
||||
{ .ipl3_crc32 = 0x6170A4A1, .cic_seed = 0x013F }, // CIC6101
|
||||
{ .ipl3_crc32 = 0x009E9EA3, .cic_seed = 0x013F }, // CIC7102
|
||||
@ -53,7 +56,7 @@ tv_type_t boot_get_tv_type(cart_header_t *cart_header) {
|
||||
case 'W':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
return E_TV_TYPE_PAL;
|
||||
return TV_PAL;
|
||||
case '7':
|
||||
case 'A':
|
||||
case 'C':
|
||||
@ -62,11 +65,11 @@ tv_type_t boot_get_tv_type(cart_header_t *cart_header) {
|
||||
case 'K':
|
||||
case 'N':
|
||||
case 'U':
|
||||
return E_TV_TYPE_NTSC;
|
||||
return TV_NTSC;
|
||||
case 'B':
|
||||
return E_TV_TYPE_MPAL;
|
||||
return TV_MPAL;
|
||||
default:
|
||||
return E_TV_TYPE_UNKNOWN;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +81,7 @@ void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type, uint
|
||||
(cic_seed == crc32_to_cic_seed[8].cic_seed) ||
|
||||
(cic_seed == crc32_to_cic_seed[9].cic_seed)
|
||||
);
|
||||
tv_type_t os_tv_type = tv_type == E_TV_TYPE_UNKNOWN ? OS_BOOT_CONFIG->tv_type : tv_type;
|
||||
tv_type_t os_tv_type = tv_type < 0 ? OS_BOOT_CONFIG->tv_type : tv_type;
|
||||
|
||||
volatile uint64_t gpr_regs[32];
|
||||
|
||||
@ -134,7 +137,7 @@ void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type, uint
|
||||
gpr_regs[CPU_REG_S6] = BOOT_SEED_IPL3(cic_seed);
|
||||
gpr_regs[CPU_REG_S7] = BOOT_SEED_OS_VERSION(cic_seed);
|
||||
gpr_regs[CPU_REG_SP] = CPU_ADDRESS_IN_REG(SP_MEM->imem[ARRAY_ITEMS(SP_MEM->imem) - 4]);
|
||||
gpr_regs[CPU_REG_RA] = CPU_ADDRESS_IN_REG(SP_MEM->imem[(os_tv_type == E_TV_TYPE_PAL) ? 341 : 340]);
|
||||
gpr_regs[CPU_REG_RA] = CPU_ADDRESS_IN_REG(SP_MEM->imem[(os_tv_type == TV_PAL) ? 341 : 340]);
|
||||
|
||||
__asm__ (
|
||||
".set noat \n\t"
|
||||
|
@ -5,18 +5,6 @@
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
struct crc32_to_cic_seed {
|
||||
uint32_t ipl3_crc32;
|
||||
uint16_t cic_seed;
|
||||
};
|
||||
|
||||
typedef enum tv_type_e {
|
||||
E_TV_TYPE_PAL,
|
||||
E_TV_TYPE_NTSC,
|
||||
E_TV_TYPE_MPAL,
|
||||
E_TV_TYPE_UNKNOWN,
|
||||
} tv_type_t;
|
||||
|
||||
struct cart_header_s {
|
||||
uint32_t pi_conf;
|
||||
uint32_t clock_rate;
|
||||
|
@ -1,45 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "error_display.h"
|
||||
|
||||
|
||||
void error_display_and_halt(menu_load_error_t error, const char *path) {
|
||||
init_interrupts();
|
||||
|
||||
display_init(RESOLUTION_320x240, DEPTH_32_BPP, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE);
|
||||
|
||||
console_init();
|
||||
console_set_render_mode(RENDER_MANUAL);
|
||||
console_clear();
|
||||
|
||||
printf("SC64 Bootloader ver. %d.%02d error:\n\n%2d: ", BOOTLOADER_VERSION_MAJOR, BOOTLOADER_VERSION_MINOR, error);
|
||||
|
||||
switch (error) {
|
||||
case E_MENU_OK:
|
||||
printf("No error :O");
|
||||
break;
|
||||
case E_MENU_ERROR_NOT_SC64:
|
||||
printf("SummerCart64 not detected");
|
||||
break;
|
||||
case E_MENU_ERROR_NO_CARD:
|
||||
printf("SD Card not detected");
|
||||
break;
|
||||
case E_MENU_ERROR_NO_FILESYSTEM:
|
||||
printf("No filesystem (FAT or exFAT)\nfound on SD Card");
|
||||
break;
|
||||
case E_MENU_ERROR_NO_FILE:
|
||||
printf("Unable to locate menu file:\n(%s)", path);
|
||||
break;
|
||||
case E_MENU_ERROR_READ_ERROR:
|
||||
printf("Error while reading data from\nSD Card");
|
||||
break;
|
||||
case E_MENU_ERROR_OTHER_ERROR:
|
||||
default:
|
||||
printf("Unknown error");
|
||||
break;
|
||||
}
|
||||
|
||||
console_render();
|
||||
|
||||
while (1);
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
#ifndef ERROR_DISPLAY_H__
|
||||
#define ERROR_DISPLAY_H__
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
#ifndef ERRORS_H__
|
||||
#define ERRORS_H__
|
||||
|
||||
|
||||
typedef enum menu_load_error_e {
|
||||
@ -13,10 +10,8 @@ typedef enum menu_load_error_e {
|
||||
E_MENU_ERROR_NO_FILE,
|
||||
E_MENU_ERROR_READ_ERROR,
|
||||
E_MENU_ERROR_OTHER_ERROR,
|
||||
E_MENU_END,
|
||||
} menu_load_error_t;
|
||||
|
||||
|
||||
void error_display_and_halt(menu_load_error_t error, const char *path);
|
||||
|
||||
|
||||
#endif
|
@ -48,6 +48,14 @@ DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
#if !FF_FS_READONLY
|
||||
|
||||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
/ Function Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_FS_READONLY 1
|
||||
#define FF_FS_READONLY 0
|
||||
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
||||
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
||||
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
|
||||
|
106
sw/bootloader/src/loader/loader.c
Normal file
106
sw/bootloader/src/loader/loader.c
Normal file
@ -0,0 +1,106 @@
|
||||
#include <libdragon.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "assets/assets.h"
|
||||
|
||||
#include "loader.h"
|
||||
|
||||
|
||||
#define X_OFFSET (24)
|
||||
#define Y_OFFSET (16)
|
||||
#define Y_PADDING (12)
|
||||
|
||||
#define LAST_CHAR(s) (sizeof(s) - 1)
|
||||
#define EDIT_CHAR(s, n) s[(n) >= 0 ? 0 : LAST_CHAR((s)) + (n)]
|
||||
#define NTOA(n) ('0' + ((n) % 10))
|
||||
|
||||
|
||||
static char version_string[] = "SC64 Bootloader ver. X.X";
|
||||
static char error_number_string[] = "ERROR X";
|
||||
static const char *error_strings[] = {
|
||||
"No error :O",
|
||||
"SummerCart64 not detected",
|
||||
"SD Card not detected",
|
||||
"No filesystem (FAT or exFAT)\nfound on SD Card",
|
||||
"Unable to locate menu file",
|
||||
"Error while reading data from\nSD Card",
|
||||
"Unknown error",
|
||||
};
|
||||
|
||||
static int x_offset = X_OFFSET;
|
||||
static int y_offset = Y_OFFSET;
|
||||
|
||||
|
||||
static display_context_t loader_get_display(void) {
|
||||
display_context_t display;
|
||||
|
||||
do {
|
||||
display = display_lock();
|
||||
} while (!display);
|
||||
|
||||
x_offset = X_OFFSET;
|
||||
y_offset = Y_OFFSET;
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
static void loader_draw_version_and_logo(display_context_t display) {
|
||||
EDIT_CHAR(version_string, -3) = NTOA(BOOTLOADER_VERSION_MAJOR);
|
||||
EDIT_CHAR(version_string, -1) = NTOA(BOOTLOADER_VERSION_MINOR);
|
||||
graphics_draw_text(display, x_offset, y_offset, version_string);
|
||||
y_offset += Y_PADDING;
|
||||
|
||||
sprite_t *logo = _binary_build_sc64_logo_sprite_start;
|
||||
|
||||
int center_x = (320 / 2) - (logo->width / 2);
|
||||
int center_y = (240 / 2) - (logo->height / 2);
|
||||
|
||||
graphics_draw_sprite(display, center_x, center_y, logo);
|
||||
}
|
||||
|
||||
void loader_init(void) {
|
||||
display_context_t display;
|
||||
|
||||
init_interrupts();
|
||||
|
||||
audio_init(44100, 2);
|
||||
audio_write_silence();
|
||||
|
||||
display_init(RESOLUTION_320x240, DEPTH_32_BPP, 2, GAMMA_NONE, ANTIALIAS_OFF);
|
||||
|
||||
display = loader_get_display();
|
||||
|
||||
loader_draw_version_and_logo(display);
|
||||
|
||||
display_show(display);
|
||||
}
|
||||
|
||||
void loader_cleanup(void) {
|
||||
audio_close();
|
||||
display_close();
|
||||
}
|
||||
|
||||
void loader_display_error_and_halt(menu_load_error_t error, const char *path) {
|
||||
display_context_t display;
|
||||
|
||||
display = loader_get_display();
|
||||
|
||||
loader_draw_version_and_logo(display);
|
||||
|
||||
EDIT_CHAR(error_number_string, -1) = NTOA(error);
|
||||
graphics_draw_text(display, x_offset, y_offset, error_number_string);
|
||||
y_offset += Y_PADDING;
|
||||
|
||||
int error_string_index = error >= E_MENU_END ? (E_MENU_END - 1) : error;
|
||||
const char *error_string = error_strings[error_string_index];
|
||||
graphics_draw_text(display, x_offset, y_offset, error_string);
|
||||
y_offset += Y_PADDING;
|
||||
|
||||
if (error == E_MENU_ERROR_NO_FILE) {
|
||||
graphics_draw_text(display, x_offset, y_offset, path);
|
||||
}
|
||||
|
||||
display_show(display);
|
||||
|
||||
while (1);
|
||||
}
|
13
sw/bootloader/src/loader/loader.h
Normal file
13
sw/bootloader/src/loader/loader.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef LOADER_H__
|
||||
#define LOADER_H__
|
||||
|
||||
|
||||
#include "errors.h"
|
||||
|
||||
|
||||
void loader_init(void);
|
||||
void loader_cleanup(void);
|
||||
void loader_display_error_and_halt(menu_load_error_t error, const char *path);
|
||||
|
||||
|
||||
#endif
|
@ -1,16 +1,17 @@
|
||||
#include "boot.h"
|
||||
#include "error_display.h"
|
||||
|
||||
#include "sc64.h"
|
||||
#include "sc64_sd_fs.h"
|
||||
#include "boot/boot.h"
|
||||
#include "loader/loader.h"
|
||||
#include "sc64/sc64.h"
|
||||
#include "sc64/sc64_sd_fs.h"
|
||||
|
||||
|
||||
static const char *MENU_FILE_PATH = "SC64/MENU.z64";
|
||||
|
||||
|
||||
int main(void) {
|
||||
loader_init();
|
||||
|
||||
if (sc64_get_version() != SC64_CART_VERSION_A) {
|
||||
error_display_and_halt(E_MENU_ERROR_NOT_SC64, MENU_FILE_PATH);
|
||||
loader_display_error_and_halt(E_MENU_ERROR_NOT_SC64, "");
|
||||
}
|
||||
|
||||
sc64_enable_rom_switch();
|
||||
@ -50,7 +51,7 @@ int main(void) {
|
||||
}
|
||||
|
||||
if (error != E_MENU_OK) {
|
||||
error_display_and_halt(error, MENU_FILE_PATH);
|
||||
loader_display_error_and_halt(error, MENU_FILE_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,5 +71,7 @@ int main(void) {
|
||||
tv_type = boot_get_tv_type(cart_header);
|
||||
}
|
||||
|
||||
loader_cleanup();
|
||||
|
||||
boot(cart_header, cic_seed, tv_type, ddipl_override);
|
||||
}
|
||||
|
@ -11,10 +11,6 @@
|
||||
#define BOOTLOADER_VERSION_MAJOR (1)
|
||||
#define BOOTLOADER_VERSION_MINOR (0)
|
||||
|
||||
|
||||
#define TRUE (1)
|
||||
#define FALSE (0)
|
||||
|
||||
#define __IO volatile
|
||||
|
||||
typedef uint32_t reg_t;
|
||||
|
@ -27,7 +27,7 @@ typedef struct sc64_cart_registers {
|
||||
__IO reg_t USB_DMA_LEN; // USB transfer length for DMA to PC
|
||||
__IO reg_t DDIPL_ADDR; // 64 Disk Drive IPL location in SDRAM
|
||||
__IO reg_t SRAM_ADDR; // SRAM save emulation location in SDRAM
|
||||
__IO reg_t __reserved[1015];
|
||||
__IO reg_t __unused[1015];
|
||||
__IO reg_t USB_FIFO[1024]; // USB data from PC read FIFO memory end
|
||||
} sc64_cart_registers_t;
|
||||
|
||||
@ -35,6 +35,7 @@ typedef struct sc64_cart_registers {
|
||||
|
||||
#define SC64_CART ((__IO sc64_cart_registers_t *) SC64_CART_BASE)
|
||||
|
||||
|
||||
#define SC64_CART_SCR_FLASHRAM_ENABLE (1 << 9)
|
||||
#define SC64_CART_SCR_SRAM_768K_MODE (1 << 8)
|
||||
#define SC64_CART_SCR_SRAM_ENABLE (1 << 7)
|
||||
@ -52,6 +53,7 @@ typedef struct sc64_cart_registers {
|
||||
#define SC64_CART_BOOT_DDIPL_OVERRIDE (1 << 12)
|
||||
#define SC64_CART_BOOT_TV_TYPE_BIT (10)
|
||||
#define SC64_CART_BOOT_TV_TYPE_MASK (0x3 << SC64_CART_BOOT_TV_TYPE_BIT)
|
||||
#define SC64_CART_BOOT_ROM_LOADED (1 << 9)
|
||||
#define SC64_CART_BOOT_CIC_SEED_BIT (0)
|
||||
#define SC64_CART_BOOT_CIC_SEED_MASK (0x1FF << SC64_CART_BOOT_CIC_SEED_BIT)
|
||||
|
||||
@ -123,6 +125,7 @@ typedef struct sc64_sd_registers_s {
|
||||
|
||||
#define SC64_SD ((__IO sc64_sd_registers_t *) SC64_SD_BASE)
|
||||
|
||||
|
||||
#define SC64_SD_SCR_DAT_WIDTH (1 << 2)
|
||||
#define SC64_SD_SCR_CLK_MASK (0x3 << 0)
|
||||
#define SC64_SD_SCR_CLK_STOP (0 << 0)
|
||||
@ -130,43 +133,53 @@ typedef struct sc64_sd_registers_s {
|
||||
#define SC64_SD_SCR_CLK_25_MHZ (2 << 0)
|
||||
#define SC64_SD_SCR_CLK_50_MHZ (3 << 0)
|
||||
|
||||
#define SC64_SD_CMD_RESPONSE_CRC_ERROR (1 << 10)
|
||||
#define SC64_SD_CMD_TIMEOUT (1 << 9)
|
||||
|
||||
#define SC64_SD_CMD_RESPONSE_CRC_ERROR (1 << 8)
|
||||
#define SC64_SD_CMD_TIMEOUT (1 << 7)
|
||||
#define SC64_SD_CMD_BUSY (1 << 6)
|
||||
#define SC64_SD_CMD_INDEX_GET(cmd) ((cmd) & 0x3F)
|
||||
|
||||
#define SC64_SD_CMD_SKIP_RESPONSE (1 << 8)
|
||||
#define SC64_SD_CMD_LONG_RESPONSE (1 << 7)
|
||||
#define SC64_SD_CMD_BUSY (1 << 6)
|
||||
#define SC64_SD_CMD_START (1 << 6)
|
||||
#define SC64_SD_CMD_INDEX_GET(cmd) ((cmd) & 0x3F)
|
||||
#define SC64_SD_CMD_INDEX(i) ((i) & 0x3F)
|
||||
|
||||
#define SC64_SD_DAT_RX_FIFO_FULL (1 << 31)
|
||||
#define SC64_SD_DAT_RX_FIFO_ITEMS_GET(dat) (((dat) >> 24) & 0xFF)
|
||||
#define SC64_SD_DAT_TX_FIFO_FULL (1 << 23)
|
||||
#define SC64_SD_DAT_TX_FIFO_EMPTY (1 << 22)
|
||||
#define SC64_SD_DAT_TX_FIFO_FLUSH (1 << 22)
|
||||
#define SC64_SD_DAT_RX_FIFO_OVERRUN (1 << 21)
|
||||
#define SC64_SD_DAT_RX_FIFO_FLUSH (1 << 21)
|
||||
#define SC64_SD_DAT_NUM_BLOCKS_GET(dat) ((((dat) >> 10) & 0x7FF) + 1)
|
||||
#define SC64_SD_DAT_NUM_BLOCKS(nb) ((((nb) - 1) & 0x7FF) << 10)
|
||||
#define SC64_SD_DAT_BLOCK_SIZE_GET(dat) (((((dat) >> 3) & 0x7F) + 1) * 4)
|
||||
|
||||
#define SC64_SD_DAT_TX_FIFO_ITEMS_GET(dat) (((dat) >> 17) & 0x1FF)
|
||||
#define SC64_SD_DAT_TX_FIFO_FULL (1 << 16)
|
||||
#define SC64_SD_DAT_TX_FIFO_EMPTY (1 << 15)
|
||||
#define SC64_SD_DAT_TX_FIFO_UNDERRUN (1 << 14)
|
||||
#define SC64_SD_DAT_RX_FIFO_ITEMS_GET(dat) (((dat) >> 5) & 0x1FF)
|
||||
#define SC64_SD_DAT_RX_FIFO_FULL (1 << 4)
|
||||
#define SC64_SD_DAT_RX_FIFO_EMPTY (1 << 3)
|
||||
#define SC64_SD_DAT_RX_FIFO_OVERRUN (1 << 2)
|
||||
#define SC64_SD_DAT_CRC_ERROR (1 << 1)
|
||||
#define SC64_SD_DAT_BUSY (1 << 0)
|
||||
|
||||
#define SC64_SD_DAT_TX_FIFO_FLUSH (1 << 19)
|
||||
#define SC64_SD_DAT_RX_FIFO_FLUSH (1 << 18)
|
||||
#define SC64_SD_DAT_NUM_BLOCKS(nb) ((((nb) - 1) & 0xFF) << 10)
|
||||
#define SC64_SD_DAT_BLOCK_SIZE(bs) (((((bs) / 4) - 1) & 0x7F) << 3)
|
||||
#define SC64_SD_DAT_DIRECTION (1 << 2)
|
||||
#define SC64_SD_DAT_CRC_ERROR (1 << 1)
|
||||
#define SC64_SD_DAT_STOP (1 << 1)
|
||||
#define SC64_SD_DAT_BUSY (1 << 0)
|
||||
#define SC64_SD_DAT_START (1 << 0)
|
||||
|
||||
|
||||
#define SC64_SD_DMA_SCR_BUSY (1 << 0)
|
||||
|
||||
#define SC64_SD_DMA_SCR_DIRECTION (1 << 2)
|
||||
#define SC64_SD_DMA_SCR_STOP (1 << 1)
|
||||
#define SC64_SD_DMA_SCR_BUSY (1 << 0)
|
||||
#define SC64_SD_DMA_SCR_START (1 << 0)
|
||||
|
||||
|
||||
#define SC64_SD_DMA_ADDR_GET(addr) ((addr) & 0x3FFFFFC)
|
||||
#define SC64_SD_DMA_BANK_GET(addr) (((addr) >> 28) & 0xF)
|
||||
|
||||
#define SC64_SD_DMA_BANK_ADDR(b, a) ((((b) & 0xF) << 28) | ((a) & 0x3FFFFFC))
|
||||
|
||||
#define SC64_SD_DMA_LEN_GET(len) (((len) & 0x3FFFF) * 4)
|
||||
#define SC64_SD_DMA_LEN(l) ((((l) / 4) - 1) & 0x3FFFF)
|
||||
#define SC64_SD_DMA_LEN_GET(len) (((len) & 0x7FFF) * 4)
|
||||
|
||||
#define SC64_SD_DMA_LEN(l) ((((l) / 4) - 1) & 0x7FFF)
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
#define SD_BLOCK_SIZE (512)
|
||||
|
||||
#define MAX_NUM_BLOCKS (256)
|
||||
|
||||
|
||||
typedef enum sc64_sd_clock_e {
|
||||
CLOCK_STOP,
|
||||
@ -86,6 +88,7 @@ static void sc64_sd_set_dat_width(sc64_sd_dat_width_t dat_width) {
|
||||
static void sc64_sd_hw_init(void) {
|
||||
sc64_enable_sd();
|
||||
|
||||
while (platform_pi_io_read(&SC64_SD->CMD) & SC64_SD_CMD_BUSY);
|
||||
platform_pi_io_write(&SC64_SD->DMA_SCR, SC64_SD_DMA_SCR_STOP);
|
||||
platform_pi_io_write(&SC64_SD->DAT, SC64_SD_DAT_TX_FIFO_FLUSH | SC64_SD_DAT_RX_FIFO_FLUSH | SC64_SD_DAT_STOP);
|
||||
platform_pi_io_write(&SC64_SD->SCR, 0);
|
||||
@ -156,7 +159,7 @@ static void sc64_sd_dat_prepare(size_t num_blocks, size_t block_size, sc64_sd_da
|
||||
platform_pi_io_write(&SC64_SD->DAT, (
|
||||
SC64_SD_DAT_NUM_BLOCKS(num_blocks) |
|
||||
SC64_SD_DAT_BLOCK_SIZE(block_size) |
|
||||
(direction ? SC64_SD_DAT_DIRECTION : 0) |
|
||||
((direction == DAT_DIR_TX) ? SC64_SD_DAT_DIRECTION : 0) |
|
||||
SC64_SD_DAT_START
|
||||
));
|
||||
}
|
||||
@ -179,7 +182,7 @@ static sc64_sd_err_t sc64_sd_dat_read(size_t block_size, void *buffer) {
|
||||
if (SC64_SD_DAT_RX_FIFO_ITEMS_GET(reg) >= block_size) {
|
||||
break;
|
||||
}
|
||||
} while ((reg & SC64_SD_DAT_BUSY) && (timeout--));
|
||||
} while ((reg & SC64_SD_DAT_BUSY) && (--timeout));
|
||||
|
||||
if (reg & SC64_SD_DAT_CRC_ERROR) {
|
||||
return E_CRC_ERROR;
|
||||
@ -350,7 +353,7 @@ sc64_sd_err_t sc64_sd_read_sectors(uint32_t starting_sector, size_t count, void
|
||||
timeout = 100000;
|
||||
do {
|
||||
reg = platform_pi_io_read(&SC64_SD->DAT);
|
||||
} while ((reg & SC64_SD_DAT_BUSY) && (timeout--));
|
||||
} while ((reg & SC64_SD_DAT_BUSY) && (--timeout));
|
||||
|
||||
if (reg & SC64_SD_DAT_CRC_ERROR) {
|
||||
return E_CRC_ERROR;
|
||||
@ -404,7 +407,7 @@ sc64_sd_err_t sc64_sd_read_sectors_dma(uint32_t starting_sector, size_t count, u
|
||||
current_address = address;
|
||||
|
||||
do {
|
||||
num_blocks = (sectors_left > 2048) ? 2048 : sectors_left;
|
||||
num_blocks = (sectors_left > MAX_NUM_BLOCKS) ? MAX_NUM_BLOCKS : sectors_left;
|
||||
|
||||
platform_pi_io_write(&SC64_SD->DMA_ADDR, SC64_SD_DMA_BANK_ADDR(bank, current_address));
|
||||
platform_pi_io_write(&SC64_SD->DMA_LEN, SC64_SD_DMA_LEN(num_blocks * SD_BLOCK_SIZE));
|
||||
@ -421,7 +424,7 @@ sc64_sd_err_t sc64_sd_read_sectors_dma(uint32_t starting_sector, size_t count, u
|
||||
timeout = 1000000;
|
||||
do {
|
||||
reg = platform_pi_io_read(&SC64_SD->DAT);
|
||||
} while ((reg & SC64_SD_DAT_BUSY) && (timeout--));
|
||||
} while ((reg & SC64_SD_DAT_BUSY) && (--timeout));
|
||||
|
||||
error = sc64_sd_cmd_send(12, 0, NO_FLAGS, &response);
|
||||
if (error != E_OK) {
|
||||
|
Loading…
Reference in New Issue
Block a user