From 59491be835c767870b5138076997dd40a31b821f Mon Sep 17 00:00:00 2001 From: Polprzewodnikowy Date: Tue, 9 Feb 2021 23:58:02 +0100 Subject: [PATCH] boot screen --- fw/SummerCart64.qsf | 2 +- fw/rtl/sd/sd_dat.v | 8 +- fw/rtl/sd/sd_dma.v | 97 ++++++++------- fw/rtl/sd/sd_fifo.v | 24 ++-- fw/rtl/sd/sd_interface.v | 25 ++-- fw/rtl/sd/sd_regs.v | 111 ++++++++++-------- sw/bootloader/Makefile | 77 ++++++------ sw/bootloader/README.md | 4 - sw/bootloader/build.sh | 9 +- sw/bootloader/src/assets/assets.h | 12 ++ sw/bootloader/src/assets/sc64_logo.png | Bin 0 -> 8552 bytes sw/bootloader/src/boot/boot.c | 17 +-- sw/bootloader/src/boot/boot.h | 12 -- sw/bootloader/src/error_display.c | 45 ------- .../src/{error_display.h => errors.h} | 11 +- sw/bootloader/src/fatfs/diskio.c | 8 ++ sw/bootloader/src/fatfs/ffconf.h | 2 +- sw/bootloader/src/loader/loader.c | 106 +++++++++++++++++ sw/bootloader/src/loader/loader.h | 13 ++ sw/bootloader/src/main.c | 17 +-- sw/bootloader/src/platform.h | 4 - sw/bootloader/src/sc64/sc64_regs.h | 53 +++++---- sw/bootloader/src/sc64/sc64_sd.c | 13 +- 23 files changed, 406 insertions(+), 264 deletions(-) create mode 100644 sw/bootloader/src/assets/assets.h create mode 100644 sw/bootloader/src/assets/sc64_logo.png delete mode 100644 sw/bootloader/src/error_display.c rename sw/bootloader/src/{error_display.h => errors.h} (62%) create mode 100644 sw/bootloader/src/loader/loader.c create mode 100644 sw/bootloader/src/loader/loader.h diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index af94a2b..283c21f 100644 --- a/fw/SummerCart64.qsf +++ b/fw/SummerCart64.qsf @@ -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 # ================================ diff --git a/fw/rtl/sd/sd_dat.v b/fw/rtl/sd/sd_dat.v index 00ddbb9..a6998c3 100644 --- a/fw/rtl/sd/sd_dat.v +++ b/fw/rtl/sd/sd_dat.v @@ -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 diff --git a/fw/rtl/sd/sd_dma.v b/fw/rtl/sd/sd_dma.v index 64167ad..378be8e 100644 --- a/fw/rtl/sd/sd_dma.v +++ b/fw/rtl/sd/sd_dma.v @@ -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 diff --git a/fw/rtl/sd/sd_fifo.v b/fw/rtl/sd/sd_fifo.v index 8b4606a..a5da5e3 100644 --- a/fw/rtl/sd/sd_fifo.v +++ b/fw/rtl/sd/sd_fifo.v @@ -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 diff --git a/fw/rtl/sd/sd_interface.v b/fw/rtl/sd/sd_interface.v index ac2d622..07f5478 100644 --- a/fw/rtl/sd/sd_interface.v +++ b/fw/rtl/sd/sd_interface.v @@ -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), diff --git a/fw/rtl/sd/sd_regs.v b/fw/rtl/sd/sd_regs.v index 4ae4434..095c13c 100644 --- a/fw/rtl/sd/sd_regs.v +++ b/fw/rtl/sd/sd_regs.v @@ -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 diff --git a/sw/bootloader/Makefile b/sw/bootloader/Makefile index dd54c9d..e217e80 100644 --- a/sw/bootloader/Makefile +++ b/sw/bootloader/Makefile @@ -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 diff --git a/sw/bootloader/README.md b/sw/bootloader/README.md index d034c11..bc293c9 100644 --- a/sw/bootloader/README.md +++ b/sw/bootloader/README.md @@ -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 diff --git a/sw/bootloader/build.sh b/sw/bootloader/build.sh index b3af794..a85afa5 100644 --- a/sw/bootloader/build.sh +++ b/sw/bootloader/build.sh @@ -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" diff --git a/sw/bootloader/src/assets/assets.h b/sw/bootloader/src/assets/assets.h new file mode 100644 index 0000000..0b133ca --- /dev/null +++ b/sw/bootloader/src/assets/assets.h @@ -0,0 +1,12 @@ +#ifndef ASSETS_H__ +#define ASSETS_H__ + + +#include + + +extern sprite_t _binary_build_sc64_logo_sprite_start[]; +extern sprite_t _binary_build_sc64_logo_sprite_end[]; + + +#endif diff --git a/sw/bootloader/src/assets/sc64_logo.png b/sw/bootloader/src/assets/sc64_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..f326e9d40b51a636669a42b644288b41d46c772b GIT binary patch literal 8552 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

