diff --git a/.github/workflows/test-build-renesas-rx.yml b/.github/workflows/test-build-renesas-rx.yml index 8cb8245cc4..10e5f08b0e 100644 --- a/.github/workflows/test-build-renesas-rx.yml +++ b/.github/workflows/test-build-renesas-rx.yml @@ -55,12 +55,34 @@ jobs: run: | make USE_GCC=0 CROSS_COMPILE=rx-elf- ${{inputs.make-args}} - - name: Check RX71M ROMCODE word + - name: Check RX71M/RX24T ROMCODE word # ROMCODE (0xFFFFFF9C, 100 bytes before the end of wolfboot.bin) set to # 0x00000000 or 0x00000001 enables ROM code protection - if: contains(inputs.config-file, 'rx71m') + if: contains(inputs.config-file, 'rx71m') || contains(inputs.config-file, 'rx24t') run: | size=$(stat -c %s wolfboot.bin) romcode=$(od -An -tx1 -j $((size - 100)) -N 4 wolfboot.bin | tr -d ' \n') echo "ROMCODE: $romcode" test "$romcode" = "ffffffff" + + - name: Check RX24T ID code and MDE + # ID code at 0xFFFFFFA0 (96 bytes before the end): without control + # code 45h every programmer connection erases the flash. + # MDE at 0xFFFFFF80 (128 bytes before the end) selects big endian. + if: contains(inputs.config-file, 'rx24t') + run: | + case "${{inputs.make-args}}" in + *BIG_ENDIAN=1*) + want_id=450102030405060708090a0b0c0d0e0f + want_mde=fffffff8 ;; + *) + want_id=03020145070605040b0a09080f0e0d0c + want_mde=ffffffff ;; + esac + size=$(stat -c %s wolfboot.bin) + id=$(od -An -tx1 -j $((size - 96)) -N 16 wolfboot.bin | tr -d ' \n') + mde=$(od -An -tx1 -j $((size - 128)) -N 4 wolfboot.bin | tr -d ' \n') + echo "ID code: $id" + echo "MDE: $mde" + test "$id" = "$want_id" + test "$mde" = "$want_mde" diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 452ebc6a5f..ddc6ee2a7e 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -1684,3 +1684,16 @@ jobs: arch: rx config-file: ./config/examples/renesas-rx71m.config make-args: BIG_ENDIAN=1 CFLAGS_EXTRA=-DWOLFBOOT_RENESAS_OSM + + renesas_rx24t_test: + uses: ./.github/workflows/test-build-renesas-rx.yml + with: + arch: rx + config-file: ./config/examples/renesas-rx24t.config + + renesas_rx24t_bigendian_osm_test: + uses: ./.github/workflows/test-build-renesas-rx.yml + with: + arch: rx + config-file: ./config/examples/renesas-rx24t.config + make-args: BIG_ENDIAN=1 CFLAGS_EXTRA=-DWOLFBOOT_RENESAS_OSM diff --git a/.gitignore b/.gitignore index 93a59348c3..c62ba9e3bb 100644 --- a/.gitignore +++ b/.gitignore @@ -413,6 +413,10 @@ IDE/Renesas/e2studio/RX71M/app_RenesasRX01/HardwareDebug IDE/Renesas/e2studio/RX71M/app_RenesasRX01/src/smc_gen IDE/Renesas/e2studio/RX71M/wolfBoot/HardwareDebug IDE/Renesas/e2studio/RX71M/wolfBoot/src/smc_gen +IDE/Renesas/e2studio/RX24T/app_RenesasRX01/HardwareDebug +IDE/Renesas/e2studio/RX24T/app_RenesasRX01/src/smc_gen +IDE/Renesas/e2studio/RX24T/wolfBoot/HardwareDebug +IDE/Renesas/e2studio/RX24T/wolfBoot/src/smc_gen # IDE pico-sdk build directories IDE/pico-sdk/rp2350/wolfboot/build diff --git a/IDE/Renesas/e2studio/RX24T/Readme.md b/IDE/Renesas/e2studio/RX24T/Readme.md new file mode 100644 index 0000000000..ba9132c37b --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/Readme.md @@ -0,0 +1,229 @@ +## wolfBoot for Renesas RX24T (CC-RX, e2 studio) + +## 1. Overview + +This example builds wolfBoot and a sample application for the Renesas Starter +Kit for RX24T with the CC-RX compiler in e2 studio. The application v1 is +updated to v2 by wolfBoot. Both versions are the same program; they print +their version and the state of the two partitions. + +- Signature ECC256, hash SHA256, 256-byte image header, software crypto. +- The flash layout, image header and partition flags are the same as in the + GCC build (`config/examples/renesas-rx24t.config`). Build wolfBoot and the + application with the same compiler: the GCC wolfBoot calls the address + stored at the application start, while the CC-RX wolfBoot jumps to the + application start. See + [docs/Targets.md](../../../../docs/Targets.md#renesas-rx24t). +- The console is SCI1 (PD3/PD5) on the board's USB serial port at 115200 8N1, + driven by wolfBoot's own UART code (`DEBUG_UART`). The BSP stdio is not + used, so no debugger is needed to see the output. + +| Region | Address | Size | +| --- | --- | --- | +| Boot partition (application) | 0xFFFC0000 | 0x18000 | +| Update partition | 0xFFFD8000 | 0x18000 | +| Swap sector | 0xFFFF0000 | 0x800 | +| wolfBoot, with the vector tables, OFS and ID code | 0xFFFF8000 | 0x8000 | + +## 2. Components and Tools + +| Item | Name/Version | Note | +| :-- | :-- | :-- | +| Board | Renesas Starter Kit for RX24T | R5F524TAADFP | +| IDE | e2 studio 2026-10 | | +| Compiler | CC-RX V3.08.00 | | +| BSP | r_bsp 7.71 | Downloaded by the Smart Configurator | +| Flash programmer | Renesas Flash Programmer V3 (GUI or `rfp-cli`) | E2 emulator Lite, FINE interface | +| rx-elf-objcopy | GCC for Renesas RX | Used by `make_images.sh` | +| Key tools | keygen and sign | Included in wolfBoot | + +Board settings: leave J8 open (single-chip mode). Power the board from its +5V jack. + +## 3. How to build and use + +### 3-1 Key generation + +``` +$ cd +$ make keytools +$ ./tools/keytools/keygen --ecc256 -g ./wolfboot_signing_private_key.der +``` + +The public key is written to `src/keystore.c`, which the wolfBoot project +compiles. Rebuild wolfBoot after generating a new key, and sign the +application with the same private key. + +### 3-2 Import the projects and generate the BSP code + +1. In e2 studio, File > Import > General > Existing Projects into Workspace, + select `/IDE/Renesas/e2studio/RX24T`, and import `wolfBoot` and + `app_RenesasRX01`. Do not tick "Copy projects into workspace": the + projects link to the wolfBoot sources by relative path. +2. Open `wolfBoot.scfg`, let the Smart Configurator download r_bsp 7.71 if + asked, and press "Generate Code". Do the same with + `app_RenesasRX01.scfg`. The code goes to `src/smc_gen` of each project. + +The Smart Configurator settings are already made: + +| Setting | wolfBoot | app_RenesasRX01 | +| :-- | :-- | :-- | +| Clocks | HOCO 32 MHz, PLL /4 x10: ICLK 80 MHz, PCLKA 80 MHz, PCLKB/D 40 MHz, FCLK 20 MHz | same | +| `BSP_CFG_USER_STACK_ENABLE` | 0 | 0 | +| `BSP_CFG_ISTACK_BYTES` | `0x1400` | `0x1400` | +| `BSP_CFG_HEAP_BYTES` | `0` | `0` | +| `BSP_CFG_IO_LIB_ENABLE` | 0 | 0 | +| `BSP_CFG_ID_CODE_LONG_1`-`4` | `0x45010203`, `0x04050607`, `0x08090A0B`, `0x0C0D0E0F` | not used (left out of the image) | +| `BSP_CFG_ROM_CODE_PROTECT_VALUE` | `0xFFFFFFFF` | not used | + +The wolfBoot clocks must stay as listed: the flash driver and the UART take +FCLK and PCLKB from these settings, and its delays assume ICLK 80 MHz at most. + +### 3-3 The boot mode ID code + +The BSP writes the ID code to `0xFFFFFFA0`, inside the wolfBoot image. +This project has the example ID to enable the boot protection. See +[docs/Targets.md](../../../../docs/Targets.md#rx24t-boot-mode-id-code). + +### 3-4 Build + +Build both projects (configuration HardwareDebug). The project settings are +preset: + +| Setting | wolfBoot | app_RenesasRX01 | +| :-- | :-- | :-- | +| Macros | `__WOLFBOOT`, `TARGET_rx24t`, `__RX__`, `WOLFSSL_USER_SETTINGS` | `WOLFBOOT_RENESAS_APP`, `TARGET_rx24t`, `__RX__`, `WOLFSSL_USER_SETTINGS`, `XMEMCPY=memcpy` | +| Pre-include | `../../include/user_settings.h` (sets `DEBUG_UART`), `../../include/target.h` | same | +| Compiler options | `-branch=32`, `-goptimize` | same | +| Linker optimization | `-optimize=symbol_delete` (unreferenced functions and variables are removed) | same | +| Standard library | `string.h` only, no `stdio.h` | same | +| ROM to RAM mapped sections | `D=R`, `D_1=R_1`, `D_2=R_2`, `PFRAM=RPFRAM` | same | +| Code start | `0xFFFF8000` | `0xFFFC0100` (after the 256-byte header) | + +The outputs are `wolfBoot.x` and `app_RenesasRX01.x` under each project's +`HardwareDebug` folder. + +### 3-5 Make the images + +``` +$ ./IDE/Renesas/e2studio/RX24T/make_images.sh ./wolfboot_signing_private_key.der +``` + +`` is the folder containing `rx-elf-objcopy`. The script +writes: + +| File | Address | +| :-- | :-- | +| `wolfboot.bin` | 0xFFFF8000 (32 KB, wolfBoot, the vector tables, OFS and ID code) | +| `app_RenesasRX01_v1_signed.bin` | 0xFFFC0000 (boot partition) | +| `app_RenesasRX01_v2_signed.bin` | 0xFFFD8000 (update partition) | + +### 3-6 Program the board + +With Renesas Flash Programmer, program the three binary files at the +addresses above, for example: + +``` +rfp-cli -if fine -t e2l -device RX200 -pv -auth id 450102030405060708090A0B0C0D0E0F \ + -bin FFFF8000 wolfboot.bin \ + -bin FFFC0000 app_RenesasRX01_v1_signed.bin \ + -bin FFFD8000 app_RenesasRX01_v2_signed.bin \ + -run +``` + +Do not program the `.mot` or `.abs` files: the application's ones carry an +all-`FF` ID code, which replaces wolfBoot's and makes the next connection +erase the flash. + +### 3-7 Run + +Open the board's USB serial port at 115200 8N1 and reset the board (or use +`-run` above). wolfBoot verifies and starts v1: + +``` +wolfBoot HAL Init +RAM Function start = 0x1D94 +RAM Function end = 0x2C0F +RAM Function size = 3707 +Boot partition: 0xFFFC0000 (sz 6993, ver 0x1, type 0x201) +Partition 1 header magic 0xFFFFFFFF invalid at 0xFFFD8000 +Boot partition: 0xFFFC0000 (sz 6993, ver 0x1, type 0x201) +Booting version: 0x1 +Checking integrity...done +Verifying signature...done +wolfBoot HAL Init +RAM Function start = 0x1D74 +RAM Function end = 0x242B +RAM Function size = 1719 +| ------------------------------------------------------------------- | +| Renesas RX User Application in BOOT partition started by wolfBoot | +| ------------------------------------------------------------------- | + + +=== Boot Partition[FFFC0000] === +Magic: WOLF +Version: 01 +Status: FF (New) +Trailer Mgc: none + +=== Update Partition[FFFD8000] === +Magic: ���� +Version: 00 +Status: FF (New) +Trailer Mgc: none + +Current Firmware Version: 1 +Hit any key to call wolfBoot_success the firmware. +``` + +This output is from a board programmed without v2. Type a key in the +terminal. The application calls `wolfBoot_success()` (boot partition +`00 (Success)`), then waits for a second key and calls +`wolfBoot_update_trigger()` (update partition `70 (Updating)`). + +### 3-8 Update to v2 + +With v2 in the update partition, reset the board after the trigger. +wolfBoot swaps the partitions and starts v2: + +``` +Starting Update (fallback allowed 0) +Update partition: 0xFFFD8000 (sz 6993, ver 0x2, type 0x201) +Boot partition: 0xFFFC0000 (sz 6993, ver 0x1, type 0x201) +Versions: Current 0x1, Update 0x2 +Copy sector 0 (part 1->2) +Copy sector 0 (part 0->1) +Copy sector 0 (part 2->0) +... +Erasing remainder of partition (42 sectors)... +... +Copied boot sector to swap +Boot partition: 0xFFFC0000 (sz 6993, ver 0x2, type 0x201) +Booting version: 0x2 +Checking integrity...done +Verifying signature...done +... +=== Boot Partition[FFFC0000] === +Magic: WOLF +Version: 02 +Status: 10 (Testing) +Trailer Mgc: BOOT +``` + +Type a key to call `wolfBoot_success()`. If v2 is reset before that, +wolfBoot rolls back to v1. + +## 4. Notes + +- Code flash is rated for 1,000 erase cycles per block, and an update erases + the flag sectors several times per image sector. See + [docs/Targets.md](../../../../docs/Targets.md#renesas-rx24t). +- wolfBoot uses about 11 KB of the 16 KB RAM, including the 5 KB stack + (`BSP_CFG_ISTACK_BYTES`); the deepest path, an update, uses about 3.7 KB + of it. +- An e2 studio debug session on the RX24T can rewrite code flash, including + the ID code. After a session, program `wolfboot.bin` again before any + other `rfp-cli` connection. +- `include/user_settings.h` sets the include guard of the wolfBoot + `include/user_settings.h`, which CC-RX could otherwise find next to the + wolfBoot headers and add to this configuration. diff --git a/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/.cproject b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/.cproject new file mode 100644 index 0000000000..a2295dab28 --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/.cproject @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/.project b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/.project new file mode 100644 index 0000000000..d1061ce12d --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/.project @@ -0,0 +1,58 @@ + + + app_RenesasRX01 + + + + + + com.renesas.smc.ui.pgsupport.SCContentBuilder + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + src/target.h + 1 + PARENT-1-PROJECT_LOC/include/target.h + + + src/user_settings.h + 1 + PARENT-1-PROJECT_LOC/include/user_settings.h + + + src/libwolfboot.c + 1 + PARENT-5-PROJECT_LOC/src/libwolfboot.c + + + src/renesas-rx.c + 1 + PARENT-5-PROJECT_LOC/hal/renesas-rx.c + + + src/string.c + 1 + PARENT-5-PROJECT_LOC/src/string.c + + + diff --git a/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/.settings/com.renesas.smc.generationsetting.properties b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/.settings/com.renesas.smc.generationsetting.properties new file mode 100644 index 0000000000..1676c085d1 --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/.settings/com.renesas.smc.generationsetting.properties @@ -0,0 +1,4 @@ +# +#Wed Nov 04 14:06:14 JST 2026 +FirstGeneration=false +PreGenerationPath=src/smc_gen diff --git a/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/app_RenesasRX01.scfg b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/app_RenesasRX01.scfg new file mode 100644 index 0000000000..5deb481803 --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/app_RenesasRX01.scfg @@ -0,0 +1,526 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
diff --git a/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/src/app_RenesasRX01.c b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/src/app_RenesasRX01.c new file mode 100644 index 0000000000..3fecaac498 --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/app_RenesasRX01/src/app_RenesasRX01.c @@ -0,0 +1,119 @@ +/* app_RenesasRX01.c + * + * Test bare-metal application for the RX24T CC-RX project. + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include "hal.h" +#include "printf.h" +#include "wolfboot/wolfboot.h" +#include "r_smc_entry.h" + +/* Console on SCI1 through wolfBoot's uart_read(), not BSP stdio */ +static void wait_key(void) +{ + char c; + + uart_read(&c, 1); +} + +static const char* state2str(uint8_t s) +{ + switch (s) { + case IMG_STATE_NEW: return "New"; + case IMG_STATE_UPDATING: return "Updating"; + case IMG_STATE_TESTING: return "Testing"; + case IMG_STATE_SUCCESS: return "Success"; + default: return "Unknown"; + } +} + +static void printPart(uint8_t part_id, uint8_t *part) +{ + uint8_t *magic; + uint32_t ver; + uint8_t state; + int has_trailer; + + magic = part; + wolfBoot_printf("Magic: %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]); + ver = wolfBoot_get_blob_version(part); + wolfBoot_printf("Version: %02x\n", (uint8_t)ver); + has_trailer = (wolfBoot_get_partition_state(part_id, &state) == 0); + if (!has_trailer) + state = IMG_STATE_NEW; + wolfBoot_printf("Status: %02x (%s)\n", state, state2str(state)); + wolfBoot_printf("Trailer Mgc: %s\n", has_trailer ? "BOOT" : "none"); +} + +static void printPartitions(void) +{ + wolfBoot_printf("\n=== Boot Partition[%08x] ===\n", WOLFBOOT_PARTITION_BOOT_ADDRESS); + printPart(PART_BOOT, (uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS); + wolfBoot_printf("\n=== Update Partition[%08x] ===\n", WOLFBOOT_PARTITION_UPDATE_ADDRESS); + printPart(PART_UPDATE, (uint8_t*)WOLFBOOT_PARTITION_UPDATE_ADDRESS); +} + +void main(void) +{ + uint8_t firmware_version = 0; + + hal_init(); + + wolfBoot_printf("| ------------------------------------------------------------------- |\n"); + wolfBoot_printf("| Renesas RX User Application in BOOT partition started by wolfBoot |\n"); + wolfBoot_printf("| ------------------------------------------------------------------- |\n\n"); + + printPartitions(); + + firmware_version = wolfBoot_current_firmware_version(); + + wolfBoot_printf("\nCurrent Firmware Version: %d\n", firmware_version); + + if (firmware_version == 1) { + wolfBoot_printf("Hit any key to call wolfBoot_success the firmware.\n"); + wait_key(); + + wolfBoot_success(); + printPartitions(); + + wolfBoot_printf("\nHit any key to update the firmware.\n"); + wait_key(); + + wolfBoot_update_trigger(); + wolfBoot_printf("Firmware Update is triggered\n"); + printPartitions(); + } + else if (firmware_version == 2) { + wolfBoot_printf("Hit any key to call wolfBoot_success the firmware.\n"); + wait_key(); + + wolfBoot_success(); + printPartitions(); + } + else if (firmware_version == 0) { + wolfBoot_printf("Invalid Firmware Version\n"); + } + + /* busy wait */ + while (1) + ; +} diff --git a/IDE/Renesas/e2studio/RX24T/include/target.h b/IDE/Renesas/e2studio/RX24T/include/target.h new file mode 100644 index 0000000000..1fb4b201e2 --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/include/target.h @@ -0,0 +1,41 @@ +/* target.h + * + * Flash layout for the RX24T CC-RX projects, the same as + * config/examples/renesas-rx24t.config. + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef H_TARGETS_TARGET_ +#define H_TARGETS_TARGET_ + +#ifndef WOLFBOOT_NO_PARTITIONS +# define WOLFBOOT_FIXED_PARTITIONS +#endif + +/* wolfBoot: 0xFFFF8000-0xFFFFFFFF (last 32 KB, with the vector tables) */ +#define WOLFBOOT_ORIGIN 0xFFFF8000 +#define BOOTLOADER_PARTITION_SIZE 0x8000 +#define WOLFBOOT_SECTOR_SIZE 0x800 +#define WOLFBOOT_PARTITION_SIZE 0x18000 +#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0xFFFC0000 +#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0xFFFD8000 +#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0xFFFF0000 + +#endif /* !H_TARGETS_TARGET_ */ diff --git a/IDE/Renesas/e2studio/RX24T/include/user_settings.h b/IDE/Renesas/e2studio/RX24T/include/user_settings.h new file mode 100644 index 0000000000..dc2e530081 --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/include/user_settings.h @@ -0,0 +1,118 @@ +/* user_settings.h + * + * wolfBoot and wolfCrypt configuration for the RX24T CC-RX projects: + * ECC256 signatures, SHA256 hash. Enabled via WOLFSSL_USER_SETTINGS. + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef H_USER_SETTINGS_ +#define H_USER_SETTINGS_ + +/* keep include/user_settings.h out; CC-RX can find it next to wolfBoot headers */ +#define _WOLFBOOT_USER_SETTINGS_H_ + +/* wolfBoot */ +#define WOLFBOOT_SIGN_ECC256 +#define WOLFBOOT_HASH_SHA256 +#define IMAGE_HEADER_SIZE 256 +#define NVM_FLASH_WRITEONCE +#define PRINTF_ENABLED +/* Console on SCI1 through wolfBoot's uart_printf(), not BSP stdio */ +#define DEBUG_UART +/* Hand over to the application on the LOCO, as after a reset */ +#define WOLFBOOT_RESTORE_CLOCK + +#include /* min() and max() */ +#define WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MAX + +/* System */ +#define WOLFSSL_GENERAL_ALIGNMENT 4 +#define SINGLE_THREADED +#define WOLFSSL_USER_MUTEX +#define WOLFCRYPT_ONLY +#define SIZEOF_LONG_LONG 8 +#define WC_NO_RNG_SIMPLE + +/* ECC256 with SP math */ +#define HAVE_ECC +#define HAVE_ECC256 +#define ECC_TIMING_RESISTANT +#define ECC_USER_CURVES +#define FP_MAX_BITS (256 + 32) +#define WOLFSSL_SP +#define WOLFSSL_SP_MATH +#define WOLFSSL_SP_SMALL +#define WOLFSSL_HAVE_SP_ECC +#define WOLFSSL_SP_NO_384 +#define WOLFSSL_SP_NO_521 +#define NO_ECC_SIGN +#define NO_ECC_EXPORT +#define NO_ECC_DHE +#define NO_ECC_KEY_EXPORT +#define NO_RSA +#define NO_ASN + +/* Disables - for a minimum wolfCrypt build */ +#define NO_AES +#define NO_HMAC +#define NO_CMAC +#define NO_CODING +#define WOLFSSL_NO_PEM +#define NO_ASN_TIME +#define NO_RC4 +#define NO_SHA +#define NO_DH +#define NO_DSA +#define NO_MD4 +#define NO_RABBIT +#define NO_MD5 +#define NO_SIG_WRAPPER +#define NO_CERT +#define NO_SESSION_CACHE +#define NO_HC128 +#define NO_DES3 +#define NO_PWDBASED +#define NO_KDF +#define NO_PKCS8 +#define NO_PKCS12 +#define NO_CHECK_PRIVATE_KEY +#define WC_NO_RNG +#define WC_NO_HASHDRBG +#define NO_WRITEV +#define NO_DEV_RANDOM +#define NO_FILESYSTEM +#define NO_MAIN_DRIVER +#define NO_OLD_RNGNAME +#define NO_WOLFSSL_DIR +#define WOLFSSL_NO_SOCK +#define WOLFSSL_IGNORE_FILE_WARN +#define NO_ERROR_STRINGS +#define BENCH_EMBEDDED +#define NO_CRYPT_TEST +#define NO_CRYPT_BENCHMARK + +/* Memory model: no heap */ +#define WOLFSSL_SP_NO_MALLOC +#define WOLFSSL_SP_NO_DYN_STACK +#define WOLFSSL_NO_MALLOC +#define NO_WOLFSSL_MEMORY + +#endif /* !H_USER_SETTINGS_ */ diff --git a/IDE/Renesas/e2studio/RX24T/make_images.sh b/IDE/Renesas/e2studio/RX24T/make_images.sh new file mode 100755 index 0000000000..95869ed956 --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/make_images.sh @@ -0,0 +1,124 @@ +#!/bin/bash +# +# Make the RX24T flash images from the CC-RX e2 studio builds: +# wolfboot.bin code flash 0xFFFF8000-0xFFFFFFFF +# app_RenesasRX01_v1_signed.bin, app_RenesasRX01_v2_signed.bin +# boot (0xFFFC0000) / update (0xFFFD8000) images +# +# wolfboot.bin carries the BSP's MDE, OFS1, OFS0, ROMCODE and ID code words +# at 0xFFFFFF80-0xFFFFFFAF; the application image stops before 0xFFFFFF80. +# +# Usage: make_images.sh [OUTPUT_DIR] +# RX_ELF_BIN_DIR folder with rx-elf-objcopy (GCC for Renesas RX) +# SIGNING_KEY the private key whose public part is in src/keystore.c +# OUTPUT_DIR default: the current directory +# + +set -e + +if [ $# -lt 2 ] || [ $# -gt 3 ]; then + echo "Usage: $0 [OUTPUT_DIR]" + exit 1 +fi + +HERE=$(cd "$(dirname "$0")" && pwd) +WOLFBOOT_DIR=$(cd "$HERE/../../../.." && pwd) +OBJCOPY="$1/rx-elf-objcopy" +OBJDUMP="$1/rx-elf-objdump" +KEY="$2" +OUT="${3:-.}" +SIGN="$WOLFBOOT_DIR/tools/keytools/sign" +BOOT_X="$HERE/wolfBoot/HardwareDebug/wolfBoot.x" +APP_X="$HERE/app_RenesasRX01/HardwareDebug/app_RenesasRX01.x" + +for f in "$OBJCOPY" "$OBJDUMP" "$SIGN"; do + if [ ! -x "$f" ] && [ ! -x "$f.exe" ]; then + echo "Not found: $f (for sign: make -C tools/keytools)" + exit 1 + fi +done +for f in "$KEY" "$BOOT_X" "$APP_X"; do + if [ ! -f "$f" ]; then + echo "Not found: $f" + exit 1 + fi +done + +# Print "
" for each section with contents in [lo, hi) +sections() { + "$OBJDUMP" -h "$1" | awk -v lo=$(($2)) -v hi=$(($3)) ' + function hex(s, i, v) { + v = 0 + s = tolower(s) + for (i = 1; i <= length(s); i++) + v = v * 16 + index("0123456789abcdef", substr(s, i, 1)) - 1 + return v + } + $1 ~ /^[0-9]+$/ { name = $2; size = hex($3); vma = hex($4); next } + name != "" && /CONTENTS/ && size > 0 && vma >= lo && vma < hi { + printf "%.0f %s\n", vma, name + } + { name = "" }' +} + +# Copy the code flash sections of $1 in [$3, $4) to binary file $2; the +# lowest section must start at $3 +extract() { + local args=() first="" vma name + while read -r vma name; do + args+=(-j "$name") + if [ -z "$first" ] || [ "$vma" -lt "$first" ]; then + first=$vma + fi + done < <(sections "$1" "$3" "$4") + if [ ${#args[@]} -eq 0 ]; then + echo "No sections in $1 between $3 and $4" + exit 1 + fi + if [ "$first" -ne $(($3)) ]; then + printf "%s starts at 0x%X, not at %s\n" "$1" "$first" "$3" + exit 1 + fi + "$OBJCOPY" -O binary --gap-fill 0xFF "${args[@]}" "$1" "$2" +} + +mkdir -p "$OUT" + +echo "wolfBoot: $BOOT_X" +extract "$BOOT_X" "$OUT/wolfboot.bin" 0xFFFF8000 0x100000000 +if [ "$(wc -c < "$OUT/wolfboot.bin")" -ne 32768 ]; then + echo "wolfboot.bin must cover 0xFFFF8000-0xFFFFFFFF (32768 bytes)" + exit 1 +fi +# Hex bytes of wolfboot.bin from address $1, $2 bytes long +bytes() { + od -An -tx1 -j $(($1 - 0xFFFF8000)) -N $2 "$OUT/wolfboot.bin" | tr -d ' \n' +} +if [ "$(bytes 0xFFFFFF9C 4)" != "ffffffff" ]; then + echo "ROMCODE at 0xFFFFFF9C is $(bytes 0xFFFFFF9C 4), expected ffffffff" + exit 1 +fi +if [ "$(bytes 0xFFFFFFA3 1)" != "45" ]; then + echo "ID code control code is $(bytes 0xFFFFFFA3 1)h, expected 45h" \ + "(BSP_CFG_ID_CODE_LONG_1)" + exit 1 +fi + +echo "Application: $APP_X" +extract "$APP_X" "$OUT/app_RenesasRX01.bin" 0xFFFC0100 0xFFFFFF80 +# Header and application must end before the two partition flag sectors +APP_MAX=$((0x18000 - 2 * 0x800 - 256)) +if [ "$(wc -c < "$OUT/app_RenesasRX01.bin")" -gt $APP_MAX ]; then + echo "app_RenesasRX01.bin is larger than $APP_MAX bytes" + exit 1 +fi + +for v in 1 2; do + "$SIGN" --ecc256 "$OUT/app_RenesasRX01.bin" "$KEY" $v +done + +echo +echo "Program with Renesas Flash Programmer (code flash only):" +echo " wolfboot.bin at FFFF8000" +echo " app_RenesasRX01_v1_signed.bin at FFFC0000 (boot partition)" +echo " app_RenesasRX01_v2_signed.bin at FFFD8000 (update partition)" diff --git a/IDE/Renesas/e2studio/RX24T/wolfBoot/.cproject b/IDE/Renesas/e2studio/RX24T/wolfBoot/.cproject new file mode 100644 index 0000000000..31e9fd93bc --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/wolfBoot/.cproject @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/IDE/Renesas/e2studio/RX24T/wolfBoot/.project b/IDE/Renesas/e2studio/RX24T/wolfBoot/.project new file mode 100644 index 0000000000..cdd3f14367 --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/wolfBoot/.project @@ -0,0 +1,143 @@ + + + wolfBoot + + + + + + com.renesas.smc.ui.pgsupport.SCContentBuilder + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + + + src/target.h + 1 + PARENT-1-PROJECT_LOC/include/target.h + + + src/user_settings.h + 1 + PARENT-1-PROJECT_LOC/include/user_settings.h + + + src/keystore.c + 1 + PARENT-5-PROJECT_LOC/src/keystore.c + + + src/hal/hal.c + 1 + PARENT-5-PROJECT_LOC/hal/hal.c + + + src/hal/renesas-rx.c + 1 + PARENT-5-PROJECT_LOC/hal/renesas-rx.c + + + src/wolfboot/boot_renesas.c + 1 + PARENT-5-PROJECT_LOC/src/boot_renesas.c + + + src/wolfboot/image.c + 1 + PARENT-5-PROJECT_LOC/src/image.c + + + src/wolfboot/libwolfboot.c + 1 + PARENT-5-PROJECT_LOC/src/libwolfboot.c + + + src/wolfboot/loader.c + 1 + PARENT-5-PROJECT_LOC/src/loader.c + + + src/wolfboot/string.c + 1 + PARENT-5-PROJECT_LOC/src/string.c + + + src/wolfboot/update_flash.c + 1 + PARENT-5-PROJECT_LOC/src/update_flash.c + + + src/wolfcrypt/asn.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/asn.c + + + src/wolfcrypt/coding.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/coding.c + + + src/wolfcrypt/ecc.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/ecc.c + + + src/wolfcrypt/hash.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/hash.c + + + src/wolfcrypt/logging.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/logging.c + + + src/wolfcrypt/memory.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/memory.c + + + src/wolfcrypt/sha256.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/sha256.c + + + src/wolfcrypt/sp_c32.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/sp_c32.c + + + src/wolfcrypt/sp_int.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/sp_int.c + + + src/wolfcrypt/wc_port.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/wc_port.c + + + src/wolfcrypt/wolfmath.c + 1 + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/wolfmath.c + + + diff --git a/IDE/Renesas/e2studio/RX24T/wolfBoot/.settings/com.renesas.smc.generationsetting.properties b/IDE/Renesas/e2studio/RX24T/wolfBoot/.settings/com.renesas.smc.generationsetting.properties new file mode 100644 index 0000000000..b04b7aca6b --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/wolfBoot/.settings/com.renesas.smc.generationsetting.properties @@ -0,0 +1,4 @@ +# +#Wed Nov 04 13:21:41 JST 2026 +FirstGeneration=false +PreGenerationPath=src/smc_gen diff --git a/IDE/Renesas/e2studio/RX24T/wolfBoot/wolfBoot.scfg b/IDE/Renesas/e2studio/RX24T/wolfBoot/wolfBoot.scfg new file mode 100644 index 0000000000..d3813171b6 --- /dev/null +++ b/IDE/Renesas/e2studio/RX24T/wolfBoot/wolfBoot.scfg @@ -0,0 +1,526 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
diff --git a/arch.mk b/arch.mk index 0da7cdd03f..ddd8a52676 100644 --- a/arch.mk +++ b/arch.mk @@ -1266,6 +1266,10 @@ ifeq ($(ARCH),RENESAS_RX) else LDFLAGS+=--oformat=elf32-rx-be endif + # The ELF stores code sections byte-swapped in 4-byte groups, the order + # the CPU fetches them. elf32-rx-be-ns is necessary to prevent objcopy + # from swapping them back. + OBJCOPY_FLAGS+=-I elf32-rx-be-ns else CFLAGS+=-mlittle-endian-data ifeq ($(USE_GCC),1) @@ -1300,6 +1304,41 @@ ifeq ($(ARCH),RENESAS_RX) OBJCOPY_FLAGS+=-R .ofs_rx71m --gap-fill 0xFF endif + ifeq ($(TARGET),rx24t) + ifeq ($(PKA),1) + $(error TARGET=rx24t has no TSIP; set PKA=0) + endif + ifneq ($(NVM_FLASH_WRITEONCE),1) + $(error TARGET=rx24t requires NVM_FLASH_WRITEONCE=1) + endif + ifeq ($(DELTA_UPDATES),1) + $(error TARGET=rx24t does not support DELTA_UPDATES) + endif + ifeq ($(BIG_ENDIAN),1) + ifeq ($(findstring WOLFBOOT_RENESAS_OSM,$(CFLAGS) $(CFLAGS_EXTRA)),) + $(error TARGET=rx24t BIG_ENDIAN=1 requires CFLAGS_EXTRA+=-DWOLFBOOT_RENESAS_OSM to set MDE) + endif + endif + # RXv2 core + ifeq ($(USE_GCC),0) + CFLAGS+=-misa=v2 + endif + # Fill gaps with 0xFF, the erased value + OBJCOPY_FLAGS+=--gap-fill 0xFF + ifneq ($(RENESAS_ID_CODE),) + ifeq ($(shell echo '$(RENESAS_ID_CODE)' | grep -E -x '[0-9A-Fa-f]{32}'),) + $(error RENESAS_ID_CODE must be 32 hex digits) + endif + ifeq ($(shell echo '$(RENESAS_ID_CODE)' | cut -c1-2),52) + $(error RENESAS_ID_CODE control code 52h can disable the programmer) + endif + CFLAGS+=-DWOLFBOOT_RENESAS_ID_CODE0=0x$(shell echo '$(RENESAS_ID_CODE)' | cut -c1-8) + CFLAGS+=-DWOLFBOOT_RENESAS_ID_CODE1=0x$(shell echo '$(RENESAS_ID_CODE)' | cut -c9-16) + CFLAGS+=-DWOLFBOOT_RENESAS_ID_CODE2=0x$(shell echo '$(RENESAS_ID_CODE)' | cut -c17-24) + CFLAGS+=-DWOLFBOOT_RENESAS_ID_CODE3=0x$(shell echo '$(RENESAS_ID_CODE)' | cut -c25-32) + endif + endif + ifeq ($(PKA),1) CFLAGS+=-DWOLFBOOT_RENESAS_TSIP CFLAGS+=-DWOLFBOOT_DEVID_PUBKEY=7890 diff --git a/config/examples/renesas-rx24t.config b/config/examples/renesas-rx24t.config new file mode 100644 index 0000000000..0211b0cc05 --- /dev/null +++ b/config/examples/renesas-rx24t.config @@ -0,0 +1,62 @@ +ARCH?=RENESAS_RX +TARGET?=rx24t +SIGN?=ECC256 +HASH?=SHA256 +DEBUG?=0 +DEBUG_UART?=1 +VTOR?=1 +NO_ASM?=0 +NO_MPU=1 +EXT_FLASH?=0 +SPI_FLASH?=0 +QSPI_FLASH?=0 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=1 +WOLFBOOT_VERSION?=0 +SPMATH?=1 +RAM_CODE?=1 +DUALBANK_SWAP?=0 + +# GNURX 14.2: gcc cannot drive the link, so ld is called directly +USE_GCC?=0 + +# reserve 1KB for wolfBoot header +# Requires building keytools with "make IMAGE_HEADER_SIZE=1024" +#IMAGE_HEADER_SIZE=1024 + +# Optionally switch to big endian data if MDE is set +#BIG_ENDIAN=1 + +# Flash is 256KB; partitions use the 2KB blocks +WOLFBOOT_SECTOR_SIZE?=0x800 + +# wolfBoot is last 32KB of flash and includes vector tables +WOLFBOOT_ORIGIN=0xFFFF8000 + +# wolfBoot partition size (32KB) +BOOTLOADER_PARTITION_SIZE=0x8000 +# Application Partition Size (96KB, last two sectors hold the flags) +WOLFBOOT_PARTITION_SIZE?=0x18000 + +# Boot partition at the start of flash, update partition right after it +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xFFFC0000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0xFFFD8000 + +# Swap sector +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFF0000 + +# No crypto hardware on RX24T +PKA?=0 + +# Include debug symbols (even for release build) +#DEBUG_SYMBOLS=1 + +# Optional option-setting memory (MDE/OFS1/OFS0 at 0xFFFFFF80), see docs +#CFLAGS_EXTRA+=-DWOLFBOOT_RENESAS_OSM + +# Boot mode ID code at 0xFFFFFFA0: control code + ID codes 1-15 +#RENESAS_ID_CODE?=450102030405060708090A0B0C0D0E0F + +# External watchdog (e.g. MAX6316-MAX6322): toggle WDI from wolfBoot's long +# loops. WATCHDOG_WDI_PORT = RX port, WATCHDOG_WDI_PIN = bit (see renesas-rx.c). +#CFLAGS_EXTRA+=-DWATCHDOG -DWATCHDOG_WDI_PORT= -DWATCHDOG_WDI_PIN= diff --git a/docs/Renesas.md b/docs/Renesas.md index bddedda5f3..b64acc663a 100644 --- a/docs/Renesas.md +++ b/docs/Renesas.md @@ -16,6 +16,9 @@ Platforms Supported: * Renesas RX (RX71M) (software crypto, no TSIP) - [docs/Targets.md#renesas-rx71m](/docs/Targets.md#renesas-rx71m) - [IDE/Renesas/e2studio/RX71M/Readme.md](/IDE/Renesas/e2studio/RX71M/Readme.md) +* Renesas RX (RX24T) (software crypto) + - [docs/Targets.md#renesas-rx24t](/docs/Targets.md#renesas-rx24t) + - [IDE/Renesas/e2studio/RX24T/Readme.md](/IDE/Renesas/e2studio/RX24T/Readme.md) All of the Renesas examples include an e2Studio project. The Renesas RX parts support using wolfBoot Makefile's with the rx-elf-gcc cross-compiler and example .config files. diff --git a/docs/Targets.md b/docs/Targets.md index 53026cd31c..37742bcde6 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -52,6 +52,7 @@ This README describes configuration of supported targets. * [Raspberry Pi pico 2 (rp2350)](#raspberry-pi-pico-rp2350) * [RealTek RTL8735B (AmebaPro2)](#realtek-rtl8735b-amebapro2) * [Renesas RA6M4](#renesas-ra6m4) +* [Renesas RX24T](#renesas-rx24t) * [Renesas RX65N](#renesas-rx65n) * [Renesas RX71M](#renesas-rx71m) * [Renesas RX72N](#renesas-rx72n) @@ -7868,6 +7869,115 @@ Note: This also works on Mac OS, but `objcopy` does not exist. Install with `bre See instructions in [IDE/pico-sdk/rp2350/README.md](/IDE/pico-sdk/rp2350/README.md) +## Renesas RX24T + +Target board: Renesas Starter Kit for RX24T, with the R5F524TAADFP (256KB code flash, 16KB RAM, 8KB data flash). + +The RX24T is supported either natively with "make" (GCC for Renesas RX) or through e2Studio with CC-RX. If using e2Studio see [Readme.md](../IDE/Renesas/e2studio/RX24T/Readme.md). + +Default UART Serial on SCI1 at PD3-TXD1 PD5-RXD1, connected to the on-board USB serial converter. This feature is enabled with `DEBUG_UART=1`. + +Example Boot Output (with DEBUG_UART=1): + +``` +wolfBoot HAL Init +Boot partition: 0xFFFC0000 (sz 5489, ver 0x1, type 0x201) +Partition 1 header magic 0xFFFFFFFF invalid at 0xFFFD8000 +Boot partition: 0xFFFC0000 (sz 5489, ver 0x1, type 0x201) +Booting version: 0x1 +Checking integrity...done +Verifying signature...done +wolfBoot HAL Init +| ------------------------------------------------------------------- | +| Renesas RX User Application in BOOT partition started by wolfBoot | +| ------------------------------------------------------------------- | + + +=== Boot Partition[fffc0000] === +Magic: WOLF +Version: 01 +Status: ff (New) +Trailer Mgc: none + +=== Update Partition[fffd8000] === +Magic: ˇˇˇˇ +Version: 00 +Status: ff (New) +Trailer Mgc: none + +Current Firmware Version: 1 +Hit any key to call wolfBoot_success the firmware. +``` + +### RX24T Flash Layout + +Default Onboard Flash Memory Layout (256KB) (2KB sector): + +| Description | Address | Size | +| ---------------------- | ---------- | -------------------- | +| Application | 0xFFFC0000 | 0x00018000 ( 96 KB) | +| Update | 0xFFFD8000 | 0x00018000 ( 96 KB) | +| Swap | 0xFFFF0000 | 0x00000800 ( 2 KB) | +| Unused | 0xFFFF0800 | 0x00007800 ( 30 KB) | +| wolfBoot | 0xFFFF8000 | 0x00008000 ( 32 KB) | + +The last 128 bytes of the wolfBoot partition hold the option-setting memory (`0xFFFFFF80`), `ROMCODE` (`0xFFFFFF9C`), the boot mode ID code (`0xFFFFFFA0`) and the exception vectors, so `wolfboot.bin` programs all of them. + +### RX24T Notes + +* `NVM_FLASH_WRITEONCE=1` and `RAM_CODE=1` are mandatory on this target. Code flash cannot be programmed again before an erase, and it cannot be read while it is being programmed or erased, so the flash driver runs from RAM. `DELTA_UPDATES` is not supported. +* Code flash is rated for 1,000 erase cycles per 2KB block. Each update erases the two flag sectors at the end of the update partition about three times per image sector, and the swap sector once per image sector. One update of the test application erases about 131 blocks in total, most of them once. Keep images small if many updates are expected. +* wolfBoot uses about 6KB of the 16KB RAM for data and RAM code, and up to 3.8KB of stack during an update. The linker script stops the build if less than 5KB is left for the stack. +* The clock runs from the HOCO (32 MHz, PLL to 80 MHz). The HOCO is accurate to within 1.5%, which keeps the UART at 115200 within its tolerance. +* `ROMCODE` at `0xFFFFFF9C` enables ROM code protection when set to `0x00000000` or `0x00000001`. wolfBoot sets it to `0xFFFFFFFF`. +* An application that calls `wolfBoot_success()` or `wolfBoot_update_trigger()` writes flash through the same driver, which must run from RAM: with GCC, build `hal/renesas-rx.c` with `RAM_CODE` and `__WOLFBOOT` defined and place its `.ramcode` section in RAM, as `test-app/Makefile` and `test-app/RENESAS_RX-rx24t.ld` do. The driver masks interrupts while it writes. It sets the flash sequencer for a 20 MHz FCLK, so call it only with the clocks set up as `hal_init()` does, and with the ROM cache (`ROMCE`) disabled. +* The option-setting memory (`MDE`, `OFS1`, `OFS0` at `0xFFFFFF80`) is written only when built with `CFLAGS_EXTRA+=-DWOLFBOOT_RENESAS_OSM`. It sits inside the wolfBoot partition, so `wolfboot.bin` carries it. + +To switch to big endian data, build with both `BIG_ENDIAN=1` and `CFLAGS_EXTRA+=-DWOLFBOOT_RENESAS_OSM`, which sets `MDE` to big endian. The boot mode ignores `MDE` and reads the ID code with the endianness given to `rfp-cli`, so add `-endian big` to every `rfp-cli` call while the board holds big endian images. + +### RX24T Boot Mode ID Code + +The boot mode ID code at `0xFFFFFFA0` decides what a programmer connection may do. If its control code (bits 31-24 of the word at `0xFFFFFFA0`) is not `45h` or `52h`, as on a blank part, every connection erases all code flash and data flash. With `45h`, the programmer must send the matching 16-byte ID, and three wrong IDs in a row erase the flash. + +wolfBoot therefore writes control code `45h` with the ID code `450102030405060708090A0B0C0D0E0F` by default. This is the example: set your own for production with `RENESAS_ID_CODE` in `.config` or on the `make` line: + +```sh +make RENESAS_ID_CODE=45xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +``` + +The build rejects a value that is not 32 hex digits and the control code `52h`, which with some ID codes disables the programmer for good. Pass the same ID to `rfp-cli -auth id` and to the debugger. + +### Building Renesas RX24T + +Building requires GCC for Renesas RX 14.2 (https://llvm-gcc-renesas.com/rx-download-toolchains/). The example config sets `USE_GCC=0` (`ld` links directly) and the build adds `-misa=v2` for the RXv2 core. + +```sh +cp ./config/examples/renesas-rx24t.config .config +make RX_GCC_PATH=/path/to/gcc_rx_elf +``` + +`RX_GCC_PATH` is the toolchain install directory (the one containing `bin/rx-elf-gcc`). If `rx-elf-gcc` is already on the `PATH`, use `make CROSS_COMPILE=rx-elf-` instead. + +### Flashing Renesas RX24T + +Leave J8 open (single-chip mode). Power the board from its 5V jack, not from the emulator. The E2 Lite programs the RX24T over the FINE interface (`-if fine`); `-auth id` must match the ID code in `wolfboot.bin` (see [RX24T Boot Mode ID Code](#rx24t-boot-mode-id-code)). + +```sh +rfp-cli -if fine -t e2l -device RX200 -auto -auth id 450102030405060708090A0B0C0D0E0F \ + -bin FFFF8000 wolfboot.bin \ + -bin FFFC0000 test-app/image_v1_signed.bin \ + -run +``` + +`-auto` erases the whole code flash and data flash before programming. To reprogram only the blocks being written, use `-pv` in place of `-auto`. + +### Debugging Renesas RX24T + +In e² studio create a "Renesas Debug" project with the "E2 Lite" emulator, target device R5F524TA and the built `wolfboot.elf`. In the debug configuration select the FINE connection, select HOCO as the clock source, set "Power Target From The Emulator" to No, and enter the ID code when asked. + +A debug session can rewrite code flash, including the ID code. After a session, program `wolfboot.bin` again before any other `rfp-cli` connection: with the ID code lost, that connection erases the flash. + + ## Renesas RX65N Tested on the: diff --git a/hal/renesas-rx.c b/hal/renesas-rx.c index 795a220172..292f405057 100644 --- a/hal/renesas-rx.c +++ b/hal/renesas-rx.c @@ -88,6 +88,10 @@ void hal_led_on(void) /* RX71M RSK+ LED0 P03 */ PORT_PDR(0) |= (1 << 3); /* output */ PORT_PODR(0) &= ~(1 << 3); /* low */ +#elif defined(TARGET_rx24t) + /* RX24T RSK LED0 PB3 */ + PORT_PDR(11) |= (1 << 3); /* output */ + PORT_PODR(11) &= ~(1 << 3); /* low */ #endif } @@ -105,6 +109,10 @@ void hal_led_off(void) /* RX71M RSK+ LED0 P03 */ PORT_PDR(0) |= (1 << 3); /* output */ PORT_PODR(0) |= (1 << 3); /* high */ +#elif defined(TARGET_rx24t) + /* RX24T RSK LED0 PB3 */ + PORT_PDR(11) |= (1 << 3); /* output */ + PORT_PODR(11) |= (1 << 3); /* high */ #endif } #endif @@ -117,7 +125,7 @@ void hal_delay_us(uint32_t us) } } -#ifndef TARGET_rx71m +#if !defined(TARGET_rx71m) && !defined(TARGET_rx24t) static flash_err_t flash_check_error() { uint32_t st = FLASH_FSTATR; @@ -133,7 +141,7 @@ static flash_err_t flash_check_error() return FLASH_OK; } -#endif /* !TARGET_rx71m */ +#endif /* !TARGET_rx71m && !TARGET_rx24t */ #ifdef DEBUG_UART #ifndef DEBUG_UART_SCI @@ -143,6 +151,9 @@ static flash_err_t flash_check_error() #elif defined(TARGET_rx71m) /* SCI7: TXD7/P90, RXD7/P92 (RSK+ USB serial) */ #define DEBUG_UART_SCI 7 + #elif defined(TARGET_rx24t) + /* SCI1: TXD1/PD3, RXD1/PD5 */ + #define DEBUG_UART_SCI 1 #else /* SCI8: TXD8/PJ2, RXD8/PJ1 */ #define DEBUG_UART_SCI 8 @@ -151,6 +162,21 @@ static flash_err_t flash_check_error() #ifndef DEBUG_BAUD_RATE #define DEBUG_BAUD_RATE 115200 #endif +#ifdef TARGET_rx24t +#ifdef __CCRX__ +#define DEBUG_UART_PCLKB ((uint32_t)BSP_PCLKB_HZ) +#else +#define DEBUG_UART_PCLKB PCLKB +#endif +/* Rounded BRR for the /8 divider */ +#define DEBUG_UART_BRR \ + (((DEBUG_UART_PCLKB + (4 * DEBUG_BAUD_RATE)) / (8 * DEBUG_BAUD_RATE)) - 1) +#ifndef __CCRX__ +#if DEBUG_UART_BRR > 255 + #error DEBUG_BAUD_RATE too low for the RX24T SCI divider: BRR exceeds 255 +#endif +#endif +#endif void uart_init(void) { @@ -176,6 +202,9 @@ void uart_init(void) #elif defined(TARGET_rx71m) /* PFS may only change while PMR is 0 */ PORT_PMR(0x9) &= ~((1 << 0) | (1 << 2)); +#elif defined(TARGET_rx24t) + /* PFS may only change while PMR is 0 */ + PORT_PMR(0xD) &= ~((1 << 3) | (1 << 5)); #else /* Configure PJ1/PJ2 for UART */ PORT_PMR(0x12) |= ((1 << 1) | (1 << 2)); @@ -193,6 +222,9 @@ void uart_init(void) #elif defined(TARGET_rx71m) MPC_PFS(0x48) = 0xA; /* P90-TXD7 */ MPC_PFS(0x4A) = 0xA; /* P92-RXD7 */ +#elif defined(TARGET_rx24t) + MPC_PFS(0x6B) = 0xA; /* PD3-TXD1 */ + MPC_PFS(0x6D) = 0xA; /* PD5-RXD1 */ #else MPC_PFS(0xF1) = 0xA; /* PJ1-RXD8 */ MPC_PFS(0xF2) = 0xA; /* PJ2-TXD8 */ @@ -205,26 +237,36 @@ void uart_init(void) #ifdef TARGET_rx71m /* Configure P90/P92 for UART */ PORT_PMR(0x9) |= ((1 << 0) | (1 << 2)); +#elif defined(TARGET_rx24t) + /* Configure PD3/PD5 for UART */ + PORT_PMR(0xD) |= ((1 << 3) | (1 << 5)); #endif /* baud rate table: */ /* divisor, abcs, bgdm, cks - * 8, 1, 1, 0 + * 8, 1, 1, 0 (using this one for RX24T) * 16, 0, 1, 0 * 32, 0, 0, 0 * 64, 0, 1, 1 * 128, 0, 0, 1 * 256, 0, 1, 2 - * 512, 0, 0, 2 (using this one) + * 512, 0, 0, 2 (using this one for others) * 1024, 0, 1, 3 * 2048, 0, 0, 3 */ +#ifdef TARGET_rx24t + /* 8-bit, 1-stop, no parity, cks=0, bgdm=1, abcs=1 (/8) */ + SCI_BRR(DEBUG_UART_SCI) = DEBUG_UART_BRR; + SCI_SEMR(DEBUG_UART_SCI) |= (SCI_SEMR_ABCS | SCI_SEMR_BGDM); + SCI_SMR(DEBUG_UART_SCI) = SCI_SMR_CKS(0); +#else /* 8-bit, 1-stop, no parity, cks=2 (/512), bgdm=0, abcs=0 */ SCI_BRR(DEBUG_UART_SCI) = (PCLKB / (512 * DEBUG_BAUD_RATE)) - 1; SCI_SEMR(DEBUG_UART_SCI) &= ~SCI_SEMR_ABCS; SCI_SEMR(DEBUG_UART_SCI) &= ~SCI_SEMR_BGDM; SCI_SMR(DEBUG_UART_SCI) = SCI_SMR_CKS(2); +#endif SCI_SCMR(DEBUG_UART_SCI) |= SCI_SCMR_CHR1; /* Enable TX/RX */ SCI_SCR(DEBUG_UART_SCI) = (SCI_SCR_RE | SCI_SCR_TE); @@ -281,10 +323,16 @@ void uart_read(char* buf, unsigned int sz) #else /* This function will switch to using on-chip HOCO through PLL */ #define CFG_CKSEL 1 /* 0=LOCO, 1=HOCO, 2=Main, 3=Sub, 4=PLL */ +#ifdef TARGET_rx24t +#define CFG_HCO_FRQ (32000000) +#define CFD_PLL_DIV (2) +#define CFG_PLL_MUL (SYS_CLK / (CFG_HCO_FRQ / 4)) +#else #define CFG_HCO_FRQ (16000000) #define CFD_PLL_DIV (0) #define CFG_PLL_MUL (SYS_CLK / (CFG_HCO_FRQ / 2)) #endif +#endif void hal_clk_init(void) { @@ -293,17 +341,26 @@ void hal_clk_init(void) PROTECT_OFF(); /* write protect off */ +#ifdef TARGET_rx24t + /* Move to high-speed operating mode */ + while (SYS_OPCCR & SYS_OPCCR_OPCMTSF) { RX_NOP(); } + SYS_OPCCR = SYS_OPCCR_OPCM(0); + while (SYS_OPCCR & SYS_OPCCR_OPCMTSF) { RX_NOP(); } +#endif + /* ---- High Speed OSC (HOCO) ---- */ #if CFG_CKSEL == 1 if (SYS_HOCOCR & SYS_HOCOCR_HCSTP) { +#ifndef TARGET_rx24t /* Turn on power to HOCO */ SYS_HOCOPCR &= ~SYS_HOCOPCR_HOCOPCNT; +#endif /* Stop HOCO */ SYS_HOCOCR |= SYS_HOCOCR_HCSTP; /* Wait for HOCO to stop */ while (SYS_OSCOVFSR & SYS_OSCOVFSR_HCOVF) { RX_NOP(); } - /* Set 16MHz -> CFG_HCO_FRQ */ + /* Set 16MHz (or 32MHz for RX24T) -> CFG_HCO_FRQ */ SYS_HOCOCR2 = SYS_HOCOCR2_HCFRQ(0); /* Enable HOCO */ @@ -313,10 +370,12 @@ void hal_clk_init(void) /* Wait for HOCO oscillator stabilization */ while ((SYS_OSCOVFSR & SYS_OSCOVFSR_HCOVF) == 0) { RX_NOP(); } #else +#ifndef TARGET_rx24t if (SYS_HOCOCR & SYS_HOCOCR_HCSTP) { /* Turn off power to HOCO */ SYS_HOCOPCR |= SYS_HOCOPCR_HOCOPCNT; } +#endif #endif /* ---- Main-Clock ---- */ @@ -338,6 +397,7 @@ void hal_clk_init(void) while ((SYS_OSCOVFSR & SYS_OSCOVFSR_MOOVF) != 0) { RX_NOP(); } #endif +#ifndef TARGET_rx24t /* ---- RTC Clock ---- */ if ((SYS_RSTSR1 & SYS_RSTSR1_CWSF) == 0) { /* cold start */ /* Stop the RTC sub-clock */ @@ -352,16 +412,19 @@ void hal_clk_init(void) } if ((RTC_RCR3 & RTC_RCR3_RTCEN) != 0) { RX_NOP(); } } +#endif /* ---- Sub-Clock OSC ---- */ #if CFG_CKSEL == 3 /* TODO: Add support for running from sub-clock */ #else +#ifndef TARGET_rx24t /* Stop the sub-clock */ SYS_SOSCCR = SYS_SOSCCR_SOSTP; reg = SYS_SOSCCR; /* dummy read (required) */ while ((SYS_OSCOVFSR & SYS_OSCOVFSR_SOOVF) != 0) { RX_NOP(); } #endif +#endif #if CFG_CKSEL == 1 || CFG_CKSEL == 2 /* ---- PLL ---- */ @@ -374,7 +437,7 @@ void hal_clk_init(void) /* convert multiplier to STC value */ #define PLL_MUL_STC ((CFG_PLL_MUL * 2) - 1) reg = ( - SYS_PLLCR_PLIDIV(CFD_PLL_DIV) | /* no div */ + SYS_PLLCR_PLIDIV(CFD_PLL_DIV) | /* divider */ PLL_SRCSEL | /* clock source (0=main, 1=HOCO) */ SYS_PLLCR_STC(PLL_MUL_STC) /* multiplier */ ); @@ -394,6 +457,9 @@ void hal_clk_init(void) #elif defined(TARGET_rx71m) SYS_MEMWAIT = SYS_MEMWAIT_MEMWAIT; /* required for ICLK > 120MHz */ if (SYS_MEMWAIT == SYS_MEMWAIT_MEMWAIT) { RX_NOP(); } +#elif defined(TARGET_rx24t) + FLASH_MEMWAIT = FLASH_MEMWAIT_MEMWAIT(2); /* (2=ICLK<=80MHZ) */ + reg = FLASH_MEMWAIT; #else FLASH_ROMWT = FLASH_ROMWT_ROMWT(2); /* (1=50-100MHz, 2= >100MHz) */ reg = FLASH_ROMWT; @@ -412,6 +478,15 @@ void hal_clk_init(void) SYS_SCKCR_PSTOP1 | /* BCLK Pin Output (PSTOP1): 0=Disabled */ SYS_SCKCR_PSTOP0 /* SDCLK Pin Output (PSTOP0): 0=Disabled */ ); +#elif defined(TARGET_rx24t) + reg = ( + SYS_SCKCR_ICK(0) | /* System Clock (ICK)=0: 1/1 = 80MHz */ + SYS_SCKCR_FCK(2) | /* Flash-IF Clock FCK=2: 1/4 = 20MHz */ + SYS_SCKCR_PCKA(0) | /* Peripheral Module Clock A (PCKA)=0: 1/1 = 80MHz */ + SYS_SCKCR_PCKB(1) | /* Peripheral Module Clock B (PCKB)=1: 1/2 = 40MHz */ + SYS_SCKCR_BCK(1) | /* Reserved b19-16: same value as PCKB */ + SYS_SCKCR_PCKD(1) /* Peripheral Module Clock D (PCKD)=1: 1/2 = 40MHz */ + ); #elif SYS_CLK >= 240000000 reg = ( SYS_SCKCR_ICK(1) | /* System Clock (ICK)=1: 1/2 = 240MHz */ @@ -440,8 +515,10 @@ void hal_clk_init(void) SYS_SCKCR = reg; reg = SYS_SCKCR; /* dummy read (required) */ -/* RX71M: UCK stays at its reset value 0001b while USB is unused */ -#if CFG_CKSEL == 2 && !defined(TARGET_rx71m) /* USB only on main clock */ +/* RX71M: UCK stays at its reset value 0001b while USB is unused. + * RX24T has no USB clock. */ +#if CFG_CKSEL == 2 && !defined(TARGET_rx71m) && \ + !defined(TARGET_rx24t) /* USB only on main clock */ /* USB Clock=4: 1/5 = 48MHz */ SYS_SCKCR2 |= SYS_SCKCR2_UCK(4); reg = SYS_SCKCR2; /* dummy read (required) */ @@ -622,6 +699,24 @@ void hal_prepare_boot(void) SYS_MOSCCR = SYS_MOSCCR_MOSTP; while ((SYS_OSCOVFSR & SYS_OSCOVFSR_MOOVF) != 0) { RX_NOP(); } PROTECT_ON(); +#elif defined(TARGET_rx24t) && defined(WOLFBOOT_RESTORE_CLOCK) + /* Run from the LOCO with the PLL and HOCO stopped, so the + * application can set up its own clocks */ + PROTECT_OFF(); + SYS_LOCOCR = 0; + hal_delay_us(1); /* LOCO settling time */ + SYS_SCKCR3 = SYS_SCKCR3_CKSEL(0); + if (SYS_SCKCR3 == 0) { RX_NOP(); } + SYS_SCKCR = 0; + if (SYS_SCKCR == 0) { RX_NOP(); } + /* No wait states only once ICLK is 32MHz or less */ + FLASH_MEMWAIT = FLASH_MEMWAIT_MEMWAIT(0); + if (FLASH_MEMWAIT == 0) { RX_NOP(); } + SYS_PLLCR2 = SYS_PLLCR2_PLLEN; + while ((SYS_OSCOVFSR & SYS_OSCOVFSR_PLOVF) != 0) { RX_NOP(); } + SYS_HOCOCR = SYS_HOCOCR_HCSTP; + while ((SYS_OSCOVFSR & SYS_OSCOVFSR_HCOVF) != 0) { RX_NOP(); } + PROTECT_ON(); #endif } @@ -640,12 +735,55 @@ static void copyfuncs(void) *dst++ = *src++; } - wolfBoot_printf("RAM Function start = 0x%p\n", __sectop("RPFRAM")); - wolfBoot_printf("RAM Function end = 0x%p\n", __secend("RPFRAM")); + wolfBoot_printf("RAM Function start = 0x%x\n", + (unsigned int)__sectop("RPFRAM")); + wolfBoot_printf("RAM Function end = 0x%x\n", + (unsigned int)__secend("RPFRAM")); wolfBoot_printf("RAM Function size = %d\n", n); } #endif +#if defined(TARGET_rx71m) || defined(TARGET_rx24t) +#ifdef __CCRX__ +#pragma section FRAM +#endif +static uint32_t RAMFUNCTION flash_irq_save(void) +{ +#ifdef __CCRX__ + uint32_t psw = (uint32_t)get_psw(); + + clrpsw_i(); +#else + uint32_t psw = __builtin_rx_mvfc(0); + + __builtin_rx_clrpsw('I'); +#endif + return psw; +} + +static void RAMFUNCTION flash_irq_restore(uint32_t psw) +{ + if ((psw & RX_PSW_I) != 0) { +#ifdef __CCRX__ + setpsw_i(); +#else + __builtin_rx_setpsw('I'); +#endif + } +} + +/* [address, address + len) must lie inside code flash */ +static int RAMFUNCTION flash_range_valid(uint32_t address, int len) +{ + return (len >= 0 && IS_FLASH_ADDR(address) && + (len == 0 || (uint32_t)(len - 1) <= (0xFFFFFFFFUL - address))); +} + +#ifdef __CCRX__ +#pragma section +#endif +#endif + #ifdef TARGET_rx71m /* RX71M code flash driver */ #if !defined(__CCRX__) && (!defined(RAM_CODE) || !defined(__WOLFBOOT)) #error RX71M flash driver must run from RAM: define RAM_CODE and __WOLFBOOT @@ -736,31 +874,6 @@ static int RAMFUNCTION flash_check_error(void) return ret; } -static uint32_t RAMFUNCTION flash_irq_save(void) -{ -#ifdef __CCRX__ - uint32_t psw = (uint32_t)get_psw(); - - clrpsw_i(); -#else - uint32_t psw = __builtin_rx_mvfc(0); - - __builtin_rx_clrpsw('I'); -#endif - return psw; -} - -static void RAMFUNCTION flash_irq_restore(uint32_t psw) -{ - if ((psw & RX_PSW_I) != 0) { -#ifdef __CCRX__ - setpsw_i(); -#else - __builtin_rx_setpsw('I'); -#endif - } -} - /* mode: FLASH_FENTRYR_CODE_PR (code flash) or FLASH_FENTRYR_DATA_PE * (data flash) */ static int RAMFUNCTION flash_enter_pe_mode(uint16_t mode) @@ -834,13 +947,6 @@ static int RAMFUNCTION flash_write_256(uint32_t address, const uint16_t *data) return ret; } -/* [address, address + len) must lie inside code flash */ -static int RAMFUNCTION flash_range_valid(uint32_t address, int len) -{ - return (len >= 0 && IS_FLASH_ADDR(address) && - (len == 0 || (uint32_t)(len - 1) <= (0xFFFFFFFFUL - address))); -} - /* The FCU runs firmware copied from ROM to FCURAM; do this once before any * write or erase */ #ifdef __CCRX__ @@ -984,7 +1090,294 @@ int hal_flash_init(void) FLASH_FPCKAR_PCKA(FLASH_FCLK_MHZ)); return flash_fcu_firmware_copy(); } -#else /* !TARGET_rx71m */ +#elif defined(TARGET_rx24t) /* RX24T code flash driver */ +#if !defined(__CCRX__) && (!defined(RAM_CODE) || !defined(__WOLFBOOT)) + #error RX24T flash driver must run from RAM: define RAM_CODE and __WOLFBOOT +#endif + +#ifdef __CCRX__ +#define FLASH_FCLK_MHZ ((uint32_t)(BSP_FCLK_HZ / 1000000UL)) +#else +#define FLASH_FCLK_MHZ (FCLK / 1000000UL) +#endif + +/* Timeouts as poll counts; each poll takes at least one ICLK */ +#define FLASH_POLLS_PER_MS (SYS_CLK / 1000UL) +#define FLASH_PROGRAM_TIMEOUT (2UL * FLASH_POLLS_PER_MS) +#define FLASH_ERASE_TIMEOUT (300UL * FLASH_POLLS_PER_MS) +#define FLASH_MODE_TIMEOUT (1UL * FLASH_POLLS_PER_MS) + +/* ROM mode transition waits tDIS and tMS, in microseconds */ +#define FLASH_WAIT_TDIS_US 3U +#define FLASH_WAIT_TMS_US 6U + +#ifdef __CCRX__ +#pragma section FRAM +#endif +static void RAMFUNCTION flash_delay_us(uint32_t us) +{ + uint32_t i; + + for (i = 0; i < us * (SYS_CLK / 1000000UL); i++) { + RX_NOP(); + } +} + +static int RAMFUNCTION flash_write_fpmcr(uint8_t value) +{ + FLASH_FPR = FLASH_FPR_KEY; + FLASH_FPMCR = value; + FLASH_FPMCR = (uint8_t)~value; + FLASH_FPMCR = value; + return ((FLASH_FPSR & FLASH_FPSR_PERR) != 0) ? FLASH_ERR_FESET : FLASH_OK; +} + +/* Wait for FRDY, clear FCR, then wait for FRDY to drop. An erase that + * does not finish is forcibly stopped first. */ +static int RAMFUNCTION flash_wait_ready(uint32_t limit) +{ + uint32_t i; + uint8_t fcr; + int ret = FLASH_ERR_TIMEOUT; + + for (i = 0; i < limit; i++) { + if ((FLASH_FSTATR1 & FLASH_FSTATR1_FRDY) != 0) { + ret = FLASH_OK; + break; + } + } + fcr = FLASH_FCR; + /* STOP does not apply to program */ + if (ret != FLASH_OK && fcr != FLASH_FCR_CMD_PROGRAM) { + FLASH_FCR = (uint8_t)(fcr | FLASH_FCR_STOP); + for (i = 0; i < FLASH_MODE_TIMEOUT; i++) { + if ((FLASH_FSTATR1 & FLASH_FSTATR1_FRDY) != 0) + break; + } + } + FLASH_FCR = FLASH_FCR_CMD_CLEAR; + for (i = 0; i < FLASH_MODE_TIMEOUT; i++) { + if ((FLASH_FSTATR1 & FLASH_FSTATR1_FRDY) == 0) + break; + } + if (i == FLASH_MODE_TIMEOUT) + ret = FLASH_ERR_TIMEOUT; + return ret; +} + +static int RAMFUNCTION flash_check_error(void) +{ + uint8_t st = FLASH_FSTATR0; + int ret = FLASH_OK; + + if ((st & FLASH_FSTATR0_ILGLERR) != 0) + ret = FLASH_ERR_ILGL; + else if ((st & FLASH_FSTATR0_PRGERR) != 0) + ret = FLASH_ERR_PRG; + else if ((st & FLASH_FSTATR0_ERERR) != 0) + ret = FLASH_ERR_ERS; + else if ((st & (FLASH_FSTATR0_BCERR | FLASH_FSTATR0_EILGLERR)) != 0) + ret = FLASH_ERR_UNKNOWN; + + if (ret != FLASH_OK) { + FLASH_FRESETR = FLASH_FRESETR_FRESET; + FLASH_FRESETR = 0; + } + return ret; +} + +static int RAMFUNCTION flash_enter_pe_mode(void) +{ + uint32_t i; + int ret = FLASH_ERR_TIMEOUT; + + FLASH_FENTRYR = (uint16_t)(FLASH_FENTRYR_KEY | FLASH_FENTRYR_CODE_PR); + for (i = 0; i < FLASH_MODE_TIMEOUT; i++) { + if (FLASH_FENTRYR == FLASH_FENTRYR_CODE_PR) { + ret = FLASH_OK; + break; + } + } + if (ret == FLASH_OK) + ret = flash_write_fpmcr(FLASH_FPMCR_DISCHARGE1); + if (ret == FLASH_OK) { + flash_delay_us(FLASH_WAIT_TDIS_US); + ret = flash_write_fpmcr(FLASH_FPMCR_DISCHARGE2); + } + if (ret == FLASH_OK) + ret = flash_write_fpmcr(FLASH_FPMCR_CODE_PE); + if (ret == FLASH_OK) { + flash_delay_us(FLASH_WAIT_TMS_US); + FLASH_FISR = FLASH_FISR_PCKA(FLASH_FCLK_MHZ); + FLASH_FASR = 0; /* user area */ + } + return ret; +} + +static int RAMFUNCTION flash_enter_read_mode(void) +{ + int ret = FLASH_OK; + + if (FLASH_FENTRYR == FLASH_FENTRYR_CODE_PR) { + ret = flash_write_fpmcr(FLASH_FPMCR_DISCHARGE2); + flash_delay_us(FLASH_WAIT_TDIS_US); + if (flash_write_fpmcr(FLASH_FPMCR_DISCHARGE1) != FLASH_OK) + ret = FLASH_ERR_FESET; + if (flash_write_fpmcr(FLASH_FPMCR_READ) != FLASH_OK) + ret = FLASH_ERR_FESET; + flash_delay_us(FLASH_WAIT_TMS_US); + } + FLASH_FENTRYR = (uint16_t)(FLASH_FENTRYR_KEY | FLASH_FENTRYR_CODE_READ); + /* Stay in RAM until code flash is readable again */ + while (FLASH_FENTRYR != FLASH_FENTRYR_CODE_READ); + return ret; +} + +/* start and end are read addresses; the sequencer takes P/E addresses */ +static int RAMFUNCTION flash_cmd(uint8_t cmd, uint32_t start, uint32_t end, + uint32_t limit) +{ + int ret; + + start -= FLASH_CF_PE_OFFSET; + end -= FLASH_CF_PE_OFFSET; + FLASH_FSARH = (uint16_t)(start >> 16); + FLASH_FSARL = (uint16_t)(start & 0xFFF8U); + FLASH_FEARH = (uint16_t)(end >> 16); + FLASH_FEARL = (uint16_t)(end & 0xFFF8U); + FLASH_FCR = cmd; + ret = flash_wait_ready(limit); + if (ret == FLASH_OK) + ret = flash_check_error(); + return ret; +} + +/* address must be 8-byte aligned; b must be in RAM, since code flash + * cannot be read in P/E mode */ +static int RAMFUNCTION flash_program_unit(uint32_t address, const uint8_t *b) +{ + uint32_t psw; + int ret, mode_ret; + + psw = flash_irq_save(); + ret = flash_enter_pe_mode(); + if (ret == FLASH_OK) { +#ifdef __RX_BIG_ENDIAN__ + FLASH_FWB0 = (uint16_t)(b[3] | ((uint16_t)b[2] << 8)); + FLASH_FWB1 = (uint16_t)(b[1] | ((uint16_t)b[0] << 8)); + FLASH_FWB2 = (uint16_t)(b[7] | ((uint16_t)b[6] << 8)); + FLASH_FWB3 = (uint16_t)(b[5] | ((uint16_t)b[4] << 8)); +#else + FLASH_FWB0 = (uint16_t)(b[0] | ((uint16_t)b[1] << 8)); + FLASH_FWB1 = (uint16_t)(b[2] | ((uint16_t)b[3] << 8)); + FLASH_FWB2 = (uint16_t)(b[4] | ((uint16_t)b[5] << 8)); + FLASH_FWB3 = (uint16_t)(b[6] | ((uint16_t)b[7] << 8)); +#endif + ret = flash_cmd(FLASH_FCR_CMD_PROGRAM, address, address, + FLASH_PROGRAM_TIMEOUT); + } + mode_ret = flash_enter_read_mode(); + flash_irq_restore(psw); + if (ret == FLASH_OK) + ret = mode_ret; + return ret; +} + +int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + uint8_t unit[FLASH_CF_UNIT_SIZE]; + const uint8_t *cur; + uint32_t base, off, n, i; + int changed, blank; + int ret = FLASH_OK; + + if (data == NULL || !flash_range_valid(address, len)) + ret = -1; + + while (ret == FLASH_OK && len > 0) { + base = address & ~(uint32_t)(FLASH_CF_UNIT_SIZE - 1); + off = address - base; + n = FLASH_CF_UNIT_SIZE - off; + if (n > (uint32_t)len) + n = (uint32_t)len; + + cur = (const uint8_t *)(uintptr_t)base; + changed = 0; + blank = 1; + for (i = 0; i < FLASH_CF_UNIT_SIZE; i++) { + unit[i] = cur[i]; + if (i >= off && i < off + n && data[i - off] != cur[i]) { + unit[i] = data[i - off]; + changed = 1; + } + if (cur[i] != 0xFF) + blank = 0; + } + + if (changed && !blank) + ret = FLASH_ERR_NOT_BLANK; + else if (changed) + ret = flash_program_unit(base, unit); + + address += n; + data += n; + len -= (int)n; + } + return ret; +} + +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) +{ + uint32_t psw; + int ret = FLASH_OK; + int mode_ret; + + /* Reject a bad range before erasing anything */ + if (!flash_range_valid(address, len) || + (address & (FLASH_CF_BLOCK_SIZE - 1)) != 0 || + (len % FLASH_CF_BLOCK_SIZE) != 0) + ret = -1; + + while (ret == FLASH_OK && len > 0) { + psw = flash_irq_save(); + ret = flash_enter_pe_mode(); + if (ret == FLASH_OK) { + /* FEARL bits 2-0 must be 0, so the end is the last unit */ + ret = flash_cmd(FLASH_FCR_CMD_ERASE, address, + address + FLASH_CF_BLOCK_SIZE - FLASH_CF_UNIT_SIZE, + FLASH_ERASE_TIMEOUT); + } + mode_ret = flash_enter_read_mode(); + flash_irq_restore(psw); + if (ret == FLASH_OK) + ret = mode_ret; + + address += FLASH_CF_BLOCK_SIZE; + len -= FLASH_CF_BLOCK_SIZE; + } + return ret; +} + +void RAMFUNCTION hal_flash_unlock(void) +{ +} + +void RAMFUNCTION hal_flash_lock(void) +{ +} +#ifdef __CCRX__ +#pragma section +#endif + +/* FISR and FASR are set on each P/E mode entry */ +int hal_flash_init(void) +{ +#ifdef __CCRX__ + copyfuncs(); +#endif + return FLASH_OK; +} +#else /* !TARGET_rx71m && !TARGET_rx24t */ int hal_flash_init(void) { #ifdef __CCRX__ @@ -1157,7 +1550,7 @@ void RAMFUNCTION hal_flash_lock(void) #ifdef __CCRX__ #pragma section #endif -#endif /* !TARGET_rx71m */ +#endif /* !TARGET_rx71m && !TARGET_rx24t */ #if !defined(WOLFBOOT_NO_PARTITIONS) && !defined(TARGET_library) void* hal_get_primary_address(void) { diff --git a/hal/renesas-rx.h b/hal/renesas-rx.h index 7cdc337cfe..6f2d9da448 100644 --- a/hal/renesas-rx.h +++ b/hal/renesas-rx.h @@ -39,12 +39,20 @@ void hal_delay_us(uint32_t us); /* Clocks */ #if defined(TARGET_rx72n) || defined(TARGET_rx71m) #define SYS_CLK (240000000) /* 240MHz */ +#elif defined(TARGET_rx24t) +#define SYS_CLK (80000000) /* 80MHz */ #else #define SYS_CLK (120000000) /* 120MHz */ #endif +#ifdef TARGET_rx24t +#define PCLKA (80000000) /* 80MHz */ +#define PCLKB (40000000) /* 40MHz */ +#define FCLK (20000000) /* 20MHz */ +#else #define PCLKA (120000000) /* 120MHz */ #define PCLKB (60000000) /* 60MHz */ #define FCLK (60000000) /* 60MHz */ +#endif /* System Registers */ #define SYSTEM_BASE (0x80000) @@ -73,8 +81,12 @@ void hal_delay_us(uint32_t us); #define SYS_SCKCR3_CKSEL(n) ((n) << 8) /* 0=LOCO, 1=HOCO, 2=Main, 3=Sub, 4=PLL */ #define SYS_PLLCR (*(volatile uint16_t *)(SYSTEM_BASE + 0x28)) -#define SYS_PLLCR_PLIDIV(n) ((n) << 0) /* 0=x1, 1=x1/2, 2=x1/3 */ +#define SYS_PLLCR_PLIDIV(n) ((n) << 0) /* 0=x1, 1=x1/2, 2=x1/3 (RX24T: 2=x1/4) */ +#ifdef TARGET_rx24t +#define SYS_PLLCR_PLLSRCSEL (1 << 2) /* 0=main, 1=HOCO */ +#else #define SYS_PLLCR_PLLSRCSEL (1 << 4) /* 0=main, 1=HOCO */ +#endif #define SYS_PLLCR_STC(n) (((n) & 0x7F) << 8) /* Frequency Multiplication Factor */ #define SYS_PLLCR2 (*(volatile uint8_t *)(SYSTEM_BASE + 0x2A)) @@ -85,21 +97,23 @@ void hal_delay_us(uint32_t us); #define SYS_MOSCCR (*(volatile uint8_t *)(SYSTEM_BASE + 0x32)) #define SYS_MOSCCR_MOSTP (1 << 0) /* Main-clock osc: 0=operating, 1=stopped */ - +#ifndef TARGET_rx24t #define SYS_SOSCCR (*(volatile uint8_t *)(SYSTEM_BASE + 0x33)) /* Sub-Clock Oscillator Control */ #define SYS_SOSCCR_SOSTP (1 << 0) /* Sub-clock osc: 0=operating, 1=stopped */ - +#endif #define SYS_LOCOCR (*(volatile uint8_t *)(SYSTEM_BASE + 0x34)) #define SYS_LOCOCR_LCSTP (1 << 0) /* Low-Speed On-Chip Oscillator Control: 0=On, 1=Off */ #define SYS_HOCOCR (*(volatile uint8_t *)(SYSTEM_BASE + 0x36)) #define SYS_HOCOCR_HCSTP (1 << 0) /* High Speed On-Chip Osc - 1=STOPPED */ #define SYS_HOCOCR2 (*(volatile uint8_t *)(SYSTEM_BASE + 0x37)) -#define SYS_HOCOCR2_HCFRQ(n) ((n) << 0) /* 0=16MHz, 1=18MHz, 2=20MHz */ +#define SYS_HOCOCR2_HCFRQ(n) ((n) << 0) /* 0=16MHz, 1=18MHz, 2=20MHz (RX24T: 0=32MHz, 3=64MHz) */ #define SYS_OSCOVFSR (*(volatile uint8_t *)(SYSTEM_BASE + 0x3C)) #define SYS_OSCOVFSR_MOOVF (1 << 0) /* Main clock */ +#ifndef TARGET_rx24t #define SYS_OSCOVFSR_SOOVF (1 << 1) /* Sub clock */ +#endif #define SYS_OSCOVFSR_PLOVF (1 << 2) /* PLL */ #define SYS_OSCOVFSR_HCOVF (1 << 3) /* HOCO */ #define SYS_OSCOVFSR_ILCOVF (1 << 4) /* IWDT */ @@ -115,22 +129,42 @@ void hal_delay_us(uint32_t us); #define SYS_PRCR_PRKEY (0xA5 << 8) #define SYS_PRCR_PRC0 (1 << 0) /* Enables writing to clock generation circuit */ #define SYS_PRCR_PRC1 (1 << 1) /* Enables writing to operating modes, clock R/W generation circuit, low power consumption, and software reset */ +#ifdef TARGET_rx24t +#define SYS_PRCR_PRC2 (1 << 2) /* Enables writing to HOCOWTCR */ +#endif #define SYS_PRCR_PRC3 (1 << 3) /* Enables writing to LVD */ +#ifdef TARGET_rx24t +#define PROTECT_OFF() SYS_PRCR = (SYS_PRCR_PRKEY | SYS_PRCR_PRC0 | SYS_PRCR_PRC1 | SYS_PRCR_PRC2 | SYS_PRCR_PRC3) +#else #define PROTECT_OFF() SYS_PRCR = (SYS_PRCR_PRKEY | SYS_PRCR_PRC0 | SYS_PRCR_PRC1 | SYS_PRCR_PRC3) +#endif #define PROTECT_ON() SYS_PRCR = (SYS_PRCR_PRKEY) #define SYS_MOFCR (*(volatile uint8_t *)(SYSTEM_BASE + 0xC293)) +#ifdef TARGET_rx24t +#define SYS_MOFCR_MODRV21 (1 << 5) /* OSC MHz: 0=1-10, 1=10-20 */ +#else #define SYS_MOFCR_MOFXIN (1 << 0) /* OSC Force Oscillation: 0=not controlled, 1=main clock forced */ #define SYS_MOFCR_MODRV2(n) ((n) << 4) /* OSC MHz: 0=20.1-24, 1=16.1-20, 2=8.1-16, 3=8 */ +#endif #define SYS_MOFCR_MOSEL (1 << 6) /* 0=resonator, 1=external clk in*/ +#ifndef TARGET_rx24t #define SYS_HOCOPCR (*(volatile uint8_t *)(SYSTEM_BASE + 0xC294)) #define SYS_HOCOPCR_HOCOPCNT (1 << 0) /* High-Speed On-Chip Oscillator Power Supply Control: 0=On, 1=Off */ +#endif #define SYS_RSTSR1 (*(volatile uint8_t *)(SYSTEM_BASE + 0xC291)) #define SYS_RSTSR1_CWSF (1 << 0) /* 0=Cold Start, 1=Warm Start */ +#ifdef TARGET_rx24t +#define SYS_OPCCR (*(volatile uint8_t *)(SYSTEM_BASE + 0xA0)) +#define SYS_OPCCR_OPCM(n) ((n) & 0x7) /* Operating Power Control Mode: 0=High-speed, 2=Middle-speed */ +#define SYS_OPCCR_OPCMTSF (1 << 4) /* 0=Transition completed, 1=During transition */ +#endif + +#ifndef TARGET_rx24t /* RTC */ #define RTC_BASE (SYSTEM_BASE + 0xC400) #define RTC_RCR3 (*(volatile uint8_t *)(RTC_BASE + 0x26)) @@ -138,8 +172,83 @@ void hal_delay_us(uint32_t us); #define RTC_RCR3_RTCDV(n) ((n) << 1) #define RTC_RCR4 (*(volatile uint8_t *)(RTC_BASE + 0x28)) #define RTC_RCR4_RCKSEL (1 << 0) /* 0=Sub Clock, 1=Main Clock */ +#endif /* Flash */ +#ifdef TARGET_rx24t +#define FLASH_BASE 0x7FC000 + +#define FLASH_DFLCTL (*(volatile uint8_t *)(FLASH_BASE + 0x90)) +#define FLASH_DFLCTL_DFLEN (1 << 0) /* Data Flash Access: 0=disabled, 1=enabled */ + +#define FLASH_FPMCR (*(volatile uint8_t *)(FLASH_BASE + 0x100)) /* Flash P/E Mode Control Register */ +#define FLASH_FPMCR_FMS0 (1<<1) +#define FLASH_FPMCR_FMS1 (1<<4) +#define FLASH_FPMCR_FMS2 (1<<7) +#define FLASH_FPMCR_RPDIS (1<<3) /* ROM P/E Disable: 0=enabled, 1=disabled */ +#define FLASH_FPMCR_LVPE (1<<6) /* Low Voltage P/E Mode Enable: 0=disabled, 1=enabled */ +#define FLASH_FPMCR_DISCHARGE1 (FLASH_FPMCR_FMS1 | FLASH_FPMCR_FMS0) /* FMS=011 */ +#define FLASH_FPMCR_DISCHARGE2 (FLASH_FPMCR_FMS2 | FLASH_FPMCR_FMS1 | FLASH_FPMCR_FMS0) /* FMS=111 */ +#define FLASH_FPMCR_CODE_PE (FLASH_FPMCR_FMS2 | FLASH_FPMCR_FMS0) /* FMS=101: ROM P/E mode */ +#define FLASH_FPMCR_READ FLASH_FPMCR_RPDIS /* FMS=000: read mode */ + +#define FLASH_FASR (*(volatile uint8_t *)(FLASH_BASE + 0x104)) /* Flash Area Select Register */ +#define FLASH_FASR_EXS (1<<0) /* 0=User area or data area */ + +#define FLASH_FSARL (*(volatile uint16_t *)(FLASH_BASE + 0x108)) /* Flash Processing Start Address Register L */ +#define FLASH_FSARH (*(volatile uint16_t *)(FLASH_BASE + 0x110)) /* Flash Processing Start Address Register H */ + +#define FLASH_FCR (*(volatile uint8_t *)(FLASH_BASE + 0x114)) /* Flash Control Register */ +#define FLASH_FCR_CMD_PROGRAM (0x81) /* CMD=Program, OPST=Start*/ +#define FLASH_FCR_CMD_BLANKCHECK (0x83) /* CMD=BlankCheck, OPST=Start*/ +#define FLASH_FCR_CMD_ERASE (0x84) /* CMD=BlockErase, OPST=Start*/ +#define FLASH_FCR_CMD_ALLERASE (0x86) /* CMD=AllBlockErase, OPST=Start*/ +#define FLASH_FCR_CMD_CLEAR (0x0) +#define FLASH_FCR_STOP (1<<6) /* Forced Processing Stop */ + +#define FLASH_FEARL (*(volatile uint16_t *)(FLASH_BASE + 0x118)) /* Flash Processing End Address Register L */ +#define FLASH_FEARH (*(volatile uint16_t *)(FLASH_BASE + 0x120)) /* Flash Processing End Address Register H */ +#define FLASH_FRESETR (*(volatile uint8_t *)(FLASH_BASE + 0x124)) /* Flash Reset Register */ +#define FLASH_FRESETR_FRESET (1<<0) /* 1=reset the sequencer */ + +#define FLASH_FSTATR0 (*(volatile uint8_t *)(FLASH_BASE + 0x1F0)) /* Flash Status Register 0 */ +#define FLASH_FSTATR0_ERERR (1<<0) /* Erase Error Flag */ +#define FLASH_FSTATR0_PRGERR (1<<1) /* Program Error Flag */ +#define FLASH_FSTATR0_BCERR (1<<3) /* Blank Check Error Flag */ +#define FLASH_FSTATR0_ILGLERR (1<<4) /* Illegal Command Error Flag */ +#define FLASH_FSTATR0_EILGLERR (1<<5) /* Extra Area Illegal Command Error Flag */ +#define FLASH_FSTATR1 (*(volatile uint8_t *)(FLASH_BASE + 0x12C)) /* Flash Status Register 1 */ +#define FLASH_FSTATR1_FRDY (1<<6) /* Flash Ready Flag */ +#define FLASH_FSTATR1_EXRDY (1<<7) /* Extra Area Ready Flag */ + +#define FLASH_FWB0 (*(volatile uint16_t *)(FLASH_BASE + 0x130)) /* Flash Write Buffer 0 */ +#define FLASH_FWB1 (*(volatile uint16_t *)(FLASH_BASE + 0x138)) /* Flash Write Buffer 1 */ +#define FLASH_FWB2 (*(volatile uint16_t *)(FLASH_BASE + 0x140)) /* Flash Write Buffer 2 */ +#define FLASH_FWB3 (*(volatile uint16_t *)(FLASH_BASE + 0x144)) /* Flash Write Buffer 3 */ + +#define FLASH_FPR (*(volatile uint8_t *)(FLASH_BASE + 0x180)) /* Protection Unlock Register */ +#define FLASH_FPR_KEY (0xA5) +#define FLASH_FPSR (*(volatile uint8_t *)(FLASH_BASE + 0x184)) /* Protection Unlock Status Register */ +#define FLASH_FPSR_PERR (1<<0) /* Protection Error Flag: 1=error */ + +#define FLASH_FSCMR (*(volatile uint16_t *)(FLASH_BASE + 0x1C0)) /* Flash Start-Up Setting Monitor Register */ +#define FLASH_FAWSMR (*(volatile uint16_t *)(FLASH_BASE + 0x1C8)) /* Flash Access Window Start Address Monitor Register */ +#define FLASH_FAWEMR (*(volatile uint16_t *)(FLASH_BASE + 0x1D0)) /* Flash Access Window End Address Monitor Register */ + +#define FLASH_FISR (*(volatile uint8_t *)(FLASH_BASE + 0x1D8)) /* Flash Initial Setting Register */ +#define FLASH_FISR_PCKA(mhz) (((mhz) - 1) & 0x1F) /* PCKA: FCLK in MHz (1-32) */ +#define FLASH_FEXCR (*(volatile uint8_t *)(FLASH_BASE + 0x1DC)) /* Flash Extra Area Control Register */ +#define FLASH_FEAML (*(volatile uint16_t *)(FLASH_BASE + 0x1E0)) /* Flash Error Address Monitor Register L */ +#define FLASH_FEAMH (*(volatile uint16_t *)(FLASH_BASE + 0x1E8)) /* Flash Error Address Monitor Register H */ + +#define FLASH_FENTRYR (*(volatile uint16_t *)(0x7FFFB2)) /* Flash P/E Mode Entry Register */ +#define FLASH_FENTRYR_KEY (0xAA00) +#define FLASH_FENTRYR_CODE_READ (0) +#define FLASH_FENTRYR_CODE_PR (1 << 0) /* Code Flash Memory P/E Mode Entry */ +#define FLASH_FENTRYR_DATA_READ (0) +#define FLASH_FENTRYR_DATA_PE (1 << 7) /* Data Flash Memory P/E Mode Entry */ + +#else #define FLASH_BASE (SYSTEM_BASE + 0x1000) #define FLASH_FWEPROR (*(volatile uint8_t *)(SYSTEM_BASE + 0xC296)) /* Flash P/E Protect Register */ @@ -201,6 +310,7 @@ void hal_delay_us(uint32_t us); #define FCU_RAM_AREA (0x007F8000) #define FCU_RAM_SIZE (4096) +#endif #ifdef TARGET_rx71m #define FCU_FIRMWARE_ADDR (0xFEFFF000) @@ -231,6 +341,14 @@ void hal_delay_us(uint32_t us); #define SYS_MEMWAIT (*(volatile uint32_t *)(SYSTEM_BASE + 0x6610)) #define SYS_MEMWAIT_MEMWAIT (1 << 0) /* 1=wait cycle, required for ICLK > 120MHz */ +#elif defined(TARGET_rx24t) + #define FLASH_SIZE 0x40000UL /* 256KB */ + #define FLASH_CF_BLOCK_SIZE 2048 /* erase block */ + #define FLASH_CF_UNIT_SIZE 8 /* program unit */ + #define FLASH_CF_PE_OFFSET 0x03E00000UL /* read address - P/E address */ + + #define FLASH_MEMWAIT (*(volatile uint8_t *)(SYSTEM_BASE + 0x31)) + #define FLASH_MEMWAIT_MEMWAIT(n) ((n) << 0) /* 0=no wait, 1=ICLK<=64MHz, 2=ICLK<=80MHZ */ #else #define FLASH_SIZE 0x200000UL /* 2MB */ @@ -291,7 +409,7 @@ void hal_delay_us(uint32_t us); #define SCI_SCMR_SDIR (1 << 3) /* Transmitted/Received Data Transfer Direction */ #define SCI_SCMR_SINV (1 << 2) /* Transmitted/Received Data Invert */ -#define SCI_SEMR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x08)) +#define SCI_SEMR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x07)) #define SCI_SEMR_ASC0 (1 << 0) /* Asynchronous Mode Clock Source Select 0=external clock input */ #define SCI_SEMR_BRME (1 << 2) /* Bit Rate Modulation Enable */ #define SCI_SEMR_ABCS (1 << 4) /* Asynchronous Mode Base Clock Select */ @@ -311,7 +429,8 @@ void hal_delay_us(uint32_t us); #define MPC_PWPR_B0WI (1 << 7) #define MPC_PWPR_PFSWE (1 << 6) -#if defined(TARGET_rx72n) || defined(TARGET_rx71m) +#if defined(TARGET_rx72n) || defined(TARGET_rx71m) || \ + defined(TARGET_rx24t) #define MPC_PFS(n) (*(volatile uint8_t *)(SYSTEM_BASE + 0xC140 + (n))) #else #define MPC_PFS(n) (*(volatile uint8_t *)(SYSTEM_BASE + 0xC0E0 + (n))) diff --git a/hal/rx24t.c b/hal/rx24t.c new file mode 100644 index 0000000000..5fe5e6d384 --- /dev/null +++ b/hal/rx24t.c @@ -0,0 +1,23 @@ +/* rx24t.c + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* See hal/renesas-rx.c for HAL. + * Differences adjusted with TARGET_rx24t macro. */ diff --git a/hal/rx24t.ld b/hal/rx24t.ld new file mode 100644 index 0000000000..66654ba3bb --- /dev/null +++ b/hal/rx24t.ld @@ -0,0 +1,171 @@ +OUTPUT_ARCH(rx) +ENTRY(_PowerON_Reset) + +MEMORY +{ + /* Do not use 0x0 RAM base, as it will fail NULL checks */ + RAM : ORIGIN = 0x10, LENGTH = 16384 - 0x10 + /* Ends before the fixed words at 0xFFFFFF80 (MDE, OFS, ID code, vectors) */ + ROM : ORIGIN = @WOLFBOOT_ORIGIN@ /* 0xFFFF8000 */, LENGTH = @BOOTLOADER_PARTITION_SIZE@ - 0x80 +} + +SECTIONS +{ + /* Option-setting memory (MDE, OFS1, OFS0), see WOLFBOOT_RENESAS_OSM */ + .ofs_rx24t 0xFFFFFF80: + { + KEEP(*(.ofs_rx24t)) + } = 0xFF + + /* Fixed words including ROMCODE at 0xFFFFFF9C */ + .romcode 0xFFFFFF90: + { + KEEP(*(.romcode)) + } = 0xFF + ASSERT(SIZEOF(.romcode) == 0x6C, "RomCodeArea[] must fill 0xFFFFFF90-0xFFFFFFFB") + . = ALIGN(4); + + .fvectors 0xFFFFFFFC: + { + KEEP(*(.fvectors)) + } = 0x4 + + .rvectors ORIGIN(ROM) : + { + _rvectors_start = .; + KEEP(*(.rvectors)) + _rvectors_end = .; + } > ROM + + .exvectors : ALIGN(128) + { + KEEP(*(.exvectors)) + } > ROM + + .text : + { + _start_text = .; + __start_text = .; + *(.text) + *(.text.*) + *(P) + etext = .; + } > ROM + + .init : + { + KEEP(*(.init)) + __preinit_array_start = .; + KEEP(*(.preinit_array)) + __preinit_array_end = .; + __init_array_start = (. + 3) & ~ 3; + KEEP(*(.init_array)) + KEEP(*(SORT(.init_array.*))) + __init_array_end = .; + __fini_array_start = .; + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + __fini_array_end = .; + } > ROM + + .fini : + { + KEEP(*(.fini)) + } > ROM + + .got : + { + *(.got) + *(.got.plt) + } > ROM + + .rodata : + { + *(.rodata) + *(.rodata.*) + *(C_1) + *(C_2) + *(C) + _erodata = .; + } > ROM + + gcc_exceptions_table : + { + KEEP (*(.gcc_except_table)) + *(.gcc_except_table.*) + } > ROM + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > ROM + + .eh_frame : + { + *(.eh_frame) + } > ROM + + .jcr : + { + *(.jcr) + } > ROM + + .tors : + { + __CTOR_LIST__ = .; + . = ALIGN(2); + ___ctors = .; + *(.ctors) + ___ctors_end = .; + __CTOR_END__ = .; + __DTOR_LIST__ = .; + ___dtors = .; + *(.dtors) + ___dtors_end = .; + __DTOR_END__ = .; + . = ALIGN(4); + _mdata = .; + } > ROM + + .data : AT(_mdata) + { + _data = .; + . = ALIGN(4); + KEEP(*(.ramcode)) + *(.data) + *(.data.*) + *(D) + *(D_1) + *(D_2) + . = ALIGN(4); + _edata = .; + } > RAM + + /* Pin .bss LMA to its VMA; else it chains past ROM at the top of the + * address space and newer ld errors "LMA wraps around address space". */ + .bss (NOLOAD) : AT (ADDR (.bss)) + { + _bss = .; + *(.dynbss) + *(.bss) + *(.bss.**) + *(COMMON) + *(B) + *(B_1) + *(B_2) + _ebss = .; + . = ALIGN(128); + _end = .; + } > RAM +} + + +/* wolfBoot runs on the interrupt stack (PSW.U stays 0) */ +PROVIDE(_istack = ORIGIN(RAM) + LENGTH(RAM) ); +PROVIDE(_ustack = _istack ); +ASSERT(_istack - _end >= 0x1400, "less than 5KB of RAM left for the interrupt stack") + +_wolfboot_partition_boot_address = @WOLFBOOT_PARTITION_BOOT_ADDRESS@; +_wolfboot_partition_size = @WOLFBOOT_PARTITION_SIZE@; +_wolfboot_partition_update_address = @WOLFBOOT_PARTITION_UPDATE_ADDRESS@; +_wolfboot_partition_swap_address = @WOLFBOOT_PARTITION_SWAP_ADDRESS@; diff --git a/include/printf.h b/include/printf.h index 6a5661edf9..b09a8d2b14 100644 --- a/include/printf.h +++ b/include/printf.h @@ -65,7 +65,12 @@ # elif defined(DEBUG_UART) /* use minimal printf support in string.h */ void uart_printf(const char* fmt, ...); -# define wolfBoot_printf(_f_, ...) uart_printf(_f_, ##__VA_ARGS__) +# if defined(__CCRX__) + /* CC-RX has no ##__VA_ARGS__ */ +# define wolfBoot_printf uart_printf +# else +# define wolfBoot_printf(_f_, ...) uart_printf(_f_, ##__VA_ARGS__) +# endif # elif defined(__CCRX__) # define wolfBoot_printf printf # elif defined(WOLFBOOT_LOG_PRINTF) diff --git a/src/boot_renesas.c b/src/boot_renesas.c index dcf460b627..48545c330b 100644 --- a/src/boot_renesas.c +++ b/src/boot_renesas.c @@ -92,7 +92,9 @@ void do_boot(const uint32_t *app_offset) #if defined(__RX__) /* Do unconditional jump (r1 = app_offset) */ #if defined(__CCRX__) - printf("app_offset 0x%p\n", app_offset); + #ifndef TARGET_rx24t /* RX24T project: no stdio */ + printf("app_offset 0x%p\n", app_offset); + #endif longJump(app_offset); #else app_entry = (void(*))(*app_offset); @@ -151,8 +153,10 @@ extern void PowerON_Reset(void); #define OFS_OSIS __attribute__ ((section (".ofs6"))) /* 0xFE7F5D50 */ #define OFS_FAW __attribute__ ((section (".ofs7"))) /* 0xFE7F5D64 */ #define OFS_RCP __attribute__ ((section (".ofs8"))) /* 0xFE7F5D70 */ -#define ROMCODE_SECT __attribute__ ((section (".romcode"))) /* 0xFFFFFF80 */ +/* .romcode is at 0xFFFFFF80 on RX71M and 0xFFFFFF90 on RX24T */ +#define ROMCODE_SECT __attribute__ ((section (".romcode"))) #define OFS_RX71M __attribute__ ((section (".ofs_rx71m"))) /* 0x00120040 */ +#define OFS_RX24T __attribute__ ((section (".ofs_rx24t"))) /* 0xFFFFFF80 */ /* Generic Interrupt Handler */ void INT_Dummy(void) __attribute__ ((interrupt)); @@ -161,7 +165,7 @@ void INT_Dummy(void) { /* wait(); */ } -#ifdef TARGET_rx71m +#if defined(TARGET_rx71m) || defined(TARGET_rx24t) /* Fault exceptions stop here */ void INT_Fault(void) __attribute__ ((interrupt)); void INT_Fault(void) @@ -318,25 +322,48 @@ const void *HardwareVectors[] FVECT_SECT = { #endif }; -#if defined(TARGET_rx71m) && !defined(WOLFBOOT_RENESAS_APP) +#if (defined(TARGET_rx71m) || defined(TARGET_rx24t)) && \ + !defined(WOLFBOOT_RENESAS_APP) /* ROMCODE 0x00000000 or 0x00000001 enables ROM code protection */ #define ROMCODE_VALUE (0xFFFFFFFF) -/* On RX71M, ROMCODE sits in the exception table area at reset (0xFFFFFF80), +#ifdef TARGET_rx24t +#ifndef WOLFBOOT_RENESAS_ID_CODE0 +#define WOLFBOOT_RENESAS_ID_CODE0 (0x45010203) +#endif +#ifndef WOLFBOOT_RENESAS_ID_CODE1 +#define WOLFBOOT_RENESAS_ID_CODE1 (0x04050607) +#endif +#ifndef WOLFBOOT_RENESAS_ID_CODE2 +#define WOLFBOOT_RENESAS_ID_CODE2 (0x08090A0B) +#endif +#ifndef WOLFBOOT_RENESAS_ID_CODE3 +#define WOLFBOOT_RENESAS_ID_CODE3 (0x0C0D0E0F) +#endif +#else +#define WOLFBOOT_RENESAS_ID_CODE0 (0xFFFFFFFF) +#define WOLFBOOT_RENESAS_ID_CODE1 (0xFFFFFFFF) +#define WOLFBOOT_RENESAS_ID_CODE2 (0xFFFFFFFF) +#define WOLFBOOT_RENESAS_ID_CODE3 (0xFFFFFFFF) +#endif + +/* ROMCODE sits in the exception table area at reset (0xFFFFFF80), * so ExceptVectors[] is placed in ROM and the startup points EXTB at it. */ const void *RomCodeArea[] ROMCODE_SECT = { +#ifdef TARGET_rx71m (fp)0xFFFFFFFF, /* 0x00 reserved */ (fp)0xFFFFFFFF, /* 0x04 reserved */ (fp)0xFFFFFFFF, /* 0x08 reserved */ (fp)0xFFFFFFFF, /* 0x0C reserved */ +#endif /* RX24T: MDE, OFS1, OFS0 at 0x00-0x0C are in .ofs_rx24t */ (fp)0xFFFFFFFF, /* 0x10 reserved */ (fp)0xFFFFFFFF, /* 0x14 reserved */ (fp)0xFFFFFFFF, /* 0x18 reserved */ (fp)ROMCODE_VALUE, /* 0x1C ROMCODE */ - (fp)0xFFFFFFFF, /* 0x20 reserved */ - (fp)0xFFFFFFFF, /* 0x24 reserved */ - (fp)0xFFFFFFFF, /* 0x28 reserved */ - (fp)0xFFFFFFFF, /* 0x2C reserved */ + (fp)WOLFBOOT_RENESAS_ID_CODE0, /* 0x20 reserved (RX24T: ID code) */ + (fp)WOLFBOOT_RENESAS_ID_CODE1, /* 0x24 reserved (RX24T: ID code) */ + (fp)WOLFBOOT_RENESAS_ID_CODE2, /* 0x28 reserved (RX24T: ID code) */ + (fp)WOLFBOOT_RENESAS_ID_CODE3, /* 0x2C reserved (RX24T: ID code) */ (fp)0xFFFFFFFF, /* 0x30 reserved */ (fp)0xFFFFFFFF, /* 0x34 reserved */ (fp)0xFFFFFFFF, /* 0x38 reserved */ @@ -903,6 +930,15 @@ const unsigned long __ofsm_rx71m[12] OFS_RX71M = { __OFS1_VALUE, /* 0x6C OFS1 */ }; #endif /* !WOLFBOOT_RENESAS_APP */ +#elif defined(TARGET_rx24t) +#ifndef WOLFBOOT_RENESAS_APP +const unsigned long __ofsm_rx24t[4] OFS_RX24T = { + __MDE_VALUE, /* 0x80 MDE */ + 0xffffffff, /* 0x84 reserved */ + __OFS1_VALUE, /* 0x88 OFS1 */ + __OFS0_VALUE, /* 0x8C OFS0 */ +}; +#endif /* !WOLFBOOT_RENESAS_APP */ #else const unsigned long __ofsm_sec_ofs1[] OFS_REG = { __MDE_VALUE, @@ -935,7 +971,7 @@ const unsigned long __FAWreg OFS_FAW = 0xffffffff; /* RCP register */ const unsigned long __RCPreg OFS_RCP = 0xffffffff; -#endif /* TARGET_rx71m */ +#endif /* TARGET_rx71m, TARGET_rx24t */ #endif /* WOLFBOOT_RENESAS_OSM */ #endif /* __RX__ */ diff --git a/test-app/Makefile b/test-app/Makefile index 1da5f5429e..0a14f7fd4a 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -127,7 +127,7 @@ else LDFLAGS+=-ffreestanding -nostartfiles endif CFLAGS+=-DWOLFBOOT_RENESAS_APP - ifeq ($(TARGET),rx71m) + ifneq ($(filter rx71m rx24t,$(TARGET)),) # The flash driver must run from RAM: code flash cannot be read in P/E mode ../hal/renesas-rx.o: CFLAGS+=-DRAM_CODE -D__WOLFBOOT endif @@ -648,6 +648,10 @@ ENTRY_POINT=`cat .entry-point-address` LSCRIPT:=../config/target-app.ld LSCRIPT_TEMPLATE:=$(ARCH).ld +ifeq ($(TARGET),rx24t) + LSCRIPT_TEMPLATE:=$(ARCH)-$(TARGET).ld +endif + ifeq ($(TARGET),stm32f7) LSCRIPT_TEMPLATE=ARM-stm32f7.ld CFLAGS+=-DDUALBANK_SWAP diff --git a/test-app/RENESAS_RX-rx24t.ld b/test-app/RENESAS_RX-rx24t.ld new file mode 100644 index 0000000000..ace9634858 --- /dev/null +++ b/test-app/RENESAS_RX-rx24t.ld @@ -0,0 +1,150 @@ +OUTPUT_ARCH(rx) +ENTRY(_PowerON_Reset) + +MEMORY +{ + /* Do not use 0x0 RAM base, as it will fail NULL checks */ + RAM : ORIGIN = 0x10, LENGTH = 16384 - 0x10 + ROM : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ +} + +SECTIONS +{ + .fvectors : + { + KEEP(*(.fvectors)) + } > ROM + + .exvectors : + { + KEEP(*(.exvectors)) + } > ROM + + .rvectors : + { + _rvectors_start = .; + KEEP(*(.rvectors)) + _rvectors_end = .; + } > ROM + + .text : + { + *(.text) + *(.text.*) + *(P) + etext = .; + } > ROM + + .init : + { + KEEP(*(.init)) + __preinit_array_start = .; + KEEP(*(.preinit_array)) + __preinit_array_end = .; + __init_array_start = (. + 3) & ~ 3; + KEEP(*(.init_array)) + KEEP(*(SORT(.init_array.*))) + __init_array_end = .; + __fini_array_start = .; + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + __fini_array_end = .; + } > ROM + + .fini : + { + KEEP(*(.fini)) + } > ROM + + .got : + { + *(.got) + *(.got.plt) + } > ROM + + .rodata : + { + *(.rodata) + *(.rodata.*) + *(C_1) + *(C_2) + *(C) + _erodata = .; + } > ROM + + gcc_exceptions_table : + { + KEEP (*(.gcc_except_table)) + *(.gcc_except_table.*) + } > ROM + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > ROM + + .eh_frame : + { + *(.eh_frame) + } > ROM + + .jcr : + { + *(.jcr) + } > ROM + + .tors : + { + __CTOR_LIST__ = .; + . = ALIGN(2); + ___ctors = .; + *(.ctors) + ___ctors_end = .; + __CTOR_END__ = .; + __DTOR_LIST__ = .; + ___dtors = .; + *(.dtors) + ___dtors_end = .; + __DTOR_END__ = .; + . = ALIGN(4); + _mdata = .; + } > ROM + + .data : AT(_mdata) + { + _data = .; + . = ALIGN(4); + KEEP(*(.ramcode)) + *(.data) + *(.data.*) + *(D) + *(D_1) + *(D_2) + . = ALIGN(4); + _edata = .; + } > RAM + + .bss : + { + _bss = .; + *(.bss) + *(.bss.**) + *(COMMON) + *(B) + *(B_1) + *(B_2) + _ebss = .; + . = ALIGN(128); + _end = .; + } > RAM +} + +/* The test-app runs on the interrupt stack (PSW.U stays 0) */ +PROVIDE(_istack = ORIGIN(RAM) + LENGTH(RAM) ); +PROVIDE(_ustack = _istack ); +ASSERT(_istack - _end >= 0x1000, "less than 4KB of RAM left for the test-app stack") + +_wolfboot_partition_boot_address = @WOLFBOOT_PARTITION_BOOT_ADDRESS@; +_wolfboot_partition_size = @WOLFBOOT_PARTITION_SIZE@; +_wolfboot_partition_update_address = @WOLFBOOT_PARTITION_UPDATE_ADDRESS@; +_wolfboot_partition_swap_address = @WOLFBOOT_PARTITION_SWAP_ADDRESS@;