Skip to content

Commit

Permalink
[SC64][FW][SW] SD card byte swap on reads support (#39)
Browse files Browse the repository at this point in the history
And other bug fixes related to DMA write mask
  • Loading branch information
Polprzewodnikowy authored Jun 29, 2023
1 parent 8c7f97b commit c4f6a0d
Show file tree
Hide file tree
Showing 18 changed files with 170 additions and 41 deletions.
2 changes: 2 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ PACKAGE_FILE_NAME="sc64-extra"

TOP_FILES=(
"./fw/ftdi/ft232h_config.xml"
"./fw/project/lcmxo2/impl1/fpga_max_frequency.txt"
"./sw/tools/primer.py"
"./sw/tools/requirements.txt"
"./sc64-firmware-${SC64_VERSION}.bin"
Expand Down Expand Up @@ -90,6 +91,7 @@ build_update () {
rm -f ../../sc64-firmware-*.bin
fi
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 "${GIT_BRANCH}" ]; then GIT_INFO+=$'\n'"branch: $GIT_BRANCH"; fi
if [ ! -z "${GIT_TAG}" ]; then GIT_INFO+=$'\n'"tag: $GIT_TAG"; fi
Expand Down
47 changes: 24 additions & 23 deletions docs/03_n64_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@

## N64 commands

| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
| --- | --------------------- | ---------- | ------------ | ---------------- | -------------- | -------------------------------------------------- |
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
| `V` | **VERSION_GET** | --- | --- | version | --- | Get flashcart firmware version |
| `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` | **SETTING_GET** | setting_id | --- | --- | current_value | Get 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_SET** | time_0 | time_1 | --- | --- | Set new RTC value |
| `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 |
| `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 |
| `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 |
| `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 |
| `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 |
| `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |
| `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 |
| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
| --- | --------------------- | -------------- | ------------ | ---------------- | -------------- | ---------------------------------------------------------- |
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
| `V` | **VERSION_GET** | --- | --- | version | --- | Get flashcart firmware version |
| `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` | **SETTING_GET** | setting_id | --- | --- | current_value | Get 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_SET** | time_0 | time_1 | --- | --- | Set new RTC value |
| `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 |
| `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 |
| `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 |
| `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 |
| `D` | **DD_SD_INFO** | pi_address | table_size | --- | --- | Set 64DD disk SD sector info |
| `w` | **WRITEBACK_PENDING** | pending_status | --- | --- | --- | Get save writeback status (is write queued to the SD card) |
| `W` | **WRITEBACK_SD_INFO** | pi_address | --- | --- | --- | Load writeback SD sector table and enable it |
| `K` | **FLASH_PROGRAM** | pi_address | length | --- | --- | Program flash with bytes loaded into data buffer |
| `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 |
26 changes: 26 additions & 0 deletions fw/project/lcmxo2/build.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
#!/bin/bash

set -e

source $bindir/diamond_env

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
10 changes: 8 additions & 2 deletions fw/project/lcmxo2/sc64.lpf
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ IOBUF PORT "inclk" 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_int" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "mcu_miso" IO_TYPE=LVCMOS33 PULLMODE=NONE ;
IOBUF PORT "mcu_mosi" IO_TYPE=LVCMOS33 PULLMODE=NONE ;
IOBUF PORT "mcu_miso" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
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_nmi" PULLMODE=DOWN IO_TYPE=LVCMOS33 ;
IOBUF PORT "n64_pi_ad[0]" PULLMODE=NONE IO_TYPE=LVCMOS33 ;
Expand All @@ -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_si_clk" PULLMODE=DOWN 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_cmd" PULLMODE=UP IO_TYPE=LVCMOS33 ;
IOBUF PORT "sd_dat[0]" PULLMODE=UP IO_TYPE=LVCMOS33 ;
Expand Down Expand Up @@ -120,6 +123,8 @@ LOCATE COMP "mcu_miso" SITE "119" ;
LOCATE COMP "mcu_mosi" SITE "120" ;
LOCATE COMP "n64_irq" SITE "32" ;
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[1]" SITE "58" ;
LOCATE COMP "n64_pi_ad[10]" SITE "42" ;
Expand All @@ -143,6 +148,7 @@ LOCATE COMP "n64_pi_write" SITE "49" ;
LOCATE COMP "n64_reset" SITE "31" ;
LOCATE COMP "n64_si_clk" SITE "33" ;
LOCATE COMP "n64_si_dq" SITE "27" ;
LOCATE COMP "n64_video_sync" SITE "26" ;
LOCATE COMP "sd_clk" SITE "111" ;
LOCATE COMP "sd_cmd" SITE "112" ;
LOCATE COMP "sd_dat[0]" SITE "110" ;
Expand Down
13 changes: 7 additions & 6 deletions fw/rtl/mcu/mcu_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ module mcu_top (
logic bootloader_skip;

assign n64_scb.cfg_identifier = 32'h53437632;
assign usb_dma_scb.byte_swap = 1'b0;

logic dd_bm_ack;

Expand Down Expand Up @@ -577,7 +578,8 @@ module mcu_top (

REG_SD_DMA_SCR: begin
reg_rdata <= {
28'd0,
27'd0,
sd_dma_scb.byte_swap,
sd_dma_scb.busy,
sd_dma_scb.direction,
2'b00
Expand Down Expand Up @@ -855,11 +857,10 @@ module mcu_top (
end

REG_SD_DMA_SCR: begin
{
sd_dma_scb.direction,
sd_dma_scb.stop,
sd_dma_scb.start
} <= reg_wdata[2:0];
sd_dma_scb.byte_swap <= reg_wdata[4];
sd_dma_scb.direction <= reg_wdata[2];
sd_dma_scb.stop <= reg_wdata[1];
sd_dma_scb.start <= reg_wdata[0];
end

REG_DD_SCR: begin
Expand Down
18 changes: 14 additions & 4 deletions fw/rtl/memory/memory_dma.sv
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ interface dma_scb ();
logic stop;
logic busy;
logic direction;
logic byte_swap;
logic [26:0] starting_address;
logic [26:0] transfer_length;

Expand All @@ -12,6 +13,7 @@ interface dma_scb ();
output stop,
input busy,
output direction,
output byte_swap,
output starting_address,
output transfer_length
);
Expand All @@ -21,6 +23,7 @@ interface dma_scb ();
input stop,
output busy,
input direction,
input byte_swap,
input starting_address,
input transfer_length
);
Expand Down Expand Up @@ -61,6 +64,7 @@ module memory_dma (

// RX FIFO controller

logic [1:0] rx_wmask;
logic rx_rdata_pop;
logic rx_rdata_shift;
logic rx_rdata_valid;
Expand Down Expand Up @@ -88,11 +92,11 @@ module memory_dma (

if (dma_start) begin
if (dma_scb.starting_address[0]) begin
mem_bus.wmask <= 2'b01;
rx_wmask <= 2'b01;
rx_buffer_counter <= 2'd1;
rx_buffer_valid_counter <= 2'd1;
end else begin
mem_bus.wmask <= 2'b11;
rx_wmask <= 2'b11;
rx_buffer_counter <= 2'd0;
rx_buffer_valid_counter <= 2'd0;
end
Expand All @@ -103,16 +107,21 @@ module memory_dma (
end

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;
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_buffer_counter <= rx_buffer_counter + 1'd1;
end
end

if (rx_buffer_valid && !mem_bus.request) begin
rx_wmask <= 2'b11;
rx_buffer_counter <= 2'd0;
rx_buffer_valid_counter <= 2'd0;
end
Expand Down Expand Up @@ -209,6 +218,7 @@ module memory_dma (
if (mem_bus.write) begin
if (rx_buffer_valid) begin
mem_bus.request <= 1'b1;
mem_bus.wmask <= rx_wmask;
mem_bus.wdata <= rx_buffer;
end
end else begin
Expand Down
14 changes: 13 additions & 1 deletion fw/rtl/top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ module top (
input mcu_clk,
input mcu_cs,
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;
Expand Down Expand Up @@ -264,4 +269,11 @@ module top (
.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
10 changes: 10 additions & 0 deletions sw/bootloader/src/sc64.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ typedef enum {
SD_CARD_OP_INIT = 1,
SD_CARD_OP_GET_STATUS = 2,
SD_CARD_OP_GET_INFO = 3,
SD_CARD_OP_BYTE_SWAP_ON = 4,
SD_CARD_OP_BYTE_SWAP_OFF = 5,
} sd_card_op_t;


Expand Down Expand Up @@ -235,6 +237,14 @@ bool sc64_sd_card_get_info (void *address) {
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) {
uint32_t sector_set_args[2] = { sector, 0 };
uint32_t read_args[2] = { (uint32_t) (address), count };
Expand Down
2 changes: 2 additions & 0 deletions sw/bootloader/src/sc64.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ typedef enum {
SD_CARD_STATUS_INITIALIZED = (1 << 1),
SD_CARD_STATUS_TYPE_BLOCK = (1 << 2),
SD_CARD_STATUS_50MHZ_MODE = (1 << 3),
SD_CARD_STATUS_BYTE_SWAP = (1 << 4),
} sc64_sd_card_status_t;

typedef struct {
Expand Down Expand Up @@ -143,6 +144,7 @@ bool sc64_sd_card_init (void);
bool sc64_sd_card_deinit (void);
sc64_sd_card_status_t sc64_sd_card_get_status (void);
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_read_sectors (void *address, uint32_t sector, uint32_t count);
bool sc64_dd_set_sd_disk_info (void *address, uint32_t length);
Expand Down
3 changes: 3 additions & 0 deletions sw/bootloader/src/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ static void test_sd_card (void) {
if (card_status & SD_CARD_STATUS_50MHZ_MODE) {
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))) {
display_printf("SD card get info error!\n");
Expand Down
20 changes: 19 additions & 1 deletion sw/controller/src/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ typedef enum {
SD_CARD_OP_INIT = 1,
SD_CARD_OP_GET_STATUS = 2,
SD_CARD_OP_GET_INFO = 3,
SD_CARD_OP_BYTE_SWAP_ON = 4,
SD_CARD_OP_BYTE_SWAP_OFF = 5,
} sd_card_op_t;

typedef enum {
Expand Down Expand Up @@ -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) {
if (save_type > SAVE_TYPE_SRAM_BANKED) {
if (save_type > SAVE_TYPE_SRAM_1M) {
return true;
}

Expand Down Expand Up @@ -575,6 +577,18 @@ void cfg_process (void) {
return;
}
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:
cfg_set_error(CFG_ERROR_BAD_ARGUMENT);
return;
Expand Down Expand Up @@ -625,6 +639,10 @@ void cfg_process (void) {
dd_set_sd_info(args[0], args[1]);
break;

case 'w':
args[0] = writeback_pending();
break;

case 'W':
if (cfg_translate_address(&args[0], WRITEBACK_SECTOR_TABLE_SIZE, (SDRAM | BRAM))) {
cfg_set_error(CFG_ERROR_BAD_ADDRESS);
Expand Down
1 change: 1 addition & 0 deletions sw/controller/src/fpga.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ typedef enum {
#define DMA_SCR_STOP (1 << 1)
#define DMA_SCR_DIRECTION (1 << 2)
#define DMA_SCR_BUSY (1 << 3)
#define DMA_SCR_BYTE_SWAP (1 << 4)

#define CFG_SCR_BOOTLOADER_ENABLED (1 << 0)
#define CFG_SCR_BOOTLOADER_SKIP (1 << 1)
Expand Down
2 changes: 1 addition & 1 deletion sw/controller/src/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ static void hw_init_crc (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_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_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);
Expand Down
Loading

0 comments on commit c4f6a0d

Please sign in to comment.