Skip to content

Commit

Permalink
[SC64][FW][SW] Controller rewrite to remove task subsystem + minor bu…
Browse files Browse the repository at this point in the history
…g fixes (#64)

This PR completely removes `task.c / task.h` from `sw/controller` STM32
code.
Additionally, these changes were implemented:
- Updated IPL3
- Added new diagnostic data (voltage and temperature) readout commands
for USB and N64
- Fixed some issues with FlashRAM save type
- Joybus timings were relaxed to accommodate communication with
unsynchronized master controller (like _Datel Game Killer_, thanks
@RWeick)
- N64 embedded test program now waits for release of button press to
proceed
- Fixed issue where, in rare circumstances, I2C peripheral in STM32
would get locked-up on power-up
- LED blinking behavior on SD card access was changed
- LED blink duration on save writeback has been extended
- Minor fixes through the entire of hardware abstraction layer for STM32
code
- Primer now correctly detects issues with I2C bus during first time
programming
- `primer.py` script gives more meaningful error messages
- Fixed bug where RTC time was always written on N64FlashcartMenu boot
- sc64deployer now displays "Diagnostic data" instead of "MCU stack
usage"
  • Loading branch information
Polprzewodnikowy authored Jan 29, 2024
1 parent be37025 commit 421d043
Show file tree
Hide file tree
Showing 62 changed files with 1,793 additions and 1,950 deletions.
2 changes: 2 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ build_cic () {
build_fpga () {
if [ "$BUILT_FPGA" = true ]; then return; fi

build_cic

pushd fw/project/lcmxo2 > /dev/null
if [ "$FORCE_CLEAN" = true ]; then
rm -rf ./impl1/
Expand Down
2 changes: 1 addition & 1 deletion docker_build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

BUILDER_IMAGE="ghcr.io/polprzewodnikowy/sc64env:v1.8"
BUILDER_IMAGE="ghcr.io/polprzewodnikowy/sc64env:v1.9"

pushd $(dirname $0) > /dev/null

Expand Down
49 changes: 25 additions & 24 deletions docs/02_n64_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,28 @@

## N64 commands

| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
| --- | --------------------- | -------------- | ------------ | ---------------- | -------------- | ---------------------------------------------------------- |
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
| `V` | **VERSION_GET** | --- | --- | major/minor | revision | 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 |
| `a` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
| `A` | **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` | **DISK_MAPPING_SET** | pi_address | table_size | --- | --- | Set 64DD disk mapping for SD mode |
| `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 |
| id | name | arg0 | arg1 | rsp0 | rsp1 | description |
| --- | --------------------- | ------------- | ------------ | ---------------- | -------------- | ---------------------------------------------------------- |
| `v` | **IDENTIFIER_GET** | --- | --- | identifier | --- | Get flashcart identifier `SCv2` |
| `V` | **VERSION_GET** | --- | --- | major/minor | revision | 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 |
| `a` | **SETTING_GET** | setting_id | --- | --- | current_value | Get persistent setting option |
| `A` | **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` | **DISK_MAPPING_SET** | pi_address | table_size | --- | --- | Set 64DD disk mapping for SD mode |
| `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 |
| `%` | **DIAGNOSTIC_GET** | diagnostic_id | --- | --- | value | Get diagnostic data |
2 changes: 1 addition & 1 deletion docs/03_usb_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Available packet IDs are listed in the [asynchronous packets](#asynchronous-pack
| `f` | **FIRMWARE_BACKUP** | address | --- | --- | status/length | Backup firmware to specified memory address |
| `F` | **FIRMWARE_UPDATE** | address | length | --- | status | Update firmware from specified memory address |
| `?` | **DEBUG_GET** | --- | --- | --- | debug_data | Get internal FPGA debug info |
| `%` | **STACK_USAGE_GET** | --- | --- | --- | stack_usage | Get per task stack usage |
| `%` | **DIAGNOSTIC_GET** | --- | --- | --- | diagnostic_data | Get diagnostic data |

---

Expand Down
2 changes: 1 addition & 1 deletion fw/rtl/mcu/mcu_top.sv
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ module mcu_top (
18'd0,
n64_scb.flashram_write_or_erase,
n64_scb.flashram_sector_or_all,
n64_scb.flashram_sector,
n64_scb.flashram_page,
n64_scb.flashram_pending,
1'b0
};
Expand Down
14 changes: 7 additions & 7 deletions fw/rtl/n64/n64_flashram.sv
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module n64_flashram (
);

localparam [31:0] FLASH_TYPE_ID = 32'h1111_8001;
localparam [31:0] FLASH_MODEL_ID = 32'h00C2_001D;
localparam [31:0] FLASH_MODEL_ID = 32'h0032_00F1;

typedef enum bit [7:0] {
CMD_STATUS_MODE = 8'hD2,
Expand Down Expand Up @@ -97,14 +97,14 @@ module n64_flashram (
CMD_ERASE_SECTOR: begin
state <= STATE_STATUS;
erase_enabled <= 1'b1;
n64_scb.flashram_sector <= reg_bus.wdata[9:0];
n64_scb.flashram_page <= reg_bus.wdata[9:0];
n64_scb.flashram_sector_or_all <= 1'b0;
end

CMD_ERASE_CHIP: begin
state <= STATE_STATUS;
erase_enabled <= 1'b1;
n64_scb.flashram_sector <= 10'd0;
n64_scb.flashram_page <= 10'd0;
n64_scb.flashram_sector_or_all <= 1'b1;
end

Expand All @@ -126,17 +126,17 @@ module n64_flashram (
state <= STATE_STATUS;
status[WRITE_BUSY] <= 1'b1;
status[WRITE_DONE] <= 1'b0;
n64_scb.flashram_sector <= reg_bus.wdata[9:0];
n64_scb.flashram_page <= reg_bus.wdata[9:0];
n64_scb.flashram_pending <= 1'b1;
n64_scb.flashram_write_or_erase <= 1'b0;
n64_scb.flashram_sector_or_all <= 1'b0;
end
endcase
end
end else begin
if (reg_bus.address[1] && state != STATE_BUFFER) begin
status[ERASE_BUSY] <= reg_bus.wdata[ERASE_BUSY];
status[WRITE_BUSY] <= reg_bus.wdata[WRITE_BUSY];
if (reg_bus.address[1] && state == STATE_STATUS) begin
status[ERASE_DONE] <= 1'b0;
status[WRITE_DONE] <= 1'b0;
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions fw/rtl/n64/n64_scb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ interface n64_scb ();

logic flashram_pending;
logic flashram_done;
logic [9:0] flashram_sector;
logic [9:0] flashram_page;
logic flashram_sector_or_all;
logic flashram_write_or_erase;
logic flashram_read_mode;
Expand Down Expand Up @@ -84,7 +84,7 @@ interface n64_scb ();

input flashram_pending,
output flashram_done,
input flashram_sector,
input flashram_page,
input flashram_sector_or_all,
input flashram_write_or_erase,

Expand Down Expand Up @@ -143,7 +143,7 @@ interface n64_scb ();
modport flashram (
output flashram_pending,
input flashram_done,
output flashram_sector,
output flashram_page,
output flashram_sector_or_all,
output flashram_write_or_erase,

Expand Down
25 changes: 18 additions & 7 deletions fw/rtl/n64/n64_si.sv
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ module n64_si (
// Data falling/rising event generator

logic last_si_dq_in;
logic si_dq_in_inhibit;

always_ff @(posedge clk) begin
if (si_clk_rising_edge) begin
Expand All @@ -70,14 +71,14 @@ module n64_si (
logic si_dq_rising_edge;

always_comb begin
si_dq_falling_edge = si_clk_rising_edge && last_si_dq_in && !si_dq_in;
si_dq_rising_edge = si_clk_rising_edge && !last_si_dq_in && si_dq_in;
si_dq_falling_edge = si_clk_rising_edge && last_si_dq_in && !si_dq_in && !si_dq_in_inhibit;
si_dq_rising_edge = si_clk_rising_edge && !last_si_dq_in && si_dq_in && !si_dq_in_inhibit;
end


// RX bit generator

logic [3:0] rx_sub_bit_counter;
logic [4:0] rx_sub_bit_counter;
logic rx_timeout;
logic rx_bit_valid;
logic rx_bit_data;
Expand All @@ -94,7 +95,7 @@ module n64_si (
always_comb begin
rx_timeout = si_clk_rising_edge && si_dq_in && (&rx_sub_bit_counter);
rx_bit_valid = si_dq_rising_edge;
rx_bit_data = (rx_sub_bit_counter >= 4'd3) ? 1'b0 : 1'b1;
rx_bit_data = (rx_sub_bit_counter >= 5'd4) ? 1'b0 : 1'b1;
end


Expand Down Expand Up @@ -124,7 +125,7 @@ module n64_si (
logic rx_stop;

always_comb begin
rx_stop = si_clk_rising_edge && si_dq_in && (rx_sub_bit_counter == 4'd7) && (rx_bit_counter == 3'd1);
rx_stop = si_clk_rising_edge && si_dq_in && (rx_sub_bit_counter == 5'd15) && (rx_bit_counter == 3'd1);
end


Expand Down Expand Up @@ -260,7 +261,8 @@ module n64_si (
typedef enum bit [1:0] {
TX_STATE_IDLE,
TX_STATE_DATA,
TX_STATE_STOP
TX_STATE_STOP,
TX_STATE_STOP_WAIT
} e_tx_state;

e_tx_state tx_state;
Expand All @@ -278,12 +280,14 @@ module n64_si (

if (reset) begin
tx_state <= TX_STATE_IDLE;
si_dq_in_inhibit <= 1'b0;
end else begin
case (tx_state)
TX_STATE_IDLE: begin
if (tx_start) begin
tx_byte_counter <= 4'd0;
tx_state <= TX_STATE_DATA;
si_dq_in_inhibit <= 1'b1;
end
end

Expand All @@ -299,7 +303,14 @@ module n64_si (
TX_STATE_STOP: begin
tx_stop <= 1'b1;
if (!tx_busy && tx_stop) begin
tx_state <= TX_STATE_STOP_WAIT;
end
end

TX_STATE_STOP_WAIT: begin
if (!tx_busy) begin
tx_state <= TX_STATE_IDLE;
si_dq_in_inhibit <= 1'b0;
end
end
endcase
Expand Down Expand Up @@ -382,7 +393,7 @@ module n64_si (
4'd1: {rtc_time_wp, rtc_backup_wp} <= rx_byte_data[1:0];
4'd2: begin
rtc_stopped <= rx_byte_data[2:1];
if (rx_byte_data[2:1] == 2'b00) begin
if ((|rtc_stopped) && (rx_byte_data[2:1] == 2'b00)) begin
n64_scb.rtc_pending <= 1'b1;
end
end
Expand Down
2 changes: 1 addition & 1 deletion sw/bootloader/src/font.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ const uint8_t font_data[96][FONT_CHAR_BYTES] = {
{ 0x38, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x00, },
{ 0x00, 0x38, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, },
{ 0x00, 0x18, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, },
{ 0x1C, 0x63, 0x63, 0x1C, 0x00, 0x00, 0x00, 0x00, },
{ 0x00, 0x3C, 0x60, 0x7C, 0x66, 0x66, 0x7C, 0x00, },
{ 0x06, 0x06, 0x3E, 0x66, 0x66, 0x66, 0x3E, 0x00, },
{ 0x00, 0x3C, 0x66, 0x06, 0x06, 0x06, 0x7C, 0x00, },
Expand Down
12 changes: 12 additions & 0 deletions sw/bootloader/src/sc64.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ typedef enum {
CMD_ID_FLASH_PROGRAM = 'K',
CMD_ID_FLASH_WAIT_BUSY = 'p',
CMD_ID_FLASH_ERASE_BLOCK = 'P',
CMD_ID_DIAGNOSTIC_GET = '%',
} sc64_cmd_id_t;

typedef enum {
Expand Down Expand Up @@ -436,3 +437,14 @@ sc64_error_t sc64_flash_erase_block (void *address) {
};
return sc64_execute_cmd(&cmd);
}


sc64_error_t sc64_get_diagnostic (sc64_diagnostic_id_t id, uint32_t *value) {
sc64_cmd_t cmd = {
.id = CMD_ID_DIAGNOSTIC_GET,
.arg = { id }
};
sc64_error_t error = sc64_execute_cmd(&cmd);
*value = cmd.rsp[1];
return error;
}
6 changes: 6 additions & 0 deletions sw/bootloader/src/sc64.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ typedef enum {
BUTTON_MODE_DD_DISK_SWAP,
} sc64_button_mode_t;

typedef enum {
DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE,
} sc64_diagnostic_id_t;

typedef struct {
sc64_boot_mode_t boot_mode;
sc64_cic_seed_t cic_seed;
Expand Down Expand Up @@ -174,5 +178,7 @@ sc64_error_t sc64_flash_wait_busy (void);
sc64_error_t sc64_flash_get_erase_block_size (size_t *erase_block_size);
sc64_error_t sc64_flash_erase_block (void *address);

sc64_error_t sc64_get_diagnostic (sc64_diagnostic_id_t id, uint32_t *value);


#endif
30 changes: 26 additions & 4 deletions sw/bootloader/src/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,46 @@

static void test_sc64_cfg (void) {
sc64_error_t error;
uint32_t button_state;
uint32_t identifier;
uint16_t major;
uint16_t minor;
uint32_t revision;
uint32_t tmp;

display_printf("Waiting for the button to be released... ");

do {
if ((error = sc64_get_config(CFG_ID_BUTTON_STATE, &button_state)) != SC64_OK) {
error_display("Command CONFIG_GET [BUTTON_STATE] failed: %d", error);
}
} while (button_state != 0);

display_printf("done\n\n");

if ((error = sc64_get_identifier(&identifier)) != SC64_OK) {
error_display("Command IDENTIFIER_GET failed: %d", error);
return;
}

if ((error = sc64_get_version(&major, &minor, &revision)) != SC64_OK) {
error_display("Command VERSION_GET failed: %d", error);
return;
}

display_printf("Identifier: 0x%08X\n\n", identifier);
if ((error = sc64_get_diagnostic(DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE, &tmp)) != SC64_OK) {
error_display("Command DIAGNOSTIC_GET failed: %d", error);
return;
}

uint16_t voltage = (uint16_t) (tmp >> 16);
int16_t temperature = (int16_t) (tmp & 0xFFFF);

display_printf("Identifier: 0x%08X\n", identifier);
display_printf("SC64 firmware version: %d.%d.%d\n\n", major, minor, revision);

display_printf("SC64 firmware version: %d.%d.%d\n", major, minor, revision);
display_printf("Voltage: %d.%03d V\n", (voltage / 1000), (voltage % 1000));
display_printf("Temperature: %d.%01d `C\n", (temperature / 10), (temperature % 10));
}

static void test_rtc (void) {
Expand Down Expand Up @@ -233,7 +255,7 @@ bool test_check (void) {
error_display("Command CONFIG_GET [BUTTON_STATE] failed: %d", error);
}

return button_state != 0;
return (button_state != 0);
}

static struct {
Expand Down
2 changes: 1 addition & 1 deletion sw/controller/app.ld
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ SECTIONS {
.text : {
. = ALIGN(4);
*(.text)
*(.text*)
*(.text*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
Expand Down
2 changes: 0 additions & 2 deletions sw/controller/app.mk
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@ SRC_FILES = \
flash.c \
flashram.c \
fpga.c \
gvr.c \
hw.c \
isv.c \
lcmxo2.c \
led.c \
rtc.c \
sd.c \
task.c \
timer.c \
update.c \
usb.c \
Expand Down
2 changes: 1 addition & 1 deletion sw/controller/loader.ld
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ SECTIONS {
. = ALIGN(4);
_stext = .;
*(.text)
*(.text*)
*(.text*)
*(.glue_7)
*(.glue_7t)
. = ALIGN(4);
Expand Down
Loading

0 comments on commit 421d043

Please sign in to comment.