From 9a5bdfba6c16a66203c70db1a1a694d673b08c24 Mon Sep 17 00:00:00 2001 From: Lukas Pajak <9783727+LukasP46@users.noreply.github.com> Date: Thu, 28 Nov 2024 11:20:31 +0100 Subject: [PATCH 01/16] [sw/bootloader] add TWI boot option --- sw/bootloader/bootloader.c | 184 +++++++++++++++++++++++++++++++------ 1 file changed, 157 insertions(+), 27 deletions(-) diff --git a/sw/bootloader/bootloader.c b/sw/bootloader/bootloader.c index cf31453b4..b9083beac 100644 --- a/sw/bootloader/bootloader.c +++ b/sw/bootloader/bootloader.c @@ -58,6 +58,7 @@ #endif /* -------- Auto-boot configuration -------- */ +/* Priority SPI > TWI */ /** Time until the auto-boot sequence starts (in seconds); 0 = disabled */ #ifndef AUTO_BOOT_TIMEOUT @@ -103,6 +104,29 @@ #define XIP_EN 1 #endif +/* -------- TWI configuration -------- */ +/* assumes single byte address */ + +/** Enable TWI for cooping to RAM */ +#ifndef TWI_EN + #define TWI_EN 1 +#endif + +/** TWI Clock pre-scaler */ +#ifndef TWI_CLK_PRSC + #define TWI_CLK_PRSC CLK_PRSC_64 +#endif + +/** TWI Clock divider */ +#ifndef TWI_CLK_DIV + #define TWI_CLK_DIV 3 +#endif + +/** TWI First Slave ID*/ +#ifndef TWI_SLAVE_ID + #define TWI_SLAVE_ID 0x50 +#endif + /**@}*/ @@ -111,7 +135,8 @@ **************************************************************************/ enum EXE_STREAM_SOURCE_enum { EXE_STREAM_UART = 0, /**< Get executable via UART */ - EXE_STREAM_FLASH = 1 /**< Get executable via SPI flash */ + EXE_STREAM_FLASH = 1, /**< Get executable via SPI flash */ + EXE_STREAM_TWI = 2 /**< Get executable via I2c Slave */ }; @@ -122,18 +147,20 @@ enum ERROR_CODES_enum { ERROR_SIGNATURE = 0, /**< 0: Wrong signature in executable */ ERROR_SIZE = 1, /**< 1: Insufficient instruction memory capacity */ ERROR_CHECKSUM = 2, /**< 2: Checksum error in executable */ - ERROR_FLASH = 3 /**< 3: SPI flash access error */ + ERROR_FLASH = 3, /**< 3: SPI flash access error */ + ERROR_TWI = 4 /**< 3: TWI access error (missing ACK) */ }; /**********************************************************************//** * Error messages **************************************************************************/ -const char error_message[4][5] = { +const char error_message[5][5] = { "EXE", "SIZE", "CHKS", - "FLSH" + "FLSH", + "TWI" }; @@ -237,6 +264,9 @@ void spi_flash_write_disable(void); uint8_t spi_flash_read_status(void); void spi_flash_write_addr(uint32_t addr); +// TWI driver functions +uint32_t twi_read_addr(uint32_t addr); + /**********************************************************************//** * Sanity check: Base RV32I ISA only! @@ -287,6 +317,11 @@ int main(void) { #endif #endif +#if (TWI_EN != 0) + // setup TWI + neorv32_twi_setup(TWI_CLK_PRSC, TWI_CLK_DIV, 0); +#endif + // Configure machine system timer interrupt if (neorv32_mtime_available()) { NEORV32_MTIME->TIME_LO = 0; @@ -322,7 +357,7 @@ int main(void) { // ------------------------------------------------ // Auto boot sequence // ------------------------------------------------ -#if (SPI_EN != 0) +#if (SPI_EN != 0 || TWI_EN != 0) #if (AUTO_BOOT_TIMEOUT != 0) if (neorv32_mtime_available()) { @@ -339,7 +374,11 @@ int main(void) { } if (neorv32_mtime_get_time() >= timeout_time) { // timeout? start auto boot sequence - get_exe(EXE_STREAM_FLASH); // try booting from flash + #if (SPI_EN != 0) + get_exe(EXE_STREAM_FLASH); // try booting from flash + #elif (TWI_EN != 0) + get_exe(EXE_STREAM_TWI); // try booting from twi + #endif PRINT_TEXT("\n"); start_app(0); while(1); @@ -385,6 +424,11 @@ int main(void) { else if (c == 'l') { // copy executable from flash get_exe(EXE_STREAM_FLASH); } +#endif +#if (TWI_EN != 0) + else if (c == 't') { // copy executable from TWI + get_exe(EXE_STREAM_TWI); + } #endif else if (c == 'e') { // start application program from IMEM if (exe_available == 0) { // executable available? @@ -430,6 +474,9 @@ void print_help(void) { " s: Store to flash\n" " l: Load from flash\n" #endif +#if (TWI_EN != 0) + " t: Load from TWI Slave\n" +#endif #if (XIP_EN != 0) " x: Boot from flash (XIP)\n" #endif @@ -532,25 +579,35 @@ void get_exe(int src) { getting_exe = 1; // to inform trap handler we were trying to get an executable // flash image base address - uint32_t addr = (uint32_t)SPI_BOOT_BASE_ADDR; + uint32_t addr = 0; + if (src == EXE_STREAM_FLASH) { + addr = (uint32_t)SPI_BOOT_BASE_ADDR; + } + // get image from UART? if (src == EXE_STREAM_UART) { PRINT_TEXT("Awaiting neorv32_exe.bin... "); } -#if (SPI_EN != 0) - else { + #if (SPI_EN != 0) + else if(src == EXE_STREAM_FLASH) { PRINT_TEXT("Loading from SPI flash @"); PRINT_XNUM(addr); PRINT_TEXT("...\n"); // flash checks if (((NEORV32_SYSINFO->SOC & (1< Date: Wed, 4 Dec 2024 10:00:05 +0100 Subject: [PATCH 02/16] [sw/bootloader] disable twi by default --- sw/bootloader/bootloader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sw/bootloader/bootloader.c b/sw/bootloader/bootloader.c index b9083beac..3cfcdae6b 100644 --- a/sw/bootloader/bootloader.c +++ b/sw/bootloader/bootloader.c @@ -109,7 +109,7 @@ /** Enable TWI for cooping to RAM */ #ifndef TWI_EN - #define TWI_EN 1 + #define TWI_EN 0 #endif /** TWI Clock pre-scaler */ From ea16b6abdc9f4eedf25f0bfbdd223278643ae966 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Wed, 4 Dec 2024 10:10:09 +0100 Subject: [PATCH 03/16] [sw/bootloader] add feature switches to makefile --- sw/bootloader/makefile | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sw/bootloader/makefile b/sw/bootloader/makefile index bffcb9c76..1d2865c25 100644 --- a/sw/bootloader/makefile +++ b/sw/bootloader/makefile @@ -18,6 +18,32 @@ USER_FLAGS += \ -DMAKE_BOOTLOADER \ -flto +# Set which bootloader features to compile and associated settings. +# Warning: Enabling them all while sticking to the minimal RISC-V ISA will result in a too-large binary! + +#USER_FLAGS += -DUART_EN=1 +#USER_FLAGS += -DUART_EN=19200 +#USER_FLAGS += -DUART_HW_HANDSHAKE_EN=0 + +#USER_FLAGS += -DSTATUS_LED_EN=1 +#USER_FLAGS += -DSTATUS_LED_PIN=0 + +#USER_FLAGS += -DAUTO_BOOT_TIMEOUT=10 + +#USER_FLAGS += -DSPI_EN=0 +#USER_FLAGS += -DSPI_FLASH_CS=0 +#USER_FLAGS += -DSPI_FLASH_ADDR_BYTES=3 +#USER_FLAGS += -DSPI_FLASH_SECTOR_SIZE=65536 +#USER_FLAGS += -DSPI_FLASH_CLK_PRSC=CLK_PRSC_8 +#USER_FLAGS += -DSPI_BOOT_BASE_ADDR=0x00400000UL + +#USER_FLAGS += -DXIP_EN=1 + +#USER_FLAGS += -DTWI_EN=1 +#USER_FLAGS += -DTWI_CLK_PRSC=CLK_PRSC_64 +#USER_FLAGS += -DTWI_CLK_DIV=3 +#USER_FLAGS += -DTWI_SLAVE_ID=0x50 + # Set path to NEORV32 root directory NEORV32_HOME ?= ../.. From e5ea480868e1e6438002fcdcc7d8b1a399820ba1 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Wed, 4 Dec 2024 10:56:48 +0100 Subject: [PATCH 04/16] [docs] Add TWI bootloader capabilities --- README.md | 2 +- docs/datasheet/software_bootloader.adoc | 15 ++++++++++++++- docs/userguide/customizing_the_bootloader.adoc | 10 +++++++++- docs/userguide/executable_upload.adoc | 3 +++ 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fec5536f2..a47f3d1ea 100644 --- a/README.md +++ b/README.md @@ -148,7 +148,7 @@ for **custom RISC-V instructions**; caches ([iCACHE](https://stnolting.github.io/neorv32/#_processor_internal_instruction_cache_icache) and [dCACHE](https://stnolting.github.io/neorv32/#_processor_internal_data_cache_dcache)) * pre-installed bootloader ([BOOTLDROM](https://stnolting.github.io/neorv32/#_bootloader_rom_bootrom)) with serial user interface; -allows booting application code via UART or from external SPI flash +allows booting application code via UART, TWI or from external SPI flash **Timers and Counters** diff --git a/docs/datasheet/software_bootloader.adoc b/docs/datasheet/software_bootloader.adoc index acd282789..0213da620 100644 --- a/docs/datasheet/software_bootloader.adoc +++ b/docs/datasheet/software_bootloader.adoc @@ -34,6 +34,7 @@ The bootloader requires certain CPU and SoC extensions and modules to be enabled | _RECOMMENDED_ | The <<_machine_system_timer_mtime>> is used to control blinking of the status LED and also to automatically trigger the <<_auto_boot_sequence>>. | OPTIONAL | The SPI controller (<<_serial_peripheral_interface_controller_spi>>) is needed to store/load executable from external flash using the <<_auto_boot_sequence>>. | OPTIONAL | The XIP controller (<<_execute_in_place_module_xip>>) is needed to boot/execute code directly from a pre-programmed SPI flash. +| OPTIONAL | The TWI controller (<<_two_wire_serial_interface_controller_twi>>) is needed to boot/execute code directly from pre-programmed TWI memory. |======================= @@ -58,6 +59,14 @@ Most properties (like chip select line, flash address width, SPI clock frequency without the need to change the source code. Custom configuration can be made using command line switches (defines) when recompiling the bootloader. See the User Guide https://stnolting.github.io/neorv32/ug/#_customizing_the_internal_bootloader for more information. +:sectnums: +==== Bootloader TWI memory Requirements + +The bootloader can access an TWI-compatible memory via the processor's top entity TWI port. Only single-address memory is supported, and reading is done in the following pattern +`Slave Address + Enabled Read | Memory Address | Read Byte 0 | Read Byte 1 | Read Byte 2 | Read Byte 3`. +The addresses are incremented until the end of the program binary is reached. + +Clock speed information can be read here: <<_two_wire_serial_interface_controller_twi>>. :sectnums: ==== Bootloader Console @@ -142,6 +151,7 @@ Available CMDs: u: Upload s: Store to flash l: Load from flash + t: Load from TWI Slave x: Boot from flash (XIP) e: Execute CMD:> @@ -155,6 +165,7 @@ The auto boot countdown is stopped and the bootloader's user console is ready to * `u`: Upload new program executable (`neorv32_exe.bin`) via UART into the instruction memory * `s`: Store executable to SPI flash at `spi_csn_o(0)` (little-endian byte order) * `l`: Load executable from SPI flash at `spi_csn_o(0)` (little-endian byte order) +* `t`: Load executable from TWI memory at `0x50` (little-endian byte order) (disabled by default) * `x`: Boot program directly from flash via XIP (requires a pre-programmed image) * `e`: Start the application, which is currently stored in the instruction memory (IMEM) @@ -194,7 +205,8 @@ https://stnolting.github.io/neorv32/ug/#_programming_an_external_spi_flash_via_t When you reset the NEORV32 processor, the bootloader waits 8 seconds for a UART console input before it starts the automatic boot sequence. This sequence tries to fetch a valid boot image from the external SPI -flash, connected to SPI chip select `spi_csn_o(0)`. If a valid boot image is found that can be successfully +flash, connected to SPI chip select `spi_csn_o(0)` or from external TWI memory. If both are enabled, the bootloader +will select SPI. If a valid boot image is found that can be successfully transferred into the instruction memory, it is automatically started. If no SPI flash is detected or if there is no valid boot image found, and error code will be shown. @@ -216,6 +228,7 @@ In many cases the error source is just _temporary_ (like some HF spike during an | **`ERR_CHKS`** | This indicates a checksum error. Something went wrong during the transfer of the program image (upload via UART or loading from the external SPI flash). If the error was caused by a UART upload, just try it again. When the error was generated during a flash access, the stored image might be corrupted. | **`ERR_FLSH`** | This error occurs if the attached SPI flash cannot be accessed. Make sure you have the right type of flash and that it is properly connected to the NEORV32 SPI port using chip select #0. | **`ERR_EXC`** | The bootloader encountered an unexpected exception during operation. This might be caused when it tries to access peripherals that were not implemented during synthesis. Example: executing commands `l` or `s` (SPI flash operations) without the SPI module being implemented. +| **`ERR_TWI`** | The TWI received an unexpected NACK while reading the external memory. Are the address and speed settings correct? |======================= [TIP] diff --git a/docs/userguide/customizing_the_bootloader.adoc b/docs/userguide/customizing_the_bootloader.adoc index 32a4cbc48..f16ce4839 100644 --- a/docs/userguide/customizing_the_bootloader.adoc +++ b/docs/userguide/customizing_the_bootloader.adoc @@ -39,14 +39,22 @@ minimal base & privileged ISA `rv32i_zicsr_zifencei` only to ensure it can work | `SPI_BOOT_BASE_ADDR` | `0x00400000` | _any_ 32-bit value | Defines the _base_ address of the executable in external flash 4+^| XIP configuration | `XIP_EN` | `0` | `0`, `1` | Set `1` to enable the XIP options +4+^| TWI configuration +| `TWI_EN` | `0` | `0`, `1` | Set `1` to enable the usage of the SPI module (including load/store executables from/to SPI flash options) +| `TWI_CLK_PRSC` | `CLK_PRSC_64` | `CLK_PRSC_2` `CLK_PRSC_4` `CLK_PRSC_8` `CLK_PRSC_64` `CLK_PRSC_128` `CLK_PRSC_1024` `CLK_PRSC_2024` `CLK_PRSC_4096` | TWI clock pre-scaler (dividing main processor clock) +| `TWI_CLK_DIV` | `3` | `0` ... `15` | TWI clock divider (dividing twi clock) +| `TWI_SLAVE_ID` | `0x50` | `0x00` ... `0x7F` | First TWI slave ID to start. Is incremented until the end of the program is reached. |======================= +[IMPORTANT] +Enabling all features while sticking to the minimal RISC-V ISA will result in a too-large binary! + [NOTE] The XIP options re-use the "SPI configuration" options for configuring the XIP's SPI connection. Each configuration parameter is implemented as C-language `define` that can be manually overridden (_redefined_) when invoking the bootloader's makefile. The according parameter and its new value has to be _appended_ -(using `+=`) to the makefile `USER_FLAGS` variable. Make sure to use the `-D` prefix here. +(using `+=`) to the makefile `USER_FLAGS` variable. Make sure to use the `-D` prefix here. The configuration is also listed in the makefile of the bootloader. For example, to configure a UART Baud rate of 57600 and redirecting the status LED to GPIO output pin 20 use the following command: diff --git a/docs/userguide/executable_upload.adoc b/docs/userguide/executable_upload.adoc index 11a9c3f2d..63d7688f7 100644 --- a/docs/userguide/executable_upload.adoc +++ b/docs/userguide/executable_upload.adoc @@ -123,6 +123,9 @@ See section https://stnolting.github.io/neorv32/#_bootloader[Bootloader] of the See section <<_programming_an_external_spi_flash_via_the_bootloader>> to learn how to use an external SPI flash for nonvolatile program storage. +[TIP] +The bootloader also supports booting from external TWI memory. Enable it in the bootloader makefile, but be caution, enabling all features might result in a too-big binary. + [TIP] Executables can also be uploaded via the **on-chip debugger**. See section <<_debugging_with_gdb>> for more information. From e20f25127a44595ce6a1003c20af3c4ff6ff2131 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Thu, 2 Jan 2025 13:38:12 +0100 Subject: [PATCH 05/16] Fix typo --- sw/bootloader/bootloader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sw/bootloader/bootloader.c b/sw/bootloader/bootloader.c index 3cfcdae6b..9f87c96cf 100644 --- a/sw/bootloader/bootloader.c +++ b/sw/bootloader/bootloader.c @@ -107,7 +107,7 @@ /* -------- TWI configuration -------- */ /* assumes single byte address */ -/** Enable TWI for cooping to RAM */ +/** Enable TWI for copying to RAM */ #ifndef TWI_EN #define TWI_EN 0 #endif From 6955eb5734fdcfcf882bcb7afb08d449c5c31882 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Thu, 2 Jan 2025 16:27:08 +0100 Subject: [PATCH 06/16] [sw/bootloader] add two byte twi addressing --- sw/bootloader/bootloader.c | 25 ++++++++++++++++++++++--- sw/bootloader/makefile | 1 + 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/sw/bootloader/bootloader.c b/sw/bootloader/bootloader.c index 9f87c96cf..6d47721b0 100644 --- a/sw/bootloader/bootloader.c +++ b/sw/bootloader/bootloader.c @@ -122,11 +122,16 @@ #define TWI_CLK_DIV 3 #endif -/** TWI First Slave ID*/ +/** TWI First Slave ID */ #ifndef TWI_SLAVE_ID #define TWI_SLAVE_ID 0x50 #endif +/** TWI Memory address width (in numbers of bytes; 1 or 2) */ +#ifndef TWI_ADDR_BYTES + #define TWI_ADDR_BYTES 1 +#endif + /**@}*/ @@ -1040,8 +1045,13 @@ uint32_t twi_read_addr(uint32_t addr) { address.uint32 = addr; - uint8_t device_id = address.uint8[1] + TWI_SLAVE_ID; - +#if (TWI_ADDR_BYTES == 1) + uint8_t device_id = address.uint8[TWI_ADDR_BYTES] + TWI_SLAVE_ID; +#elif (TWI_ADDR_BYTES == 2) + uint8_t device_id = TWI_SLAVE_ID; +#else + #error "Unsupported TWI_ADDR_BYTES configuration!" +#endif /*********************** @@ -1055,8 +1065,17 @@ uint32_t twi_read_addr(uint32_t addr) { device_nack |= neorv32_twi_trans(&transfer, 0); // Send read address +#if (TWI_ADDR_BYTES == 1) transfer = address.uint8[0]; device_nack |= neorv32_twi_trans(&transfer, 0); +#elif (TWI_ADDR_BYTES == 2) + transfer = address.uint8[1]; + device_nack |= neorv32_twi_trans(&transfer, 0); + transfer = address.uint8[0]; + device_nack |= neorv32_twi_trans(&transfer, 0); +#else + #error "Unsupported TWI_ADDR_BYTES configuration!" +#endif /*********************** * Read data diff --git a/sw/bootloader/makefile b/sw/bootloader/makefile index 1d2865c25..925a3ff03 100644 --- a/sw/bootloader/makefile +++ b/sw/bootloader/makefile @@ -43,6 +43,7 @@ USER_FLAGS += \ #USER_FLAGS += -DTWI_CLK_PRSC=CLK_PRSC_64 #USER_FLAGS += -DTWI_CLK_DIV=3 #USER_FLAGS += -DTWI_SLAVE_ID=0x50 +#USER_FLAGS += -DTWI_ADDR_BYTES=0x50 # Set path to NEORV32 root directory NEORV32_HOME ?= ../.. From 2670ee11674c45a07abca6e505870959f0c90823 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Fri, 3 Jan 2025 16:55:04 +0100 Subject: [PATCH 07/16] [sw/bootloader] fix makefile default --- sw/bootloader/makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sw/bootloader/makefile b/sw/bootloader/makefile index 925a3ff03..75a5be6c3 100644 --- a/sw/bootloader/makefile +++ b/sw/bootloader/makefile @@ -43,7 +43,7 @@ USER_FLAGS += \ #USER_FLAGS += -DTWI_CLK_PRSC=CLK_PRSC_64 #USER_FLAGS += -DTWI_CLK_DIV=3 #USER_FLAGS += -DTWI_SLAVE_ID=0x50 -#USER_FLAGS += -DTWI_ADDR_BYTES=0x50 +#USER_FLAGS += -DTWI_ADDR_BYTES=1 # Set path to NEORV32 root directory NEORV32_HOME ?= ../.. From cc6cd4e0993f15324fe77090fb7ea8b1712eb069 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Fri, 3 Jan 2025 17:11:58 +0100 Subject: [PATCH 08/16] [docs] Add bootloader two-byte-addressing --- docs/datasheet/software_bootloader.adoc | 4 ++-- docs/userguide/customizing_the_bootloader.adoc | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/datasheet/software_bootloader.adoc b/docs/datasheet/software_bootloader.adoc index 6178d3444..2c2c4d9a8 100644 --- a/docs/datasheet/software_bootloader.adoc +++ b/docs/datasheet/software_bootloader.adoc @@ -74,8 +74,8 @@ the bootloader. See the User Guide https://stnolting.github.io/neorv32/ug/#_cust :sectnums: ==== Bootloader TWI memory Requirements -The bootloader can access an TWI-compatible memory via the processor's top entity TWI port. Only single-address memory is supported, and reading is done in the following pattern -`Slave Address + Enabled Read | Memory Address | Read Byte 0 | Read Byte 1 | Read Byte 2 | Read Byte 3`. +The bootloader can access an TWI-compatible memory via the processor's top entity TWI port. Single- and dual address memory is supported, and reading is done in the following pattern +`Slave Address + Enabled Read | Memory Address Byte 0 | Memory Address 1 (optional) | Read Byte 0 | Read Byte 1 | Read Byte 2 | Read Byte 3`. The addresses are incremented until the end of the program binary is reached. Clock speed information can be read here: <<_two_wire_serial_interface_controller_twi>>. diff --git a/docs/userguide/customizing_the_bootloader.adoc b/docs/userguide/customizing_the_bootloader.adoc index 467dcf839..69da2b8e2 100644 --- a/docs/userguide/customizing_the_bootloader.adoc +++ b/docs/userguide/customizing_the_bootloader.adoc @@ -43,7 +43,8 @@ minimal base & privileged ISA `rv32e_zicsr_zifencei` only to ensure it can work | `TWI_EN` | `0` | `0`, `1` | Set `1` to enable the usage of the SPI module (including load/store executables from/to SPI flash options) | `TWI_CLK_PRSC` | `CLK_PRSC_64` | `CLK_PRSC_2` `CLK_PRSC_4` `CLK_PRSC_8` `CLK_PRSC_64` `CLK_PRSC_128` `CLK_PRSC_1024` `CLK_PRSC_2024` `CLK_PRSC_4096` | TWI clock pre-scaler (dividing main processor clock) | `TWI_CLK_DIV` | `3` | `0` ... `15` | TWI clock divider (dividing twi clock) -| `TWI_SLAVE_ID` | `0x50` | `0x00` ... `0x7F` | First TWI slave ID to start. Is incremented until the end of the program is reached. +| `TWI_SLAVE_ID` | `0x50` | `0x00` ... `0x7F` | First TWI slave ID to start. Is incremented until the end of the program is reached, when `TWI_ADDR_BYTES` is `1`. +| `TWI_ADDR_BYTES` | `1` | `1`, `2` | TWI memory address size in number of bytes. When `TWI_ADDR_BYTES` is `1`, `TWI_SLAVE_ID` the gets incremented as well. |======================= [IMPORTANT] From 96a8dd969f345f67338aaebcb0003f2f80f1387d Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Fri, 3 Jan 2025 17:27:18 +0100 Subject: [PATCH 09/16] [sw] Add eeprom upload tool --- sw/eeprom_upload/eeprom_upload.py | 134 ++++++++++++++++++++++++++++++ sw/eeprom_upload/requirements.txt | 2 + 2 files changed, 136 insertions(+) create mode 100644 sw/eeprom_upload/eeprom_upload.py create mode 100644 sw/eeprom_upload/requirements.txt diff --git a/sw/eeprom_upload/eeprom_upload.py b/sw/eeprom_upload/eeprom_upload.py new file mode 100644 index 000000000..b0a54ae46 --- /dev/null +++ b/sw/eeprom_upload/eeprom_upload.py @@ -0,0 +1,134 @@ +import sys +from usb_iss import UsbIss, defs +import time +import argparse +from argparse import ArgumentDefaultsHelpFormatter + + +class Interface: + """Interface for I2C Memory""" + + # bootloader.c notation + EXE_OFFSET_SIZE = 4 + EXE_OFFSET_DATA = 12 + + def __init__(self, port, slave_id, max_bytes_size, two_address_bytes): + # Test for Value Errors + if not (0 <= slave_id <= 127): + raise ValueError( + f"Not fulfilled: 0 <= slave_id({slave_id}) <= 127") + self._iss = UsbIss() + self._iss.open(port) + self._iss.setup_i2c() + self._slave_id = slave_id + self._max_bytes_size = max_bytes_size + self._two_address_bytes = two_address_bytes + + def _i2c_write(self, i2c_slave_id, register, data): + if self._two_address_bytes: + self._iss.i2c.write_ad2(i2c_slave_id, register, data) + else: + self._iss.i2c.write_ad1(i2c_slave_id, register, data) + + def _i2c_read(self, i2c_slave_id, register, byte_count): + if self._two_address_bytes: + return self._iss.i2c.read_ad2(i2c_slave_id, register, byte_count) + else: + return self._iss.i2c.read_ad1(i2c_slave_id, register, byte_count) + + def _split_addr(self, address): + if self._two_address_bytes: + # Pseudo offset and one 16-bit block + return 0, address & 0xFFFF + else: + # Split into two 8-bit blocks (though the first one actually cannot be that high) + return (address >> 8) & 0xFF, address & 0xFF + + def write_bin_file(self, file_path): + """Write a binary file byte-wise to slave until last Slave ID. Fill-in with 0x00.""" + with open(file_path, 'rb') as f: + # Read the entire file content + bin_data = f.read() + if len(bin_data) > (self._max_bytes_size): + raise RuntimeError(f"File too big {len(bin_data)} > {self._max_bytes_size} [bytes]") + print("Write size: ", len(bin_data), " bytes") + # New array with filled up 0x0 + write_data = bin_data + b'\x00' * (self._max_bytes_size - len(bin_data)) + print("Write...", end="") + sys.stdout.flush() + for i in range(0, len(write_data), 8): # Write in block of 8 bytes + block = write_data[i:i + 8] + address_blocks = self._split_addr(i) + self._i2c_write(address_blocks[0] + self._slave_id, address_blocks[1] , list(block)) + time.sleep(0.01) + print("done") + + def read_bin_file(self): + """Read image from memory""" + size_bytes = self._i2c_read(self._slave_id, self.EXE_OFFSET_SIZE, 4) + size = (size_bytes[3] << 24) | (size_bytes[2] << 16) | (size_bytes[1] << 8) | size_bytes[0] + size += self.EXE_OFFSET_DATA # Add padding for executable header + if size > (self._max_bytes_size): + raise RuntimeError(f"Noted size too big {size} > {self._max_bytes_size} [bytes]") + print("Read size: ", size, " bytes") + print("Read...", end="") + read_data = b'' + for i in range (0, size, 32): # Read in max. block of 32 bytes + byte_count = max(32, i - size) # Last block may be smaller + address_blocks = self._split_addr(i) + read_data += bytes(self._i2c_read(address_blocks[0] + self._slave_id, address_blocks[1], byte_count)) + + print("done") + return read_data + + def validate_bin_file(self, file_path): + """Compare read file and given file""" + with open(file_path, 'rb') as f: + # Read the entire file content + reference_data = f.read() + read_data = self.read_bin_file() + read_size = len(read_data) + reference_size = ((len(read_data) + 31) // 32) * 32 # Round up to next multiple of 32 + assert reference_size == read_size, f"Read size {read_size} != {len(reference_data)} (32 bit aligned) [bytes]" + for i in range(0, len(reference_data)): # Compare only to data content + assert reference_data[i] == read_data[i], f"Read data {read_data[i]} != {reference_data[i]} at address {i}" + print("Validation successful") + +if __name__ == "__main__": + # Argparse + parser = argparse.ArgumentParser( + description="Python script to upload program to I2C Memory via USB ISS.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + parser.add_argument( + "file", type=str, + help="Path to binary file, read if no -s, write with -s") + parser.add_argument( + "-p", "--port", type=str, + default="/dev/ttyACM0", + help="I2C ISS Port") + parser.add_argument( + "-s", "--save", action='store_true', + default=False, + help="Readout memory and safe to file") + parser.add_argument( + "-i", "--slave-id", type=int, + default=0x50, + help="First I2C Slave ID") + parser.add_argument( + "-m", "--max-bytes-size", type=int, + default=2048, + help="Size of memory in bytes") + parser.add_argument( + "-t", "--two-address-bytes", action='store_true', + default=False, + help="Enables two-bytes-addressing") + args = parser.parse_args() + + ifc = Interface(args.port, args.slave_id, args.max_bytes_size, args.two_address_bytes) + if(args.save): + with open(args.file, "wb") as f: + f.write(ifc.read_bin_file()) + else: + ifc.write_bin_file(args.file) + ifc.validate_bin_file(args.file) \ No newline at end of file diff --git a/sw/eeprom_upload/requirements.txt b/sw/eeprom_upload/requirements.txt new file mode 100644 index 000000000..8bc567616 --- /dev/null +++ b/sw/eeprom_upload/requirements.txt @@ -0,0 +1,2 @@ +pyserial==3.5 +usb-iss==2.0.1 From 19102666e387f320fd60baca2ed30b808b94a46b Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Fri, 3 Jan 2025 17:30:45 +0100 Subject: [PATCH 10/16] [docs] Add eeprom upload tool --- docs/datasheet/software_bootloader.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/datasheet/software_bootloader.adoc b/docs/datasheet/software_bootloader.adoc index 2c2c4d9a8..dcae039ce 100644 --- a/docs/datasheet/software_bootloader.adoc +++ b/docs/datasheet/software_bootloader.adoc @@ -78,6 +78,9 @@ The bootloader can access an TWI-compatible memory via the processor's top entit `Slave Address + Enabled Read | Memory Address Byte 0 | Memory Address 1 (optional) | Read Byte 0 | Read Byte 1 | Read Byte 2 | Read Byte 3`. The addresses are incremented until the end of the program binary is reached. +A python upload script for uploading is provided in the `sw/eeprom_upload` folder. Currently only for the https://www.robot-electronics.co.uk/htm/usb_iss_tech.htm[USB-ISS] module. + + Clock speed information can be read here: <<_two_wire_serial_interface_controller_twi>>. :sectnums: From 27320b462937f91329989bbbfa5cd3d0cbe48816 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Wed, 8 Jan 2025 08:51:40 +0100 Subject: [PATCH 11/16] [sw] remove eeprom upload script --- sw/eeprom_upload/eeprom_upload.py | 134 ------------------------------ sw/eeprom_upload/requirements.txt | 2 - 2 files changed, 136 deletions(-) delete mode 100644 sw/eeprom_upload/eeprom_upload.py delete mode 100644 sw/eeprom_upload/requirements.txt diff --git a/sw/eeprom_upload/eeprom_upload.py b/sw/eeprom_upload/eeprom_upload.py deleted file mode 100644 index b0a54ae46..000000000 --- a/sw/eeprom_upload/eeprom_upload.py +++ /dev/null @@ -1,134 +0,0 @@ -import sys -from usb_iss import UsbIss, defs -import time -import argparse -from argparse import ArgumentDefaultsHelpFormatter - - -class Interface: - """Interface for I2C Memory""" - - # bootloader.c notation - EXE_OFFSET_SIZE = 4 - EXE_OFFSET_DATA = 12 - - def __init__(self, port, slave_id, max_bytes_size, two_address_bytes): - # Test for Value Errors - if not (0 <= slave_id <= 127): - raise ValueError( - f"Not fulfilled: 0 <= slave_id({slave_id}) <= 127") - self._iss = UsbIss() - self._iss.open(port) - self._iss.setup_i2c() - self._slave_id = slave_id - self._max_bytes_size = max_bytes_size - self._two_address_bytes = two_address_bytes - - def _i2c_write(self, i2c_slave_id, register, data): - if self._two_address_bytes: - self._iss.i2c.write_ad2(i2c_slave_id, register, data) - else: - self._iss.i2c.write_ad1(i2c_slave_id, register, data) - - def _i2c_read(self, i2c_slave_id, register, byte_count): - if self._two_address_bytes: - return self._iss.i2c.read_ad2(i2c_slave_id, register, byte_count) - else: - return self._iss.i2c.read_ad1(i2c_slave_id, register, byte_count) - - def _split_addr(self, address): - if self._two_address_bytes: - # Pseudo offset and one 16-bit block - return 0, address & 0xFFFF - else: - # Split into two 8-bit blocks (though the first one actually cannot be that high) - return (address >> 8) & 0xFF, address & 0xFF - - def write_bin_file(self, file_path): - """Write a binary file byte-wise to slave until last Slave ID. Fill-in with 0x00.""" - with open(file_path, 'rb') as f: - # Read the entire file content - bin_data = f.read() - if len(bin_data) > (self._max_bytes_size): - raise RuntimeError(f"File too big {len(bin_data)} > {self._max_bytes_size} [bytes]") - print("Write size: ", len(bin_data), " bytes") - # New array with filled up 0x0 - write_data = bin_data + b'\x00' * (self._max_bytes_size - len(bin_data)) - print("Write...", end="") - sys.stdout.flush() - for i in range(0, len(write_data), 8): # Write in block of 8 bytes - block = write_data[i:i + 8] - address_blocks = self._split_addr(i) - self._i2c_write(address_blocks[0] + self._slave_id, address_blocks[1] , list(block)) - time.sleep(0.01) - print("done") - - def read_bin_file(self): - """Read image from memory""" - size_bytes = self._i2c_read(self._slave_id, self.EXE_OFFSET_SIZE, 4) - size = (size_bytes[3] << 24) | (size_bytes[2] << 16) | (size_bytes[1] << 8) | size_bytes[0] - size += self.EXE_OFFSET_DATA # Add padding for executable header - if size > (self._max_bytes_size): - raise RuntimeError(f"Noted size too big {size} > {self._max_bytes_size} [bytes]") - print("Read size: ", size, " bytes") - print("Read...", end="") - read_data = b'' - for i in range (0, size, 32): # Read in max. block of 32 bytes - byte_count = max(32, i - size) # Last block may be smaller - address_blocks = self._split_addr(i) - read_data += bytes(self._i2c_read(address_blocks[0] + self._slave_id, address_blocks[1], byte_count)) - - print("done") - return read_data - - def validate_bin_file(self, file_path): - """Compare read file and given file""" - with open(file_path, 'rb') as f: - # Read the entire file content - reference_data = f.read() - read_data = self.read_bin_file() - read_size = len(read_data) - reference_size = ((len(read_data) + 31) // 32) * 32 # Round up to next multiple of 32 - assert reference_size == read_size, f"Read size {read_size} != {len(reference_data)} (32 bit aligned) [bytes]" - for i in range(0, len(reference_data)): # Compare only to data content - assert reference_data[i] == read_data[i], f"Read data {read_data[i]} != {reference_data[i]} at address {i}" - print("Validation successful") - -if __name__ == "__main__": - # Argparse - parser = argparse.ArgumentParser( - description="Python script to upload program to I2C Memory via USB ISS.", - formatter_class=argparse.ArgumentDefaultsHelpFormatter - ) - parser.add_argument( - "file", type=str, - help="Path to binary file, read if no -s, write with -s") - parser.add_argument( - "-p", "--port", type=str, - default="/dev/ttyACM0", - help="I2C ISS Port") - parser.add_argument( - "-s", "--save", action='store_true', - default=False, - help="Readout memory and safe to file") - parser.add_argument( - "-i", "--slave-id", type=int, - default=0x50, - help="First I2C Slave ID") - parser.add_argument( - "-m", "--max-bytes-size", type=int, - default=2048, - help="Size of memory in bytes") - parser.add_argument( - "-t", "--two-address-bytes", action='store_true', - default=False, - help="Enables two-bytes-addressing") - args = parser.parse_args() - - ifc = Interface(args.port, args.slave_id, args.max_bytes_size, args.two_address_bytes) - if(args.save): - with open(args.file, "wb") as f: - f.write(ifc.read_bin_file()) - else: - ifc.write_bin_file(args.file) - ifc.validate_bin_file(args.file) \ No newline at end of file diff --git a/sw/eeprom_upload/requirements.txt b/sw/eeprom_upload/requirements.txt deleted file mode 100644 index 8bc567616..000000000 --- a/sw/eeprom_upload/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pyserial==3.5 -usb-iss==2.0.1 From 2426943a15032c628fb9116d7bdae03ee13f9b23 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Wed, 8 Jan 2025 08:55:45 +0100 Subject: [PATCH 12/16] Renaming TWI_SLAVE_ID to TWI_DEVICE_ID --- docs/userguide/customizing_the_bootloader.adoc | 4 ++-- sw/bootloader/bootloader.c | 10 +++++----- sw/bootloader/makefile | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/userguide/customizing_the_bootloader.adoc b/docs/userguide/customizing_the_bootloader.adoc index 69da2b8e2..a589e61f6 100644 --- a/docs/userguide/customizing_the_bootloader.adoc +++ b/docs/userguide/customizing_the_bootloader.adoc @@ -43,8 +43,8 @@ minimal base & privileged ISA `rv32e_zicsr_zifencei` only to ensure it can work | `TWI_EN` | `0` | `0`, `1` | Set `1` to enable the usage of the SPI module (including load/store executables from/to SPI flash options) | `TWI_CLK_PRSC` | `CLK_PRSC_64` | `CLK_PRSC_2` `CLK_PRSC_4` `CLK_PRSC_8` `CLK_PRSC_64` `CLK_PRSC_128` `CLK_PRSC_1024` `CLK_PRSC_2024` `CLK_PRSC_4096` | TWI clock pre-scaler (dividing main processor clock) | `TWI_CLK_DIV` | `3` | `0` ... `15` | TWI clock divider (dividing twi clock) -| `TWI_SLAVE_ID` | `0x50` | `0x00` ... `0x7F` | First TWI slave ID to start. Is incremented until the end of the program is reached, when `TWI_ADDR_BYTES` is `1`. -| `TWI_ADDR_BYTES` | `1` | `1`, `2` | TWI memory address size in number of bytes. When `TWI_ADDR_BYTES` is `1`, `TWI_SLAVE_ID` the gets incremented as well. +| `TWI_DEVICE_ID` | `0x50` | `0x00` ... `0x7F` | First TWI slave ID to start. Is incremented until the end of the program is reached, when `TWI_ADDR_BYTES` is `1`. +| `TWI_ADDR_BYTES` | `1` | `1`, `2` | TWI memory address size in number of bytes. When `TWI_ADDR_BYTES` is `1`, `TWI_DEVICE_ID` the gets incremented as well. |======================= [IMPORTANT] diff --git a/sw/bootloader/bootloader.c b/sw/bootloader/bootloader.c index 066dd2574..72fc7c92d 100644 --- a/sw/bootloader/bootloader.c +++ b/sw/bootloader/bootloader.c @@ -123,8 +123,8 @@ #endif /** TWI First Slave ID */ -#ifndef TWI_SLAVE_ID - #define TWI_SLAVE_ID 0x50 +#ifndef TWI_DEVICE_ID + #define TWI_DEVICE_ID 0x50 #endif /** TWI Memory address width (in numbers of bytes; 1 or 2) */ @@ -603,7 +603,7 @@ void get_exe(int src) { #elif (TWI_EN) else { PRINT_TEXT("Loading from TWI slaves, starting with "); - PRINT_XNUM(TWI_SLAVE_ID); + PRINT_XNUM(TWI_DEVICE_ID); PRINT_TEXT("...\n"); } #endif @@ -1040,9 +1040,9 @@ uint32_t twi_read_addr(uint32_t addr) { address.uint32 = addr; #if (TWI_ADDR_BYTES == 1) - uint8_t device_id = address.uint8[TWI_ADDR_BYTES] + TWI_SLAVE_ID; + uint8_t device_id = address.uint8[TWI_ADDR_BYTES] + TWI_DEVICE_ID; #elif (TWI_ADDR_BYTES == 2) - uint8_t device_id = TWI_SLAVE_ID; + uint8_t device_id = TWI_DEVICE_ID; #else #error "Unsupported TWI_ADDR_BYTES configuration!" #endif diff --git a/sw/bootloader/makefile b/sw/bootloader/makefile index 86fce9a84..5518e3b6c 100644 --- a/sw/bootloader/makefile +++ b/sw/bootloader/makefile @@ -42,7 +42,7 @@ USER_FLAGS += \ #USER_FLAGS += -DTWI_EN=1 #USER_FLAGS += -DTWI_CLK_PRSC=CLK_PRSC_64 #USER_FLAGS += -DTWI_CLK_DIV=3 -#USER_FLAGS += -DTWI_SLAVE_ID=0x50 +#USER_FLAGS += -DTWI_DEVICE_ID=0x50 #USER_FLAGS += -DTWI_ADDR_BYTES=1 # Set path to NEORV32 root directory From 3b00009542a2060585da18acf895f57cf7c1d56b Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Wed, 8 Jan 2025 09:01:29 +0100 Subject: [PATCH 13/16] [docs] fix twi typo --- docs/userguide/customizing_the_bootloader.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/userguide/customizing_the_bootloader.adoc b/docs/userguide/customizing_the_bootloader.adoc index a589e61f6..a492ce073 100644 --- a/docs/userguide/customizing_the_bootloader.adoc +++ b/docs/userguide/customizing_the_bootloader.adoc @@ -43,7 +43,7 @@ minimal base & privileged ISA `rv32e_zicsr_zifencei` only to ensure it can work | `TWI_EN` | `0` | `0`, `1` | Set `1` to enable the usage of the SPI module (including load/store executables from/to SPI flash options) | `TWI_CLK_PRSC` | `CLK_PRSC_64` | `CLK_PRSC_2` `CLK_PRSC_4` `CLK_PRSC_8` `CLK_PRSC_64` `CLK_PRSC_128` `CLK_PRSC_1024` `CLK_PRSC_2024` `CLK_PRSC_4096` | TWI clock pre-scaler (dividing main processor clock) | `TWI_CLK_DIV` | `3` | `0` ... `15` | TWI clock divider (dividing twi clock) -| `TWI_DEVICE_ID` | `0x50` | `0x00` ... `0x7F` | First TWI slave ID to start. Is incremented until the end of the program is reached, when `TWI_ADDR_BYTES` is `1`. +| `TWI_DEVICE_ID` | `0x50` | `0x00` ... `0x7F` | First TWI device ID to start. Is incremented until the end of the program is reached, when `TWI_ADDR_BYTES` is `1`. | `TWI_ADDR_BYTES` | `1` | `1`, `2` | TWI memory address size in number of bytes. When `TWI_ADDR_BYTES` is `1`, `TWI_DEVICE_ID` the gets incremented as well. |======================= From b351ae6134d188d89a32ff846fdd918b13754473 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Wed, 8 Jan 2025 17:30:32 +0100 Subject: [PATCH 14/16] More twi device renaming --- docs/datasheet/software_bootloader.adoc | 4 ++-- sw/bootloader/bootloader.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/datasheet/software_bootloader.adoc b/docs/datasheet/software_bootloader.adoc index dcae039ce..88261221e 100644 --- a/docs/datasheet/software_bootloader.adoc +++ b/docs/datasheet/software_bootloader.adoc @@ -75,7 +75,7 @@ the bootloader. See the User Guide https://stnolting.github.io/neorv32/ug/#_cust ==== Bootloader TWI memory Requirements The bootloader can access an TWI-compatible memory via the processor's top entity TWI port. Single- and dual address memory is supported, and reading is done in the following pattern -`Slave Address + Enabled Read | Memory Address Byte 0 | Memory Address 1 (optional) | Read Byte 0 | Read Byte 1 | Read Byte 2 | Read Byte 3`. +`Device Address + Enabled Read | Memory Address Byte 0 | Memory Address 1 (optional) | Read Byte 0 | Read Byte 1 | Read Byte 2 | Read Byte 3`. The addresses are incremented until the end of the program binary is reached. A python upload script for uploading is provided in the `sw/eeprom_upload` folder. Currently only for the https://www.robot-electronics.co.uk/htm/usb_iss_tech.htm[USB-ISS] module. @@ -166,7 +166,7 @@ Available CMDs: u: Upload s: Store to flash l: Load from flash - t: Load from TWI Slave + t: Load from TWI Device x: Boot from flash (XIP) e: Execute CMD:> diff --git a/sw/bootloader/bootloader.c b/sw/bootloader/bootloader.c index 72fc7c92d..9dcb86dec 100644 --- a/sw/bootloader/bootloader.c +++ b/sw/bootloader/bootloader.c @@ -122,7 +122,7 @@ #define TWI_CLK_DIV 3 #endif -/** TWI First Slave ID */ +/** TWI First Device ID */ #ifndef TWI_DEVICE_ID #define TWI_DEVICE_ID 0x50 #endif @@ -141,7 +141,7 @@ enum EXE_STREAM_SOURCE_enum { EXE_STREAM_UART = 0, /**< Get executable via UART */ EXE_STREAM_FLASH = 1, /**< Get executable via SPI flash */ - EXE_STREAM_TWI = 2 /**< Get executable via I2c Slave */ + EXE_STREAM_TWI = 2 /**< Get executable via I2c Device */ }; @@ -474,7 +474,7 @@ void print_help(void) { " l: Load from flash\n" #endif #if (TWI_EN != 0) - " t: Load from TWI Slave\n" + " t: Load from TWI Device\n" #endif #if (XIP_EN != 0) " x: Boot from flash (XIP)\n" @@ -602,7 +602,7 @@ void get_exe(int src) { } #elif (TWI_EN) else { - PRINT_TEXT("Loading from TWI slaves, starting with "); + PRINT_TEXT("Loading from TWI Devices, starting with "); PRINT_XNUM(TWI_DEVICE_ID); PRINT_TEXT("...\n"); } @@ -714,7 +714,7 @@ void save_exe(void) { * Get word from executable stream * * @param src Source of executable stream data. See #EXE_STREAM_SOURCE_enum. - * @param addr Address when accessing SPI flash or TWI slave. + * @param addr Address when accessing SPI flash or TWI Device. * @return 32-bit data word from stream. **************************************************************************/ uint32_t get_exe_word(int src, uint32_t addr) { From cf119857c7eaf1f07b0fb7a28fdabafcd085b05f Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Thu, 9 Jan 2025 09:13:10 +0100 Subject: [PATCH 15/16] [sw/bootloader] renaming and minor optimizations --- docs/userguide/customizing_the_bootloader.adoc | 2 +- docs/userguide/executable_upload.adoc | 2 +- sw/bootloader/bootloader.c | 10 +++++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/docs/userguide/customizing_the_bootloader.adoc b/docs/userguide/customizing_the_bootloader.adoc index a492ce073..da8229db0 100644 --- a/docs/userguide/customizing_the_bootloader.adoc +++ b/docs/userguide/customizing_the_bootloader.adoc @@ -40,7 +40,7 @@ minimal base & privileged ISA `rv32e_zicsr_zifencei` only to ensure it can work 4+^| XIP configuration | `XIP_EN` | `0` | `0`, `1` | Set `1` to enable the XIP options 4+^| TWI configuration -| `TWI_EN` | `0` | `0`, `1` | Set `1` to enable the usage of the SPI module (including load/store executables from/to SPI flash options) +| `TWI_EN` | `0` | `0`, `1` | Set `1` to enable the usage of the TWI module (including load executables from TWI device option) | `TWI_CLK_PRSC` | `CLK_PRSC_64` | `CLK_PRSC_2` `CLK_PRSC_4` `CLK_PRSC_8` `CLK_PRSC_64` `CLK_PRSC_128` `CLK_PRSC_1024` `CLK_PRSC_2024` `CLK_PRSC_4096` | TWI clock pre-scaler (dividing main processor clock) | `TWI_CLK_DIV` | `3` | `0` ... `15` | TWI clock divider (dividing twi clock) | `TWI_DEVICE_ID` | `0x50` | `0x00` ... `0x7F` | First TWI device ID to start. Is incremented until the end of the program is reached, when `TWI_ADDR_BYTES` is `1`. diff --git a/docs/userguide/executable_upload.adoc b/docs/userguide/executable_upload.adoc index 63d7688f7..668756485 100644 --- a/docs/userguide/executable_upload.adoc +++ b/docs/userguide/executable_upload.adoc @@ -124,7 +124,7 @@ See section <<_programming_an_external_spi_flash_via_the_bootloader>> to learn h flash for nonvolatile program storage. [TIP] -The bootloader also supports booting from external TWI memory. Enable it in the bootloader makefile, but be caution, enabling all features might result in a too-big binary. +The bootloader also supports booting from external TWI memory. Enable it in the bootloader makefile, but be careful, enabling all features may result in a too-big binary. [TIP] Executables can also be uploaded via the **on-chip debugger**. diff --git a/sw/bootloader/bootloader.c b/sw/bootloader/bootloader.c index 9dcb86dec..e09c03caf 100644 --- a/sw/bootloader/bootloader.c +++ b/sw/bootloader/bootloader.c @@ -141,7 +141,7 @@ enum EXE_STREAM_SOURCE_enum { EXE_STREAM_UART = 0, /**< Get executable via UART */ EXE_STREAM_FLASH = 1, /**< Get executable via SPI flash */ - EXE_STREAM_TWI = 2 /**< Get executable via I2c Device */ + EXE_STREAM_TWI = 2 /**< Get executable via TWI device */ }; @@ -164,7 +164,7 @@ const char error_message[5][5] = { "EXE", "SIZE", "CHKS", - "FLSH", + "SPI", "TWI" }; @@ -718,9 +718,11 @@ void save_exe(void) { * @return 32-bit data word from stream. **************************************************************************/ uint32_t get_exe_word(int src, uint32_t addr) { +#if (TWI_EN != 0) if (src == EXE_STREAM_TWI) { return twi_read_addr(addr); } else { +#endif union { uint32_t uint32; uint8_t uint8[sizeof(uint32_t)]; @@ -737,7 +739,9 @@ uint32_t get_exe_word(int src, uint32_t addr) { } } return data.uint32; +#if (TWI_EN != 0) } +#endif } @@ -1105,4 +1109,4 @@ uint32_t twi_read_addr(uint32_t addr) { #else return 0; #endif -} \ No newline at end of file +} From 3854d3f2afa2f66e5a1a9580aadf141eed081934 Mon Sep 17 00:00:00 2001 From: Lukas Pajak Date: Thu, 9 Jan 2025 16:22:06 +0100 Subject: [PATCH 16/16] [sw/bootloader] remove obsolete comment --- sw/bootloader/bootloader.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sw/bootloader/bootloader.c b/sw/bootloader/bootloader.c index e09c03caf..a46137f5d 100644 --- a/sw/bootloader/bootloader.c +++ b/sw/bootloader/bootloader.c @@ -105,7 +105,6 @@ #endif /* -------- TWI configuration -------- */ -/* assumes single byte address */ /** Enable TWI for copying to RAM */ #ifndef TWI_EN