axibUS%lxW{Y+Q~n6Sp1pZY`4 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 : 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" diff --git a/sw/bootloader/src/boot/boot.h b/sw/bootloader/src/boot/boot.h index aa2232d..36a202d 100644 --- a/sw/bootloader/src/boot/boot.h +++ b/sw/bootloader/src/boot/boot.h @@ -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; diff --git a/sw/bootloader/src/error_display.c b/sw/bootloader/src/error_display.c deleted file mode 100644 index 0efe673..0000000 --- a/sw/bootloader/src/error_display.c +++ /dev/null @@ -1,45 +0,0 @@ -#include - -#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); -} diff --git a/sw/bootloader/src/error_display.h b/sw/bootloader/src/errors.h similarity index 62% rename from sw/bootloader/src/error_display.h rename to sw/bootloader/src/errors.h index b0f83e4..acf3bd1 100644 --- a/sw/bootloader/src/error_display.h +++ b/sw/bootloader/src/errors.h @@ -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 diff --git a/sw/bootloader/src/fatfs/diskio.c b/sw/bootloader/src/fatfs/diskio.c index ca2fd7c..ed38e4e 100644 --- a/sw/bootloader/src/fatfs/diskio.c +++ b/sw/bootloader/src/fatfs/diskio.c @@ -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; } diff --git a/sw/bootloader/src/fatfs/ffconf.h b/sw/bootloader/src/fatfs/ffconf.h index d0f6502..bb5a6e0 100644 --- a/sw/bootloader/src/fatfs/ffconf.h +++ b/sw/bootloader/src/fatfs/ffconf.h @@ -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() diff --git a/sw/bootloader/src/loader/loader.c b/sw/bootloader/src/loader/loader.c new file mode 100644 index 0000000..fe1df90 --- /dev/null +++ b/sw/bootloader/src/loader/loader.c @@ -0,0 +1,106 @@ +#include + +#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); +} diff --git a/sw/bootloader/src/loader/loader.h b/sw/bootloader/src/loader/loader.h new file mode 100644 index 0000000..1379526 --- /dev/null +++ b/sw/bootloader/src/loader/loader.h @@ -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 diff --git a/sw/bootloader/src/main.c b/sw/bootloader/src/main.c index d6a57bc..dc84e9d 100644 --- a/sw/bootloader/src/main.c +++ b/sw/bootloader/src/main.c @@ -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); } diff --git a/sw/bootloader/src/platform.h b/sw/bootloader/src/platform.h index 2982734..c2a8333 100644 --- a/sw/bootloader/src/platform.h +++ b/sw/bootloader/src/platform.h @@ -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; diff --git a/sw/bootloader/src/sc64/sc64_regs.h b/sw/bootloader/src/sc64/sc64_regs.h index 399bb64..98869c0 100644 --- a/sw/bootloader/src/sc64/sc64_regs.h +++ b/sw/bootloader/src/sc64/sc64_regs.h @@ -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 diff --git a/sw/bootloader/src/sc64/sc64_sd.c b/sw/bootloader/src/sc64/sc64_sd.c index a8ae0ca..40944f2 100644 --- a/sw/bootloader/src/sc64/sc64_sd.c +++ b/sw/bootloader/src/sc64/sc64_sd.c @@ -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) {