From 421d0438f345e693d50bc461ddd8291512bb4cbf Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Mon, 29 Jan 2024 14:23:18 +0100 Subject: [PATCH] [SC64][FW][SW] Controller rewrite to remove task subsystem + minor bug 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" --- build.sh | 2 + docker_build.sh | 2 +- docs/02_n64_commands.md | 49 +- docs/03_usb_interface.md | 2 +- fw/rtl/mcu/mcu_top.sv | 2 +- fw/rtl/n64/n64_flashram.sv | 14 +- fw/rtl/n64/n64_scb.sv | 6 +- fw/rtl/n64/n64_si.sv | 25 +- sw/bootloader/src/font.c | 2 +- sw/bootloader/src/sc64.c | 12 + sw/bootloader/src/sc64.h | 6 + sw/bootloader/src/test.c | 30 +- sw/controller/app.ld | 2 +- sw/controller/app.mk | 2 - sw/controller/loader.ld | 2 +- sw/controller/primer.ld | 2 +- sw/controller/src/app.S | 2 +- sw/controller/src/app.c | 67 ++- sw/controller/src/app.h | 11 - sw/controller/src/button.c | 9 +- sw/controller/src/button.h | 11 +- sw/controller/src/cfg.c | 99 +++- sw/controller/src/cfg.h | 3 + sw/controller/src/cic.c | 77 ++- sw/controller/src/cic.h | 2 + sw/controller/src/dd.c | 29 +- sw/controller/src/dd.h | 2 + sw/controller/src/flashram.c | 75 +-- sw/controller/src/flashram.h | 1 + sw/controller/src/fpga.c | 40 +- sw/controller/src/gvr.c | 39 -- sw/controller/src/gvr.h | 8 - sw/controller/src/hw.c | 804 +++++++++++++-------------- sw/controller/src/hw.h | 67 ++- sw/controller/src/isv.c | 2 + sw/controller/src/isv.h | 2 + sw/controller/src/lcmxo2.c | 116 ++-- sw/controller/src/led.c | 203 ++++--- sw/controller/src/led.h | 10 +- sw/controller/src/loader.c | 1 + sw/controller/src/primer.c | 7 +- sw/controller/src/rtc.c | 298 +++++----- sw/controller/src/rtc.h | 27 +- sw/controller/src/sd.c | 79 ++- sw/controller/src/sd.h | 5 + sw/controller/src/task.c | 135 ----- sw/controller/src/task.h | 23 - sw/controller/src/timer.c | 62 ++- sw/controller/src/timer.h | 12 +- sw/controller/src/update.c | 6 +- sw/controller/src/usb.c | 37 +- sw/controller/src/usb.h | 3 + sw/controller/src/writeback.c | 51 +- sw/controller/src/writeback.h | 5 +- sw/deployer/Cargo.lock | 958 ++++++++++++++------------------- sw/deployer/Cargo.toml | 4 +- sw/deployer/src/debug.rs | 28 +- sw/deployer/src/main.rs | 12 +- sw/deployer/src/sc64/mod.rs | 65 +-- sw/deployer/src/sc64/server.rs | 17 +- sw/deployer/src/sc64/types.rs | 80 ++- sw/tools/primer.py | 77 ++- 62 files changed, 1837 insertions(+), 1994 deletions(-) delete mode 100644 sw/controller/src/app.h delete mode 100644 sw/controller/src/gvr.c delete mode 100644 sw/controller/src/gvr.h delete mode 100644 sw/controller/src/task.c delete mode 100644 sw/controller/src/task.h diff --git a/build.sh b/build.sh index fd52d0d..2f81590 100755 --- a/build.sh +++ b/build.sh @@ -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/ diff --git a/docker_build.sh b/docker_build.sh index b336eb8..f244af9 100755 --- a/docker_build.sh +++ b/docker_build.sh @@ -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 diff --git a/docs/02_n64_commands.md b/docs/02_n64_commands.md index c10d2c9..a832454 100644 --- a/docs/02_n64_commands.md +++ b/docs/02_n64_commands.md @@ -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 | diff --git a/docs/03_usb_interface.md b/docs/03_usb_interface.md index 8b6b089..8b85b06 100644 --- a/docs/03_usb_interface.md +++ b/docs/03_usb_interface.md @@ -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 | --- diff --git a/fw/rtl/mcu/mcu_top.sv b/fw/rtl/mcu/mcu_top.sv index 9996b23..683b252 100644 --- a/fw/rtl/mcu/mcu_top.sv +++ b/fw/rtl/mcu/mcu_top.sv @@ -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 }; diff --git a/fw/rtl/n64/n64_flashram.sv b/fw/rtl/n64/n64_flashram.sv index bbc9464..db84b81 100644 --- a/fw/rtl/n64/n64_flashram.sv +++ b/fw/rtl/n64/n64_flashram.sv @@ -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, @@ -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 @@ -126,7 +126,7 @@ 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; @@ -134,9 +134,9 @@ module n64_flashram ( 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 diff --git a/fw/rtl/n64/n64_scb.sv b/fw/rtl/n64/n64_scb.sv index b2ba869..f1afa4a 100644 --- a/fw/rtl/n64/n64_scb.sv +++ b/fw/rtl/n64/n64_scb.sv @@ -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; @@ -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, @@ -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, diff --git a/fw/rtl/n64/n64_si.sv b/fw/rtl/n64/n64_si.sv index cbc7482..73875a4 100644 --- a/fw/rtl/n64/n64_si.sv +++ b/fw/rtl/n64/n64_si.sv @@ -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 @@ -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; @@ -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 @@ -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 @@ -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; @@ -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 @@ -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 @@ -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 diff --git a/sw/bootloader/src/font.c b/sw/bootloader/src/font.c index 0732a3f..b688666 100644 --- a/sw/bootloader/src/font.c +++ b/sw/bootloader/src/font.c @@ -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, }, diff --git a/sw/bootloader/src/sc64.c b/sw/bootloader/src/sc64.c index b560f60..f6ada8f 100644 --- a/sw/bootloader/src/sc64.c +++ b/sw/bootloader/src/sc64.c @@ -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 { @@ -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; +} diff --git a/sw/bootloader/src/sc64.h b/sw/bootloader/src/sc64.h index 775acb7..4d6457b 100644 --- a/sw/bootloader/src/sc64.h +++ b/sw/bootloader/src/sc64.h @@ -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; @@ -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 diff --git a/sw/bootloader/src/test.c b/sw/bootloader/src/test.c index bba6629..89eac45 100644 --- a/sw/bootloader/src/test.c +++ b/sw/bootloader/src/test.c @@ -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; + } - display_printf("SC64 firmware version: %d.%d.%d\n", major, minor, revision); + 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("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) { @@ -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 { diff --git a/sw/controller/app.ld b/sw/controller/app.ld index dbcb537..660776c 100644 --- a/sw/controller/app.ld +++ b/sw/controller/app.ld @@ -24,7 +24,7 @@ SECTIONS { .text : { . = ALIGN(4); *(.text) - *(.text*) + *(.text*) *(.glue_7) *(.glue_7t) . = ALIGN(4); diff --git a/sw/controller/app.mk b/sw/controller/app.mk index f3ae8b6..946da5a 100644 --- a/sw/controller/app.mk +++ b/sw/controller/app.mk @@ -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 \ diff --git a/sw/controller/loader.ld b/sw/controller/loader.ld index 97f2f37..ffc1f64 100644 --- a/sw/controller/loader.ld +++ b/sw/controller/loader.ld @@ -23,7 +23,7 @@ SECTIONS { . = ALIGN(4); _stext = .; *(.text) - *(.text*) + *(.text*) *(.glue_7) *(.glue_7t) . = ALIGN(4); diff --git a/sw/controller/primer.ld b/sw/controller/primer.ld index 7225e46..98f7caf 100644 --- a/sw/controller/primer.ld +++ b/sw/controller/primer.ld @@ -16,7 +16,7 @@ SECTIONS { .text : { . = ALIGN(4); *(.text) - *(.text*) + *(.text*) *(.glue_7) *(.glue_7t) . = ALIGN(4); diff --git a/sw/controller/src/app.S b/sw/controller/src/app.S index 01b6ea0..04076d0 100644 --- a/sw/controller/src/app.S +++ b/sw/controller/src/app.S @@ -8,7 +8,7 @@ .type loader, %object loader: .incbin "build/loader/loader.bin" - + .org 0x1000, 0xFF .section .text.Reset_Handler .type Reset_Handler, %function diff --git a/sw/controller/src/app.c b/sw/controller/src/app.c index 16be2f7..2568874 100644 --- a/sw/controller/src/app.c +++ b/sw/controller/src/app.c @@ -1,34 +1,51 @@ -#include "app.h" -#include "gvr.h" +#include +#include "button.h" +#include "cfg.h" +#include "cic.h" +#include "dd.h" +#include "flashram.h" +#include "fpga.h" #include "hw.h" +#include "isv.h" #include "led.h" #include "rtc.h" -#include "task.h" +#include "sd.h" +#include "timer.h" +#include "usb.h" +#include "writeback.h" -#define RTC_STACK_SIZE (256) -#define LED_STACK_SIZE (256) -#define GVR_STACK_SIZE (2048) - - -uint8_t rtc_stack[RTC_STACK_SIZE] __attribute__((aligned(8))); -uint8_t led_stack[LED_STACK_SIZE] __attribute__((aligned(8))); -uint8_t gvr_stack[GVR_STACK_SIZE] __attribute__((aligned(8))); - - -void app_get_stack_usage (uint32_t *usage) { - *usage++ = 0; - *usage++ = task_get_stack_usage(rtc_stack, RTC_STACK_SIZE); - *usage++ = task_get_stack_usage(led_stack, LED_STACK_SIZE); - *usage++ = task_get_stack_usage(gvr_stack, GVR_STACK_SIZE); -} - void app (void) { - hw_init(); + hw_app_init(); - task_create(TASK_ID_RTC, rtc_task, rtc_stack, RTC_STACK_SIZE); - task_create(TASK_ID_LED, led_task, led_stack, LED_STACK_SIZE); - task_create(TASK_ID_GVR, gvr_task, gvr_stack, GVR_STACK_SIZE); + timer_init(); - task_scheduler_start(); + while (fpga_id_get() != FPGA_ID); + + rtc_init(); + + button_init(); + cfg_init(); + cic_init(); + dd_init(); + flashram_init(); + isv_init(); + led_init(); + sd_init(); + usb_init(); + writeback_init(); + + while (true) { + button_process(); + cfg_process(); + cic_process(); + dd_process(); + flashram_process(); + isv_process(); + led_process(); + rtc_process(); + sd_process(); + usb_process(); + writeback_process(); + } } diff --git a/sw/controller/src/app.h b/sw/controller/src/app.h deleted file mode 100644 index e0d24ca..0000000 --- a/sw/controller/src/app.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef APP_H__ -#define APP_H__ - - -#include - - -void app_get_stack_usage (uint32_t *usage); - - -#endif diff --git a/sw/controller/src/button.c b/sw/controller/src/button.c index 1c10b30..9a220ba 100644 --- a/sw/controller/src/button.c +++ b/sw/controller/src/button.c @@ -25,7 +25,7 @@ bool button_get_state (void) { } bool button_set_mode (button_mode_t mode) { - if (mode > BUTTON_MODE_DD_DISK_SWAP) { + if (mode >= __BUTTON_MODE_COUNT) { return true; } p.mode = mode; @@ -39,6 +39,7 @@ button_mode_t button_get_mode (void) { return p.mode; } + void button_init (void) { p.counter = 0; p.state = false; @@ -46,9 +47,12 @@ void button_init (void) { p.trigger = false; } + void button_process (void) { usb_tx_info_t packet_info; + uint32_t status = fpga_reg_get(REG_CFG_SCR); + if (status & CFG_SCR_BUTTON_STATE) { if (p.counter < BUTTON_COUNTER_TRIGGER_ON) { p.counter += 1; @@ -58,13 +62,16 @@ void button_process (void) { p.counter -= 1; } } + if (!p.state && p.counter == BUTTON_COUNTER_TRIGGER_ON) { p.state = true; p.trigger = true; } + if (p.state && p.counter == BUTTON_COUNTER_TRIGGER_OFF) { p.state = false; } + if (p.trigger) { switch (p.mode) { case BUTTON_MODE_N64_IRQ: diff --git a/sw/controller/src/button.h b/sw/controller/src/button.h index 3c41913..bd4cac8 100644 --- a/sw/controller/src/button.h +++ b/sw/controller/src/button.h @@ -6,17 +6,20 @@ typedef enum { - BUTTON_MODE_NONE, - BUTTON_MODE_N64_IRQ, - BUTTON_MODE_USB_PACKET, - BUTTON_MODE_DD_DISK_SWAP, + BUTTON_MODE_NONE = 0, + BUTTON_MODE_N64_IRQ = 1, + BUTTON_MODE_USB_PACKET = 2, + BUTTON_MODE_DD_DISK_SWAP = 3, + __BUTTON_MODE_COUNT } button_mode_t; bool button_get_state (void); bool button_set_mode (button_mode_t mode); button_mode_t button_get_mode (void); + void button_init (void); + void button_process (void); diff --git a/sw/controller/src/cfg.c b/sw/controller/src/cfg.c index a962982..7dad6a5 100644 --- a/sw/controller/src/cfg.c +++ b/sw/controller/src/cfg.c @@ -4,7 +4,9 @@ #include "dd.h" #include "flash.h" #include "fpga.h" +#include "hw.h" #include "isv.h" +#include "led.h" #include "rtc.h" #include "sd.h" #include "usb.h" @@ -17,25 +19,25 @@ typedef enum { - CFG_ID_BOOTLOADER_SWITCH, - CFG_ID_ROM_WRITE_ENABLE, - CFG_ID_ROM_SHADOW_ENABLE, - CFG_ID_DD_MODE, - CFG_ID_ISV_ADDRESS, - CFG_ID_BOOT_MODE, - CFG_ID_SAVE_TYPE, - CFG_ID_CIC_SEED, - CFG_ID_TV_TYPE, - CFG_ID_DD_SD_ENABLE, - CFG_ID_DD_DRIVE_TYPE, - CFG_ID_DD_DISK_STATE, - CFG_ID_BUTTON_STATE, - CFG_ID_BUTTON_MODE, - CFG_ID_ROM_EXTENDED_ENABLE, + CFG_ID_BOOTLOADER_SWITCH = 0, + CFG_ID_ROM_WRITE_ENABLE = 1, + CFG_ID_ROM_SHADOW_ENABLE = 2, + CFG_ID_DD_MODE = 3, + CFG_ID_ISV_ADDRESS = 4, + CFG_ID_BOOT_MODE = 5, + CFG_ID_SAVE_TYPE = 6, + CFG_ID_CIC_SEED = 7, + CFG_ID_TV_TYPE = 8, + CFG_ID_DD_SD_ENABLE = 9, + CFG_ID_DD_DRIVE_TYPE = 10, + CFG_ID_DD_DISK_STATE = 11, + CFG_ID_BUTTON_STATE = 12, + CFG_ID_BUTTON_MODE = 13, + CFG_ID_ROM_EXTENDED_ENABLE = 14, } cfg_id_t; typedef enum { - SETTING_ID_LED_ENABLE, + SETTING_ID_LED_ENABLE = 0, } setting_id_t; typedef enum { @@ -83,6 +85,10 @@ typedef enum { SD_CARD_OP_BYTE_SWAP_OFF = 5, } sd_card_op_t; +typedef enum { + DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE = 0, +} diagnostic_id_t; + typedef enum { SDRAM = (1 << 0), FLASH = (1 << 1), @@ -178,7 +184,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_1M) { + if (save_type >= __SAVE_TYPE_COUNT) { return true; } @@ -225,6 +231,22 @@ static bool cfg_set_save_type (save_type_t save_type) { return false; } +static bool cfg_read_diagnostic_data (uint32_t *args) { + switch (args[0]) { + case DIAGNOSTIC_ID_VOLTAGE_TEMPERATURE: { + uint16_t voltage; + int16_t temperature; + hw_adc_read_voltage_temperature(&voltage, &temperature); + args[1] = ((uint32_t) (voltage) << 16) | ((uint32_t) (temperature)); + break; + } + default: + return true; + } + + return false; +} + uint32_t cfg_get_identifier (void) { return fpga_reg_get(REG_CFG_IDENTIFIER); @@ -373,11 +395,11 @@ bool cfg_update (uint32_t *args) { } bool cfg_query_setting (uint32_t *args) { - rtc_settings_t settings = (*rtc_get_settings()); + rtc_settings_t *settings = rtc_get_settings(); switch (args[0]) { case SETTING_ID_LED_ENABLE: - args[1] = settings.led_enabled; + args[1] = settings->led_enabled; break; default: return true; @@ -387,17 +409,17 @@ bool cfg_query_setting (uint32_t *args) { } bool cfg_update_setting (uint32_t *args) { - rtc_settings_t settings = (*rtc_get_settings()); + rtc_settings_t *settings = rtc_get_settings(); switch (args[0]) { case SETTING_ID_LED_ENABLE: - settings.led_enabled = args[1]; + settings->led_enabled = args[1]; break; default: return true; } - rtc_set_settings(&settings); + rtc_save_settings(); return false; } @@ -450,12 +472,14 @@ void cfg_reset_state (void) { p.boot_mode = BOOT_MODE_MENU; } + void cfg_init (void) { fpga_reg_set(REG_CFG_SCR, CFG_SCR_BOOTLOADER_ENABLED); cfg_reset_state(); p.usb_output_ready = true; } + void cfg_process (void) { uint32_t reg; uint32_t args[2]; @@ -558,12 +582,16 @@ void cfg_process (void) { case SD_CARD_OP_DEINIT: sd_card_deinit(); break; - case SD_CARD_OP_INIT: - if (sd_card_init()) { + case SD_CARD_OP_INIT: { + led_activity_on(); + bool error = sd_card_init(); + led_activity_off(); + if (error) { cfg_set_error(CFG_ERROR_SD_CARD); return; } break; + } case SD_CARD_OP_GET_STATUS: args[1] = sd_card_get_status(); break; @@ -599,7 +627,7 @@ void cfg_process (void) { p.sd_card_sector = args[0]; break; - case 's': + case 's': { if (args[1] >= 0x800000) { cfg_set_error(CFG_ERROR_BAD_ARGUMENT); return; @@ -608,14 +636,18 @@ void cfg_process (void) { cfg_set_error(CFG_ERROR_BAD_ADDRESS); return; } - if (sd_read_sectors(args[0], p.sd_card_sector, args[1])) { + led_activity_on(); + bool error = sd_read_sectors(args[0], p.sd_card_sector, args[1]); + led_activity_off(); + if (error) { cfg_set_error(CFG_ERROR_SD_CARD); return; } p.sd_card_sector += args[1]; break; + } - case 'S': + case 'S': { if (args[1] >= 0x800000) { cfg_set_error(CFG_ERROR_BAD_ARGUMENT); return; @@ -624,12 +656,16 @@ void cfg_process (void) { cfg_set_error(CFG_ERROR_BAD_ADDRESS); return; } - if (sd_write_sectors(args[0], p.sd_card_sector, args[1])) { + led_activity_on(); + bool error = sd_write_sectors(args[0], p.sd_card_sector, args[1]); + led_activity_off(); + if (error) { cfg_set_error(CFG_ERROR_SD_CARD); return; } p.sd_card_sector += args[1]; break; + } case 'D': if (cfg_translate_address(&args[0], args[1], (SDRAM | BRAM))) { @@ -685,6 +721,13 @@ void cfg_process (void) { } break; + case '%': + if (cfg_read_diagnostic_data(args)) { + cfg_set_error(CFG_ERROR_BAD_CONFIG_ID); + return; + } + break; + default: cfg_set_error(CFG_ERROR_UNKNOWN_CMD); return; diff --git a/sw/controller/src/cfg.h b/sw/controller/src/cfg.h index bc3611c..0459fe3 100644 --- a/sw/controller/src/cfg.h +++ b/sw/controller/src/cfg.h @@ -14,6 +14,7 @@ typedef enum { SAVE_TYPE_FLASHRAM = 4, SAVE_TYPE_SRAM_BANKED = 5, SAVE_TYPE_SRAM_1M = 6, + __SAVE_TYPE_COUNT } save_type_t; @@ -27,7 +28,9 @@ save_type_t cfg_get_save_type (void); void cfg_get_time (uint32_t *args); void cfg_set_time (uint32_t *args); void cfg_reset_state (void); + void cfg_init (void); + void cfg_process (void); diff --git a/sw/controller/src/cic.c b/sw/controller/src/cic.c index d67ac5d..a184485 100644 --- a/sw/controller/src/cic.c +++ b/sw/controller/src/cic.c @@ -12,12 +12,7 @@ typedef enum { } cic_region_t; -static bool cic_initialized = false; - - -static void cic_irq_reset_falling (void) { - led_clear_error(LED_ERROR_CIC); -} +static bool cic_error_active = false; void cic_reset_parameters (void) { @@ -26,72 +21,70 @@ void cic_reset_parameters (void) { const uint8_t default_seed = 0x3F; const uint64_t default_checksum = 0xA536C0F1D859ULL; - uint32_t cic_config_0 = (default_seed << CIC_SEED_BIT) | ((default_checksum >> 32) & 0xFFFF); - uint32_t cic_config_1 = (default_checksum & 0xFFFFFFFFUL); + uint32_t cfg[2] = { + (default_seed << CIC_SEED_BIT) | ((default_checksum >> 32) & 0xFFFF), + (default_checksum & 0xFFFFFFFFUL) + }; if (region == REGION_PAL) { - cic_config_0 |= CIC_REGION; + cfg[0] |= CIC_REGION; } - - fpga_reg_set(REG_CIC_0, cic_config_0); - fpga_reg_set(REG_CIC_1, cic_config_1); + + fpga_reg_set(REG_CIC_0, cfg[0]); + fpga_reg_set(REG_CIC_1, cfg[1]); } void cic_set_parameters (uint32_t *args) { - uint32_t cic_config_0 = args[0] & (0x00FFFFFF); - uint32_t cic_config_1 = args[1]; + uint32_t cfg[2] = { + args[0] & (0x00FFFFFF), + args[1] + }; - cic_config_0 |= fpga_reg_get(REG_CIC_0) & (CIC_64DD_MODE | CIC_REGION); + cfg[0] |= fpga_reg_get(REG_CIC_0) & (CIC_64DD_MODE | CIC_REGION); if (args[0] & (1 << 24)) { - cic_config_0 |= CIC_DISABLED; + cfg[0] |= CIC_DISABLED; } - fpga_reg_set(REG_CIC_0, cic_config_0); - fpga_reg_set(REG_CIC_1, cic_config_1); + fpga_reg_set(REG_CIC_0, cfg[0]); + fpga_reg_set(REG_CIC_1, cfg[1]); } void cic_set_dd_mode (bool enabled) { - uint32_t cic_config_0 = fpga_reg_get(REG_CIC_0); + uint32_t cfg = fpga_reg_get(REG_CIC_0); if (enabled) { - cic_config_0 |= CIC_64DD_MODE; + cfg |= CIC_64DD_MODE; } else { - cic_config_0 &= ~(CIC_64DD_MODE); + cfg &= ~(CIC_64DD_MODE); } - fpga_reg_set(REG_CIC_0, cic_config_0); + fpga_reg_set(REG_CIC_0, cfg); } void cic_init (void) { - hw_gpio_irq_setup(GPIO_ID_N64_RESET, GPIO_IRQ_FALLING, cic_irq_reset_falling); + cic_reset_parameters(); } void cic_process (void) { - if (!cic_initialized) { - if (rtc_is_initialized()) { - cic_reset_parameters(); - cic_initialized = true; - } else { - return; - } - } + uint32_t cfg = fpga_reg_get(REG_CIC_0); - uint32_t cic_config_0 = fpga_reg_get(REG_CIC_0); + if (cfg & CIC_INVALID_REGION_DETECTED) { + cfg ^= CIC_REGION; + cfg |= CIC_INVALID_REGION_RESET; + fpga_reg_set(REG_CIC_0, cfg); - if (cic_config_0 & CIC_INVALID_REGION_DETECTED) { - cic_config_0 ^= CIC_REGION; - cic_config_0 |= CIC_INVALID_REGION_RESET; - fpga_reg_set(REG_CIC_0, cic_config_0); - - if (cic_config_0 & CIC_REGION) { - rtc_set_region(REGION_PAL); - } else { - rtc_set_region(REGION_NTSC); - } + cic_region_t region = (cfg & CIC_REGION) ? REGION_PAL : REGION_NTSC; + rtc_set_region(region); + cic_error_active = true; led_blink_error(LED_ERROR_CIC); } + + if (cic_error_active && (!hw_gpio_get(GPIO_ID_N64_RESET))) { + cic_error_active = false; + led_clear_error(LED_ERROR_CIC); + } } diff --git a/sw/controller/src/cic.h b/sw/controller/src/cic.h index 56f006e..6702560 100644 --- a/sw/controller/src/cic.h +++ b/sw/controller/src/cic.h @@ -9,7 +9,9 @@ void cic_reset_parameters (void); void cic_set_parameters (uint32_t *args); void cic_set_dd_mode (bool enabled); + void cic_init (void); + void cic_process (void); diff --git a/sw/controller/src/dd.c b/sw/controller/src/dd.c index 9db7bb3..4b1331a 100644 --- a/sw/controller/src/dd.c +++ b/sw/controller/src/dd.c @@ -1,10 +1,9 @@ -#include #include "dd.h" #include "fpga.h" -#include "hw.h" #include "led.h" #include "rtc.h" #include "sd.h" +#include "timer.h" #include "usb.h" @@ -20,7 +19,7 @@ #define DD_DRIVE_ID_DEVELOPMENT (0x0004) #define DD_VERSION_RETAIL (0x0114) -#define DD_SPIN_UP_TIME (2000) +#define DD_SPIN_UP_TIME_MS (2000) #define DD_THB_UNMAPPED (0xFFFFFFFF) #define DD_THB_WRITABLE_FLAG (1 << 31) @@ -75,7 +74,6 @@ struct process { rtc_time_t time; bool disk_spinning; bool cmd_response_delayed; - bool cmd_response_ready; bool bm_running; bool transfer_mode; bool full_track_transfer; @@ -138,7 +136,9 @@ static bool dd_block_read_request (void) { if (p.sd_mode) { uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE]; uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, false); + led_activity_on(); bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_read_sectors); + led_activity_off(); dd_set_block_ready(!error); } else { usb_tx_info_t packet_info; @@ -160,7 +160,9 @@ static bool dd_block_write_request (void) { if (p.sd_mode) { uint32_t sector_table[DD_SD_SECTOR_TABLE_SIZE]; uint32_t sectors = dd_fill_sd_sector_table(index, sector_table, true); + led_activity_on(); bool error = sd_optimize_sectors(buffer_address, sector_table, sectors, sd_write_sectors); + led_activity_off(); dd_set_block_ready(!error); } else { usb_tx_info_t packet_info; @@ -178,10 +180,6 @@ static bool dd_block_write_request (void) { return true; } -static void dd_set_cmd_response_ready (void) { - p.cmd_response_ready = true; -} - void dd_set_block_ready (bool valid) { p.block_ready = true; @@ -269,7 +267,7 @@ void dd_set_disk_mapping (uint32_t address, uint32_t length) { } void dd_handle_button (void) { - led_blink_act(); + led_activity_pulse(); if (dd_get_disk_state() == DD_DISK_STATE_EJECTED) { dd_set_disk_state(DD_DISK_STATE_INSERTED); } else { @@ -284,13 +282,13 @@ void dd_handle_button (void) { } } + void dd_init (void) { fpga_reg_set(REG_DD_SCR, 0); fpga_reg_set(REG_DD_HEAD_TRACK, 0); fpga_reg_set(REG_DD_DRIVE_ID, DD_DRIVE_ID_RETAIL); p.state = STATE_IDLE; p.cmd_response_delayed = false; - p.cmd_response_ready = false; p.disk_spinning = false; p.bm_running = false; p.drive_type = DD_DRIVE_TYPE_RETAIL; @@ -299,6 +297,7 @@ void dd_init (void) { dd_set_disk_mapping(0, 0); } + void dd_process (void) { uint32_t starting_scr = fpga_reg_get(REG_DD_SCR); uint32_t scr = starting_scr; @@ -306,7 +305,6 @@ void dd_process (void) { if (scr & DD_SCR_HARD_RESET) { p.state = STATE_IDLE; p.cmd_response_delayed = false; - p.cmd_response_ready = false; p.disk_spinning = false; p.bm_running = false; p.head_track = 0; @@ -319,19 +317,16 @@ void dd_process (void) { uint16_t data = cmd_data & 0xFFFF; if (p.cmd_response_delayed) { - if (p.cmd_response_ready) { + if (timer_countdown_elapsed(TIMER_ID_DD)) { p.cmd_response_delayed = false; fpga_reg_set(REG_DD_HEAD_TRACK, DD_HEAD_TRACK_INDEX_LOCK | data); scr |= DD_SCR_CMD_READY; } } else if ((cmd == DD_CMD_SEEK_READ) || (cmd == DD_CMD_SEEK_WRITE)) { p.cmd_response_delayed = true; - p.cmd_response_ready = false; if (!p.disk_spinning) { p.disk_spinning = true; - hw_tim_setup(TIM_ID_DD, DD_SPIN_UP_TIME, dd_set_cmd_response_ready); - } else { - p.cmd_response_ready = true; + timer_countdown_start(TIMER_ID_DD, DD_SPIN_UP_TIME_MS); } fpga_reg_set(REG_DD_HEAD_TRACK, p.head_track & ~(DD_HEAD_TRACK_INDEX_LOCK)); p.head_track = data & DD_HEAD_TRACK_MASK; @@ -397,7 +392,7 @@ void dd_process (void) { fpga_reg_set(REG_DD_CMD_DATA, data); scr |= DD_SCR_CMD_READY; } - } + } if (scr & DD_SCR_BM_STOP) { scr |= DD_SCR_BM_STOP_CLEAR; diff --git a/sw/controller/src/dd.h b/sw/controller/src/dd.h index cdd84fd..4c8b1b0 100644 --- a/sw/controller/src/dd.h +++ b/sw/controller/src/dd.h @@ -27,7 +27,9 @@ bool dd_get_sd_mode (void); void dd_set_sd_mode (bool value); void dd_set_disk_mapping (uint32_t address, uint32_t length); void dd_handle_button (void); + void dd_init (void); + void dd_process (void); diff --git a/sw/controller/src/flashram.c b/sw/controller/src/flashram.c index 4869a44..60bcb91 100644 --- a/sw/controller/src/flashram.c +++ b/sw/controller/src/flashram.c @@ -9,15 +9,15 @@ #define FLASHRAM_BUFFER_ADDRESS (0x05002900UL) -enum operation { +typedef enum { OP_NONE, OP_ERASE_ALL, OP_ERASE_SECTOR, OP_WRITE_PAGE -}; +} flashram_op_t; -static enum operation flashram_operation_type (uint32_t scr) { +static flashram_op_t flashram_operation_type (uint32_t scr) { if (!(scr & FLASHRAM_SCR_PENDING)) { return OP_NONE; } @@ -40,40 +40,47 @@ void flashram_init (void) { } } + void flashram_process (void) { uint32_t scr = fpga_reg_get(REG_FLASHRAM_SCR); - enum operation op = flashram_operation_type(scr); - uint8_t read_buffer[FLASHRAM_PAGE_SIZE]; - uint8_t write_buffer[FLASHRAM_PAGE_SIZE]; - uint32_t address = FLASHRAM_ADDRESS; - uint32_t erase_size = (op == OP_ERASE_SECTOR) ? FLASHRAM_SECTOR_SIZE : FLASHRAM_SIZE; - uint32_t page = (op != OP_ERASE_ALL) ? ((scr & FLASHRAM_SCR_PAGE_MASK) >> FLASHRAM_SCR_PAGE_BIT) : 0; - address += page * FLASHRAM_PAGE_SIZE; - switch (op) { - case OP_ERASE_ALL: - case OP_ERASE_SECTOR: - for (int i = 0; i < FLASHRAM_PAGE_SIZE; i++) { - write_buffer[i] = 0xFF; - } - for (int i = 0; i < erase_size; i += FLASHRAM_PAGE_SIZE) { - fpga_mem_write(address + i, FLASHRAM_PAGE_SIZE, write_buffer); - } - fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE); - break; + flashram_op_t op = flashram_operation_type(scr); - case OP_WRITE_PAGE: - fpga_mem_read(FLASHRAM_BUFFER_ADDRESS, FLASHRAM_PAGE_SIZE, read_buffer); - fpga_mem_read(address, FLASHRAM_PAGE_SIZE, write_buffer); - for (int i = 0; i < FLASHRAM_PAGE_SIZE; i++) { - write_buffer[i] &= read_buffer[i]; - } - fpga_mem_write(address, FLASHRAM_PAGE_SIZE, write_buffer); - fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE); - break; - - case OP_NONE: - default: - break; + if (op == OP_NONE) { + return; } + + uint8_t write_buffer[FLASHRAM_PAGE_SIZE]; + + uint32_t page = ((scr & FLASHRAM_SCR_PAGE_MASK) >> FLASHRAM_SCR_PAGE_BIT); + + if (op == OP_WRITE_PAGE) { + uint8_t page_buffer[FLASHRAM_PAGE_SIZE]; + + uint32_t address = (FLASHRAM_ADDRESS + (page * FLASHRAM_PAGE_SIZE)); + + fpga_mem_read(FLASHRAM_BUFFER_ADDRESS, FLASHRAM_PAGE_SIZE, page_buffer); + fpga_mem_read(address, FLASHRAM_PAGE_SIZE, write_buffer); + + for (int i = 0; i < FLASHRAM_PAGE_SIZE; i++) { + write_buffer[i] &= page_buffer[i]; + } + + fpga_mem_write(address, FLASHRAM_PAGE_SIZE, write_buffer); + } else if ((op == OP_ERASE_SECTOR) || (op == OP_ERASE_ALL)) { + for (int i = 0; i < FLASHRAM_PAGE_SIZE; i++) { + write_buffer[i] = 0xFF; + } + + page &= ~((FLASHRAM_SECTOR_SIZE / FLASHRAM_PAGE_SIZE) - 1); + + uint32_t erase_size = (op == OP_ERASE_ALL) ? FLASHRAM_SIZE : FLASHRAM_SECTOR_SIZE; + uint32_t address = (FLASHRAM_ADDRESS + (page * FLASHRAM_PAGE_SIZE)); + + for (uint32_t offset = 0; offset < erase_size; offset += FLASHRAM_PAGE_SIZE) { + fpga_mem_write(address + offset, FLASHRAM_PAGE_SIZE, write_buffer); + } + } + + fpga_reg_set(REG_FLASHRAM_SCR, FLASHRAM_SCR_DONE); } diff --git a/sw/controller/src/flashram.h b/sw/controller/src/flashram.h index 4fdb24d..d1dbfe0 100644 --- a/sw/controller/src/flashram.h +++ b/sw/controller/src/flashram.h @@ -3,6 +3,7 @@ void flashram_init (void); + void flashram_process (void); diff --git a/sw/controller/src/fpga.c b/sw/controller/src/fpga.c index 9edf7c6..2dc0671 100644 --- a/sw/controller/src/fpga.c +++ b/sw/controller/src/fpga.c @@ -7,8 +7,8 @@ uint8_t fpga_id_get (void) { uint8_t id; hw_spi_start(); - hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX); - hw_spi_trx(&id, 1, SPI_RX); + hw_spi_tx((uint8_t *) (&cmd), 1); + hw_spi_rx(&id, 1); hw_spi_stop(); return id; @@ -19,9 +19,9 @@ uint32_t fpga_reg_get (fpga_reg_t reg) { uint32_t value; hw_spi_start(); - hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX); - hw_spi_trx(®, 1, SPI_TX); - hw_spi_trx((uint8_t *) (&value), 4, SPI_RX); + hw_spi_tx((uint8_t *) (&cmd), 1); + hw_spi_tx(®, 1); + hw_spi_rx((uint8_t *) (&value), 4); hw_spi_stop(); return value; @@ -31,9 +31,9 @@ void fpga_reg_set (fpga_reg_t reg, uint32_t value) { fpga_cmd_t cmd = CMD_REG_WRITE; hw_spi_start(); - hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX); - hw_spi_trx(®, 1, SPI_TX); - hw_spi_trx((uint8_t *) (&value), 4, SPI_TX); + hw_spi_tx((uint8_t *) (&cmd), 1); + hw_spi_tx(®, 1); + hw_spi_tx((uint8_t *) (&value), 4); hw_spi_stop(); } @@ -50,9 +50,9 @@ void fpga_mem_read (uint32_t address, size_t length, uint8_t *buffer) { while (fpga_reg_get(REG_MEM_SCR) & MEM_SCR_BUSY); hw_spi_start(); - hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX); - hw_spi_trx(&buffer_address, 1, SPI_TX); - hw_spi_trx(buffer, length, SPI_RX); + hw_spi_tx((uint8_t *) (&cmd), 1); + hw_spi_tx(&buffer_address, 1); + hw_spi_rx(buffer, length); hw_spi_stop(); } @@ -65,9 +65,9 @@ void fpga_mem_write (uint32_t address, size_t length, uint8_t *buffer) { } hw_spi_start(); - hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX); - hw_spi_trx(&buffer_address, 1, SPI_TX); - hw_spi_trx(buffer, length, SPI_TX); + hw_spi_tx((uint8_t *) (&cmd), 1); + hw_spi_tx(&buffer_address, 1); + hw_spi_tx(buffer, length); hw_spi_stop(); fpga_reg_set(REG_MEM_ADDRESS, address); @@ -95,8 +95,8 @@ uint8_t fpga_usb_status_get (void) { uint8_t status; hw_spi_start(); - hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX); - hw_spi_trx(&status, 1, SPI_RX); + hw_spi_tx((uint8_t *) (&cmd), 1); + hw_spi_rx(&status, 1); hw_spi_stop(); return status; @@ -107,8 +107,8 @@ uint8_t fpga_usb_pop (void) { uint8_t data; hw_spi_start(); - hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX); - hw_spi_trx(&data, 1, SPI_RX); + hw_spi_tx((uint8_t *) (&cmd), 1); + hw_spi_rx(&data, 1); hw_spi_stop(); return data; @@ -118,7 +118,7 @@ void fpga_usb_push (uint8_t data) { fpga_cmd_t cmd = CMD_USB_WRITE; hw_spi_start(); - hw_spi_trx((uint8_t *) (&cmd), 1, SPI_TX); - hw_spi_trx(&data, 1, SPI_TX); + hw_spi_tx((uint8_t *) (&cmd), 1); + hw_spi_tx(&data, 1); hw_spi_stop(); } diff --git a/sw/controller/src/gvr.c b/sw/controller/src/gvr.c deleted file mode 100644 index 70c7909..0000000 --- a/sw/controller/src/gvr.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "button.h" -#include "cfg.h" -#include "cic.h" -#include "dd.h" -#include "flashram.h" -#include "fpga.h" -#include "isv.h" -#include "rtc.h" -#include "sd.h" -#include "usb.h" -#include "writeback.h" - - -void gvr_task (void) { - while (fpga_id_get() != FPGA_ID); - - button_init(); - cfg_init(); - cic_init(); - dd_init(); - flashram_init(); - isv_init(); - sd_init(); - usb_init(); - writeback_init(); - - while (1) { - button_process(); - cfg_process(); - cic_process(); - dd_process(); - flashram_process(); - isv_process(); - rtc_process(); - sd_process(); - usb_process(); - writeback_process(); - } -} diff --git a/sw/controller/src/gvr.h b/sw/controller/src/gvr.h deleted file mode 100644 index 2a782d1..0000000 --- a/sw/controller/src/gvr.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef GVR_H__ -#define GVR_H__ - - -void gvr_task (void); - - -#endif diff --git a/sw/controller/src/hw.c b/sw/controller/src/hw.c index 6b7af28..28fae2d 100644 --- a/sw/controller/src/hw.c +++ b/sw/controller/src/hw.c @@ -1,9 +1,134 @@ +#include #include #include #include "hw.h" -#define UART_BAUD (115200) +#define CPU_FREQ (64000000UL) + + +void hw_set_vector_table (uint32_t offset) { + SCB->VTOR = (__IOM uint32_t) (offset); +} + + +void hw_enter_critical (void) { + __disable_irq(); +} + +void hw_exit_critical (void) { + __enable_irq(); +} + + +static void hw_clock_init (void) { + FLASH->ACR |= (FLASH_ACR_PRFTEN | (2 << FLASH_ACR_LATENCY_Pos)); + while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != (2 << FLASH_ACR_LATENCY_Pos)); + + RCC->PLLCFGR = ( + ((2 - 1) << RCC_PLLCFGR_PLLR_Pos) + | RCC_PLLCFGR_PLLREN + | (16 << RCC_PLLCFGR_PLLN_Pos) + | ((2 - 1) << RCC_PLLCFGR_PLLM_Pos) + | RCC_PLLCFGR_PLLSRC_HSI + ); + + RCC->CR |= RCC_CR_PLLON; + while ((RCC->CR & RCC_CR_PLLRDY_Msk) != RCC_CR_PLLRDY); + + RCC->CFGR = RCC_CFGR_SW_1; + while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_1); +} + + +#define TIMEOUT_US_PER_TICK (10) + +static void hw_timeout_init (void) { + RCC->APBENR1 |= RCC_APBENR1_DBGEN; + DBG->APBFZ2 |= DBG_APB_FZ2_DBG_TIM1_STOP; + + RCC->APBENR2 |= RCC_APBENR2_TIM1EN; + + TIM1->CR1 = TIM_CR1_OPM; + TIM1->PSC = (((CPU_FREQ / 1000 / 1000) * TIMEOUT_US_PER_TICK) - 1); + TIM1->EGR = TIM_EGR_UG; +} + +static void hw_timeout_start (void) { + TIM1->CR1 &= ~(TIM_CR1_CEN); + TIM1->CNT = 0; + TIM1->CR1 |= TIM_CR1_CEN; +} + +static bool hw_timeout_occured (uint32_t timeout_us) { + uint16_t count = TIM1->CNT; + + uint32_t adjusted_timeout = ((timeout_us + (TIMEOUT_US_PER_TICK - 1)) / TIMEOUT_US_PER_TICK); + + if ((count >= adjusted_timeout) || (count == 0xFFFF)) { + return true; + } + + return false; +} + + +#define DELAY_US_PER_TICK (1) +#define DELAY_MS_PER_TICK (1) + +static void hw_delay_init (void) { + RCC->APBENR1 |= RCC_APBENR1_DBGEN; + DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM3_STOP; + + RCC->APBENR1 |= RCC_APBENR1_TIM3EN; + + TIM3->CR1 = TIM_CR1_OPM; + TIM3->EGR = TIM_EGR_UG; +} + +void hw_delay_us (uint32_t delay_us) { + TIM3->CR1 &= ~(TIM_CR1_CEN); + TIM3->PSC = (((CPU_FREQ / 1000 / 1000) * DELAY_US_PER_TICK) - 1); + TIM3->CNT = 0; + TIM3->EGR = TIM_EGR_UG; + TIM3->CR1 |= TIM_CR1_CEN; + + uint32_t adjusted_delay = ((delay_us + (DELAY_US_PER_TICK - 1)) / DELAY_US_PER_TICK); + + uint16_t count; + do { + count = TIM3->CNT; + } while ((count < adjusted_delay) && (count != 0xFFFF)); +} + +void hw_delay_ms (uint32_t delay_ms) { + TIM3->CR1 &= ~(TIM_CR1_CEN); + TIM3->PSC = (((CPU_FREQ / 1000) * DELAY_MS_PER_TICK) - 1); + TIM3->CNT = 0; + TIM3->EGR = TIM_EGR_UG; + TIM3->CR1 |= TIM_CR1_CEN; + + uint32_t adjusted_delay = ((delay_ms + (DELAY_MS_PER_TICK - 1)) / DELAY_MS_PER_TICK); + + uint16_t count; + do { + count = TIM3->CNT; + } while ((count < adjusted_delay) && (count != 0xFFFF)); +} + + +static void (*systick_callback) (void) = NULL; + +void hw_systick_config (uint32_t period_ms, void (*callback) (void)) { + SysTick_Config((CPU_FREQ / 1000) * period_ms); + systick_callback = callback; +} + +void SysTick_Handler (void) { + if (systick_callback) { + systick_callback(); + } +} typedef enum { @@ -42,22 +167,7 @@ typedef enum { GPIO_AF_7 = 0x07 } gpio_af_t; - -typedef struct { - void (*volatile falling)(void); - void (*volatile rising)(void); -} gpio_irq_callback_t; - - static const GPIO_TypeDef *gpios[] = { GPIOA, GPIOB, 0, 0, 0, 0, 0, 0 }; -static gpio_irq_callback_t gpio_irq_callbacks[16]; -static volatile uint8_t *i2c_data_txptr; -static volatile uint8_t *i2c_data_rxptr; -static volatile uint32_t i2c_next_cr2; -static void (*volatile i2c_callback)(void); -static const TIM_TypeDef *tims[] = { TIM14, TIM16, TIM17, TIM3, TIM1 }; -static void (*volatile tim_callbacks[5])(void); - static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_ospeed_t ospeed, gpio_pupd_t pupd, gpio_af_t af, int value) { GPIO_TypeDef tmp; @@ -65,6 +175,8 @@ static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_osp uint8_t pin = (id & 0x0F); uint8_t afr = ((pin < 8) ? 0 : 1); + RCC->IOPENR |= (RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN); + tmp.MODER = (gpio->MODER & ~(GPIO_MODER_MODE0_Msk << (pin * 2))); tmp.OTYPER = (gpio->OTYPER & ~(GPIO_OTYPER_OT0_Msk << pin)); tmp.OSPEEDR = (gpio->OSPEEDR & ~(GPIO_OSPEEDR_OSPEED0_Msk << (pin * 2))); @@ -80,22 +192,6 @@ static void hw_gpio_init (gpio_id_t id, gpio_mode_t mode, gpio_ot_t ot, gpio_osp gpio->MODER = (tmp.MODER | (mode << (pin * 2))); } -void hw_gpio_irq_setup (gpio_id_t id, gpio_irq_t irq, void (*callback)(void)) { - uint8_t port = ((id >> 4) & 0x07); - uint8_t pin = (id & 0x0F); - __disable_irq(); - if (irq == GPIO_IRQ_FALLING) { - EXTI->FTSR1 |= (EXTI_FTSR1_FT0 << pin); - gpio_irq_callbacks[pin].falling = callback; - } else { - EXTI->RTSR1 |= (EXTI_RTSR1_RT0 << pin); - gpio_irq_callbacks[pin].rising = callback; - } - EXTI->EXTICR[pin / 4] |= (port << (8 * (pin % 4))); - EXTI->IMR1 |= (EXTI_IMR1_IM0 << pin); - __enable_irq(); -} - uint32_t hw_gpio_get (gpio_id_t id) { GPIO_TypeDef *gpio = ((GPIO_TypeDef *) (gpios[(id >> 4) & 0x07])); uint8_t pin = (id & 0x0F); @@ -114,6 +210,22 @@ void hw_gpio_reset (gpio_id_t id) { gpio->BSRR = (GPIO_BSRR_BR0 << pin); } + +#define UART_BAUD (115200UL) + +static void hw_uart_init (void) { + RCC->APBENR2 |= (RCC_APBENR2_USART1EN | RCC_APBENR2_SYSCFGEN); + + SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA12_RMP | SYSCFG_CFGR1_PA11_RMP); + + hw_gpio_init(GPIO_ID_UART_TX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0); + hw_gpio_init(GPIO_ID_UART_RX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0); + + USART1->BRR = (CPU_FREQ / UART_BAUD); + USART1->RQR = (USART_RQR_TXFRQ | USART_RQR_RXFRQ); + USART1->CR1 = (USART_CR1_FIFOEN | USART_CR1_M0 | USART_CR1_PCE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE); +} + void hw_uart_read (uint8_t *data, int length) { for (int i = 0; i < length; i++) { while (!(USART1->ISR & USART_ISR_RXNE_RXFNE)); @@ -128,10 +240,42 @@ void hw_uart_write (uint8_t *data, int length) { } } -void hw_uart_wait_busy (void) { +void hw_uart_write_wait_busy (void) { while (!(USART1->ISR & USART_ISR_TC)); } + +static void hw_spi_init (void) { + RCC->AHBENR |= RCC_AHBENR_DMA1EN; + RCC->APBENR2 |= RCC_APBENR2_SPI1EN; + + DMAMUX1_Channel0->CCR = (16 << DMAMUX_CxCR_DMAREQ_ID_Pos); + DMAMUX1_Channel1->CCR = (17 << DMAMUX_CxCR_DMAREQ_ID_Pos); + + DMA1_Channel1->CPAR = (uint32_t) (&SPI1->DR); + DMA1_Channel2->CPAR = (uint32_t) (&SPI1->DR); + + SPI1->CR2 = ( + SPI_CR2_FRXTH | + (8 - 1) << SPI_CR2_DS_Pos | + SPI_CR2_TXDMAEN | + SPI_CR2_RXDMAEN + ); + SPI1->CR1 = ( + SPI_CR1_SSM | + SPI_CR1_SSI | + SPI_CR1_BR_1 | + SPI_CR1_SPE | + SPI_CR1_MSTR | + SPI_CR1_CPHA + ); + + hw_gpio_init(GPIO_ID_SPI_CS, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 1); + hw_gpio_init(GPIO_ID_SPI_CLK, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0); + hw_gpio_init(GPIO_ID_SPI_MOSI, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0); + hw_gpio_init(GPIO_ID_SPI_MISO, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_DOWN, GPIO_AF_0, 0); +} + void hw_spi_start (void) { hw_gpio_reset(GPIO_ID_SPI_CS); } @@ -141,186 +285,149 @@ void hw_spi_stop (void) { hw_gpio_set(GPIO_ID_SPI_CS); } -void hw_spi_trx (uint8_t *data, int length, spi_direction_t direction) { +void hw_spi_rx (uint8_t *data, int length) { + volatile uint8_t dummy = 0x00; + + DMA1_Channel1->CNDTR = length; + DMA1_Channel2->CNDTR = length; + + DMA1_Channel1->CMAR = (uint32_t) (data); + DMA1_Channel1->CCR = (DMA_CCR_MINC | DMA_CCR_EN); + + DMA1_Channel2->CMAR = (uint32_t) (&dummy); + DMA1_Channel2->CCR = (DMA_CCR_DIR | DMA_CCR_EN); + + while (DMA1_Channel1->CNDTR || DMA1_Channel2->CNDTR); + + DMA1_Channel1->CCR = 0; + DMA1_Channel2->CCR = 0; +} + +void hw_spi_tx (uint8_t *data, int length) { volatile uint8_t dummy __attribute__((unused)); DMA1_Channel1->CNDTR = length; DMA1_Channel2->CNDTR = length; - if (direction == SPI_TX) { - DMA1_Channel1->CMAR = (uint32_t) (&dummy); - DMA1_Channel1->CCR = DMA_CCR_EN; + DMA1_Channel1->CMAR = (uint32_t) (&dummy); + DMA1_Channel1->CCR = DMA_CCR_EN; - DMA1_Channel2->CMAR = (uint32_t) (data); - DMA1_Channel2->CCR = (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN); - } else { - DMA1_Channel1->CMAR = (uint32_t) (data); - DMA1_Channel1->CCR = (DMA_CCR_MINC | DMA_CCR_EN); - - DMA1_Channel2->CMAR = (uint32_t) (&dummy); - DMA1_Channel2->CCR = (DMA_CCR_DIR | DMA_CCR_EN); - } + DMA1_Channel2->CMAR = (uint32_t) (data); + DMA1_Channel2->CCR = (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_EN); while (DMA1_Channel1->CNDTR || DMA1_Channel2->CNDTR); - DMA1_Channel1->CCR = 0; + DMA1_Channel1->CCR = 0; DMA1_Channel2->CCR = 0; } -void hw_i2c_read (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)) { - i2c_data_rxptr = data; - i2c_callback = callback; - I2C1->TXDR = address; - i2c_next_cr2 = ( - I2C_CR2_AUTOEND | - (length << I2C_CR2_NBYTES_Pos) | - I2C_CR2_START | - I2C_CR2_RD_WRN | - (i2c_address << I2C_CR2_SADD_Pos) - ); - I2C1->CR2 = ( - (1 << I2C_CR2_NBYTES_Pos) | - I2C_CR2_START | - (i2c_address << I2C_CR2_SADD_Pos) - ); + +#define I2C_TIMEOUT_US_BUSY (10000) +#define I2C_TIMEOUT_US_PER_BYTE (1000) + +static void hw_i2c_init (void) { + RCC->APBENR1 |= RCC_APBENR1_I2C1EN; + + I2C1->CR1 = 0; + + hw_gpio_init(GPIO_ID_I2C_SCL, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0); + hw_gpio_init(GPIO_ID_I2C_SDA, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0); + + while (!(hw_gpio_get(GPIO_ID_I2C_SCL) && hw_gpio_get(GPIO_ID_I2C_SDA))); + + I2C1->TIMINGR = 0x10901032UL; + I2C1->CR1 |= I2C_CR1_PE; } -void hw_i2c_write (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)) { - i2c_data_txptr = data; - i2c_callback = callback; - I2C1->TXDR = address; - I2C1->CR2 = ( - I2C_CR2_AUTOEND | - ((length + 1) << I2C_CR2_NBYTES_Pos) | - I2C_CR2_START | - (i2c_address << I2C_CR2_SADD_Pos) - ); -} +i2c_err_t hw_i2c_trx (uint8_t address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length) { + hw_timeout_start(); -uint32_t hw_i2c_get_error (void) { - return (I2C1->ISR & I2C_ISR_NACKF); -} - -void hw_i2c_raw (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length) { - while (I2C1->ISR & I2C_ISR_BUSY); + while (I2C1->ISR & I2C_ISR_BUSY) { + if (hw_timeout_occured(I2C_TIMEOUT_US_BUSY)) { + return I2C_ERR_BUSY; + } + } if (tx_length > 0) { + uint32_t tx_timeout = ((tx_length + 1) * I2C_TIMEOUT_US_PER_BYTE); + + hw_timeout_start(); + I2C1->ICR = I2C_ICR_NACKCF; I2C1->CR2 = ( - ((rx_length == 0) ? I2C_CR2_AUTOEND : 0) | + ((rx_length > 0) ? 0 : I2C_CR2_AUTOEND) | (tx_length << I2C_CR2_NBYTES_Pos) | I2C_CR2_START | - (i2c_address << I2C_CR2_SADD_Pos) + (address << I2C_CR2_SADD_Pos) ); - for (int i = 0; i < tx_length; i++) { - while (!(I2C1->ISR & I2C_ISR_TXIS)); - I2C1->TXDR = *tx_data++; + + uint8_t left = tx_length; + + while (left > 0) { + uint32_t isr = I2C1->ISR; + + if (isr & I2C_ISR_TXIS) { + I2C1->TXDR = *tx_data++; + left -= 1; + } + + if (isr & I2C_ISR_NACKF) { + return I2C_ERR_NACK; + } + + if (hw_timeout_occured(tx_timeout)) { + return I2C_ERR_TIMEOUT; + } } - if (!(I2C1->CR2 & I2C_CR2_AUTOEND)) { - while (!(I2C1->ISR & (I2C_ISR_NACKF | I2C_ISR_TC))); + + if (rx_length == 0) { + return I2C_OK; + } + + while (!(I2C1->ISR & I2C_ISR_TC)) { + if (hw_timeout_occured(tx_timeout)) { + return I2C_ERR_TIMEOUT; + } } } if (rx_length > 0) { + uint32_t rx_timeout = ((rx_length + 1) * I2C_TIMEOUT_US_PER_BYTE); + + hw_timeout_start(); + I2C1->CR2 = ( I2C_CR2_AUTOEND | (rx_length << I2C_CR2_NBYTES_Pos) | I2C_CR2_START | I2C_CR2_RD_WRN | - (i2c_address << I2C_CR2_SADD_Pos) + (address << I2C_CR2_SADD_Pos) ); - for (int i = 0; i < rx_length; i++) { - while (!(I2C1->ISR & I2C_ISR_RXNE)); - *rx_data++ = I2C1->RXDR; + + uint8_t left = rx_length; + + while (left > 0) { + uint32_t isr = I2C1->ISR; + + if (isr & I2C_ISR_RXNE) { + *rx_data++ = I2C1->RXDR; + left -= 1; + } + + if (hw_timeout_occured(rx_timeout)) { + return I2C_ERR_TIMEOUT; + } } } - if ((tx_length > 0) || (rx_length > 0)) { - while (!(I2C1->ISR & I2C_ISR_STOPF)); - } + return I2C_OK; } -void hw_i2c_disable_irq (void) { - NVIC_DisableIRQ(I2C1_IRQn); -} -void hw_i2c_enable_irq (void) { - NVIC_EnableIRQ(I2C1_IRQn); -} +static void hw_crc32_init (void) { + RCC->AHBENR |= RCC_AHBENR_CRCEN; -void hw_tim_setup (tim_id_t id, uint16_t delay, void (*callback)(void)) { - if (delay == 0) { - if (callback) { - callback(); - } - return; - } - TIM_TypeDef *tim = ((TIM_TypeDef *) (tims[id])); - tim->CR1 = (TIM_CR1_OPM | TIM_CR1_URS); - tim->PSC = (64000 - 1); - tim->ARR = delay; - tim->DIER = TIM_DIER_UIE; - tim->EGR = TIM_EGR_UG; - tim->SR = 0; - tim->CR1 |= TIM_CR1_CEN; - tim_callbacks[id] = callback; -} - -void hw_tim_stop (tim_id_t id) { - TIM_TypeDef *tim = ((TIM_TypeDef *) (tims[id])); - tim->CR1 &= ~(TIM_CR1_CEN); - tim_callbacks[id] = 0; -} - -void hw_tim_disable_irq (tim_id_t id) { - switch (id) { - case TIM_ID_CIC: - NVIC_DisableIRQ(TIM14_IRQn); - break; - case TIM_ID_RTC: - NVIC_DisableIRQ(TIM16_IRQn); - break; - case TIM_ID_SD: - NVIC_DisableIRQ(TIM17_IRQn); - break; - case TIM_ID_DD: - NVIC_DisableIRQ(TIM3_IRQn); - break; - case TIM_ID_LED: - NVIC_DisableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); - break; - default: - break; - } -} - -void hw_tim_enable_irq (tim_id_t id) { - switch (id) { - case TIM_ID_CIC: - NVIC_EnableIRQ(TIM14_IRQn); - break; - case TIM_ID_RTC: - NVIC_EnableIRQ(TIM16_IRQn); - break; - case TIM_ID_SD: - NVIC_EnableIRQ(TIM17_IRQn); - break; - case TIM_ID_DD: - NVIC_EnableIRQ(TIM3_IRQn); - break; - case TIM_ID_LED: - NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); - break; - default: - break; - } -} - -void hw_delay_ms (uint32_t ms) { - SysTick->VAL = 0; - for (uint32_t i = 0; i < ms; i++) { - while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); - } + CRC->CR = (CRC_CR_REV_OUT | CRC_CR_REV_IN_0); } void hw_crc32_reset (void) { @@ -334,10 +441,15 @@ uint32_t hw_crc32_calculate (uint8_t *data, uint32_t length) { return (CRC->DR ^ 0xFFFFFFFF); } + uint32_t hw_flash_size (void) { return FLASH_SIZE; } +hw_flash_t hw_flash_read (uint32_t offset) { + return *(uint64_t *) (FLASH_BASE + offset); +} + static void hw_flash_unlock (void) { while (FLASH->SR & FLASH_SR_BSY1); if (FLASH->CR & FLASH_CR_LOCK) { @@ -363,13 +475,10 @@ void hw_flash_program (uint32_t offset, hw_flash_t value) { FLASH->CR &= ~(FLASH_CR_PG); } -hw_flash_t hw_flash_read (uint32_t offset) { - return *(uint64_t *) (FLASH_BASE + offset); -} void hw_reset (loader_parameters_t *parameters) { if (parameters != NULL) { - RCC->APBENR1 |= RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN; + RCC->APBENR1 |= (RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN); PWR->CR1 |= PWR_CR1_DBP; TAMP->BKP0R = parameters->magic; TAMP->BKP1R = parameters->flags; @@ -382,8 +491,9 @@ void hw_reset (loader_parameters_t *parameters) { NVIC_SystemReset(); } + void hw_loader_get_parameters (loader_parameters_t *parameters) { - RCC->APBENR1 |= RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN; + RCC->APBENR1 |= (RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN); parameters->magic = TAMP->BKP0R; parameters->flags = TAMP->BKP1R; parameters->mcu_address = TAMP->BKP2R; @@ -399,280 +509,104 @@ void hw_loader_get_parameters (loader_parameters_t *parameters) { RCC->APBENR1 &= ~(RCC_APBENR1_PWREN | RCC_APBENR1_RTCAPBEN); } -static void hw_init_mcu (void) { - FLASH->ACR |= (FLASH_ACR_PRFTEN | (2 << FLASH_ACR_LATENCY_Pos)); - while ((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != (2 << FLASH_ACR_LATENCY_Pos)); - RCC->PLLCFGR = ( - ((2 - 1) << RCC_PLLCFGR_PLLR_Pos) - | RCC_PLLCFGR_PLLREN - | (16 << RCC_PLLCFGR_PLLN_Pos) - | ((2 - 1) << RCC_PLLCFGR_PLLM_Pos) - | RCC_PLLCFGR_PLLSRC_HSI - ); +#define ADC_VREF_CAL_POINT (3000) +#define ADC_VREF_CAL_VALUE (*(uint16_t *) (0x1FFF75AAUL)) - RCC->CR |= RCC_CR_PLLON; - while ((RCC->CR & RCC_CR_PLLRDY_Msk) != RCC_CR_PLLRDY); +#define TEMP_CAL_POINT_1 (30) +#define TEMP_CAL_VALUE_1 (*(uint16_t *) (0x1FFF75A8UL)) - RCC->CFGR = RCC_CFGR_SW_1; - while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_1); +#define TEMP_CAL_POINT_2 (130) +#define TEMP_CAL_VALUE_2 (*(uint16_t *) (0x1FFF75CAUL)) - RCC->IOPENR |= RCC_IOPENR_GPIOAEN | RCC_IOPENR_GPIOBEN; +#define TEMP_CAL_VREF (3000) - SysTick->LOAD = (((64000000 / 1000)) - 1); - SysTick->VAL = 0; - SysTick->CTRL = (SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk); +#define TEMP_SCALE (10) +static void hw_adc_init (void) { + RCC->APBENR2 |= RCC_APBENR2_ADCEN; + + ADC1->CFGR2 = ADC_CFGR2_CKMODE_1; + + ADC->CCR = (ADC_CCR_TSEN | ADC_CCR_VREFEN); + ADC1->CR = ADC_CR_ADVREGEN; + + hw_delay_us(120); + + ADC1->ISR = ADC_ISR_EOCAL; + ADC1->CR |= ADC_CR_ADCAL; + while (!(ADC1->ISR & ADC_ISR_EOCAL)); + + ADC1->CFGR1 = (ADC_CFGR1_AUTOFF | ADC_CFGR1_WAIT | ADC_CFGR1_SCANDIR); + ADC1->CFGR2 |= (ADC_CFGR2_OVSS_2 | ADC_CFGR2_OVSR_1 | ADC_CFGR2_OVSR_0 | ADC_CFGR2_OVSE); + ADC1->SMPR = (ADC_SMPR_SMP1_2 | ADC_SMPR_SMP1_1 | ADC_SMPR_SMP1_0); + + ADC1->ISR = ADC_ISR_CCRDY; + ADC1->CHSELR = (ADC_CHSELR_CHSEL13 | ADC_CHSELR_CHSEL12); + while (!(ADC1->ISR & ADC_ISR_CCRDY)); + + ADC1->CR |= ADC_CR_ADEN; +} + +void hw_adc_read_voltage_temperature (uint16_t *voltage, int16_t *temperature) { + ADC1->CR |= ADC_CR_ADSTART; + + while (!(ADC1->ISR & ADC_ISR_EOC)); + uint16_t adc_vref = ((ADC_VREF_CAL_POINT * ADC_VREF_CAL_VALUE) / ADC1->DR); + + while (!(ADC1->ISR & ADC_ISR_EOC)); + int16_t adc_temp = ((ADC1->DR * adc_vref) / TEMP_CAL_VREF); + + *voltage = adc_vref; + *temperature = ( + ((adc_temp - TEMP_CAL_VALUE_1) * (TEMP_CAL_POINT_2 - TEMP_CAL_POINT_1) * TEMP_SCALE) / + (TEMP_CAL_VALUE_2 - TEMP_CAL_VALUE_1) + ) + (TEMP_CAL_POINT_1 * TEMP_SCALE); +} + + +static void hw_led_init (void) { hw_gpio_init(GPIO_ID_LED, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_0, 0); } -static void hw_init_spi (void) { - RCC->AHBENR |= RCC_AHBENR_DMA1EN; - RCC->APBENR2 |= RCC_APBENR2_SPI1EN; - DMAMUX1_Channel0->CCR = (16 << DMAMUX_CxCR_DMAREQ_ID_Pos); - DMAMUX1_Channel1->CCR = (17 << DMAMUX_CxCR_DMAREQ_ID_Pos); - - DMA1_Channel1->CPAR = (uint32_t) (&SPI1->DR); - DMA1_Channel2->CPAR = (uint32_t) (&SPI1->DR); - - SPI1->CR2 = ( - SPI_CR2_FRXTH | - (8 - 1) << SPI_CR2_DS_Pos | - SPI_CR2_TXDMAEN | - SPI_CR2_RXDMAEN - ); - SPI1->CR1 = ( - SPI_CR1_SSM | - SPI_CR1_SSI | - SPI_CR1_BR_1 | - SPI_CR1_SPE | - SPI_CR1_MSTR | - SPI_CR1_CPHA - ); - - hw_gpio_init(GPIO_ID_SPI_CS, GPIO_OUTPUT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 1); - hw_gpio_init(GPIO_ID_SPI_CLK, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0); - hw_gpio_init(GPIO_ID_SPI_MISO, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_DOWN, GPIO_AF_0, 0); - hw_gpio_init(GPIO_ID_SPI_MOSI, GPIO_ALT, GPIO_PP, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_AF_0, 0); -} - -static void hw_init_i2c (void) { - RCC->APBENR1 |= RCC_APBENR1_I2C1EN; - - I2C1->TIMINGR = 0x80821B20UL; - I2C1->CR1 |= (I2C_CR1_TCIE | I2C_CR1_STOPIE | I2C_CR1_RXIE | I2C_CR1_TXIE | I2C_CR1_PE); - - hw_gpio_init(GPIO_ID_I2C_SCL, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0); - hw_gpio_init(GPIO_ID_I2C_SDA, GPIO_ALT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_NONE, GPIO_AF_6, 0); -} - -static void hw_init_uart (void) { - RCC->APBENR2 |= (RCC_APBENR2_USART1EN | RCC_APBENR2_SYSCFGEN); - - SYSCFG->CFGR1 |= (SYSCFG_CFGR1_PA12_RMP | SYSCFG_CFGR1_PA11_RMP); - - hw_gpio_init(GPIO_ID_UART_TX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0); - hw_gpio_init(GPIO_ID_UART_RX, GPIO_ALT, GPIO_PP, GPIO_SPEED_LOW, GPIO_PULL_UP, GPIO_AF_1, 0); - - USART1->BRR = (64000000UL) / UART_BAUD; - USART1->RQR = USART_RQR_TXFRQ | USART_RQR_RXFRQ; - USART1->CR1 = USART_CR1_FIFOEN | USART_CR1_M0 | USART_CR1_PCE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; -} - -static void hw_init_tim (void) { - RCC->APBENR1 |= ( - RCC_APBENR1_DBGEN | - RCC_APBENR1_TIM3EN - ); - RCC->APBENR2 |= ( - RCC_APBENR2_TIM17EN | - RCC_APBENR2_TIM16EN | - RCC_APBENR2_TIM14EN | - RCC_APBENR2_USART1EN | - RCC_APBENR2_TIM1EN - ); - - DBG->APBFZ1 |= DBG_APB_FZ1_DBG_TIM3_STOP; - DBG->APBFZ2 |= ( - DBG_APB_FZ2_DBG_TIM17_STOP | - DBG_APB_FZ2_DBG_TIM16_STOP | - DBG_APB_FZ2_DBG_TIM14_STOP | - DBG_APB_FZ2_DBG_TIM1_STOP - ); -} - -static void hw_init_crc (void) { - RCC->AHBENR |= RCC_AHBENR_CRCEN; - - CRC->CR = (CRC_CR_REV_OUT | CRC_CR_REV_IN_0); -} - -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_UP, GPIO_AF_0, 0); +static void hw_misc_init (void) { + hw_gpio_init(GPIO_ID_N64_RESET, GPIO_INPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_DOWN, GPIO_AF_0, 0); + hw_gpio_init(GPIO_ID_N64_CIC_CLK, GPIO_INPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0); hw_gpio_init(GPIO_ID_N64_CIC_DQ, GPIO_INPUT, 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); + hw_gpio_init(GPIO_ID_FPGA_INT, GPIO_INPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0); + hw_gpio_init(GPIO_ID_RTC_MFP, GPIO_INPUT, GPIO_OD, GPIO_SPEED_VLOW, GPIO_PULL_UP, GPIO_AF_0, 0); } -void hw_set_vector_table (uint32_t offset) { - SCB->VTOR = (__IOM uint32_t) (offset); -} -void hw_init (void) { - hw_init_mcu(); - hw_init_spi(); - hw_init_i2c(); - hw_init_uart(); - hw_init_tim(); - hw_init_crc(); - hw_init_misc(); - - NVIC_SetPriority(EXTI0_1_IRQn, 0); - NVIC_SetPriority(EXTI2_3_IRQn, 0); - NVIC_SetPriority(EXTI4_15_IRQn, 0); - NVIC_SetPriority(I2C1_IRQn, 0); - NVIC_SetPriority(TIM14_IRQn, 0); - NVIC_SetPriority(TIM16_IRQn, 0); - NVIC_SetPriority(TIM17_IRQn, 0); - NVIC_SetPriority(TIM3_IRQn, 0); - NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 0); - - NVIC_EnableIRQ(EXTI0_1_IRQn); - NVIC_EnableIRQ(EXTI2_3_IRQn); - NVIC_EnableIRQ(EXTI4_15_IRQn); - NVIC_EnableIRQ(I2C1_IRQn); - NVIC_EnableIRQ(TIM14_IRQn); - NVIC_EnableIRQ(TIM16_IRQn); - NVIC_EnableIRQ(TIM17_IRQn); - NVIC_EnableIRQ(TIM3_IRQn); - NVIC_EnableIRQ(TIM1_BRK_UP_TRG_COM_IRQn); +void hw_primer_init (void) { + hw_clock_init(); + hw_timeout_init(); + hw_delay_init(); + hw_led_init(); + hw_uart_init(); + hw_spi_init(); + hw_i2c_init(); + hw_crc32_init(); } void hw_loader_init (void) { - hw_init_mcu(); - hw_init_spi(); + hw_clock_init(); + hw_timeout_init(); + hw_delay_init(); + hw_led_init(); + hw_spi_init(); } -void hw_primer_init (void) { - hw_init_mcu(); - hw_init_spi(); - hw_init_i2c(); - hw_init_uart(); - hw_init_crc(); -} - - -void EXTI0_1_IRQHandler (void) { - for (int i = 0; i <= 1; i++) { - if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) { - EXTI->FPR1 = (EXTI_FPR1_FPIF0 << i); - if (gpio_irq_callbacks[i].falling) { - gpio_irq_callbacks[i].falling(); - } - } - if (EXTI->RPR1 & (EXTI_RPR1_RPIF0 << i)) { - EXTI->RPR1 = (EXTI_RPR1_RPIF0 << i); - if (gpio_irq_callbacks[i].rising) { - gpio_irq_callbacks[i].rising(); - } - } - } -} - -void EXTI2_3_IRQHandler (void) { - for (int i = 2; i <= 3; i++) { - if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) { - EXTI->FPR1 = (EXTI_FPR1_FPIF0 << i); - if (gpio_irq_callbacks[i].falling) { - gpio_irq_callbacks[i].falling(); - } - } - if (EXTI->RPR1 & (EXTI_RPR1_RPIF0 << i)) { - EXTI->RPR1 = (EXTI_RPR1_RPIF0 << i); - if (gpio_irq_callbacks[i].rising) { - gpio_irq_callbacks[i].rising(); - } - } - } -} - -void EXTI4_15_IRQHandler (void) { - for (int i = 4; i <= 15; i++) { - if (EXTI->FPR1 & (EXTI_FPR1_FPIF0 << i)) { - EXTI->FPR1 = (EXTI_FPR1_FPIF0 << i); - if (gpio_irq_callbacks[i].falling) { - gpio_irq_callbacks[i].falling(); - } - } - if (EXTI->RPR1 & (EXTI_RPR1_RPIF0 << i)) { - EXTI->RPR1 = (EXTI_RPR1_RPIF0 << i); - if (gpio_irq_callbacks[i].rising) { - gpio_irq_callbacks[i].rising(); - } - } - } -} - -void I2C1_IRQHandler (void) { - if (I2C1->ISR & I2C_ISR_TXIS) { - I2C1->TXDR = *i2c_data_txptr++; - } - - if (I2C1->ISR & I2C_ISR_RXNE) { - *i2c_data_rxptr++ = I2C1->RXDR; - } - - if (I2C1->ISR & I2C_ISR_TC) { - I2C1->CR2 = i2c_next_cr2; - } - - if (I2C1->ISR & I2C_ISR_STOPF) { - I2C1->ICR = I2C_ICR_STOPCF; - if (i2c_callback) { - i2c_callback(); - i2c_callback = 0; - } - } -} - -void TIM14_IRQHandler (void) { - TIM14->SR &= ~(TIM_SR_UIF); - if (tim_callbacks[0]) { - tim_callbacks[0](); - tim_callbacks[0] = 0; - } -} - -void TIM16_IRQHandler (void) { - TIM16->SR &= ~(TIM_SR_UIF); - if (tim_callbacks[1]) { - tim_callbacks[1](); - tim_callbacks[1] = 0; - } -} - -void TIM17_IRQHandler (void) { - TIM17->SR &= ~(TIM_SR_UIF); - if (tim_callbacks[2]) { - tim_callbacks[2](); - tim_callbacks[2] = 0; - } -} - -void TIM3_IRQHandler (void) { - TIM3->SR &= ~(TIM_SR_UIF); - if (tim_callbacks[3]) { - tim_callbacks[3](); - tim_callbacks[3] = 0; - } -} - -void TIM1_BRK_UP_TRG_COM_IRQHandler (void) { - TIM1->SR &= ~(TIM_SR_UIF); - if (tim_callbacks[4]) { - tim_callbacks[4](); - tim_callbacks[4] = 0; - } +void hw_app_init (void) { + hw_clock_init(); + hw_timeout_init(); + hw_delay_init(); + hw_adc_init(); + hw_led_init(); + hw_misc_init(); + hw_uart_init(); + hw_spi_init(); + hw_i2c_init(); + hw_crc32_init(); } diff --git a/sw/controller/src/hw.h b/sw/controller/src/hw.h index 6daaaea..d9f2d05 100644 --- a/sw/controller/src/hw.h +++ b/sw/controller/src/hw.h @@ -7,6 +7,7 @@ #define GPIO_PORT_PIN(p, n) ((((p) & 0x07) << 4) | ((n) & 0x0F)) + typedef enum { GPIO_ID_N64_RESET = GPIO_PORT_PIN(0, 0), GPIO_ID_N64_CIC_CLK = GPIO_PORT_PIN(0, 1), @@ -25,22 +26,11 @@ typedef enum { } gpio_id_t; typedef enum { - GPIO_IRQ_FALLING = 0b01, - GPIO_IRQ_RISING = 0b10, -} gpio_irq_t; - -typedef enum { - TIM_ID_CIC = 0, - TIM_ID_RTC = 1, - TIM_ID_SD = 2, - TIM_ID_DD = 3, - TIM_ID_LED = 4, -} tim_id_t; - -typedef enum { - SPI_TX, - SPI_RX, -} spi_direction_t; + I2C_OK, + I2C_ERR_BUSY, + I2C_ERR_TIMEOUT, + I2C_ERR_NACK, +} i2c_err_t; typedef uint64_t hw_flash_t; @@ -59,39 +49,48 @@ typedef struct { } loader_parameters_t; -void hw_gpio_irq_setup (gpio_id_t id, gpio_irq_t irq, void (*callback)(void)); +void hw_set_vector_table (uint32_t offset); + +void hw_enter_critical (void); +void hw_exit_critical (void); + +void hw_delay_us (uint32_t delay_us); +void hw_delay_ms (uint32_t delay_ms); + +void hw_systick_config (uint32_t period_ms, void (*callback) (void)); + uint32_t hw_gpio_get (gpio_id_t id); void hw_gpio_set (gpio_id_t id); void hw_gpio_reset (gpio_id_t id); + void hw_uart_read (uint8_t *data, int length); void hw_uart_write (uint8_t *data, int length); -void hw_uart_wait_busy (void); +void hw_uart_write_wait_busy (void); + void hw_spi_start (void); void hw_spi_stop (void); -void hw_spi_trx (uint8_t *data, int length, spi_direction_t direction); -void hw_i2c_read (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)); -void hw_i2c_write (uint8_t i2c_address, uint8_t address, uint8_t *data, uint8_t length, void (*callback)(void)); -uint32_t hw_i2c_get_error (void); -void hw_i2c_raw (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length); -void hw_i2c_disable_irq (void); -void hw_i2c_enable_irq (void); -void hw_tim_setup (tim_id_t id, uint16_t delay, void (*callback)(void)); -void hw_tim_stop (tim_id_t id); -void hw_tim_disable_irq (tim_id_t id); -void hw_tim_enable_irq (tim_id_t id); -void hw_delay_ms (uint32_t ms); +void hw_spi_rx (uint8_t *data, int length); +void hw_spi_tx (uint8_t *data, int length); + +i2c_err_t hw_i2c_trx (uint8_t i2c_address, uint8_t *tx_data, uint8_t tx_length, uint8_t *rx_data, uint8_t rx_length); + void hw_crc32_reset (void); uint32_t hw_crc32_calculate (uint8_t *data, uint32_t length); + uint32_t hw_flash_size (void); +hw_flash_t hw_flash_read (uint32_t offset); void hw_flash_erase (void); void hw_flash_program (uint32_t offset, hw_flash_t value); -hw_flash_t hw_flash_read (uint32_t offset); + void hw_reset (loader_parameters_t *parameters); + void hw_loader_get_parameters (loader_parameters_t *parameters); -void hw_set_vector_table (uint32_t offset); -void hw_init (void); -void hw_loader_init (void); + +void hw_adc_read_voltage_temperature (uint16_t *voltage, int16_t *temperature); + void hw_primer_init (void); +void hw_loader_init (void); +void hw_app_init (void); #endif diff --git a/sw/controller/src/isv.c b/sw/controller/src/isv.c index 4dbcee5..af3e25d 100644 --- a/sw/controller/src/isv.c +++ b/sw/controller/src/isv.c @@ -57,11 +57,13 @@ uint32_t isv_get_address (void) { return p.address; } + void isv_init (void) { p.address = 0; p.ready = true; } + void isv_process (void) { if ((p.address != 0) && p.ready) { if (isv_get_value(ISV_SETUP_TOKEN_ADDRESS) == ISV_TOKEN) { diff --git a/sw/controller/src/isv.h b/sw/controller/src/isv.h index 04ae2de..639b6f6 100644 --- a/sw/controller/src/isv.h +++ b/sw/controller/src/isv.h @@ -8,7 +8,9 @@ bool isv_set_address (uint32_t address); uint32_t isv_get_address (void); + void isv_init (void); + void isv_process (void); diff --git a/sw/controller/src/lcmxo2.c b/sw/controller/src/lcmxo2.c index de8535c..d7a5a56 100644 --- a/sw/controller/src/lcmxo2.c +++ b/sw/controller/src/lcmxo2.c @@ -114,27 +114,33 @@ static void lcmxo2_write_data (uint8_t *buffer, uint32_t length) { static void lcmxo2_reset_bus (void) { #ifdef LCMXO2_I2C uint8_t reset_data = 0; - hw_i2c_raw(LCMXO2_I2C_ADDR_RESET, &reset_data, sizeof(reset_data), NULL, 0); + hw_i2c_trx(LCMXO2_I2C_ADDR_RESET, &reset_data, sizeof(reset_data), NULL, 0); #else lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_RSTE); lcmxo2_reg_set(LCMXO2_CFGCR, 0); #endif } -static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint8_t *buffer, uint8_t length, bool write) { +static bool lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint8_t *buffer, uint8_t length, bool write) { #ifdef LCMXO2_I2C uint8_t packet[20] = { cmd, ((arg >> 16) & 0xFF), ((arg >> 8) & 0xFF), (arg & 0xFF) }; int packet_length = ((type == CMD_TWO_OP) ? 3 : 4); + if (write) { for (int i = 0; i < length; i++) { packet[packet_length + i] = buffer[i]; } packet_length += length; } - hw_i2c_raw(LCMXO2_I2C_ADDR_CFG, packet, packet_length, buffer, (write ? 0 : length)); + + i2c_err_t err = hw_i2c_trx(LCMXO2_I2C_ADDR_CFG, packet, packet_length, buffer, (write ? 0 : length)); + + return (err != I2C_OK); #else - uint32_t data = (cmd << 24) | (arg & 0x00FFFFFF); lcmxo2_reg_set(LCMXO2_CFGCR, CFGCR_WBCE); + + uint32_t data = (cmd << 24) | (arg & 0x00FFFFFF); + fpga_reg_set(REG_VENDOR_DATA, data); fpga_reg_set(REG_VENDOR_SCR, (LCMXO2_CFGTXDR << VENDOR_SCR_ADDRESS_BIT) | @@ -143,7 +149,9 @@ static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint VENDOR_SCR_WRITE | VENDOR_SCR_START ); + while (fpga_reg_get(REG_VENDOR_SCR) & VENDOR_SCR_BUSY); + if (length > 0) { if (write) { lcmxo2_write_data(buffer, length); @@ -151,82 +159,105 @@ static void lcmxo2_execute_cmd (uint8_t cmd, uint32_t arg, cmd_type_t type, uint lcmxo2_read_data(buffer, length); } } + lcmxo2_reg_set(LCMXO2_CFGCR, 0); + + return false; #endif } -static void lcmxo2_read_device_id (uint8_t *id) { - lcmxo2_execute_cmd(IDCODE_PUB, 0, CMD_NORMAL, id, DEVICE_ID_SIZE, false); +static bool lcmxo2_read_device_id (uint8_t *id) { + return lcmxo2_execute_cmd(IDCODE_PUB, 0, CMD_NORMAL, id, DEVICE_ID_SIZE, false); } -static uint32_t lcmxo2_read_status (void) { - uint32_t status = 0; - lcmxo2_execute_cmd(LSC_READ_STATUS, 0, CMD_NORMAL, (uint8_t *) (&status), 4, false); - return SWAP32(status); +static uint32_t lcmxo2_read_status (uint32_t *status) { + uint32_t tmp = 0; + bool error = lcmxo2_execute_cmd(LSC_READ_STATUS, 0, CMD_NORMAL, (uint8_t *) (&tmp), 4, false); + *status = SWAP32(tmp); + return error; } static bool lcmxo2_wait_busy (void) { + bool error; uint32_t status; do { - status = lcmxo2_read_status(); - } while(status & LSC_STATUS_BUSY); - return (status & LSC_STATUS_FAIL); + error = lcmxo2_read_status(&status); + } while ((!error) && (status & LSC_STATUS_BUSY)); + return (error) || (status & LSC_STATUS_FAIL); } static bool lcmxo2_enable_flash (void) { #ifdef LCMXO2_I2C - lcmxo2_execute_cmd(ISC_ENABLE, 0x080000, CMD_TWO_OP, NULL, 0, false); + if (lcmxo2_execute_cmd(ISC_ENABLE, 0x080000, CMD_TWO_OP, NULL, 0, false)) { + return true; + } #else - lcmxo2_execute_cmd(ISC_ENABLE_X, 0x080000, CMD_NORMAL, NULL, 0, false); + if (lcmxo2_execute_cmd(ISC_ENABLE_X, 0x080000, CMD_NORMAL, NULL, 0, false)) { + return true; + } #endif return lcmxo2_wait_busy(); } -static void lcmxo2_disable_flash (void) { - lcmxo2_wait_busy(); - lcmxo2_execute_cmd(ISC_DISABLE, 0, CMD_TWO_OP, NULL, 0, false); - lcmxo2_execute_cmd(ISC_NOOP, 0xFFFFFF, CMD_NORMAL, NULL, 0, false); +static bool lcmxo2_disable_flash (void) { + if (lcmxo2_wait_busy()) { + return true; + } + if (lcmxo2_execute_cmd(ISC_DISABLE, 0, CMD_TWO_OP, NULL, 0, false)) { + return true; + } + return lcmxo2_execute_cmd(ISC_NOOP, 0xFFFFFF, CMD_NORMAL, NULL, 0, false); } static bool lcmxo2_erase_featbits (void) { - lcmxo2_execute_cmd(ISC_ERASE, ISC_ERASE_FEATURE, CMD_NORMAL, NULL, 0, false); + if (lcmxo2_execute_cmd(ISC_ERASE, ISC_ERASE_FEATURE, CMD_NORMAL, NULL, 0, false)) { + return true; + } return lcmxo2_wait_busy(); } static bool lcmxo2_erase_flash (void) { - lcmxo2_execute_cmd(ISC_ERASE, (ISC_ERASE_UFM | ISC_ERASE_CFG), CMD_NORMAL, NULL, 0, false); + if (lcmxo2_execute_cmd(ISC_ERASE, (ISC_ERASE_UFM | ISC_ERASE_CFG), CMD_NORMAL, NULL, 0, false)) { + return true; + } return lcmxo2_wait_busy(); } -static void lcmxo2_reset_flash_address (void) { - lcmxo2_execute_cmd(LSC_INIT_ADDRESS, 0, CMD_NORMAL, NULL, 0, false); +static bool lcmxo2_reset_flash_address (void) { + return lcmxo2_execute_cmd(LSC_INIT_ADDRESS, 0, CMD_NORMAL, NULL, 0, false); } static bool lcmxo2_write_flash_page (uint8_t *buffer) { - lcmxo2_execute_cmd(LSC_PROG_INCR_NV, 1, CMD_NORMAL, buffer, FLASH_PAGE_SIZE, true); + if (lcmxo2_execute_cmd(LSC_PROG_INCR_NV, 1, CMD_NORMAL, buffer, FLASH_PAGE_SIZE, true)) { + return true; + } return lcmxo2_wait_busy(); } -static void lcmxo2_read_flash_page (uint8_t *buffer) { - lcmxo2_execute_cmd(LSC_READ_INCR_NV, 1, CMD_DELAYED, buffer, FLASH_PAGE_SIZE, false); +static bool lcmxo2_read_flash_page (uint8_t *buffer) { + return lcmxo2_execute_cmd(LSC_READ_INCR_NV, 1, CMD_DELAYED, buffer, FLASH_PAGE_SIZE, false); } static bool lcmxo2_program_done (void) { - lcmxo2_execute_cmd(ISC_PROGRAM_DONE, 0, CMD_NORMAL, NULL, 0, false); + if (lcmxo2_execute_cmd(ISC_PROGRAM_DONE, 0, CMD_NORMAL, NULL, 0, false)) { + return true; + } return lcmxo2_wait_busy(); } static bool lcmxo2_write_featbits (uint8_t *buffer) { - lcmxo2_execute_cmd(LSC_PROG_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, true); + if (lcmxo2_execute_cmd(LSC_PROG_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, true)) { + return true; + } return lcmxo2_wait_busy(); } -static void lcmxo2_read_featbits (uint8_t *buffer) { - lcmxo2_execute_cmd(LSC_READ_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, false); +static bool lcmxo2_read_featbits (uint8_t *buffer) { + return lcmxo2_execute_cmd(LSC_READ_FEABITS, 0, CMD_NORMAL, buffer, FEATBITS_SIZE, false); } -static void lcmxo2_refresh (void) { - lcmxo2_execute_cmd(LSC_REFRESH, 0, CMD_TWO_OP, NULL, 0, false); +static bool lcmxo2_refresh (void) { + return lcmxo2_execute_cmd(LSC_REFRESH, 0, CMD_TWO_OP, NULL, 0, false); } static vendor_error_t lcmxo2_fail (vendor_error_t error) { @@ -346,20 +377,29 @@ static bool primer_check_rx_length (primer_cmd_e cmd, size_t rx_length) { static bool lcmxo2_init_featbits (void) { uint8_t programmed[2] = { 0x00, 0x00 }; uint8_t target[2] = { FEATBITS_0_SPI_OFF, FEATBITS_1_PROGRAMN_OFF }; - lcmxo2_read_featbits(programmed); + + if (lcmxo2_read_featbits(programmed)) { + return true; + } + if ((programmed[0] == target[0]) && (programmed[1] == target[1])) { return false; } + if (lcmxo2_erase_featbits()) { return true; } if (lcmxo2_write_featbits(target)) { return true; } - lcmxo2_read_featbits(programmed); + if (lcmxo2_read_featbits(programmed)) { + return true; + } + if ((programmed[0] != target[0]) || (programmed[1] != target[1])) { return true; } + return false; } @@ -403,7 +443,7 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons break; case CMD_GET_DEVICE_ID: - lcmxo2_read_device_id(buffer); + error = lcmxo2_read_device_id(buffer); tx_length = 4; break; @@ -416,7 +456,7 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons break; case CMD_RESET_ADDRESS: - lcmxo2_reset_flash_address(); + error = lcmxo2_reset_flash_address(); break; case CMD_WRITE_PAGE: @@ -424,7 +464,7 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons break; case CMD_READ_PAGE: - lcmxo2_read_flash_page(buffer); + error = lcmxo2_read_flash_page(buffer); tx_length = FLASH_PAGE_SIZE; break; @@ -437,7 +477,7 @@ void vendor_initial_configuration (vendor_get_cmd_t get_cmd, vendor_send_respons break; case CMD_REFRESH: - lcmxo2_refresh(); + error = lcmxo2_refresh(); hw_delay_ms(200); break; diff --git a/sw/controller/src/led.c b/sw/controller/src/led.c index 2cefc03..5122d8b 100644 --- a/sw/controller/src/led.c +++ b/sw/controller/src/led.c @@ -2,102 +2,46 @@ #include "hw.h" #include "led.h" #include "rtc.h" -#include "task.h" #include "timer.h" -#define LED_MS_PER_TICK (10) -#define LED_ERROR_TICKS_PERIOD (50) -#define LED_ERROR_TICKS_ON (25) -#define LED_ACT_TICKS_PERIOD (15) -#define LED_ACT_TICKS_ON (6) +#define LED_REFRESH_PERIOD_MS (50) + +#define LED_PULSE_LENGTH_MS (200) + +#define ERROR_BLINK_PERIOD_MS (100) +#define ERROR_TOTAL_PERIOD_MS (1000) + +#define CIC_ERROR_BLINKS (1) +#define RTC_ERROR_BLINKS (2) -static bool error_mode = false; -static uint32_t error_timer = 0; -static volatile bool cic_error = false; -static volatile bool rtc_error = false; +static bool activity_pulse = false; +static int activity_pulse_timer = 0; -static uint32_t act_timer = 0; -static uint32_t current_act_counter = 0; -static volatile uint32_t next_act_counter = 0; +static bool cic_error = false; +static bool rtc_error = false; +static bool error_active = false; +static int error_timer = 0; -static void led_task_resume (void) { - task_set_ready(TASK_ID_LED); +void led_activity_on (void) { + rtc_settings_t *settings = rtc_get_settings(); + if (!activity_pulse && !error_active && settings->led_enabled) { + hw_gpio_set(GPIO_ID_LED); + } } -static void led_set_state (bool state, bool force) { +void led_activity_off (void) { rtc_settings_t *settings = rtc_get_settings(); - if (settings->led_enabled || force) { - if (state) { - hw_gpio_set(GPIO_ID_LED); - } else { - hw_gpio_reset(GPIO_ID_LED); - } - } else { + if (!activity_pulse && !error_active && settings->led_enabled) { hw_gpio_reset(GPIO_ID_LED); } } -static void led_update_error_mode (void) { - if (error_mode) { - if (!(cic_error || rtc_error)) { - led_set_state(false, true); - error_mode = false; - act_timer = 0; - } - } else { - if (cic_error || rtc_error) { - led_set_state(false, true); - error_mode = true; - error_timer = 0; - } - } -} - -static void led_process_errors (void) { - if (error_timer == 0) { - error_timer = LED_ERROR_TICKS_PERIOD; - if (cic_error) { - error_timer *= 1; - } else if (rtc_error) { - error_timer *= 2; - } - error_timer += LED_ERROR_TICKS_PERIOD; - } - - if (error_timer > 0) { - error_timer -= 1; - if (error_timer >= LED_ERROR_TICKS_PERIOD) { - uint32_t error_cycle = (error_timer % LED_ERROR_TICKS_PERIOD); - if (error_cycle == LED_ERROR_TICKS_ON) { - led_set_state(true, true); - } - if (error_cycle == 0) { - led_set_state(false, true); - } - } - } -} - -static void led_process_act (void) { - if (act_timer == 0) { - if (current_act_counter != next_act_counter) { - current_act_counter = next_act_counter; - act_timer = LED_ACT_TICKS_PERIOD; - } - } - - if (act_timer > 0) { - act_timer -= 1; - if (act_timer == LED_ACT_TICKS_ON) { - led_set_state(true, false); - } - if (act_timer == 0) { - led_set_state(false, false); - } - } +void led_activity_pulse (void) { + activity_pulse = true; + activity_pulse_timer = LED_PULSE_LENGTH_MS; } @@ -106,10 +50,16 @@ void led_blink_error (led_error_t error) { case LED_ERROR_CIC: cic_error = true; break; + case LED_ERROR_RTC: rtc_error = true; break; } + + error_active = ( + cic_error | + rtc_error + ); } void led_clear_error (led_error_t error) { @@ -117,32 +67,81 @@ void led_clear_error (led_error_t error) { case LED_ERROR_CIC: cic_error = false; break; + case LED_ERROR_RTC: rtc_error = false; break; } -} -void led_blink_act (void) { - next_act_counter += 1; -} + error_active = ( + cic_error | + rtc_error + ); -void led_task (void) { - timer_init(); - - while (1) { - hw_tim_setup(TIM_ID_LED, LED_MS_PER_TICK, led_task_resume); - - led_update_error_mode(); - - if (error_mode) { - led_process_errors(); - } else { - led_process_act(); - } - - timer_update(); - - task_yield(); + if (!error_active) { + activity_pulse = false; + activity_pulse_timer = 0; + error_timer = 0; + } +} + + +void led_init (void) { + timer_countdown_start(TIMER_ID_LED, LED_REFRESH_PERIOD_MS); +} + + +void led_process (void) { + if (!timer_countdown_elapsed(TIMER_ID_LED)) { + return; + } + + timer_countdown_start(TIMER_ID_LED, LED_REFRESH_PERIOD_MS); + + if (error_active) { + int blinks = 0; + + if (cic_error) { + blinks = CIC_ERROR_BLINKS; + } else if (rtc_error) { + blinks = RTC_ERROR_BLINKS; + } + + bool led_on = false; + + for (int i = 0; i < blinks; i++) { + bool lower_bound = (error_timer >= (ERROR_BLINK_PERIOD_MS * (i * 2))); + bool upper_bound = (error_timer < (ERROR_BLINK_PERIOD_MS * ((i * 2) + 1))); + if (lower_bound && upper_bound) { + led_on = true; + break; + } + } + + if (led_on) { + hw_gpio_set(GPIO_ID_LED); + } else { + hw_gpio_reset(GPIO_ID_LED); + } + + error_timer += LED_REFRESH_PERIOD_MS; + + if (error_timer >= ERROR_TOTAL_PERIOD_MS) { + error_timer = 0; + } + + return; + } + + if (activity_pulse) { + if (activity_pulse_timer > 0) { + hw_gpio_set(GPIO_ID_LED); + } else { + activity_pulse = false; + hw_gpio_reset(GPIO_ID_LED); + return; + } + + activity_pulse_timer -= LED_REFRESH_PERIOD_MS; } } diff --git a/sw/controller/src/led.h b/sw/controller/src/led.h index 1ae724d..4a084a7 100644 --- a/sw/controller/src/led.h +++ b/sw/controller/src/led.h @@ -8,10 +8,16 @@ typedef enum { } led_error_t; +void led_activity_on (void); +void led_activity_off (void); +void led_activity_pulse (void); + void led_blink_error (led_error_t error); void led_clear_error (led_error_t error); -void led_blink_act (void); -void led_task (void); + +void led_init (void); + +void led_process (void); #endif diff --git a/sw/controller/src/loader.c b/sw/controller/src/loader.c index be5e67f..e7a8e6a 100644 --- a/sw/controller/src/loader.c +++ b/sw/controller/src/loader.c @@ -9,6 +9,7 @@ void no_valid_image (void) { hw_gpio_set(GPIO_ID_LED); } + void loader (void) { if (update_check()) { hw_loader_init(); diff --git a/sw/controller/src/primer.c b/sw/controller/src/primer.c index 94e22a3..b5083bb 100644 --- a/sw/controller/src/primer.c +++ b/sw/controller/src/primer.c @@ -19,7 +19,7 @@ static uint8_t primer_get_command (uint8_t *buffer, uint8_t *rx_length) { uint32_t received_crc32; uint8_t token[4]; - while (1) { + while (true) { hw_crc32_reset(); primer_get_and_calculate_crc32(token, 4, &calculated_crc32); @@ -69,7 +69,10 @@ static void primer_send_response (uint8_t cmd, uint8_t *buffer, uint8_t tx_lengt void primer (void) { hw_primer_init(); + vendor_initial_configuration(primer_get_command, primer_send_response); - hw_uart_wait_busy(); + + hw_uart_write_wait_busy(); + hw_reset(NULL); } diff --git a/sw/controller/src/rtc.c b/sw/controller/src/rtc.c index 827ea6f..6d898d5 100644 --- a/sw/controller/src/rtc.c +++ b/sw/controller/src/rtc.c @@ -2,7 +2,7 @@ #include "hw.h" #include "led.h" #include "rtc.h" -#include "task.h" +#include "timer.h" #define RTC_I2C_ADDRESS (0xDE) @@ -28,27 +28,27 @@ #define RTC_SETTINGS_VERSION (1) +#define RTC_TIME_REFRESH_PERIOD_MS (500) + static rtc_time_t rtc_time = { .second = 0x00, .minute = 0x00, .hour = 0x12, - .weekday = 0x02, + .weekday = 0x01, .day = 0x01, - .month = 0x03, - .year = 0x22 + .month = 0x01, + .year = 0x24 }; -static bool rtc_time_valid = false; -static volatile bool rtc_time_pending = false; +static bool rtc_time_pending = false; static uint8_t rtc_region = 0xFF; -static volatile bool rtc_region_pending = false; +static bool rtc_region_pending = false; static rtc_settings_t rtc_settings = { .led_enabled = true, }; -static volatile bool rtc_settings_pending = false; -static volatile bool rtc_initialized = false; +static bool rtc_settings_pending = false; static const uint8_t rtc_regs_bit_mask[7] = { 0b01111111, @@ -61,30 +61,29 @@ static const uint8_t rtc_regs_bit_mask[7] = { }; -static void rtc_task_resume (void) { - task_set_ready(TASK_ID_RTC); -} - -static void rtc_on_error (void) { - rtc_time_valid = false; - led_blink_error(LED_ERROR_RTC); - task_yield(); -} - -static void rtc_read (uint8_t address, uint8_t *data, uint8_t length) { - hw_i2c_read(RTC_I2C_ADDRESS, address, data, length, rtc_task_resume); - task_yield(); - if (hw_i2c_get_error()) { - rtc_on_error(); +static bool rtc_read (uint8_t address, uint8_t *data, uint8_t length) { + if (hw_i2c_trx(RTC_I2C_ADDRESS, &address, 1, data, length) != I2C_OK) { + led_blink_error(LED_ERROR_RTC); + return true; } + + return false; } -static void rtc_write (uint8_t address, uint8_t *data, uint8_t length) { - hw_i2c_write(RTC_I2C_ADDRESS, address, data, length, rtc_task_resume); - task_yield(); - if (hw_i2c_get_error()) { - rtc_on_error(); +static bool rtc_write (uint8_t address, uint8_t *data, uint8_t length) { + uint8_t buffer[16]; + buffer[0] = address; + + for (int i = 0; i < length; i++) { + buffer[i + 1] = data[i]; } + + if (hw_i2c_trx(RTC_I2C_ADDRESS, buffer, length + 1, NULL, 0) != I2C_OK) { + led_blink_error(LED_ERROR_RTC); + return true; + } + + return false; } static void rtc_sanitize_time (uint8_t *regs) { @@ -98,29 +97,25 @@ static void rtc_osc_stop (void) { rtc_write(RTC_ADDRESS_RTCSEC, &tmp, 1); - do { - rtc_read(RTC_ADDRESS_RTCWKDAY, &tmp, 1); - } while (tmp & RTC_RTCWKDAY_OSCRUN); + while ((!rtc_read(RTC_ADDRESS_RTCWKDAY, &tmp, 1)) && (tmp & RTC_RTCWKDAY_OSCRUN)); } static void rtc_read_time (void) { uint8_t regs[7]; - rtc_read(RTC_ADDRESS_RTCSEC, regs, 7); + if (rtc_read(RTC_ADDRESS_RTCSEC, regs, 7)) { + return; + } rtc_sanitize_time(regs); - if (!rtc_time_pending) { - rtc_time.second = regs[0]; - rtc_time.minute = regs[1]; - rtc_time.hour = regs[2]; - rtc_time.weekday = regs[3]; - rtc_time.day = regs[4]; - rtc_time.month = regs[5]; - rtc_time.year = regs[6]; - - rtc_time_valid = true; - } + rtc_time.second = regs[0]; + rtc_time.minute = regs[1]; + rtc_time.hour = regs[2]; + rtc_time.weekday = regs[3]; + rtc_time.day = regs[4]; + rtc_time.month = regs[5]; + rtc_time.year = regs[6]; } static void rtc_write_time (void) { @@ -161,12 +156,58 @@ static void rtc_write_settings (void) { rtc_write(RTC_ADDRESS_SRAM_SETTINGS, (uint8_t *) (&rtc_settings), sizeof(rtc_settings)); } -static void rtc_init (void) { + +void rtc_get_time (rtc_time_t *time) { + time->second = rtc_time.second; + time->minute = rtc_time.minute; + time->hour = rtc_time.hour; + time->weekday = rtc_time.weekday; + time->day = rtc_time.day; + time->month = rtc_time.month; + time->year = rtc_time.year; +} + +void rtc_set_time (rtc_time_t *time) { + rtc_time.second = time->second; + rtc_time.minute = time->minute; + rtc_time.hour = time->hour; + rtc_time.weekday = time->weekday; + rtc_time.day = time->day; + rtc_time.month = time->month; + rtc_time.year = time->year; + rtc_time_pending = true; +} + + +uint8_t rtc_get_region (void) { + return rtc_region; +} + +void rtc_set_region (uint8_t region) { + rtc_region = region; + rtc_region_pending = true; +} + + +rtc_settings_t *rtc_get_settings (void) { + return (&rtc_settings); +} + +void rtc_save_settings (void) { + rtc_settings_pending = true; +} + + +void rtc_init (void) { bool uninitialized = false; const char *magic = "SC64"; uint8_t buffer[4]; uint32_t settings_version; + for (int i = 0; i < 4; i++) { + buffer[i] = 0; + } + rtc_read(RTC_ADDRESS_SRAM_MAGIC, buffer, 4); for (int i = 0; i < 4; i++) { @@ -179,7 +220,6 @@ static void rtc_init (void) { if (uninitialized) { buffer[0] = 0; rtc_write(RTC_ADDRESS_SRAM_MAGIC, (uint8_t *) (magic), 4); - rtc_write(RTC_ADDRESS_CONTROL, buffer, 1); rtc_write(RTC_ADDRESS_OSCTRIM, buffer, 1); rtc_write_time(); rtc_write_region(); @@ -192,143 +232,73 @@ static void rtc_init (void) { rtc_write(RTC_ADDRESS_SRAM_VERSION, (uint8_t *) (&settings_version), 4); rtc_write_settings(); } -} - - -bool rtc_is_initialized (void) { - return rtc_initialized; -} - -bool rtc_get_time (rtc_time_t *time) { - bool vaild; - - hw_i2c_disable_irq(); - hw_tim_disable_irq(TIM_ID_RTC); - - time->second = rtc_time.second; - time->minute = rtc_time.minute; - time->hour = rtc_time.hour; - time->weekday = rtc_time.weekday; - time->day = rtc_time.day; - time->month = rtc_time.month; - time->year = rtc_time.year; - vaild = rtc_time_valid; - - hw_tim_enable_irq(TIM_ID_RTC); - hw_i2c_enable_irq(); - - return vaild; -} - -void rtc_set_time (rtc_time_t *time) { - hw_i2c_disable_irq(); - hw_tim_disable_irq(TIM_ID_RTC); - - rtc_time.second = time->second; - rtc_time.minute = time->minute; - rtc_time.hour = time->hour; - rtc_time.weekday = time->weekday; - rtc_time.day = time->day; - rtc_time.month = time->month; - rtc_time.year = time->year; - rtc_time_pending = true; - - hw_tim_enable_irq(TIM_ID_RTC); - hw_i2c_enable_irq(); -} - -uint8_t rtc_get_region (void) { - return rtc_region; -} - -void rtc_set_region (uint8_t region) { - rtc_region = region; - rtc_region_pending = true; -} - -rtc_settings_t *rtc_get_settings (void) { - return (&rtc_settings); -} - -void rtc_set_settings (rtc_settings_t *settings) { - hw_tim_disable_irq(TIM_ID_LED); - - rtc_settings = *settings; - rtc_settings_pending = true; - - hw_tim_enable_irq(TIM_ID_LED); -} - -void rtc_task (void) { - rtc_init(); + rtc_read_time(); rtc_read_region(); rtc_read_settings(); - rtc_initialized = true; - - while (1) { - if (rtc_time_pending) { - rtc_time_pending = false; - rtc_write_time(); - } - - if (rtc_region_pending) { - rtc_region_pending = false; - rtc_write_region(); - } - - if (rtc_settings_pending) { - rtc_settings_pending = false; - rtc_write_settings(); - } - - rtc_read_time(); - - hw_tim_setup(TIM_ID_RTC, 50, rtc_task_resume); - - task_yield(); - } + timer_countdown_start(TIMER_ID_RTC, RTC_TIME_REFRESH_PERIOD_MS); } + void rtc_process (void) { - rtc_time_t time; - uint32_t data[2]; uint32_t scr = fpga_reg_get(REG_RTC_SCR); if ((scr & RTC_SCR_PENDING) && ((scr & RTC_SCR_MAGIC_MASK) == RTC_SCR_MAGIC)) { + uint32_t data[2]; + data[0] = fpga_reg_get(REG_RTC_TIME_0); data[1] = fpga_reg_get(REG_RTC_TIME_1); - time.weekday = ((data[0] >> 24) & 0xFF) + 1; - time.hour = ((data[0] >> 16) & 0xFF); - time.minute = ((data[0] >> 8) & 0xFF); - time.second = ((data[0] >> 0) & 0xFF); - time.year = ((data[1] >> 16) & 0xFF); - time.month = ((data[1] >> 8) & 0xFF); - time.day = ((data[1] >> 0) & 0xFF); - - rtc_set_time(&time); + rtc_time.weekday = ((data[0] >> 24) & 0xFF) + 1; + rtc_time.hour = ((data[0] >> 16) & 0xFF); + rtc_time.minute = ((data[0] >> 8) & 0xFF); + rtc_time.second = ((data[0] >> 0) & 0xFF); + rtc_time.year = ((data[1] >> 16) & 0xFF); + rtc_time.month = ((data[1] >> 8) & 0xFF); + rtc_time.day = ((data[1] >> 0) & 0xFF); + rtc_time_pending = true; fpga_reg_set(REG_RTC_TIME_0, data[0]); fpga_reg_set(REG_RTC_TIME_1, data[1]); fpga_reg_set(REG_RTC_SCR, RTC_SCR_DONE); } - rtc_get_time(&time); + if (rtc_time_pending) { + rtc_time_pending = false; + rtc_write_time(); + } - data[0] = ( - ((time.weekday - 1) << 24) | - (time.hour << 16) | - (time.minute << 8) | - (time.second << 0) - ); - data[1] = ( - (time.year << 16) | - (time.month << 8) | - (time.day << 0) - ); + if (rtc_region_pending) { + rtc_region_pending = false; + rtc_write_region(); + } - fpga_reg_set(REG_RTC_TIME_0, data[0]); - fpga_reg_set(REG_RTC_TIME_1, data[1]); + if (rtc_settings_pending) { + rtc_settings_pending = false; + rtc_write_settings(); + } + + if (timer_countdown_elapsed(TIMER_ID_RTC)) { + timer_countdown_start(TIMER_ID_RTC, RTC_TIME_REFRESH_PERIOD_MS); + + rtc_read_time(); + + uint32_t data[2]; + + data[0] = ( + ((rtc_time.weekday - 1) << 24) | + (rtc_time.hour << 16) | + (rtc_time.minute << 8) | + (rtc_time.second << 0) + ); + data[1] = ( + (rtc_time.year << 16) | + (rtc_time.month << 8) | + (rtc_time.day << 0) + ); + + fpga_reg_set(REG_RTC_TIME_0, data[0]); + fpga_reg_set(REG_RTC_TIME_1, data[1]); + } } diff --git a/sw/controller/src/rtc.h b/sw/controller/src/rtc.h index be7dc8a..a8714d9 100644 --- a/sw/controller/src/rtc.h +++ b/sw/controller/src/rtc.h @@ -7,28 +7,31 @@ typedef struct { - volatile uint8_t second; - volatile uint8_t minute; - volatile uint8_t hour; - volatile uint8_t weekday; - volatile uint8_t day; - volatile uint8_t month; - volatile uint8_t year; + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t weekday; + uint8_t day; + uint8_t month; + uint8_t year; } rtc_time_t; typedef struct { - volatile bool led_enabled; + bool led_enabled; } rtc_settings_t; -bool rtc_is_initialized (void); -bool rtc_get_time (rtc_time_t *time); +void rtc_get_time (rtc_time_t *time); void rtc_set_time (rtc_time_t *time); + uint8_t rtc_get_region (void); void rtc_set_region (uint8_t region); + rtc_settings_t *rtc_get_settings (void); -void rtc_set_settings (rtc_settings_t *settings); -void rtc_task (void); +void rtc_save_settings (void); + +void rtc_init (void); + void rtc_process (void); diff --git a/sw/controller/src/sd.c b/sw/controller/src/sd.c index a07917c..20498c4 100644 --- a/sw/controller/src/sd.c +++ b/sw/controller/src/sd.c @@ -1,9 +1,7 @@ -#include -#include #include "fpga.h" #include "hw.h" -#include "led.h" #include "sd.h" +#include "timer.h" #define SD_INIT_BUFFER_ADDRESS (0x05002800UL) @@ -33,6 +31,8 @@ #define SWITCH_FUNCTION_GROUP_1 (SD_INIT_BUFFER_ADDRESS + 12) #define SWITCH_FUNCTION_GROUP_1_HS (1 << 1) +#define TIMEOUT_INIT_MS (1000) + #define DAT_BLOCK_MAX_COUNT (256) #define DAT_TIMEOUT_INIT_MS (2000) #define DAT_TIMEOUT_DATA_MS (5000) @@ -60,6 +60,12 @@ typedef enum { DAT_WRITE, } dat_mode_t; +typedef enum { + DAT_OK, + DAT_ERR_IO, + DAT_ERR_TIMEOUT, +} dat_err_t; + struct process { bool card_initialized; @@ -67,7 +73,6 @@ struct process { uint32_t rca; uint8_t csd[16]; uint8_t cid[16]; - volatile bool timeout; bool byte_swap; }; @@ -75,24 +80,6 @@ struct process { static struct process p; -static void sd_trigger_timeout (void) { - p.timeout = true; -} - -static void sd_prepare_timeout (uint16_t value) { - p.timeout = false; - hw_tim_setup(TIM_ID_SD, value, sd_trigger_timeout); -} - -static bool sd_did_timeout (void) { - return p.timeout; -} - -static void sd_clear_timeout (void) { - hw_tim_stop(TIM_ID_SD); - p.timeout = false; -} - static void sd_set_clock (sd_clock_t mode) { fpga_reg_set(REG_SD_SCR, SD_SCR_CLOCK_MODE_OFF); @@ -198,22 +185,24 @@ static void sd_dat_abort (void) { fpga_reg_set(REG_SD_DAT, SD_DAT_STOP | SD_DAT_FIFO_FLUSH); } -static bool sd_dat_wait (uint16_t timeout) { - sd_prepare_timeout(timeout); +static dat_err_t sd_dat_wait (uint16_t timeout_ms) { + timer_countdown_start(TIMER_ID_SD, timeout_ms); do { uint32_t sd_dat = fpga_reg_get(REG_SD_DAT); uint32_t sd_dma_scr = fpga_reg_get(REG_SD_DMA_SCR); - led_blink_act(); if ((!(sd_dat & SD_DAT_BUSY)) && (!(sd_dma_scr & DMA_SCR_BUSY))) { - sd_clear_timeout(); - return (sd_dat & SD_DAT_ERROR); + if (sd_dat & SD_DAT_ERROR) { + sd_dat_abort(); + return DAT_ERR_IO; + } + return DAT_OK; } - } while (!sd_did_timeout()); + } while (!timer_countdown_elapsed(TIMER_ID_SD)); sd_dat_abort(); - return true; + return DAT_ERR_TIMEOUT; } @@ -231,8 +220,6 @@ bool sd_card_init (void) { p.card_initialized = true; p.rca = 0; - led_blink_act(); - sd_set_clock(CLOCK_400KHZ); sd_cmd(0, 0, RSP_NONE, NULL); @@ -248,11 +235,11 @@ bool sd_card_init (void) { arg = (ACMD41_ARG_HCS | ACMD41_ARG_OCR); } - sd_prepare_timeout(1000); + timer_countdown_start(TIMER_ID_SD, TIMEOUT_INIT_MS); do { - if (sd_did_timeout()) { + if (timer_countdown_elapsed(TIMER_ID_SD)) { sd_card_deinit(); - return true; + return true; } if (sd_acmd(41, arg, RSP_R3, &rsp)) { sd_card_deinit(); @@ -266,8 +253,7 @@ bool sd_card_init (void) { p.card_type_block = (rsp & R3_CCS); break; } - } while (1); - sd_clear_timeout(); + } while (true); if (sd_cmd(2, 0, RSP_R2, NULL)) { sd_card_deinit(); @@ -308,8 +294,7 @@ bool sd_card_init (void) { sd_card_deinit(); return true; } - sd_dat_wait(DAT_TIMEOUT_INIT_MS); - if (sd_did_timeout()) { + if (sd_dat_wait(DAT_TIMEOUT_INIT_MS) == DAT_ERR_TIMEOUT) { sd_card_deinit(); return true; } @@ -326,8 +311,7 @@ bool sd_card_init (void) { sd_card_deinit(); return true; } - sd_dat_wait(DAT_TIMEOUT_INIT_MS); - if (sd_did_timeout()) { + if (sd_dat_wait(DAT_TIMEOUT_INIT_MS) == DAT_ERR_TIMEOUT) { sd_card_deinit(); return true; } @@ -389,6 +373,7 @@ bool sd_set_byte_swap (bool enabled) { return false; } + bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) { if (!p.card_initialized || (count == 0)) { return true; @@ -400,13 +385,11 @@ bool sd_write_sectors (uint32_t address, uint32_t sector, uint32_t count) { while (count > 0) { uint32_t blocks = ((count > DAT_BLOCK_MAX_COUNT) ? DAT_BLOCK_MAX_COUNT : count); - led_blink_act(); if (sd_cmd(25, sector, RSP_R1, NULL)) { return true; } sd_dat_prepare(address, blocks, DAT_WRITE); - if (sd_dat_wait(DAT_TIMEOUT_DATA_MS)) { - sd_dat_abort(); + if (sd_dat_wait(DAT_TIMEOUT_DATA_MS) != DAT_OK) { sd_cmd(12, 0, RSP_R1b, NULL); return true; } @@ -434,16 +417,13 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) { while (count > 0) { uint32_t blocks = ((count > DAT_BLOCK_MAX_COUNT) ? DAT_BLOCK_MAX_COUNT : count); - led_blink_act(); sd_dat_prepare(address, blocks, DAT_READ); if (sd_cmd(18, sector, RSP_R1, NULL)) { sd_dat_abort(); return true; } - if (sd_dat_wait(DAT_TIMEOUT_DATA_MS)) { - if (sd_did_timeout()) { - sd_cmd(12, 0, RSP_R1b, NULL); - } + if (sd_dat_wait(DAT_TIMEOUT_DATA_MS) != DAT_OK) { + sd_cmd(12, 0, RSP_R1b, NULL); return true; } sd_cmd(12, 0, RSP_R1b, NULL); @@ -455,6 +435,7 @@ bool sd_read_sectors (uint32_t address, uint32_t sector, uint32_t count) { return false; } + bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t count, sd_process_sectors_t sd_process_sectors) { uint32_t starting_sector = 0; uint32_t sectors_to_process = 0; @@ -483,12 +464,14 @@ bool sd_optimize_sectors (uint32_t address, uint32_t *sector_table, uint32_t cou return false; } + void sd_init (void) { p.card_initialized = false; p.byte_swap = false; sd_set_clock(CLOCK_STOP); } + void sd_process (void) { if (p.card_initialized && !sd_card_is_inserted()) { sd_card_deinit(); diff --git a/sw/controller/src/sd.h b/sw/controller/src/sd.h index 9094df4..e530af5 100644 --- a/sw/controller/src/sd.h +++ b/sw/controller/src/sd.h @@ -3,6 +3,7 @@ #include +#include #define SD_SECTOR_SIZE (512) @@ -18,10 +19,14 @@ bool sd_card_is_inserted (void); uint32_t sd_card_get_status (void); 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_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); + void sd_init (void); + void sd_process (void); diff --git a/sw/controller/src/task.c b/sw/controller/src/task.c deleted file mode 100644 index 8240aa4..0000000 --- a/sw/controller/src/task.c +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include -#include "task.h" - - -#define TASK_INITIAL_XPSR (0x21000000UL) -#define TASK_CONTEXT_SWITCH() { SCB->ICSR = (1 << SCB_ICSR_PENDSVSET_Pos); } -#define TASK_STACK_FILL_VALUE (0xDEADBEEF) - - -typedef struct { - volatile uint32_t sp; - volatile bool ready; -} task_t; - - -static task_t task_table[__TASK_ID_MAX]; -static volatile task_id_t task_current = 0; - - -static void task_exit (void) { - while (1) { - task_yield(); - } -} - -static uint32_t task_switch_context (uint32_t sp) { - task_table[task_current].sp = sp; - - for (task_id_t id = 0; id < __TASK_ID_MAX; id++) { - if (task_table[id].ready) { - task_current = id; - break; - } - } - - return task_table[task_current].sp; -} - - -void task_create (task_id_t id, void (*code)(void), void *stack, size_t stack_size) { - if (id < __TASK_ID_MAX) { - for (size_t i = 0; i < stack_size; i += sizeof(uint32_t)) { - (*(uint32_t *) (stack + i)) = TASK_STACK_FILL_VALUE; - } - uint32_t *sp = ((uint32_t *) ((uint32_t) (stack) + stack_size)); - *--sp = TASK_INITIAL_XPSR; - *--sp = (uint32_t) (code); - *--sp = ((uint32_t) (task_exit)); - for (int i = 0; i < 13; i++) { - *--sp = 0; - } - task_t *task = &task_table[id]; - task->sp = ((uint32_t) (sp)); - task->ready = true; - } -} - -void task_yield (void) { - __disable_irq(); - task_table[task_current].ready = false; - __enable_irq(); - TASK_CONTEXT_SWITCH(); -} - -void task_set_ready (task_id_t id) { - __disable_irq(); - task_table[id].ready = true; - __enable_irq(); - TASK_CONTEXT_SWITCH(); -} - -size_t task_get_stack_usage (void *stack, size_t stack_size) { - for (size_t i = 0; i < stack_size; i += sizeof(uint32_t)) { - if ((*(uint32_t *) (stack + i)) != TASK_STACK_FILL_VALUE) { - return (stack_size - i); - } - } - return 0; -} - -__attribute__((naked)) void task_scheduler_start (void) { - uint32_t sp = task_table[task_current].sp; - - NVIC_SetPriority(PendSV_IRQn, 3); - - asm volatile ( - "add %[sp], #32 \n" - "msr psp, %[sp] \n" - "movs r0, #2 \n" - "msr CONTROL, r0 \n" - "isb \n" - "pop {r0-r5} \n" - "mov lr, r5 \n" - "pop {r3} \n" - "pop {r2} \n" - "cpsie i \n" - "bx r3 \n" - :: [sp] "r" (sp) - ); - - while (1); -} - - -__attribute__((naked)) void PendSV_Handler (void) { - asm volatile ( - "mrs r1, psp \n" - "sub r1, r1, #32 \n" - "mov r0, r1 \n" - "stmia r1!, {r4-r7} \n" - "mov r4, r8 \n" - "mov r5, r9 \n" - "mov r6, r10 \n" - "mov r7, r11 \n" - "stmia r1!, {r4-r7} \n" - "push {lr} \n" - "cpsid i \n" - "blx %[task_switch_context] \n" - "cpsie i \n" - "pop {r2} \n" - "add r0, #16 \n" - "ldmia r0!, {r4-r7} \n" - "mov r8, r4 \n" - "mov r9, r5 \n" - "mov r10, r6 \n" - "mov r11, r7 \n" - "msr psp, r0 \n" - "sub r0, #32 \n" - "ldmia r0!, {r4-r7} \n" - "bx r2 \n" - :: [task_switch_context] "r" (task_switch_context) - ); -} diff --git a/sw/controller/src/task.h b/sw/controller/src/task.h deleted file mode 100644 index 71ad4e3..0000000 --- a/sw/controller/src/task.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef TASK_H__ -#define TASK_H__ - - -#include - - -typedef enum { - TASK_ID_RTC, - TASK_ID_LED, - TASK_ID_GVR, - __TASK_ID_MAX -} task_id_t; - - -void task_create (task_id_t id, void (*code)(void), void *stack, size_t stack_size); -void task_yield (void); -void task_set_ready (task_id_t id); -size_t task_get_stack_usage (void *stack, size_t stack_size); -void task_scheduler_start (void); - - -#endif diff --git a/sw/controller/src/timer.c b/sw/controller/src/timer.c index 03d44a5..bba0aa9 100644 --- a/sw/controller/src/timer.c +++ b/sw/controller/src/timer.c @@ -2,29 +2,55 @@ #include "timer.h" -static volatile uint32_t timer[__TIMER_ID_COUNT]; +#define TIMER_PERIOD_MS (25) -uint32_t timer_get (timer_id_t id) { - return (uint32_t) (timer[id]); -} +typedef struct { + volatile bool pending; + volatile bool running; + volatile uint32_t value; +} timer_t; -void timer_set (timer_id_t id, uint32_t ticks) { - hw_tim_disable_irq(TIM_ID_LED); - timer[id] = ticks; - hw_tim_enable_irq(TIM_ID_LED); -} +static timer_t timer[__TIMER_ID_COUNT]; -void timer_init (void) { + +static void timer_update (void) { for (timer_id_t id = 0; id < __TIMER_ID_COUNT; id++) { - timer[id] = 0; - } -} - -void timer_update (void) { - for (timer_id_t id = 0; id < __TIMER_ID_COUNT; id++) { - if (timer[id] > 0) { - timer[id] -= 1; + if (timer[id].value > 0) { + timer[id].value -= 1; + } + if (timer[id].pending) { + timer[id].pending = false; + } else if (timer[id].value == 0) { + timer[id].running = false; } } } + + +void timer_countdown_start (timer_id_t id, uint32_t value_ms) { + hw_enter_critical(); + if (value_ms > 0) { + timer[id].pending = true; + timer[id].running = true; + timer[id].value = ((value_ms + (TIMER_PERIOD_MS - 1)) / TIMER_PERIOD_MS); + } + hw_exit_critical(); +} + +void timer_countdown_abort (timer_id_t id) { + hw_enter_critical(); + timer[id].pending = false; + timer[id].running = false; + timer[id].value = 0; + hw_exit_critical(); +} + +bool timer_countdown_elapsed (timer_id_t id) { + return (!timer[id].running); +} + + +void timer_init (void) { + hw_systick_config(TIMER_PERIOD_MS, timer_update); +} diff --git a/sw/controller/src/timer.h b/sw/controller/src/timer.h index 916b524..1adb086 100644 --- a/sw/controller/src/timer.h +++ b/sw/controller/src/timer.h @@ -2,20 +2,26 @@ #define TIMER_H__ +#include #include typedef enum { + TIMER_ID_DD, + TIMER_ID_LED, + TIMER_ID_RTC, + TIMER_ID_SD, TIMER_ID_USB, TIMER_ID_WRITEBACK, __TIMER_ID_COUNT } timer_id_t; -uint32_t timer_get (timer_id_t id); -void timer_set (timer_id_t id, uint32_t ticks); +void timer_countdown_start (timer_id_t id, uint32_t value_ms); +void timer_countdown_abort (timer_id_t id); +bool timer_countdown_elapsed (timer_id_t id); + void timer_init (void); -void timer_update (void); #endif diff --git a/sw/controller/src/update.c b/sw/controller/src/update.c index 521e6a3..44b4d5e 100644 --- a/sw/controller/src/update.c +++ b/sw/controller/src/update.c @@ -312,7 +312,7 @@ void update_perform (void) { fpga_mem_read(parameters.mcu_address - 4, sizeof(length), (uint8_t *) (&length)); if (mcu_update(parameters.mcu_address, length)) { update_status_notify(UPDATE_STATUS_ERROR); - while (1); + while (true); } } @@ -321,7 +321,7 @@ void update_perform (void) { fpga_mem_read(parameters.fpga_address - 4, sizeof(length), (uint8_t *) (&length)); if (vendor_update(parameters.fpga_address, length) != VENDOR_OK) { update_status_notify(UPDATE_STATUS_ERROR); - while (1); + while (true); } } @@ -330,7 +330,7 @@ void update_perform (void) { fpga_mem_read(parameters.bootloader_address - 4, sizeof(length), (uint8_t *) (&length)); if (bootloader_update(parameters.bootloader_address, length)) { update_status_notify(UPDATE_STATUS_ERROR); - while (1); + while (true); } } diff --git a/sw/controller/src/usb.c b/sw/controller/src/usb.c index 6e2dd97..760f68d 100644 --- a/sw/controller/src/usb.c +++ b/sw/controller/src/usb.c @@ -1,9 +1,9 @@ -#include "app.h" #include "cfg.h" #include "cic.h" #include "dd.h" #include "flash.h" #include "fpga.h" +#include "hw.h" #include "rtc.h" #include "timer.h" #include "update.h" @@ -12,15 +12,18 @@ #include "writeback.h" -#define BOOTLOADER_ADDRESS (0x04E00000UL) -#define BOOTLOADER_LENGTH (1920 * 1024) +#define BOOTLOADER_ADDRESS (0x04E00000UL) +#define BOOTLOADER_LENGTH (1920 * 1024) -#define MEMORY_LENGTH (0x05002980UL) +#define MEMORY_LENGTH (0x05002980UL) -#define RX_FLUSH_ADDRESS (0x07F00000UL) -#define RX_FLUSH_LENGTH (1 * 1024 * 1024) +#define RX_FLUSH_ADDRESS (0x07F00000UL) +#define RX_FLUSH_LENGTH (1 * 1024 * 1024) -#define DEBUG_WRITE_TIMEOUT_TICKS (100) +#define DEBUG_WRITE_TIMEOUT_MS (1000) + +#define DIAGNOSTIC_DATA_MARKER (1 << 31) +#define DIAGNOSTIC_DATA_VERSION (1) enum rx_state { @@ -175,7 +178,7 @@ static void usb_rx_process (void) { p.response_info.dma_length = 0; p.response_info.done_callback = NULL; if (p.rx_cmd == 'U') { - timer_set(TIMER_ID_USB, DEBUG_WRITE_TIMEOUT_TICKS); + timer_countdown_start(TIMER_ID_USB, DEBUG_WRITE_TIMEOUT_MS); } } } @@ -311,9 +314,9 @@ static void usb_rx_process (void) { p.read_length -= length; p.read_address += length; p.read_ready = true; - timer_set(TIMER_ID_USB, DEBUG_WRITE_TIMEOUT_TICKS); + timer_countdown_start(TIMER_ID_USB, DEBUG_WRITE_TIMEOUT_MS); } - } else if (timer_get(TIMER_ID_USB) == 0) { + } else if (timer_countdown_elapsed(TIMER_ID_USB)) { p.rx_state = RX_STATE_FLUSH; p.flush_packet = true; } @@ -382,12 +385,19 @@ static void usb_rx_process (void) { p.response_info.data[1] = fpga_reg_get(REG_DEBUG_1); break; - case '%': + case '%': { + uint16_t voltage; + int16_t temperature; + hw_adc_read_voltage_temperature(&voltage, &temperature); p.rx_state = RX_STATE_IDLE; p.response_pending = true; p.response_info.data_length = 16; - app_get_stack_usage(p.response_info.data); + p.response_info.data[0] = (DIAGNOSTIC_DATA_MARKER | DIAGNOSTIC_DATA_VERSION); + p.response_info.data[1] = (uint32_t) (voltage); + p.response_info.data[2] = (uint32_t) (temperature); + p.response_info.data[3] = 0; break; + } default: p.rx_state = RX_STATE_IDLE; @@ -521,6 +531,7 @@ bool usb_enqueue_packet (usb_tx_info_t *info) { return true; } + bool usb_prepare_read (uint32_t *args) { if (!p.read_ready) { return false; @@ -543,6 +554,7 @@ void usb_get_read_info (uint32_t *args) { args[0] |= (scr & USB_SCR_PWRSAV) ? (1 << 29) : 0; } + void usb_init (void) { fpga_reg_set(REG_USB_DMA_SCR, DMA_SCR_STOP); fpga_reg_set(REG_USB_SCR, USB_SCR_FIFO_FLUSH); @@ -563,6 +575,7 @@ void usb_init (void) { usb_rx_cmd_counter = 0; } + void usb_process (void) { uint32_t scr = fpga_reg_get(REG_USB_SCR); if (scr & (USB_SCR_PWRSAV | USB_SCR_RESET_STATE | USB_SCR_RESET_PENDING)) { diff --git a/sw/controller/src/usb.h b/sw/controller/src/usb.h index beafc04..5837f23 100644 --- a/sw/controller/src/usb.h +++ b/sw/controller/src/usb.h @@ -29,9 +29,12 @@ typedef struct usb_tx_info { void usb_create_packet (usb_tx_info_t *info, usb_packet_cmd_e cmd); bool usb_enqueue_packet (usb_tx_info_t *info); + bool usb_prepare_read (uint32_t *args); void usb_get_read_info (uint32_t *args); + void usb_init (void); + void usb_process (void); diff --git a/sw/controller/src/writeback.c b/sw/controller/src/writeback.c index 8e65f05..d2e4c91 100644 --- a/sw/controller/src/writeback.c +++ b/sw/controller/src/writeback.c @@ -1,21 +1,25 @@ #include "cfg.h" #include "fpga.h" +#include "led.h" #include "sd.h" #include "timer.h" #include "usb.h" #include "writeback.h" -#define SAVE_MAX_SECTOR_COUNT (256) -#define EEPROM_ADDRESS (0x05002000) -#define SRAM_FLASHRAM_ADDRESS (0x03FE0000) -#define EEPROM_4K_LENGTH (512) -#define EEPROM_16K_LENGTH (2048) -#define SRAM_LENGTH (32 * 1024) -#define FLASHRAM_LENGTH (128 * 1024) -#define SRAM_BANKED_LENGTH (3 * 32 * 1024) -#define SRAM_1M_LENGTH (128 * 1024) -#define WRITEBACK_DELAY_TICKS (100) +#define SAVE_MAX_SECTOR_COUNT (256) + +#define EEPROM_ADDRESS (0x05002000) +#define SRAM_FLASHRAM_ADDRESS (0x03FE0000) + +#define EEPROM_4K_LENGTH (512) +#define EEPROM_16K_LENGTH (2048) +#define SRAM_LENGTH (32 * 1024) +#define FLASHRAM_LENGTH (128 * 1024) +#define SRAM_BANKED_LENGTH (3 * 32 * 1024) +#define SRAM_1M_LENGTH (128 * 1024) + +#define WRITEBACK_DELAY_MS (1000) struct process { @@ -78,9 +82,14 @@ static void writeback_save_to_sd (void) { return; } - if(sd_optimize_sectors(address, p.sectors, length / SD_SECTOR_SIZE, sd_write_sectors)) { + bool error = sd_optimize_sectors(address, p.sectors, (length / SD_SECTOR_SIZE), sd_write_sectors); + + if (error) { writeback_disable(); + return; } + + led_activity_pulse(); } static bool writeback_save_to_usb (void) { @@ -100,7 +109,13 @@ static bool writeback_save_to_usb (void) { packet_info.data[0] = save; packet_info.dma_length = length; packet_info.dma_address = address; - return usb_enqueue_packet(&packet_info); + bool enqueued = usb_enqueue_packet(&packet_info); + + if (enqueued) { + led_activity_pulse(); + } + + return enqueued; } @@ -111,6 +126,7 @@ void writeback_load_sector_table (uint32_t address) { } } + void writeback_enable (writeback_mode_t mode) { p.enabled = true; p.pending = false; @@ -121,13 +137,14 @@ void writeback_enable (writeback_mode_t mode) { void writeback_disable (void) { p.enabled = false; p.pending = false; - timer_set(TIMER_ID_WRITEBACK, 0); + timer_countdown_abort(TIMER_ID_WRITEBACK); } bool writeback_pending (void) { return p.enabled && p.pending; } + void writeback_init (void) { p.enabled = false; p.pending = false; @@ -137,6 +154,7 @@ void writeback_init (void) { } } + void writeback_process (void) { if (p.enabled && (p.mode == WRITEBACK_SD) && !sd_card_is_inserted()) { writeback_disable(); @@ -144,24 +162,27 @@ void writeback_process (void) { if (p.enabled) { uint16_t save_count = fpga_reg_get(REG_SAVE_COUNT); + if (save_count != p.last_save_count) { p.pending = true; p.last_save_count = save_count; - timer_set(TIMER_ID_WRITEBACK, WRITEBACK_DELAY_TICKS); + timer_countdown_start(TIMER_ID_WRITEBACK, WRITEBACK_DELAY_MS); } } - if (p.pending && (timer_get(TIMER_ID_WRITEBACK) == 0)) { + if (p.pending && timer_countdown_elapsed(TIMER_ID_WRITEBACK)) { switch (p.mode) { case WRITEBACK_SD: writeback_save_to_sd(); p.pending = false; break; + case WRITEBACK_USB: if (writeback_save_to_usb()) { p.pending = false; } break; + default: writeback_disable(); break; diff --git a/sw/controller/src/writeback.h b/sw/controller/src/writeback.h index 8e10b45..2e6a5cc 100644 --- a/sw/controller/src/writeback.h +++ b/sw/controller/src/writeback.h @@ -6,7 +6,7 @@ #include -#define WRITEBACK_SECTOR_TABLE_SIZE (1024) +#define WRITEBACK_SECTOR_TABLE_SIZE (1024) typedef enum { @@ -16,10 +16,13 @@ typedef enum { void writeback_load_sector_table (uint32_t address); + void writeback_enable (writeback_mode_t mode); void writeback_disable (void); bool writeback_pending (void); + void writeback_init (void); + void writeback_process (void); diff --git a/sw/deployer/Cargo.lock b/sw/deployer/Cargo.lock index 0de6a3b..3e5c644 100644 --- a/sw/deployer/Cargo.lock +++ b/sw/deployer/Cargo.lock @@ -2,27 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "CoreFoundation-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0e9889e6db118d49d88d84728d0e964d973a5680befb5f85f55141beea5c20b" -dependencies = [ - "libc", - "mach 0.1.2", -] - -[[package]] -name = "IOKit-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99696c398cbaf669d2368076bdb3d627fb0ce51a26899d7c61228c5c0af3bf4a" -dependencies = [ - "CoreFoundation-sys", - "libc", - "mach 0.1.2", -] - [[package]] name = "adler" version = "1.0.2" @@ -37,9 +16,9 @@ checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] name = "ahash" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" dependencies = [ "getrandom", "once_cell", @@ -48,13 +27,19 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -65,14 +50,51 @@ dependencies = [ ] [[package]] -name = "atty" -version = "0.2.14" +name = "anstream" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" + +[[package]] +name = "anstyle-parse" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", ] [[package]] @@ -94,28 +116,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bumpalo" -version = "3.12.0" +name = "bitflags" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -125,32 +156,26 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", - "time", "wasm-bindgen", - "winapi", + "windows-targets 0.48.5", ] [[package]] name = "clap" -version = "4.1.8" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" +checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ - "bitflags", + "clap_builder", "clap_derive", - "clap_lex", - "is-terminal", - "once_cell", - "strsim", - "termcolor", ] [[package]] @@ -163,36 +188,34 @@ dependencies = [ ] [[package]] -name = "clap_derive" -version = "4.1.8" +name = "clap_builder" +version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0" +checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", - "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 2.0.48", ] [[package]] name = "clap_lex" -version = "0.3.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "color_quant" @@ -201,21 +224,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] -name = "colored" -version = "2.0.0" +name = "colorchoice" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + +[[package]] +name = "colored" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" dependencies = [ - "atty", "lazy_static", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crc32fast" @@ -226,48 +254,30 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crunchy" @@ -277,56 +287,12 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "ctrlc" -version = "3.2.5" +version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639" +checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b" dependencies = [ - "nix 0.26.2", - "windows-sys", -] - -[[package]] -name = "cxx" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a140f260e6f3f79013b8bfc65e7ce630c9ab4388c6a89c71e07226f49487b72" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da6383f459341ea689374bf0a42979739dc421874f112ff26f829b8040b8e613" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90201c1a650e95ccff1c8c0bb5a343213bdd317c6e600a93075bca2eff54ec97" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.92" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b75aed41bb2e6367cae39e6326ef817a851db13c13e4f3263714ca3cfb8de56" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "nix 0.27.1", + "windows-sys 0.52.0", ] [[package]] @@ -337,45 +303,24 @@ checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] -[[package]] -name = "errno" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" -dependencies = [ - "errno-dragonfly", - "libc", - "winapi", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "exr" -version = "1.6.3" +version = "1.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd2162b720141a91a054640662d3edce3d50a944a50ffca5313cd951abb35b4" +checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" dependencies = [ "bit_field", "flume", @@ -388,10 +333,19 @@ dependencies = [ ] [[package]] -name = "flate2" -version = "1.0.25" +name = "fdeflate" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ "crc32fast", "miniz_oxide", @@ -399,47 +353,29 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.14" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project", "spin", ] -[[package]] -name = "futures-core" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" - -[[package]] -name = "futures-sink" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" - [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", - "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", + "wasi", ] [[package]] name = "gif" -version = "0.11.4" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3edd93c6756b4dfaf2709eafcc345ba2636565295c198a9cfbf75fa5e3e00b06" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" dependencies = [ "color_quant", "weezl", @@ -469,30 +405,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - [[package]] name = "hex" version = "0.4.3" @@ -501,33 +413,32 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "iana-time-zone" -version = "0.1.53" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "winapi", + "windows-core", ] [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] name = "image" -version = "0.24.5" +version = "0.24.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b7ea949b537b0fd0af141fff8c77690f2ce96f4f41f042ccb6c69c6c965945" +checksum = "034bbe799d1909622a74d1193aa50147769440040ff36cb2baa947609b0a4e23" dependencies = [ "bytemuck", "byteorder", @@ -535,10 +446,9 @@ dependencies = [ "exr", "gif", "jpeg-decoder", - "num-rational", "num-traits", "png", - "scoped_threadpool", + "qoi", "tiff", ] @@ -563,7 +473,7 @@ dependencies = [ "proc-macro-hack", "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] @@ -577,41 +487,29 @@ dependencies = [ ] [[package]] -name = "io-lifetimes" -version = "1.0.6" +name = "io-kit-sys" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" +checksum = "4769cb30e5dcf1710fc6730d3e94f78c47723a014a567de385e113c737394640" dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "is-terminal" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" -dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix", - "windows-sys", + "core-foundation-sys", + "mach2", ] [[package]] name = "jpeg-decoder" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" dependencies = [ "rayon", ] [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -630,15 +528,15 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libflate" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97822bf791bd4d5b403713886a5fbe8bf49520fe78e323b0dc480ca1a03e50b0" +checksum = "5ff4ae71b685bbad2f2f391fe74f6b7659a34871c08b210fdc039e43bee07d18" dependencies = [ "adler32", "crc32fast", @@ -674,26 +572,11 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] - -[[package]] -name = "linux-raw-sys" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" - [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -701,27 +584,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] -name = "mach" -version = "0.1.2" +name = "mach2" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd13ee2dd61cc82833ba05ade5a30bb3d63f7ced605ef827063c63078302de9" -dependencies = [ - "libc", -] - -[[package]] -name = "mach" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" dependencies = [ "libc", ] @@ -734,105 +605,56 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", -] - -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom", + "simd-adler32", ] [[package]] name = "nix" -version = "0.24.3" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "libc", ] [[package]] name = "nix" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags", + "bitflags 2.4.2", "cfg-if", "libc", - "static_assertions", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi 0.2.6", - "libc", -] - [[package]] name = "once_cell" -version = "1.17.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "ordered-multimap" @@ -844,80 +666,31 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "os_str_bytes" -version = "6.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" - [[package]] name = "panic-message" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384e52fd8fbd4cbe3c317e8216260c21a0f9134de108cea8a4dd4e7e152c472d" -[[package]] -name = "pin-project" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" [[package]] name = "png" -version = "0.17.7" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" +checksum = "1f6c3c3e617595665b8ea2ff95a86066be38fb121ff920a9c0eb282abcd1da5a" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", + "fdeflate", "flate2", "miniz_oxide", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -926,27 +699,36 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.52" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] [[package]] -name = "quote" -version = "1.0.26" +name = "qoi" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" dependencies = [ "either", "rayon-core", @@ -954,21 +736,31 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] name = "regex" -version = "1.7.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -977,9 +769,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rle-decode-fast" @@ -997,20 +789,6 @@ dependencies = [ "ordered-multimap", ] -[[package]] -name = "rustix" -version = "0.36.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "sc64deployer" version = "2.18.0" @@ -1032,29 +810,17 @@ dependencies = [ "serialport", ] -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" - [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serial2" -version = "0.1.7" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa2370e12745a20d3dcd07438fc72f399c74f59537a35863a1a7a9ff2482040" +checksum = "7eea9caf87881a41a0d01cc89ee8abc5d690b943b07b282d9cde0a1dbb30cbb6" dependencies = [ "cfg-if", "libc", @@ -1063,48 +829,44 @@ dependencies = [ [[package]] name = "serialport" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aab92efb5cf60ad310548bc3f16fa6b0d950019cb7ed8ff41968c3d03721cf12" +checksum = "8f5a15d0be940df84846264b09b51b10b931fb2f275becb80934e3568a016828" dependencies = [ - "CoreFoundation-sys", - "IOKit-sys", - "bitflags", + "bitflags 2.4.2", "cfg-if", + "core-foundation-sys", + "io-kit-sys", "libudev", - "mach 0.3.2", - "nix 0.24.3", + "mach2", + "nix 0.26.4", "regex", + "scopeguard", + "unescaper", "winapi", ] [[package]] name = "simd-adler32" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "spin" -version = "0.9.6" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5d6e0250b93c8427a177b849d144a96d5acc57006149479403d7861ab721e34" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ "lock_api", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" version = "0.10.0" @@ -1123,19 +885,41 @@ dependencies = [ ] [[package]] -name = "termcolor" -version = "1.2.0" +name = "syn" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ - "winapi-util", + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.48", ] [[package]] name = "tiff" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7449334f9ff2baf290d55d73983a7d6fa15e01198faef72af07e2a8db851e471" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" dependencies = [ "flate2", "jpeg-decoder", @@ -1143,27 +927,25 @@ dependencies = [ ] [[package]] -name = "time" -version = "0.1.45" +name = "unescaper" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +checksum = "d8f0f68e58d297ba8b22b8b5a96a87b863ba6bb46aaf51e19a4b02c5a6dd5b7f" dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", + "thiserror", ] [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] -name = "unicode-width" -version = "0.1.10" +name = "utf8parse" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "version_check" @@ -1171,12 +953,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1185,9 +961,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1195,24 +971,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn", + "syn 2.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1220,22 +996,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "weezl" @@ -1259,15 +1035,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1275,76 +1042,151 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.45.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "zune-inflate" -version = "0.2.51" +version = "0.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01728b79fb9b7e28a8c11f715e1cd8dc2cda7416a007d66cac55cebb3a8ac6b" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] diff --git a/sw/deployer/Cargo.toml b/sw/deployer/Cargo.toml index 93c77e2..b559eb1 100644 --- a/sw/deployer/Cargo.toml +++ b/sw/deployer/Cargo.toml @@ -20,8 +20,8 @@ include-flate = { version = "0.2.0", features = ["stable"] } md5 = "0.7.0" panic-message = "0.3.0" rust-ini = "0.18.0" -serial2 = "0.1.7" -serialport = "4.2.0" +serial2 = "0.2.17" +serialport = "4.3.0" [profile.release] lto = true diff --git a/sw/deployer/src/debug.rs b/sw/deployer/src/debug.rs index 734b701..d78244b 100644 --- a/sw/deployer/src/debug.rs +++ b/sw/deployer/src/debug.rs @@ -166,6 +166,20 @@ const MAX_PACKET_LENGTH: usize = 8 * 1024 * 1024; const SUPPORTED_USB_PROTOCOL_VERSION: u16 = 2; impl Handler { + pub fn new() -> Self { + let (line_tx, line_rx) = channel::(); + let external_line_tx = line_tx.clone(); + + spawn(move || stdin_thread(line_tx)); + + Handler { + header: None, + line_rx, + external_line_tx, + encoding: Encoding::UTF8, + } + } + pub fn set_text_encoding(&mut self, encoding: Encoding) { self.encoding = encoding; } @@ -391,20 +405,6 @@ impl Handler { } } -pub fn new() -> Handler { - let (line_tx, line_rx) = channel::(); - let external_line_tx = line_tx.clone(); - - spawn(move || stdin_thread(line_tx)); - - Handler { - header: None, - line_rx, - external_line_tx, - encoding: Encoding::UTF8, - } -} - fn load_file(path: &str) -> Result, String> { if path.len() == 0 { return Err(format!("Couldn't open file: Specified path is empty")); diff --git a/sw/deployer/src/main.rs b/sw/deployer/src/main.rs index 7dee5c0..82fb288 100644 --- a/sw/deployer/src/main.rs +++ b/sw/deployer/src/main.rs @@ -417,7 +417,7 @@ fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), s let mut sc64 = init_sc64(connection, true)?; - let mut debug_handler = debug::new(); + let mut debug_handler = debug::Handler::new(); println!( "{}\n{}\n{}\n{}", @@ -627,7 +627,7 @@ fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), s fn handle_debug_command(connection: Connection, args: &DebugArgs) -> Result<(), sc64::Error> { let mut sc64 = init_sc64(connection, true)?; - let mut debug_handler = debug::new(); + let mut debug_handler = debug::Handler::new(); if args.euc_jp { debug_handler.set_text_encoding(debug::Encoding::EUCJP); @@ -738,7 +738,7 @@ fn handle_info_command(connection: Connection) -> Result<(), sc64::Error> { println!(" LED blink: {}", state.led_enable); println!(" IS-Viewer 64 offset: 0x{:08X}", state.isv_address); println!(" FPGA debug data: {}", state.fpga_debug_data); - println!(" MCU stack usage: {}", state.mcu_stack_usage); + println!(" Diagnostic data: {}", state.diagnostic_data); Ok(()) } @@ -859,7 +859,7 @@ fn handle_server_command(connection: Connection, args: &ServerArgs) -> Result<() None }; - sc64::run_server(port, args.address.clone(), |event| match event { + sc64::server::run(port, args.address.clone(), |event| match event { sc64::ServerEvent::Listening(address) => { println!( "{}: Listening on address [{}]", @@ -895,8 +895,8 @@ fn handle_server_command(connection: Connection, args: &ServerArgs) -> Result<() fn init_sc64(connection: Connection, check_firmware: bool) -> Result { let mut sc64 = match connection { - Connection::Local(port) => sc64::new_local(port), - Connection::Remote(remote) => sc64::new_remote(remote), + Connection::Local(port) => sc64::SC64::open_local(port), + Connection::Remote(remote) => sc64::SC64::open_remote(remote), }?; if check_firmware { diff --git a/sw/deployer/src/sc64/mod.rs b/sw/deployer/src/sc64/mod.rs index 5f0e8eb..f3842fc 100644 --- a/sw/deployer/src/sc64/mod.rs +++ b/sw/deployer/src/sc64/mod.rs @@ -2,7 +2,7 @@ mod cic; mod error; pub mod firmware; mod link; -mod server; +pub mod server; mod time; mod types; @@ -12,7 +12,7 @@ pub use self::{ server::ServerEvent, types::{ BootMode, ButtonMode, ButtonState, CicSeed, DataPacket, DdDiskState, DdDriveType, DdMode, - DebugPacket, DiskPacket, DiskPacketKind, FpgaDebugData, McuStackUsage, SaveType, + DebugPacket, DiagnosticData, DiskPacket, DiskPacketKind, FpgaDebugData, SaveType, SaveWriteback, Switch, TvType, }, }; @@ -55,7 +55,7 @@ pub struct DeviceState { pub led_enable: Switch, pub datetime: DateTime, pub fpga_debug_data: FpgaDebugData, - pub mcu_stack_usage: McuStackUsage, + pub diagnostic_data: DiagnosticData, } const SC64_V2_IDENTIFIER: &[u8; 4] = b"SCv2"; @@ -350,7 +350,7 @@ impl SC64 { Ok(u32::from_be_bytes(data[0..4].try_into().unwrap()).try_into()?) } - fn command_debug_get(&mut self) -> Result { + fn command_fpga_debug_data_get(&mut self) -> Result { let data = self.link.execute_command(&Command { id: b'?', args: [0, 0], @@ -359,7 +359,7 @@ impl SC64 { Ok(data.try_into()?) } - fn command_stack_usage_get(&mut self) -> Result { + fn command_diagnostic_data_get(&mut self) -> Result { let data = self.link.execute_command(&Command { id: b'%', args: [0, 0], @@ -557,8 +557,8 @@ impl SC64 { rom_extended_enable: get_config!(self, RomExtendedEnable)?, led_enable: get_setting!(self, LedEnable)?, datetime: self.get_datetime()?, - fpga_debug_data: self.command_debug_get()?, - mcu_stack_usage: self.command_stack_usage_get()?, + fpga_debug_data: self.command_fpga_debug_data_get()?, + diagnostic_data: self.command_diagnostic_data_get()?, }) } @@ -787,36 +787,25 @@ impl SC64 { } } -pub fn new_local(port: Option) -> Result { - let port = if let Some(port) = port { - port - } else { - list_local_devices()?[0].port.clone() - }; - let mut sc64 = SC64 { - link: link::new_local(&port)?, - }; - sc64.check_device()?; - Ok(sc64) -} +impl SC64 { + pub fn open_local(port: Option) -> Result { + let port = if let Some(port) = port { + port + } else { + list_local_devices()?[0].port.clone() + }; + let mut sc64 = SC64 { + link: link::new_local(&port)?, + }; + sc64.check_device()?; + Ok(sc64) + } -pub fn new_remote(address: String) -> Result { - let mut sc64 = SC64 { - link: link::new_remote(&address)?, - }; - sc64.check_device()?; - Ok(sc64) -} - -pub fn run_server( - port: Option, - address: String, - event_callback: fn(ServerEvent), -) -> Result<(), Error> { - let port = if let Some(port) = port { - port - } else { - list_local_devices()?[0].port.clone() - }; - server::run_server(&port, address, event_callback) + pub fn open_remote(address: String) -> Result { + let mut sc64 = SC64 { + link: link::new_remote(&address)?, + }; + sc64.check_device()?; + Ok(sc64) + } } diff --git a/sw/deployer/src/sc64/server.rs b/sw/deployer/src/sc64/server.rs index 091a479..d27a0f0 100644 --- a/sw/deployer/src/sc64/server.rs +++ b/sw/deployer/src/sc64/server.rs @@ -1,6 +1,6 @@ use super::{ error::Error, - link::{new_serial, Command, DataType, Packet, Response, Serial}, + link::{list_local_devices, new_serial, Command, DataType, Packet, Response, Serial}, }; use std::{ collections::VecDeque, @@ -22,11 +22,16 @@ pub enum ServerEvent { Err(String), } -pub fn run_server( - port: &str, +pub fn run( + port: Option, address: String, event_callback: fn(ServerEvent), ) -> Result<(), Error> { + let port = if let Some(port) = port { + port + } else { + list_local_devices()?[0].port.clone() + }; let listener = TcpListener::bind(address)?; let listening_address = listener.local_addr()?; event_callback(ServerEvent::Listening(listening_address.to_string())); @@ -36,7 +41,7 @@ pub fn run_server( Ok(mut stream) => { let peer = stream.peer_addr()?.to_string(); event_callback(ServerEvent::Connected(peer.clone())); - match server_accept_connection(port, &mut stream) { + match server_accept_connection(port.clone(), &mut stream) { Ok(()) => event_callback(ServerEvent::Disconnected(peer.clone())), Err(error) => event_callback(ServerEvent::Err(error.to_string())), } @@ -58,14 +63,14 @@ enum Event { Closed(Option), } -fn server_accept_connection(port: &str, stream: &mut TcpStream) -> Result<(), Error> { +fn server_accept_connection(port: String, stream: &mut TcpStream) -> Result<(), Error> { let (event_sender, event_receiver) = channel::(); let exit_flag = Arc::new(AtomicBool::new(false)); let mut stream_writer = BufWriter::new(stream.try_clone()?); let mut stream_reader = stream.try_clone()?; - let serial = Arc::new(new_serial(port)?); + let serial = Arc::new(new_serial(&port)?); let serial_writer = serial.clone(); let serial_reader = serial.clone(); diff --git a/sw/deployer/src/sc64/types.rs b/sw/deployer/src/sc64/types.rs index 505db68..58ffc59 100644 --- a/sw/deployer/src/sc64/types.rs +++ b/sw/deployer/src/sc64/types.rs @@ -828,37 +828,81 @@ impl Display for FpgaDebugData { } } -pub struct McuStackUsage { +pub struct DiagnosticDataV0 { pub cic: u32, pub rtc: u32, pub led: u32, pub gvr: u32, } -impl TryFrom> for McuStackUsage { +pub struct DiagnosticDataV1 { + pub voltage: f32, + pub temperature: f32, +} + +pub enum DiagnosticData { + V0(DiagnosticDataV0), + V1(DiagnosticDataV1), + Unknown, +} + +impl TryFrom> for DiagnosticData { type Error = Error; fn try_from(value: Vec) -> Result { - if value.len() != 16 { - return Err(Error::new("Invalid data length for MCU stack usage")); + if value.len() < 4 { + return Err(Error::new("Invalid data length for diagnostic data")); + } + let raw_version = u32::from_be_bytes(value[0..4].try_into().unwrap()); + let unversioned = raw_version & (1 << 31) == 0; + let version = raw_version & !(1 << 31); + + if unversioned { + if value.len() != 16 { + return Err(Error::new("Invalid data length for V0 diagnostic data")); + } + return Ok(DiagnosticData::V0(DiagnosticDataV0 { + cic: u32::from_be_bytes(value[0..4].try_into().unwrap()), + rtc: u32::from_be_bytes(value[4..8].try_into().unwrap()), + led: u32::from_be_bytes(value[8..12].try_into().unwrap()), + gvr: u32::from_be_bytes(value[12..16].try_into().unwrap()), + })); + } + + match version { + 1 => { + if value.len() != 16 { + return Err(Error::new("Invalid data length for V1 diagnostic data")); + } + let raw_voltage = u32::from_be_bytes(value[4..8].try_into().unwrap()) as f32; + let raw_temperature = u32::from_be_bytes(value[8..12].try_into().unwrap()) as f32; + Ok(DiagnosticData::V1(DiagnosticDataV1 { + voltage: raw_voltage / 1000.0, + temperature: raw_temperature / 10.0, + })) + } + _ => Ok(DiagnosticData::Unknown), } - Ok(McuStackUsage { - cic: u32::from_be_bytes(value[0..4].try_into().unwrap()), - rtc: u32::from_be_bytes(value[4..8].try_into().unwrap()), - led: u32::from_be_bytes(value[8..12].try_into().unwrap()), - gvr: u32::from_be_bytes(value[12..16].try_into().unwrap()), - }) } } -impl Display for McuStackUsage { +impl Display for DiagnosticData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.cic > 0 { - f.write_fmt(format_args!("CIC: {}, ", self.cic))?; + match self { + DiagnosticData::V0(d) => { + if d.cic > 0 { + f.write_fmt(format_args!("CIC: {}, ", d.cic))?; + } + f.write_fmt(format_args!( + "RTC: {}, LED: {}, GVR: {}", + d.rtc, d.led, d.gvr + )) + } + DiagnosticData::V1(d) => f.write_fmt(format_args!( + "{:.03} V / {:.01} °C", + d.voltage, d.temperature + )), + DiagnosticData::Unknown => f.write_str("Unknown"), } - f.write_fmt(format_args!( - "RTC: {}, LED: {}, GVR: {}", - self.rtc, self.led, self.gvr - )) } } @@ -874,7 +918,7 @@ macro_rules! get_config { macro_rules! get_setting { ($sc64:ident, $setting:ident) => {{ - // Note: remove 'allow(irrefutable_let_patterns)' below when more settings are added + // NOTE: remove 'allow(irrefutable_let_patterns)' below when more settings are added #[allow(irrefutable_let_patterns)] if let Setting::$setting(value) = $sc64.command_setting_get(SettingId::$setting)? { Ok(value) diff --git a/sw/tools/primer.py b/sw/tools/primer.py index 495413b..4f24016 100644 --- a/sw/tools/primer.py +++ b/sw/tools/primer.py @@ -204,9 +204,16 @@ class STM32Bootloader: __connected = False - def __init__(self, write: Callable[[bytes], None], read: Callable[[int], bytes], progress: Callable[[int, int, str], None]): + def __init__( + self, + write: Callable[[bytes], None], + read: Callable[[int], bytes], + flush: Callable[[None], None], + progress: Callable[[int, int, str], None] + ): self.__write = write self.__read = read + self.__flush = flush self.__progress = progress def __append_xor(self, data: bytes) -> bytes: @@ -217,7 +224,7 @@ class STM32Bootloader: def __check_ack(self) -> None: response = self.__read(1) - if (response == None): + if (len(response) != 1): raise STM32BootloaderException('No ACK/NACK byte received') if (response == self.__NACK): raise STM32BootloaderException('NACK byte received') @@ -228,18 +235,22 @@ class STM32Bootloader: if (len(cmd) != 1): raise ValueError('Command must contain only one byte') self.__write(self.__append_xor(cmd)) + self.__flush() self.__check_ack() def __data_write(self, data: bytes) -> None: self.__write(self.__append_xor(data)) + self.__flush() self.__check_ack() def __data_read(self) -> bytes: length = self.__read(1) if (len(length) != 1): raise STM32BootloaderException('Did not receive length byte') - length = length[0] - data = self.__read(length + 1) + length = (length[0] + 1) + data = self.__read(length) + if (len(data) != length): + raise STM32BootloaderException('Did not receive requested data bytes') self.__check_ack() return data @@ -253,7 +264,10 @@ class STM32Bootloader: self.__cmd_send(b'\x11') self.__data_write(address.to_bytes(4, byteorder='big')) self.__data_write(bytes([length - 1])) - return self.__read(length) + data = self.__read(length) + if (len(data) != length): + raise STM32BootloaderException(f'Did not receive requested memory bytes') + return data def __go(self, address: int) -> None: self.__cmd_send(b'\x21') @@ -288,8 +302,12 @@ class STM32Bootloader: def connect(self, id: int) -> None: if (not self.__connected): - self.__write(self.__INIT) - self.__check_ack() + try: + self.__write(self.__INIT) + self.__flush() + self.__check_ack() + except STM32BootloaderException as e: + raise STM32BootloaderException(f'Could not connect to the STM32 ({e})') self.__connected = True dev_id = self.__get_id() if (dev_id != id): @@ -339,9 +357,16 @@ class LCMXO2Primer: DEV_ID_LCMXO2_7000HC = b'\x01\x2B\xD0\x43' - def __init__(self, write: Callable[[bytes], None], read: Callable[[int], bytes], progress: Callable[[int, int, str], None]): + def __init__( + self, + write: Callable[[bytes], None], + read: Callable[[int], bytes], + flush: Callable[[None], None], + progress: Callable[[int, int, str], None] + ): self.__write = write self.__read = read + self.__flush = flush self.__progress = progress def __cmd_execute(self, cmd: bytes, data: bytes=b'') -> bytes: @@ -355,14 +380,20 @@ class LCMXO2Primer: packet += data packet += crc32(packet).to_bytes(4, byteorder='little') self.__write(packet) + self.__flush() response = self.__read(5) if (len(response) != 5): raise LCMXO2PrimerException(f'No response received [{cmd}]') length = int.from_bytes(response[4:5], byteorder='little') - response += self.__read(length) - calculated_checksum = crc32(response) - received_checksum = int.from_bytes(self.__read(4), byteorder='little') + response_data = self.__read(length) + if (len(response_data) != length): + raise LCMXO2PrimerException(f'No response data received [{cmd}]') + checksum = self.__read(4) + if (len(checksum) != 4): + raise LCMXO2PrimerException(f'No response data checksum received [{cmd}]') + calculated_checksum = crc32(response + response_data) + received_checksum = int.from_bytes(checksum, byteorder='little') if (response[0:3] != b'RSP'): raise LCMXO2PrimerException(f'Invalid response token [{response[0:3]} / {cmd}]') @@ -371,16 +402,19 @@ class LCMXO2Primer: if (calculated_checksum != received_checksum): raise LCMXO2PrimerException(f'Invalid response checksum [{cmd}]') - return response[5:] + return response_data def connect(self, id: bytes) -> None: - primer_id = self.__cmd_execute(self.__CMD_GET_PRIMER_ID) - if (primer_id != self.__PRIMER_ID_LCMXO2): - raise LCMXO2PrimerException('Invalid primer ID received') + try: + primer_id = self.__cmd_execute(self.__CMD_GET_PRIMER_ID) + if (primer_id != self.__PRIMER_ID_LCMXO2): + raise LCMXO2PrimerException('Invalid primer ID received') - dev_id = self.__cmd_execute(self.__CMD_GET_DEVICE_ID) - if (dev_id != id): - raise LCMXO2PrimerException('Invalid FPGA device id received') + dev_id = self.__cmd_execute(self.__CMD_GET_DEVICE_ID) + if (dev_id != id): + raise LCMXO2PrimerException('Invalid FPGA device id received') + except LCMXO2PrimerException as e: + raise LCMXO2PrimerException(f'Could not connect to the LCMXO2 primer ({e})') def load_flash_and_run(self, data: bytes, description: str) -> None: erase_description = f'{description} / Erase' @@ -599,8 +633,8 @@ class SC64BringUp: write_timeout=self.__SERIAL_TIMEOUT ) - stm32_bootloader = STM32Bootloader(link.write, link.read, self.__progress) - lcmxo2_primer = LCMXO2Primer(link.write, link.read, self.__progress) + stm32_bootloader = STM32Bootloader(link.write, link.read, link.flush, self.__progress) + lcmxo2_primer = LCMXO2Primer(link.write, link.read, link.flush, self.__progress) stm32_bootloader.connect(stm32_bootloader.DEV_ID_STM32G030XX) stm32_bootloader.load_ram_and_run(self.__sc64_update_data.get_primer_data(), 'FPGA primer -> STM32 RAM') @@ -645,7 +679,7 @@ if __name__ == '__main__': sc64_bring_up = SC64BringUp(progress=utils.progress) Utils.log() - Utils.info('[ Welcome to SC64 flashcart board bring-up! ]') + Utils.info('[ Welcome to the SummerCart64 flashcart board bring-up! ]') Utils.log() Utils.log(f'Serial port: {port}') @@ -683,6 +717,7 @@ if __name__ == '__main__': original_sigint_handler = signal.getsignal(signal.SIGINT) try: signal.signal(signal.SIGINT, lambda *kwargs: utils.exit_warning()) + Utils.log('Starting SC64 flashcart board bring-up...') sc64_bring_up.start_bring_up(port, bootloader_only) except (serial.SerialException, STM32BootloaderException, LCMXO2PrimerException, SC64Exception) as e: if (utils.get_progress_active):