[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:
Mateusz Faderewski 2023-06-30 01:09:02 +02:00 committed by GitHub
parent 8c7f97b433
commit c4f6a0d555
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 170 additions and 41 deletions

View File

@ -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

View File

@ -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 |

View File

@ -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

View File

@ -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" ;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 };

View File

@ -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);

View File

@ -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");

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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();
} }
} }

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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());