mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-21 21:49:15 +01:00
[SC64][FW][SW] SD card byte swap on reads support (#39)
And other bug fixes related to DMA write mask
This commit is contained in:
parent
8c7f97b433
commit
c4f6a0d555
2
build.sh
2
build.sh
@ -8,6 +8,7 @@ PACKAGE_FILE_NAME="sc64-extra"
|
|||||||
|
|
||||||
TOP_FILES=(
|
TOP_FILES=(
|
||||||
"./fw/ftdi/ft232h_config.xml"
|
"./fw/ftdi/ft232h_config.xml"
|
||||||
|
"./fw/project/lcmxo2/impl1/fpga_max_frequency.txt"
|
||||||
"./sw/tools/primer.py"
|
"./sw/tools/primer.py"
|
||||||
"./sw/tools/requirements.txt"
|
"./sw/tools/requirements.txt"
|
||||||
"./sc64-firmware-${SC64_VERSION}.bin"
|
"./sc64-firmware-${SC64_VERSION}.bin"
|
||||||
@ -90,6 +91,7 @@ build_update () {
|
|||||||
rm -f ../../sc64-firmware-*.bin
|
rm -f ../../sc64-firmware-*.bin
|
||||||
fi
|
fi
|
||||||
GIT_INFO=""
|
GIT_INFO=""
|
||||||
|
GIT_INFO+=$'\n'"freq: $(cat ../../fw/project/lcmxo2/impl1/fpga_max_frequency.txt)"
|
||||||
if [ ! -z "${SC64_VERSION}" ]; then GIT_INFO+=$'\n'"ver: $SC64_VERSION"; fi
|
if [ ! -z "${SC64_VERSION}" ]; then GIT_INFO+=$'\n'"ver: $SC64_VERSION"; fi
|
||||||
if [ ! -z "${GIT_BRANCH}" ]; then GIT_INFO+=$'\n'"branch: $GIT_BRANCH"; fi
|
if [ ! -z "${GIT_BRANCH}" ]; then GIT_INFO+=$'\n'"branch: $GIT_BRANCH"; fi
|
||||||
if [ ! -z "${GIT_TAG}" ]; then GIT_INFO+=$'\n'"tag: $GIT_TAG"; fi
|
if [ ! -z "${GIT_TAG}" ]; then GIT_INFO+=$'\n'"tag: $GIT_TAG"; fi
|
||||||
|
@ -4,26 +4,27 @@
|
|||||||
|
|
||||||
## N64 commands
|
## N64 commands
|
||||||
|
|
||||||
| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
|
| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
|
||||||
| --- | --------------------- | ---------- | ------------ | ---------------- | -------------- | -------------------------------------------------- |
|
| --- | --------------------- | -------------- | ------------ | ---------------- | -------------- | ---------------------------------------------------------- |
|
||||||
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
|
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
|
||||||
| `V` | **VERSION_GET** | --- | --- | version | --- | Get flashcart firmware version |
|
| `V` | **VERSION_GET** | --- | --- | version | --- | Get flashcart firmware version |
|
||||||
| `c` | **CONFIG_GET** | config_id | --- | --- | current_value | Get config option |
|
| `c` | **CONFIG_GET** | config_id | --- | --- | current_value | Get config option |
|
||||||
| `C` | **CONFIG_SET** | config_id | new_value | --- | previous_value | Set config option and get previous value |
|
| `C` | **CONFIG_SET** | config_id | new_value | --- | previous_value | Set config option and get previous value |
|
||||||
| `c` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
|
| `c` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
|
||||||
| `C` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting option |
|
| `C` | **SETTING_SET** | setting_id | new_value | --- | --- | Set persistent setting option |
|
||||||
| `t` | **TIME_GET** | --- | --- | time_0 | time_1 | Get current RTC value |
|
| `t` | **TIME_GET** | --- | --- | time_0 | time_1 | Get current RTC value |
|
||||||
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set new RTC value |
|
| `T` | **TIME_SET** | time_0 | time_1 | --- | --- | Set new RTC value |
|
||||||
| `m` | **USB_READ** | pi_address | length | --- | --- | Receive data from USB to flashcart |
|
| `m` | **USB_READ** | pi_address | length | --- | --- | Receive data from USB to flashcart |
|
||||||
| `M` | **USB_WRITE** | pi_address | length/type | --- | --- | Send data from from flashcart to USB |
|
| `M` | **USB_WRITE** | pi_address | length/type | --- | --- | Send data from from flashcart to USB |
|
||||||
| `u` | **USB_READ_STATUS** | --- | --- | read_status/type | length | Get USB read status and type/length |
|
| `u` | **USB_READ_STATUS** | --- | --- | read_status/type | length | Get USB read status and type/length |
|
||||||
| `U` | **USB_WRITE_STATUS** | --- | --- | write_status | --- | Get USB write status |
|
| `U` | **USB_WRITE_STATUS** | --- | --- | write_status | --- | Get USB write status |
|
||||||
| `i` | **SD_CARD_OP** | pi_address | operation | --- | return_data | Perform special operation on SD card |
|
| `i` | **SD_CARD_OP** | pi_address | operation | --- | return_data | Perform special operation on SD card |
|
||||||
| `I` | **SD_SECTOR_SET** | sector | --- | --- | --- | Set starting sector for next SD card R/W operation |
|
| `I` | **SD_SECTOR_SET** | sector | --- | --- | --- | Set starting sector for next SD card R/W operation |
|
||||||
| `s` | **SD_READ** | pi_address | sector_count | --- | --- | Read sectors from SD card to flashcart |
|
| `s` | **SD_READ** | pi_address | sector_count | --- | --- | Read sectors from SD card to flashcart |
|
||||||
| `S` | **SD_WRITE** | pi_address | sector_count | --- | --- | Write sectors from flashcart to SD card |
|
| `S` | **SD_WRITE** | pi_address | sector_count | --- | --- | Write sectors from flashcart to SD card |
|
||||||
| `D` | **DD_SD_INFO** | pi_address | table_size | --- | --- | Set 64DD disk SD sector info |
|
| `D` | **DD_SD_INFO** | pi_address | table_size | --- | --- | Set 64DD disk SD sector info |
|
||||||
| `W` | **WRITEBACK_SD_INFO** | pi_address | --- | --- | --- | Load writeback SD sector table and enable it |
|
| `w` | **WRITEBACK_PENDING** | pending_status | --- | --- | --- | Get save writeback status (is write queued to the SD card) |
|
||||||
| `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |
|
| `W` | **WRITEBACK_SD_INFO** | pi_address | --- | --- | --- | Load writeback SD sector table and enable it |
|
||||||
| `p` | **FLASH_WAIT_BUSY** | wait | --- | erase_block_size | --- | Wait until flash ready / get block erase size |
|
| `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |
|
||||||
| `P` | **FLASH_ERASE_BLOCK** | pi_address | --- | --- | --- | Start flash block erase |
|
| `p` | **FLASH_WAIT_BUSY** | wait | --- | erase_block_size | --- | Wait until flash ready / get block erase size |
|
||||||
|
| `P` | **FLASH_ERASE_BLOCK** | pi_address | --- | --- | --- | Start flash block erase |
|
||||||
|
@ -1,5 +1,31 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
source $bindir/diamond_env
|
source $bindir/diamond_env
|
||||||
|
|
||||||
diamondc build.tcl
|
diamondc build.tcl
|
||||||
|
|
||||||
|
MINIMUM_FREQ=$(cat impl1/sc64_impl1.twr \
|
||||||
|
| grep 'Preference: FREQUENCY NET "clk"' \
|
||||||
|
| head -1 \
|
||||||
|
| awk -F ' ' '{print $5}' \
|
||||||
|
)
|
||||||
|
|
||||||
|
DESIGN_FREQ=$(cat impl1/sc64_impl1.twr \
|
||||||
|
| sed -n '/Preference: FREQUENCY NET "clk"/,$p' \
|
||||||
|
| grep 'is the maximum frequency for this preference' \
|
||||||
|
| head -1 \
|
||||||
|
| awk -F ' ' '{print $2}' \
|
||||||
|
| sed 's/MHz//' \
|
||||||
|
)
|
||||||
|
|
||||||
|
echo "Minimum required frequency: $MINIMUM_FREQ MHz"
|
||||||
|
echo "Maximum design frequency: $DESIGN_FREQ MHz"
|
||||||
|
|
||||||
|
if (( $(echo "$DESIGN_FREQ < $MINIMUM_FREQ" | bc -l) )); then
|
||||||
|
echo "Timing error detected, build failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -n "$DESIGN_FREQ MHz" > impl1/fpga_max_frequency.txt
|
||||||
|
@ -21,8 +21,10 @@ IOBUF PORT "inclk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
|||||||
IOBUF PORT "mcu_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "mcu_clk" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "mcu_cs" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "mcu_cs" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "mcu_int" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "mcu_int" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "mcu_miso" IO_TYPE=LVCMOS33 PULLMODE=NONE ;
|
IOBUF PORT "mcu_miso" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "mcu_mosi" IO_TYPE=LVCMOS33 PULLMODE=NONE ;
|
IOBUF PORT "mcu_mosi" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "n64_cic_clk" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "n64_cic_dq" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "n64_irq" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "n64_irq" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "n64_nmi" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "n64_nmi" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "n64_pi_ad[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "n64_pi_ad[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
@ -48,6 +50,7 @@ IOBUF PORT "n64_pi_write" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
|||||||
IOBUF PORT "n64_reset" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "n64_reset" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "n64_si_clk" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "n64_si_clk" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "n64_si_dq" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "n64_si_dq" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
|
IOBUF PORT "n64_video_sync" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "sd_clk" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "sd_clk" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "sd_cmd" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "sd_cmd" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
IOBUF PORT "sd_dat[0]" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
IOBUF PORT "sd_dat[0]" PULLMODE=UP IO_TYPE=LVCMOS33 ;
|
||||||
@ -120,6 +123,8 @@ LOCATE COMP "mcu_miso" SITE "119" ;
|
|||||||
LOCATE COMP "mcu_mosi" SITE "120" ;
|
LOCATE COMP "mcu_mosi" SITE "120" ;
|
||||||
LOCATE COMP "n64_irq" SITE "32" ;
|
LOCATE COMP "n64_irq" SITE "32" ;
|
||||||
LOCATE COMP "n64_nmi" SITE "28" ;
|
LOCATE COMP "n64_nmi" SITE "28" ;
|
||||||
|
LOCATE COMP "n64_cic_clk" SITE "34" ;
|
||||||
|
LOCATE COMP "n64_cic_dq" SITE "35" ;
|
||||||
LOCATE COMP "n64_pi_ad[0]" SITE "60" ;
|
LOCATE COMP "n64_pi_ad[0]" SITE "60" ;
|
||||||
LOCATE COMP "n64_pi_ad[1]" SITE "58" ;
|
LOCATE COMP "n64_pi_ad[1]" SITE "58" ;
|
||||||
LOCATE COMP "n64_pi_ad[10]" SITE "42" ;
|
LOCATE COMP "n64_pi_ad[10]" SITE "42" ;
|
||||||
@ -143,6 +148,7 @@ LOCATE COMP "n64_pi_write" SITE "49" ;
|
|||||||
LOCATE COMP "n64_reset" SITE "31" ;
|
LOCATE COMP "n64_reset" SITE "31" ;
|
||||||
LOCATE COMP "n64_si_clk" SITE "33" ;
|
LOCATE COMP "n64_si_clk" SITE "33" ;
|
||||||
LOCATE COMP "n64_si_dq" SITE "27" ;
|
LOCATE COMP "n64_si_dq" SITE "27" ;
|
||||||
|
LOCATE COMP "n64_video_sync" SITE "26" ;
|
||||||
LOCATE COMP "sd_clk" SITE "111" ;
|
LOCATE COMP "sd_clk" SITE "111" ;
|
||||||
LOCATE COMP "sd_cmd" SITE "112" ;
|
LOCATE COMP "sd_cmd" SITE "112" ;
|
||||||
LOCATE COMP "sd_dat[0]" SITE "110" ;
|
LOCATE COMP "sd_dat[0]" SITE "110" ;
|
||||||
|
@ -364,6 +364,7 @@ module mcu_top (
|
|||||||
logic bootloader_skip;
|
logic bootloader_skip;
|
||||||
|
|
||||||
assign n64_scb.cfg_identifier = 32'h53437632;
|
assign n64_scb.cfg_identifier = 32'h53437632;
|
||||||
|
assign usb_dma_scb.byte_swap = 1'b0;
|
||||||
|
|
||||||
logic dd_bm_ack;
|
logic dd_bm_ack;
|
||||||
|
|
||||||
@ -577,7 +578,8 @@ module mcu_top (
|
|||||||
|
|
||||||
REG_SD_DMA_SCR: begin
|
REG_SD_DMA_SCR: begin
|
||||||
reg_rdata <= {
|
reg_rdata <= {
|
||||||
28'd0,
|
27'd0,
|
||||||
|
sd_dma_scb.byte_swap,
|
||||||
sd_dma_scb.busy,
|
sd_dma_scb.busy,
|
||||||
sd_dma_scb.direction,
|
sd_dma_scb.direction,
|
||||||
2'b00
|
2'b00
|
||||||
@ -855,11 +857,10 @@ module mcu_top (
|
|||||||
end
|
end
|
||||||
|
|
||||||
REG_SD_DMA_SCR: begin
|
REG_SD_DMA_SCR: begin
|
||||||
{
|
sd_dma_scb.byte_swap <= reg_wdata[4];
|
||||||
sd_dma_scb.direction,
|
sd_dma_scb.direction <= reg_wdata[2];
|
||||||
sd_dma_scb.stop,
|
sd_dma_scb.stop <= reg_wdata[1];
|
||||||
sd_dma_scb.start
|
sd_dma_scb.start <= reg_wdata[0];
|
||||||
} <= reg_wdata[2:0];
|
|
||||||
end
|
end
|
||||||
|
|
||||||
REG_DD_SCR: begin
|
REG_DD_SCR: begin
|
||||||
|
@ -4,6 +4,7 @@ interface dma_scb ();
|
|||||||
logic stop;
|
logic stop;
|
||||||
logic busy;
|
logic busy;
|
||||||
logic direction;
|
logic direction;
|
||||||
|
logic byte_swap;
|
||||||
logic [26:0] starting_address;
|
logic [26:0] starting_address;
|
||||||
logic [26:0] transfer_length;
|
logic [26:0] transfer_length;
|
||||||
|
|
||||||
@ -12,6 +13,7 @@ interface dma_scb ();
|
|||||||
output stop,
|
output stop,
|
||||||
input busy,
|
input busy,
|
||||||
output direction,
|
output direction,
|
||||||
|
output byte_swap,
|
||||||
output starting_address,
|
output starting_address,
|
||||||
output transfer_length
|
output transfer_length
|
||||||
);
|
);
|
||||||
@ -21,6 +23,7 @@ interface dma_scb ();
|
|||||||
input stop,
|
input stop,
|
||||||
output busy,
|
output busy,
|
||||||
input direction,
|
input direction,
|
||||||
|
input byte_swap,
|
||||||
input starting_address,
|
input starting_address,
|
||||||
input transfer_length
|
input transfer_length
|
||||||
);
|
);
|
||||||
@ -61,6 +64,7 @@ module memory_dma (
|
|||||||
|
|
||||||
// RX FIFO controller
|
// RX FIFO controller
|
||||||
|
|
||||||
|
logic [1:0] rx_wmask;
|
||||||
logic rx_rdata_pop;
|
logic rx_rdata_pop;
|
||||||
logic rx_rdata_shift;
|
logic rx_rdata_shift;
|
||||||
logic rx_rdata_valid;
|
logic rx_rdata_valid;
|
||||||
@ -88,11 +92,11 @@ module memory_dma (
|
|||||||
|
|
||||||
if (dma_start) begin
|
if (dma_start) begin
|
||||||
if (dma_scb.starting_address[0]) begin
|
if (dma_scb.starting_address[0]) begin
|
||||||
mem_bus.wmask <= 2'b01;
|
rx_wmask <= 2'b01;
|
||||||
rx_buffer_counter <= 2'd1;
|
rx_buffer_counter <= 2'd1;
|
||||||
rx_buffer_valid_counter <= 2'd1;
|
rx_buffer_valid_counter <= 2'd1;
|
||||||
end else begin
|
end else begin
|
||||||
mem_bus.wmask <= 2'b11;
|
rx_wmask <= 2'b11;
|
||||||
rx_buffer_counter <= 2'd0;
|
rx_buffer_counter <= 2'd0;
|
||||||
rx_buffer_valid_counter <= 2'd0;
|
rx_buffer_valid_counter <= 2'd0;
|
||||||
end
|
end
|
||||||
@ -103,16 +107,21 @@ module memory_dma (
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (rx_rdata_shift || rx_rdata_valid) begin
|
if (rx_rdata_shift || rx_rdata_valid) begin
|
||||||
rx_buffer <= {rx_buffer[7:0], fifo_bus.rx_rdata};
|
if (dma_scb.byte_swap) begin
|
||||||
|
rx_buffer <= {fifo_bus.rx_rdata, rx_buffer[15:8]};
|
||||||
|
end else begin
|
||||||
|
rx_buffer <= {rx_buffer[7:0], fifo_bus.rx_rdata};
|
||||||
|
end
|
||||||
rx_buffer_valid_counter <= rx_buffer_valid_counter + 1'd1;
|
rx_buffer_valid_counter <= rx_buffer_valid_counter + 1'd1;
|
||||||
if (remaining == 27'd0 && rx_buffer_counter == 2'd1) begin
|
if (remaining == 27'd0 && rx_buffer_counter == 2'd1) begin
|
||||||
mem_bus.wmask <= 2'b10;
|
rx_wmask <= 2'b10;
|
||||||
rx_rdata_shift <= 1'b1;
|
rx_rdata_shift <= 1'b1;
|
||||||
rx_buffer_counter <= rx_buffer_counter + 1'd1;
|
rx_buffer_counter <= rx_buffer_counter + 1'd1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if (rx_buffer_valid && !mem_bus.request) begin
|
if (rx_buffer_valid && !mem_bus.request) begin
|
||||||
|
rx_wmask <= 2'b11;
|
||||||
rx_buffer_counter <= 2'd0;
|
rx_buffer_counter <= 2'd0;
|
||||||
rx_buffer_valid_counter <= 2'd0;
|
rx_buffer_valid_counter <= 2'd0;
|
||||||
end
|
end
|
||||||
@ -209,6 +218,7 @@ module memory_dma (
|
|||||||
if (mem_bus.write) begin
|
if (mem_bus.write) begin
|
||||||
if (rx_buffer_valid) begin
|
if (rx_buffer_valid) begin
|
||||||
mem_bus.request <= 1'b1;
|
mem_bus.request <= 1'b1;
|
||||||
|
mem_bus.wmask <= rx_wmask;
|
||||||
mem_bus.wdata <= rx_buffer;
|
mem_bus.wdata <= rx_buffer;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
|
@ -45,7 +45,12 @@ module top (
|
|||||||
input mcu_clk,
|
input mcu_clk,
|
||||||
input mcu_cs,
|
input mcu_cs,
|
||||||
input mcu_mosi,
|
input mcu_mosi,
|
||||||
output mcu_miso
|
output mcu_miso,
|
||||||
|
|
||||||
|
// Unused I/O
|
||||||
|
output n64_cic_clk,
|
||||||
|
output n64_cic_dq,
|
||||||
|
output n64_video_sync
|
||||||
);
|
);
|
||||||
|
|
||||||
logic clk;
|
logic clk;
|
||||||
@ -264,4 +269,11 @@ module top (
|
|||||||
.vendor_scb(vendor_scb)
|
.vendor_scb(vendor_scb)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Unused I/O
|
||||||
|
|
||||||
|
assign n64_cic_clk = 1'bZ;
|
||||||
|
assign n64_cic_dq = 1'bZ;
|
||||||
|
assign n64_video_sync = 1'bZ;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -52,6 +52,8 @@ typedef enum {
|
|||||||
SD_CARD_OP_INIT = 1,
|
SD_CARD_OP_INIT = 1,
|
||||||
SD_CARD_OP_GET_STATUS = 2,
|
SD_CARD_OP_GET_STATUS = 2,
|
||||||
SD_CARD_OP_GET_INFO = 3,
|
SD_CARD_OP_GET_INFO = 3,
|
||||||
|
SD_CARD_OP_BYTE_SWAP_ON = 4,
|
||||||
|
SD_CARD_OP_BYTE_SWAP_OFF = 5,
|
||||||
} sd_card_op_t;
|
} sd_card_op_t;
|
||||||
|
|
||||||
|
|
||||||
@ -235,6 +237,14 @@ bool sc64_sd_card_get_info (void *address) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sc64_sd_set_byte_swap (bool enabled) {
|
||||||
|
uint32_t args[2] = { (uint32_t) (NULL), enabled ? SD_CARD_OP_BYTE_SWAP_ON : SD_CARD_OP_BYTE_SWAP_OFF };
|
||||||
|
if (sc64_execute_cmd(SC64_CMD_SD_CARD_OP, args, NULL)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count) {
|
bool sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count) {
|
||||||
uint32_t sector_set_args[2] = { sector, 0 };
|
uint32_t sector_set_args[2] = { sector, 0 };
|
||||||
uint32_t read_args[2] = { (uint32_t) (address), count };
|
uint32_t read_args[2] = { (uint32_t) (address), count };
|
||||||
|
@ -86,6 +86,7 @@ typedef enum {
|
|||||||
SD_CARD_STATUS_INITIALIZED = (1 << 1),
|
SD_CARD_STATUS_INITIALIZED = (1 << 1),
|
||||||
SD_CARD_STATUS_TYPE_BLOCK = (1 << 2),
|
SD_CARD_STATUS_TYPE_BLOCK = (1 << 2),
|
||||||
SD_CARD_STATUS_50MHZ_MODE = (1 << 3),
|
SD_CARD_STATUS_50MHZ_MODE = (1 << 3),
|
||||||
|
SD_CARD_STATUS_BYTE_SWAP = (1 << 4),
|
||||||
} sc64_sd_card_status_t;
|
} sc64_sd_card_status_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -143,6 +144,7 @@ bool sc64_sd_card_init (void);
|
|||||||
bool sc64_sd_card_deinit (void);
|
bool sc64_sd_card_deinit (void);
|
||||||
sc64_sd_card_status_t sc64_sd_card_get_status (void);
|
sc64_sd_card_status_t sc64_sd_card_get_status (void);
|
||||||
bool sc64_sd_card_get_info (void *address);
|
bool sc64_sd_card_get_info (void *address);
|
||||||
|
bool sc64_sd_set_byte_swap (bool enabled);
|
||||||
bool sc64_sd_write_sectors (void *address, uint32_t sector, uint32_t count);
|
bool sc64_sd_write_sectors (void *address, uint32_t sector, uint32_t count);
|
||||||
bool sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count);
|
bool sc64_sd_read_sectors (void *address, uint32_t sector, uint32_t count);
|
||||||
bool sc64_dd_set_sd_disk_info (void *address, uint32_t length);
|
bool sc64_dd_set_sd_disk_info (void *address, uint32_t length);
|
||||||
|
@ -57,6 +57,9 @@ static void test_sd_card (void) {
|
|||||||
if (card_status & SD_CARD_STATUS_50MHZ_MODE) {
|
if (card_status & SD_CARD_STATUS_50MHZ_MODE) {
|
||||||
display_printf("SD card runs at 50 MHz clock speed\n");
|
display_printf("SD card runs at 50 MHz clock speed\n");
|
||||||
}
|
}
|
||||||
|
if (card_status & SD_CARD_STATUS_BYTE_SWAP) {
|
||||||
|
display_printf("SD card read byte swap is enabled\n");
|
||||||
|
}
|
||||||
|
|
||||||
if (sc64_sd_card_get_info((uint32_t *) (SC64_BUFFERS->BUFFER))) {
|
if (sc64_sd_card_get_info((uint32_t *) (SC64_BUFFERS->BUFFER))) {
|
||||||
display_printf("SD card get info error!\n");
|
display_printf("SD card get info error!\n");
|
||||||
|
@ -79,6 +79,8 @@ typedef enum {
|
|||||||
SD_CARD_OP_INIT = 1,
|
SD_CARD_OP_INIT = 1,
|
||||||
SD_CARD_OP_GET_STATUS = 2,
|
SD_CARD_OP_GET_STATUS = 2,
|
||||||
SD_CARD_OP_GET_INFO = 3,
|
SD_CARD_OP_GET_INFO = 3,
|
||||||
|
SD_CARD_OP_BYTE_SWAP_ON = 4,
|
||||||
|
SD_CARD_OP_BYTE_SWAP_OFF = 5,
|
||||||
} sd_card_op_t;
|
} sd_card_op_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -176,7 +178,7 @@ static void cfg_change_scr_bits (uint32_t mask, bool value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool cfg_set_save_type (save_type_t save_type) {
|
static bool cfg_set_save_type (save_type_t save_type) {
|
||||||
if (save_type > SAVE_TYPE_SRAM_BANKED) {
|
if (save_type > SAVE_TYPE_SRAM_1M) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,6 +577,18 @@ void cfg_process (void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SD_CARD_OP_BYTE_SWAP_ON:
|
||||||
|
if (sd_set_byte_swap(true)) {
|
||||||
|
cfg_set_error(CFG_ERROR_SD_CARD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SD_CARD_OP_BYTE_SWAP_OFF:
|
||||||
|
if (sd_set_byte_swap(false)) {
|
||||||
|
cfg_set_error(CFG_ERROR_SD_CARD);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
|
cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
|
||||||
return;
|
return;
|
||||||
@ -625,6 +639,10 @@ void cfg_process (void) {
|
|||||||
dd_set_sd_info(args[0], args[1]);
|
dd_set_sd_info(args[0], args[1]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
args[0] = writeback_pending();
|
||||||
|
break;
|
||||||
|
|
||||||
case 'W':
|
case 'W':
|
||||||
if (cfg_translate_address(&args[0], WRITEBACK_SECTOR_TABLE_SIZE, (SDRAM | BRAM))) {
|
if (cfg_translate_address(&args[0], WRITEBACK_SECTOR_TABLE_SIZE, (SDRAM | BRAM))) {
|
||||||
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
|
||||||
|
@ -92,6 +92,7 @@ typedef enum {
|
|||||||
#define DMA_SCR_STOP (1 << 1)
|
#define DMA_SCR_STOP (1 << 1)
|
||||||
#define DMA_SCR_DIRECTION (1 << 2)
|
#define DMA_SCR_DIRECTION (1 << 2)
|
||||||
#define DMA_SCR_BUSY (1 << 3)
|
#define DMA_SCR_BUSY (1 << 3)
|
||||||
|
#define DMA_SCR_BYTE_SWAP (1 << 4)
|
||||||
|
|
||||||
#define CFG_SCR_BOOTLOADER_ENABLED (1 << 0)
|
#define CFG_SCR_BOOTLOADER_ENABLED (1 << 0)
|
||||||
#define CFG_SCR_BOOTLOADER_SKIP (1 << 1)
|
#define CFG_SCR_BOOTLOADER_SKIP (1 << 1)
|
||||||
|
@ -508,7 +508,7 @@ static void hw_init_crc (void) {
|
|||||||
|
|
||||||
static void hw_init_misc (void) {
|
static void hw_init_misc (void) {
|
||||||
hw_gpio_init(GPIO_ID_N64_RESET, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0);
|
hw_gpio_init(GPIO_ID_N64_RESET, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0);
|
||||||
hw_gpio_init(GPIO_ID_N64_CIC_CLK, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0);
|
hw_gpio_init(GPIO_ID_N64_CIC_CLK, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
||||||
hw_gpio_init(GPIO_ID_N64_CIC_DQ, GPIO_OUTPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 1);
|
hw_gpio_init(GPIO_ID_N64_CIC_DQ, GPIO_OUTPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 1);
|
||||||
hw_gpio_init(GPIO_ID_FPGA_INT, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
hw_gpio_init(GPIO_ID_FPGA_INT, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
||||||
hw_gpio_init(GPIO_ID_RTC_MFP, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
hw_gpio_init(GPIO_ID_RTC_MFP, GPIO_INPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define SD_INIT_BUFFER_ADDRESS (0x05002800UL)
|
#define SD_INIT_BUFFER_ADDRESS (0x05002800UL)
|
||||||
|
#define BYTE_SWAP_ADDRESS_END (0x05000000UL)
|
||||||
|
|
||||||
#define CMD6_ARG_CHECK_HS (0x00FFFFF1UL)
|
#define CMD6_ARG_CHECK_HS (0x00FFFFF1UL)
|
||||||
#define CMD6_ARG_SWITCH_HS (0x80FFFFF1UL)
|
#define CMD6_ARG_SWITCH_HS (0x80FFFFF1UL)
|
||||||
@ -67,6 +68,7 @@ struct process {
|
|||||||
uint8_t csd[16];
|
uint8_t csd[16];
|
||||||
uint8_t cid[16];
|
uint8_t cid[16];
|
||||||
volatile bool timeout;
|
volatile bool timeout;
|
||||||
|
bool byte_swap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -178,6 +180,9 @@ static void sd_dat_prepare (uint32_t address, uint32_t count, dat_mode_t mode) {
|
|||||||
if (mode == DAT_READ) {
|
if (mode == DAT_READ) {
|
||||||
sd_dat |= SD_DAT_START_READ;
|
sd_dat |= SD_DAT_START_READ;
|
||||||
sd_dma_scr |= DMA_SCR_DIRECTION;
|
sd_dma_scr |= DMA_SCR_DIRECTION;
|
||||||
|
if (p.byte_swap && (address < BYTE_SWAP_ADDRESS_END)) {
|
||||||
|
sd_dma_scr |= DMA_SCR_BYTE_SWAP;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
sd_dat |= SD_DAT_START_WRITE;
|
sd_dat |= SD_DAT_START_WRITE;
|
||||||
}
|
}
|
||||||
@ -217,6 +222,8 @@ bool sd_card_init (void) {
|
|||||||
uint32_t rsp;
|
uint32_t rsp;
|
||||||
uint16_t tmp;
|
uint16_t tmp;
|
||||||
|
|
||||||
|
p.byte_swap = false;
|
||||||
|
|
||||||
if (p.card_initialized) {
|
if (p.card_initialized) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -336,6 +343,7 @@ bool sd_card_init (void) {
|
|||||||
void sd_card_deinit (void) {
|
void sd_card_deinit (void) {
|
||||||
if (p.card_initialized) {
|
if (p.card_initialized) {
|
||||||
p.card_initialized = false;
|
p.card_initialized = false;
|
||||||
|
p.byte_swap = false;
|
||||||
sd_set_clock(CLOCK_400KHZ);
|
sd_set_clock(CLOCK_400KHZ);
|
||||||
sd_cmd(0, 0, RSP_NONE, NULL);
|
sd_cmd(0, 0, RSP_NONE, NULL);
|
||||||
sd_set_clock(CLOCK_STOP);
|
sd_set_clock(CLOCK_STOP);
|
||||||
@ -348,11 +356,13 @@ bool sd_card_is_inserted (void) {
|
|||||||
|
|
||||||
uint32_t sd_card_get_status (void) {
|
uint32_t sd_card_get_status (void) {
|
||||||
uint32_t scr = fpga_reg_get(REG_SD_SCR);
|
uint32_t scr = fpga_reg_get(REG_SD_SCR);
|
||||||
|
uint32_t byte_swap = p.byte_swap ? 1 : 0;
|
||||||
uint32_t clock_mode_50mhz = ((scr & SD_SCR_CLOCK_MODE_MASK) == SD_SCR_CLOCK_MODE_50MHZ) ? 1 : 0;
|
uint32_t clock_mode_50mhz = ((scr & SD_SCR_CLOCK_MODE_MASK) == SD_SCR_CLOCK_MODE_50MHZ) ? 1 : 0;
|
||||||
uint32_t card_type_block = p.card_type_block ? 1 : 0;
|
uint32_t card_type_block = p.card_type_block ? 1 : 0;
|
||||||
uint32_t card_initialized = p.card_initialized ? 1 : 0;
|
uint32_t card_initialized = p.card_initialized ? 1 : 0;
|
||||||
uint32_t card_inserted = (scr & SD_SCR_CARD_INSERTED) ? 1 : 0;
|
uint32_t card_inserted = (scr & SD_SCR_CARD_INSERTED) ? 1 : 0;
|
||||||
return (
|
return (
|
||||||
|
(byte_swap << 4) |
|
||||||
(clock_mode_50mhz << 3) |
|
(clock_mode_50mhz << 3) |
|
||||||
(card_type_block << 2) |
|
(card_type_block << 2) |
|
||||||
(card_initialized << 1) |
|
(card_initialized << 1) |
|
||||||
@ -371,6 +381,14 @@ bool sd_card_get_info (uint32_t address) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool sd_set_byte_swap (bool enabled) {
|
||||||
|
if (!p.card_initialized) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
p.byte_swap = enabled;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
||||||
if (!p.card_initialized || (count == 0)) {
|
if (!p.card_initialized || (count == 0)) {
|
||||||
return true;
|
return true;
|
||||||
@ -406,6 +424,10 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p.byte_swap && ((address % 2) != 0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!p.card_type_block) {
|
if (!p.card_type_block) {
|
||||||
sector *= SD_SECTOR_SIZE;
|
sector *= SD_SECTOR_SIZE;
|
||||||
}
|
}
|
||||||
@ -463,11 +485,12 @@ bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t cou
|
|||||||
|
|
||||||
void sd_init (void) {
|
void sd_init (void) {
|
||||||
p.card_initialized = false;
|
p.card_initialized = false;
|
||||||
|
p.byte_swap = false;
|
||||||
sd_set_clock(CLOCK_STOP);
|
sd_set_clock(CLOCK_STOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sd_process (void) {
|
void sd_process (void) {
|
||||||
if (!sd_card_is_inserted()) {
|
if (p.card_initialized && !sd_card_is_inserted()) {
|
||||||
sd_card_deinit();
|
sd_card_deinit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ void sd_card_deinit (void);
|
|||||||
bool sd_card_is_inserted (void);
|
bool sd_card_is_inserted (void);
|
||||||
uint32_t sd_card_get_status (void);
|
uint32_t sd_card_get_status (void);
|
||||||
bool sd_card_get_info (uint32_t address);
|
bool sd_card_get_info (uint32_t address);
|
||||||
|
bool sd_set_byte_swap (bool enabled);
|
||||||
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count);
|
bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count);
|
||||||
bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count);
|
bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count);
|
||||||
bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors);
|
bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors);
|
||||||
|
@ -124,6 +124,10 @@ void writeback_disable (void) {
|
|||||||
timer_set(TIMER_ID_WRITEBACK, 0);
|
timer_set(TIMER_ID_WRITEBACK, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool writeback_pending (void) {
|
||||||
|
return p.enabled && p.pending;
|
||||||
|
}
|
||||||
|
|
||||||
void writeback_init (void) {
|
void writeback_init (void) {
|
||||||
p.enabled = false;
|
p.enabled = false;
|
||||||
p.pending = false;
|
p.pending = false;
|
||||||
|
@ -18,6 +18,7 @@ typedef enum {
|
|||||||
void writeback_load_sector_table (uint32_t address);
|
void writeback_load_sector_table (uint32_t address);
|
||||||
void writeback_enable (writeback_mode_t mode);
|
void writeback_enable (writeback_mode_t mode);
|
||||||
void writeback_disable (void);
|
void writeback_disable (void);
|
||||||
|
bool writeback_pending (void);
|
||||||
void writeback_init (void);
|
void writeback_init (void);
|
||||||
void writeback_process (void);
|
void writeback_process (void);
|
||||||
|
|
||||||
|
@ -157,6 +157,10 @@ struct DebugArgs {
|
|||||||
/// Use EUC-JP encoding for text printing
|
/// Use EUC-JP encoding for text printing
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
euc_jp: bool,
|
euc_jp: bool,
|
||||||
|
|
||||||
|
/// Do not enable save writeback via USB
|
||||||
|
#[arg(long)]
|
||||||
|
no_writeback: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
@ -612,7 +616,9 @@ fn handle_debug_command(connection: Connection, args: &DebugArgs) -> Result<(),
|
|||||||
.bright_blue()
|
.bright_blue()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
sc64.set_save_writeback(true)?;
|
if !args.no_writeback {
|
||||||
|
sc64.set_save_writeback(true)?;
|
||||||
|
}
|
||||||
|
|
||||||
println!("{}: Started", "[Debug]".bold());
|
println!("{}: Started", "[Debug]".bold());
|
||||||
|
|
||||||
@ -639,7 +645,9 @@ fn handle_debug_command(connection: Connection, args: &DebugArgs) -> Result<(),
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sc64.set_save_writeback(false)?;
|
if !args.no_writeback {
|
||||||
|
sc64.set_save_writeback(false)?;
|
||||||
|
}
|
||||||
if args.isv.is_some() {
|
if args.isv.is_some() {
|
||||||
sc64.configure_is_viewer_64(None)?;
|
sc64.configure_is_viewer_64(None)?;
|
||||||
println!("{}: Stopped listening", "[IS-Viewer 64]".bold());
|
println!("{}: Stopped listening", "[IS-Viewer 64]".bold());
|
||||||
|
Loading…
Reference in New Issue
Block a user