From d3016916fc564938b7f154fda42fa7188e9d031b Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 26 Sep 2024 15:37:18 -0700 Subject: [PATCH 01/19] Support for the Nordic nRF5340 (application and network cores): * Added nRF5340 driver support for Clock, Internal Flash (NVMC), GPIO, SPU, OTP, UART, SPI, QSPI and IPC. * Added support for updating the network core (Sign using "--id 2") * Cleanup the nRF52 port * Improved external QSPI and internal Flash tests and logging. * Improved internal printf support for formatter length. --- .gdbinit | 1 + .github/workflows/test-configs.yml | 12 + arch.mk | 4 +- config/examples/nrf52840.config | 1 + config/examples/nrf5340.config | 47 +++ config/examples/nrf5340_net.config | 48 +++ docs/Targets.md | 143 ++++++- hal/nrf52.c | 51 ++- hal/nrf52.h | 102 +++++ hal/nrf5340.c | 514 ++++++++++++++++++++++++++ hal/nrf5340.h | 389 +++++++++++++++++++ hal/nrf5340.ld | 52 +++ hal/nrf5340_net.c | 28 ++ hal/nrf5340_net.ld | 51 +++ hal/spi/spi_drv_nrf52.c | 31 +- hal/spi/spi_drv_nrf52.h | 17 +- hal/spi/spi_drv_nrf5340.c | 301 +++++++++++++++ hal/spi/spi_drv_nrf5340.h | 103 ++++++ include/image.h | 7 + include/spi_drv.h | 19 + include/spi_flash.h | 1 + src/image.c | 31 +- src/libwolfboot.c | 4 +- src/qspi_flash.c | 106 +++--- src/string.c | 26 +- test-app/ARM-nrf5340_net.ld | 57 +++ test-app/Makefile | 6 +- test-app/app_nrf52.c | 51 +-- test-app/app_nrf5340.c | 70 ++++ test-app/app_nrf5340_net.c | 70 ++++ test-app/startup_arm.c | 2 +- tools/scripts/nrf5340/build_flash.sh | 46 +++ tools/scripts/nrf5340/flash_app.jlink | 7 + tools/scripts/nrf5340/flash_net.jlink | 7 + 34 files changed, 2224 insertions(+), 181 deletions(-) create mode 100644 config/examples/nrf5340.config create mode 100644 config/examples/nrf5340_net.config create mode 100644 hal/nrf52.h create mode 100644 hal/nrf5340.c create mode 100644 hal/nrf5340.h create mode 100644 hal/nrf5340.ld create mode 100644 hal/nrf5340_net.c create mode 100644 hal/nrf5340_net.ld create mode 100644 hal/spi/spi_drv_nrf5340.c create mode 100644 hal/spi/spi_drv_nrf5340.h create mode 100644 test-app/ARM-nrf5340_net.ld create mode 100644 test-app/app_nrf5340.c create mode 100644 test-app/app_nrf5340_net.c create mode 100755 tools/scripts/nrf5340/build_flash.sh create mode 100644 tools/scripts/nrf5340/flash_app.jlink create mode 100644 tools/scripts/nrf5340/flash_net.jlink diff --git a/.gdbinit b/.gdbinit index e6d2cdfebc..ef7d89f91f 100644 --- a/.gdbinit +++ b/.gdbinit @@ -1,6 +1,7 @@ file wolfboot.elf tar rem:3333 add-symbol-file test-app/image.elf +set pagination off foc c diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 4760abd5d3..5cc2c51151 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -123,6 +123,18 @@ jobs: arch: arm config-file: ./config/examples/nrf52840.config + nrf5340_app_test: + uses: ./.github/workflows/test-build.yml + with: + arch: arm + config-file: ./config/examples/nrf5340.config + + nrf5340_net_test: + uses: ./.github/workflows/test-build.yml + with: + arch: arm + config-file: ./config/examples/nrf5340_net.config + nxp_p1021_test: uses: ./.github/workflows/test-build.yml with: diff --git a/arch.mk b/arch.mk index 0bc648df18..b8cd835e11 100644 --- a/arch.mk +++ b/arch.mk @@ -203,7 +203,9 @@ else CFLAGS+=-mcpu=cortex-m33 -DCORTEX_M33 LDFLAGS+=-mcpu=cortex-m33 ifeq ($(TZEN),1) - OBJS+=hal/stm32_tz.o + ifneq (,$(findstring stm32,$(TARGET))) + OBJS+=hal/stm32_tz.o + endif CFLAGS+=-mcmse ifeq ($(WOLFCRYPT_TZ),1) SECURE_OBJS+=./src/wc_callable.o diff --git a/config/examples/nrf52840.config b/config/examples/nrf52840.config index 97398b39de..4f3cc99bf2 100644 --- a/config/examples/nrf52840.config +++ b/config/examples/nrf52840.config @@ -3,6 +3,7 @@ TARGET?=nrf52 SIGN?=ECC256 HASH?=SHA256 DEBUG?=0 +DEBUG_UART?=1 VTOR?=1 CORTEX_M0?=0 NO_ASM?=0 diff --git a/config/examples/nrf5340.config b/config/examples/nrf5340.config new file mode 100644 index 0000000000..d12984ccd8 --- /dev/null +++ b/config/examples/nrf5340.config @@ -0,0 +1,47 @@ +ARCH?=ARM +TZEN?=0 +TARGET?=nrf5340 +SIGN?=ECC256 +HASH?=SHA256 +WOLFBOOT_VERSION?=1 +VTOR?=1 +CORTEX_M0?=0 +CORTEX_M33?=1 +NO_ASM?=0 +NO_MPU=1 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=0 + +SPMATH?=1 +RAM_CODE?=1 + +DUALBANK_SWAP?=0 +FLAGS_HOME=0 +DISABLE_BACKUP=0 +EXT_FLASH?=1 +SPI_FLASH?=0 +QSPI_FLASH?=1 + +# Flash is 4KB pages (app) +WOLFBOOT_SECTOR_SIZE?=0x1000 + +# Application offset (reserve 48KB for wolfBoot) +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xC000 + +# Application Partition Size (952KB) +WOLFBOOT_PARTITION_SIZE?=0xEE000 + +# External Flash offset for application update (1MB) +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0 + +# External Flash offset for network update at 0x100000 (size=256KB) + +# External Flash offset for swap (4KB) +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x140000 + +V?=0 +DEBUG?=0 +DEBUG_UART?=1 +USE_GCC=1 + +CFLAGS_EXTRA+=-DDEBUG_FLASH diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config new file mode 100644 index 0000000000..821033eea5 --- /dev/null +++ b/config/examples/nrf5340_net.config @@ -0,0 +1,48 @@ +ARCH?=ARM +TZEN?=0 +TARGET?=nrf5340_net +SIGN?=ECC256 +HASH?=SHA256 +WOLFBOOT_VERSION?=1 +VTOR?=1 +CORTEX_M0?=0 +CORTEX_M33?=1 +NO_ASM?=1 +NO_MPU=1 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=0 + +SPMATH?=1 +RAM_CODE?=1 + +DUALBANK_SWAP?=0 +FLAGS_HOME=0 +DISABLE_BACKUP=0 +EXT_FLASH?=0 +SPI_FLASH?=0 +QSPI_FLASH?=0 + +# Flash base for network core +ARCH_FLASH_OFFSET=0x01000000 + +# Flash is 2KB pages +WOLFBOOT_SECTOR_SIZE?=0x800 + +# Application offset (reserve 48KB for wolfBoot) +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x0100C000 + +# Application Partition Size (184KB) +WOLFBOOT_PARTITION_SIZE?=0x2E000 + +# Flash offset for update (not used - handled by application core) +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0100C000 + +# Flash offset for swap (not used - handled by application core) +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x103A800 + +V?=0 +DEBUG?=0 +DEBUG_UART?=1 +USE_GCC=1 + +CFLAGS_EXTRA+=-DDEBUG_FLASH diff --git a/docs/Targets.md b/docs/Targets.md index 3c65c7615e..304166f2e7 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -4,25 +4,28 @@ This README describes configuration of supported targets. ## Supported Targets +* [Simulated](#simulated) * [Cortex-A53 / Raspberry PI 3](#cortex-a53--raspberry-pi-3-experimental) * [Cypress PSoC-6](#cypress-psoc-6) * [Infineon AURIX TC3xx](#infineon-aurix-tc3xx) * [Intel x86-64 Intel FSP](#intel-x86_64-with-intel-fsp-support) * [Microchip SAMA5D3](#microchip-sama5d3) * [Microchip SAME51](#microchip-same51) +* [Nordic nRF52840](#nordic-nrf52840) +* [Nordic nRF5340](#nordic-nrf5340) +* [NXP iMX-RT](#nxp-imx-rt) * [NXP Kinetis](#nxp-kinetis) * [NXP LPC54xxx](#nxp-lpc54xxx) * [NXP MCXA153](#nxp-mcxa153) * [NXP P1021 PPC](#nxp-qoriq-p1021-ppc) * [NXP T1024 PPC](#nxp-qoriq-t1024-ppc) * [NXP T2080 PPC](#nxp-qoriq-t2080-ppc) -* [NXP iMX-RT](#nxp-imx-rt) -* [Nordic nRF52840](#nordic-nrf52840) * [Qemu x86-64 UEFI](#qemu-x86-64-uefi) * [Renesas RA6M4](#renesas-ra6m4) * [Renesas RX65N](#renesas-rx65n) * [Renesas RX72N](#renesas-rx72n) * [Renesas RZN2L](#renesas-rzn2l) +* [SiFive HiFive1 RISC-V](#sifive-hifive1-risc-v) * [STM32C0](#stm32c0) * [STM32F4](#stm32f4) * [STM32F7](#stm32f7) @@ -34,7 +37,6 @@ This README describes configuration of supported targets. * [STM32L5](#stm32l5) * [STM32U5](#stm32u5) * [STM32WB55](#stm32wb55) -* [SiFive HiFive1 RISC-V](#sifive-hifive1-risc-v) * [TI Hercules TMS570LC435](#ti-hercules-tms570lc435) * [Xilinx Zynq UltraScale](#xilinx-zynq-ultrascale) @@ -2177,6 +2179,135 @@ Example of flash memory layout and configuration on the nRF52: #define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x58000 ``` + +## Nordic nRF5340 + +Tested with the Nordic nRF5340-DK. This device has two cores: +1) Application core: Cortex-M33 at 128MHz, w/TrustZone, 1MB flash, 512KB RAM +2) Network core: Cortex-M33 at 64MHz, 256KB Flash and 64KB RAM + +The cores communicate using the IPC peripheral. + +The network core can access application core resources (flash, RAM, and peripherals) when granted permission through the application's DCNF and SPU settings. A small portion of the application core RAM is dedicated to the exchange of messages between the application and network cores. + +The DK board has two virtual COM ports. Application core and Network core will each output to different VCOM ports. + +Example Boot Output: + +Application Core: + +``` +wolfBoot HAL Init (app core) +QSPI Freq=24MHz (Div Clk=3/Sck=1), Addr=24-bits, PageSz=256 +QSPI Activate +QSPI Flash ID (ret 0): 0xC2 0x28 0x17 +Status Reg: Ret 0, 0x40 (Quad Enabled: Yes) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x2000022C +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x2000022C +Boot partition: 0xC000 (size 7428, version 0x1) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x20000128 +Update partition: 0x0 (size 7428, version 0x2) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x2000022C +Boot partition: 0xC000 (size 7428, version 0x1) +Booting version: 0x1 +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x100000 -> 0x20000128 +Update partition: 0x100000 (size 5492, version 0x2) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x20000230 +Network version: 0x2 +======================== +nRF5340 wolfBoot (app core) +Copyright 2024 wolfSSL Inc +GPL v3 +Version : 0x1 +======================== +Internal Flash Write: addr 0xF9FFC, len 4 +Internal Flash Write: addr 0xF9FFB, len 1 +``` + +Network Core: + +``` +wolfBoot HAL Init (net core) +Boot partition: 0x100C000 (size 5492, version 0x1) +Update partition: 0x100C000 (size 5492, version 0x1) +Boot partition: 0x100C000 (size 5492, version 0x1) +Booting version: 0x1 +======================== +nRF5340 wolfBoot (net core) +Copyright 2024 wolfSSL Inc +GPL v3 +Version : 0x1 +======================== +Internal Flash Write: addr 0x1039FFC, len 4 +Internal Flash Write: addr 0x1039FFB, len 1 +``` + +### Building / Flashing Nordic nRF5340 + +You may optionally use `./tools/scripts/nrf5340/build_flash.sh` for building and flashing both cores. + +The `nrfjprog` can be used to program external QSPI flash for testing. Example: `nrfjprog --program --verify -f nrf53` + +#### Application Core + +Flash base: 0x00000000, SRAM base: 0x20000000 + +Building Application core: + +```sh +cp config/examples/nrf5340.config .config +make clean +make +``` + +Flashing Application core with JLink: + +``` +JLinkExe -device nRF5340_xxAA_APP -if SWD -speed 4000 -jtagconf -1,-1 -autoconnect 1 +loadbin factory.bin 0x0 +rnh +``` + +#### Network Core + +Flash base: 0x01000000, SRAM base: 0x21000000 + +Building Network core: + +```sh +cp config/examples/nrf5340_net.config .config +make clean +make +``` + +Flashing Network core with JLink: + +``` +JLinkExe -device nRF5340_xxAA_NET -if SWD -speed 4000 -jtagconf -1,-1 -autoconnect 1 +loadbin factory.bin 0x01000000 +rnh +``` + +### Debugging Nordic nRF5340 + +Debugging with JLink: + +1) Start GDB Server: +``` +JLinkGDBServer -device nRF5340_xxAA_APP -if SWD -port 3333 +``` + +2) Start GDB +This will use .gdbinit, but can supply `wolfboot.elf -ex "target remote localhost:3333"` if permissions not allowing. + +``` +arm-none-eabi-gdb +b main +mon reset +c +``` + + ## Simulated You can create a simulated target that uses files to mimic an internal and @@ -2919,8 +3050,8 @@ repository that can be directly flashed into the BIOS flash of the board. ## Infineon AURIX TC3xx -wolfBoot supports the AURIX TC3xx family of devices, and provides a demo application targeting the TC375 AURIX LiteKit-V2. +wolfBoot supports the AURIX TC3xx family of devices, and provides a demo application targeting the TC375 AURIX LiteKit-V2. -For detailed instructions on using wolfBoot with the AURIX TC3xx, please refer to [IDE/AURIX/README.md](../IDE/AURIX/README.md) +For detailed instructions on using wolfBoot with the AURIX TC3xx, please refer to [IDE/AURIX/README.md](../IDE/AURIX/README.md) -wolfBoot can also integrate with [wolfHSM](https://www.wolfssl.com/products/wolfhsm/) on AURIX TC3xx devices, offloading cryptographic operations and key storage to the AURIX HSM core. For more information on using wolfBoot with wolfHSM on AURIX devices, please contact us at facts@wolfssl.com. +wolfBoot can also integrate with [wolfHSM](https://www.wolfssl.com/products/wolfhsm/) on AURIX TC3xx devices, offloading cryptographic operations and key storage to the AURIX HSM core. For more information on using wolfBoot with wolfHSM on AURIX devices, please contact us at facts@wolfssl.com. diff --git a/hal/nrf52.c b/hal/nrf52.c index 33ed1f4b7e..f15ae4f28a 100644 --- a/hal/nrf52.c +++ b/hal/nrf52.c @@ -19,32 +19,42 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +#ifdef TARGET_nrf52 + #include #include "image.h" +#include "nrf52.h" -/* Assembly helpers */ -#define DMB() __asm__ volatile ("dmb") - - -/* Instantiation */ -#define CLOCK_CONTROL_BASE (0x40000000) -#define NVMC_BASE (0x4001E000) - +#ifdef DEBUG_UART +void uart_init(void) +{ + UART0_BAUDRATE = BAUD_115200; + UART0_ENABLE = 1; +} -/* Flash write/erase control */ -#define NVMC_CONFIG *((volatile uint32_t *)(NVMC_BASE + 0x504)) -#define NVMC_ERASEPAGE *((volatile uint32_t *)(NVMC_BASE + 0x508)) -#define NVMC_READY *((volatile uint32_t *)(NVMC_BASE + 0x400)) -#define NVMC_CONFIG_REN 0 -#define NVMC_CONFIG_WEN 1 -#define NVMC_CONFIG_EEN 2 +static void uart_write_char(char c) +{ + UART0_EVENT_ENDTX = 0; -#define FLASH_PAGE_SIZE (4096) + UART0_TXD_PTR = (uint32_t)(&c); + UART0_TXD_MAXCOUNT = 1; + UART0_TASK_STARTTX = 1; + while(UART0_EVENT_ENDTX == 0) + ; +} -/* Clock control */ -#define TASKS_HFCLKSTART *((volatile uint32_t *)(CLOCK_CONTROL_BASE + 0x000)) -#define TASKS_HFCLKSTOP *((volatile uint32_t *)(CLOCK_CONTROL_BASE + 0x004)) -#define TASKS_HFCLKSTARTED *((volatile uint32_t *)(CLOCK_CONTROL_BASE + 0x100)) +void uart_write(const char* buf, unsigned int sz) +{ + uint32_t pos = 0; + while (sz-- > 0) { + char c = buf[pos++]; + if (c == '\n') { /* handle CRLF */ + uart_write_char('\r'); + } + uart_write_char(c); + } +} +#endif /* DEBUG_UART */ static void RAMFUNCTION flash_wait_complete(void) { @@ -117,3 +127,4 @@ void hal_prepare_boot(void) TASKS_HFCLKSTOP = 1; } +#endif /* TARGET_nrf52 */ diff --git a/hal/nrf52.h b/hal/nrf52.h new file mode 100644 index 0000000000..622963cb66 --- /dev/null +++ b/hal/nrf52.h @@ -0,0 +1,102 @@ +/* nrf52.h + * + * Copyright (C) 2024 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 _HAL_NRF52_H_ +#define _HAL_NRF52_H_ + +/* Assembly helpers */ +#define DMB() __asm__ volatile ("dmb") + +/* Instantiation */ +#define CLOCK_CONTROL_BASE (0x40000000) +#define NVMC_BASE (0x4001E000) + + +/* Flash write/erase control */ +#define NVMC_CONFIG *((volatile uint32_t *)(NVMC_BASE + 0x504)) +#define NVMC_ERASEPAGE *((volatile uint32_t *)(NVMC_BASE + 0x508)) +#define NVMC_READY *((volatile uint32_t *)(NVMC_BASE + 0x400)) +#define NVMC_CONFIG_REN 0 +#define NVMC_CONFIG_WEN 1 +#define NVMC_CONFIG_EEN 2 + +#define FLASH_PAGE_SIZE (4096) + +/* Clock control */ +#define TASKS_HFCLKSTART *((volatile uint32_t *)(CLOCK_CONTROL_BASE + 0x000)) +#define TASKS_HFCLKSTOP *((volatile uint32_t *)(CLOCK_CONTROL_BASE + 0x004)) +#define TASKS_HFCLKSTARTED *((volatile uint32_t *)(CLOCK_CONTROL_BASE + 0x100)) + +/* GPIO */ +#define GPIO_BASE (0x50000000) +#define GPIO_OUT *((volatile uint32_t *)(GPIO_BASE + 0x504)) +#define GPIO_OUTSET *((volatile uint32_t *)(GPIO_BASE + 0x508)) +#define GPIO_OUTCLR *((volatile uint32_t *)(GPIO_BASE + 0x50C)) +#define GPIO_DIRSET *((volatile uint32_t *)(GPIO_BASE + 0x518)) +#define GPIO_PIN_CNF ((volatile uint32_t *)(GPIO_BASE + 0x700)) /* Array */ + +#define GPIO_CNF_IN 0 +#define GPIO_CNF_OUT 3 + +/* UART */ +#define UART0_BASE (0x40002000) +#define UART0_TASK_STARTTX *((volatile uint32_t *)(UART0_BASE + 0x008)) +#define UART0_TASK_STOPTX *((volatile uint32_t *)(UART0_BASE + 0x00C)) +#define UART0_EVENT_ENDTX *((volatile uint32_t *)(UART0_BASE + 0x120)) +#define UART0_ENABLE *((volatile uint32_t *)(UART0_BASE + 0x500)) +#define UART0_TXD_PTR *((volatile uint32_t *)(UART0_BASE + 0x544)) +#define UART0_TXD_MAXCOUNT *((volatile uint32_t *)(UART0_BASE + 0x548)) +#define UART0_BAUDRATE *((volatile uint32_t *)(UART0_BASE + 0x524)) + +#define BAUD_115200 0x01D7E000 + +/* SPI */ +#define SPI0 (0x40003000) +#define SPI1 (0x40004000) +#define SPI2 (0x40023000) + +#define SPI SPI0 +#define SPI_TASKS_START *((volatile uint32_t *)(SPI + 0x10)) +#define SPI_TASKS_STOP *((volatile uint32_t *)(SPI + 0x14)) +#define SPI_EVENTS_ENDRX *((volatile uint32_t *)(SPI + 0x110)) +#define SPI_EVENTS_END *((volatile uint32_t *)(SPI + 0x118)) +#define SPI_EVENTS_ENDTX *((volatile uint32_t *)(SPI + 0x120)) +#define SPI_EV_RDY *((volatile uint32_t *)(SPI + 0x108)) +#define SPI_INTENSET *((volatile uint32_t *)(SPI + 0x304)) +#define SPI_INTENCLR *((volatile uint32_t *)(SPI + 0x308)) +#define SPI_ENABLE *((volatile uint32_t *)(SPI + 0x500)) +#define SPI_PSEL_SCK *((volatile uint32_t *)(SPI + 0x508)) +#define SPI_PSEL_MOSI *((volatile uint32_t *)(SPI + 0x50C)) +#define SPI_PSEL_MISO *((volatile uint32_t *)(SPI + 0x510)) +#define SPI_RXDATA *((volatile uint32_t *)(SPI + 0x518)) +#define SPI_TXDATA *((volatile uint32_t *)(SPI + 0x51C)) +#define SPI_FREQUENCY *((volatile uint32_t *)(SPI + 0x524)) +#define SPI_CONFIG *((volatile uint32_t *)(SPI + 0x554)) + +#define K125 0x02000000 +#define K250 0x04000000 +#define K500 0x08000000 +#define M1 0x10000000 +#define M2 0x20000000 +#define M4 0x40000000 +#define M8 0x80000000 + +#endif /* !_HAL_NRF52_H_ */ diff --git a/hal/nrf5340.c b/hal/nrf5340.c new file mode 100644 index 0000000000..41f12720bf --- /dev/null +++ b/hal/nrf5340.c @@ -0,0 +1,514 @@ +/* nrf5340.c + * + * Copyright (C) 2024 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 + */ + +/* Note: Also used by TARGET_nrf5340_net */ +#ifdef TARGET_nrf5340 + +#include + +#include "image.h" +#include "string.h" +#include "printf.h" +#include "nrf5340.h" +#include "spi_flash.h" + +/* TODO: + * Key Storage: See 7.1.18.4.2 Key storage: + * The key storage region of the UICR can contain multiple keys of different type, including symmetrical keys, hashes, public/private key pairs and other device secrets + * Key headers are allocated an address range of 0x400 in the UICR memory map, allowing a total of 128 keys to be addressable inside the key storage region. + * The key storage region contains multiple key slots, where each slot consists of a key header and an associated key value. The key value is limited to 128 bits. + * Any key size greater than 128 bits must be divided and distributed over multiple key slot instances. + */ + +#ifdef TEST_FLASH +static int test_flash(void); +#endif + +/* Network updates can be signed with "--id 2" and placed into the normal update partition, + * or they can be placed into the external flash at offset 0x100000 */ +#ifndef PART_NET_ID +#define PART_NET_ID 2 +#endif +#ifndef PART_NET_ADDR +#define PART_NET_ADDR 0x100000UL +#endif + +/* Shared Memory between network and application cores */ +/* first 64KB (0x10000) is used by wolfBoot and limited in nrf5340.ld */ +#ifndef SHARED_MEM_ADDR + #define SHARED_MEM_ADDR (0x20000000UL + (64 * 1024)) + #define SHARED_MEM_SIZE (256 * 1024) /* enable access to full 256KB for entire network update image */ +#endif +/* Shared memory states */ +#define SHARED_STATUS_UNKNOWN 0 +#define SHARED_STATUS_READY 1 +#define SHARED_STATUS_UPDATE_START 2 +#define SHARED_STATUS_UPDATE_DONE 3 +#define SHARED_STATUS_DO_BOOT 4 + +#define SHAREM_MEM_MAGIC 0x5753484D /* WSHM */ + +typedef struct { + uint32_t magic; + uint32_t status; + uint32_t version; /* always refers to network core version */ + uint32_t size; +} ShmInfo_t; + +typedef struct { + ShmInfo_t net; /* network core write location */ + ShmInfo_t app; /* application core write location */ + + /* application places firmware here */ + uint8_t data[0]; +} SharedMem_t; +static SharedMem_t* shm = (SharedMem_t*)SHARED_MEM_ADDR; + + +#ifdef DEBUG_UART +#ifndef UART_SEL + #define UART_SEL 0 /* select UART 0 or 1 */ +#endif +#if !defined(UART_PORT) && !defined(UART_PIN) + #if UART_SEL == 0 && !defined(TARGET_nrf5340_net) + #define UART_PORT 0 + #define UART_PIN 20 + #else + #define UART_PORT 1 + #define UART_PIN 1 + #endif +#endif + +void uart_init(void) +{ + /* nRF5340-DK: + * App: UART0=P1.01, UART1=P0.20 */ + UART_ENABLE(UART_SEL) = 0; + GPIO_PIN_CNF(UART_PORT, UART_PIN) = (GPIO_CNF_OUT + #ifdef TARGET_nrf5340_net + | GPIO_CNF_MCUSEL(1) + #endif + ); + UART_PSEL_TXD(UART_SEL) = (PSEL_PORT(UART_PORT) | UART_PIN); + UART_BAUDRATE(UART_SEL) = BAUD_115200; + UART_CONFIG(UART_SEL) = 0; /* Flow=Diabled, Stop=1-bit, Parity exclude */ + UART_ENABLE(UART_SEL) = 8; + + /* allow network core access to P1.01 - must be set from application core */ +#ifdef TARGET_nrf5340_app + GPIO_PIN_CNF(1, 1) = (GPIO_CNF_OUT | GPIO_CNF_MCUSEL(1)); +#endif +} + +#ifndef UART_TX_MAX_SZ +#define UART_TX_MAX_SZ 128 +#endif +void uart_write_sz(const char* c, unsigned int sz) +{ + /* EasyDMA must be a RAM buffer */ + static uint8_t uartTxBuf[UART_TX_MAX_SZ]; + + while (sz > 0) { + unsigned int xfer = sz; + if (xfer > sizeof(uartTxBuf)) + xfer = sizeof(uartTxBuf); + memcpy(uartTxBuf, c, xfer); + + UART_EVENT_ENDTX(UART_SEL) = 0; + + UART_TXD_PTR(UART_SEL) = (uint32_t)uartTxBuf; + UART_TXD_MAXCOUNT(UART_SEL) = xfer; + UART_TASK_STARTTX(UART_SEL) = 1; + while (UART_EVENT_ENDTX(UART_SEL) == 0); + + sz -= xfer; + c += xfer; + } +} + +void uart_write(const char* buf, unsigned int sz) +{ + const char* line; + unsigned int lineSz; + do { + /* find `\n` */ + line = memchr(buf, sz, '\n'); + if (line == NULL) { + uart_write_sz(buf, sz); + break; + } + lineSz = line - buf; + + uart_write_sz(line, lineSz); + uart_write_sz("\r", 1); /* handle CRLF */ + + buf = line; + sz -= lineSz; + } while ((int)sz > 0); +} +#endif /* DEBUG_UART */ + +/* Non-volatile memory controller - use actual flash address */ +int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + int i = 0; + uint32_t *src, *dst; +#ifdef DEBUG_FLASH + wolfBoot_printf("Internal Flash Write: addr 0x%x, len %d\n", address, len); +#endif + while (i < len) { + if ((len - i > 3) && ((((address + i) & 0x03) == 0) && + ((((uint32_t)data) + i) & 0x03) == 0)) { + src = (uint32_t *)data; + dst = (uint32_t *)address; + /* set both secure and non-secure registers */ + NVMC_CONFIG = NVMC_CONFIG_WEN; + NVMC_CONFIGNS = NVMC_CONFIG_WEN; + while (NVMC_READY == 0); + dst[i >> 2] = src[i >> 2]; + while (NVMC_READY == 0); + i+=4; + } else { + uint32_t val; + uint8_t *vbytes = (uint8_t *)(&val); + int off = (address + i) - (((address + i) >> 2) << 2); + dst = (uint32_t *)(address - off); + val = dst[i >> 2]; + vbytes[off] = data[i]; + /* set both secure and non-secure registers */ + NVMC_CONFIG = NVMC_CONFIG_WEN; + NVMC_CONFIGNS = NVMC_CONFIG_WEN; + while (NVMC_READY == 0); + dst[i >> 2] = val; + while (NVMC_READY == 0); + i++; + } + } + return 0; +} + +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) +{ + uint32_t end = address + len - 1; + uint32_t p; + uint32_t page_sz = (address < FLASH_BASE_NET) ? + FLASH_PAGESZ_APP : + FLASH_PAGESZ_NET; +#ifdef DEBUG_FLASH + wolfBoot_printf("Internal Flash Erase: addr 0x%x, len %d\n", address, len); +#endif + for (p = address; p <= end; p += page_sz) { + /* set both secure and non-secure registers */ + NVMC_CONFIG = NVMC_CONFIG_EEN; + NVMC_CONFIGNS = NVMC_CONFIG_EEN; + while (NVMC_READY == 0); + *(volatile uint32_t *)p = 0xFFFFFFFF; + while (NVMC_READY == 0); + } + return 0; +} + +void RAMFUNCTION hal_flash_unlock(void) +{ +} + +void RAMFUNCTION hal_flash_lock(void) +{ +} + +static void clock_init(void) +{ +#ifndef TARGET_nrf5340_net + CLOCK_HFCLKSRC = 1; /* use external high frequency clock */ + CLOCK_HFCLKSTART = 1; + /* wait for high frequency clock startup */ + while (CLOCK_HFCLKSTARTED == 0); +#endif +} + +void sleep_us(unsigned int us) +{ + /* Calculate ops per us (128MHz=128 instructions per 1us */ + unsigned long nop_us = (CPU_CLOCK / 10000000); + nop_us *= us; + /* instruction for each iteration */ +#ifdef DEBUG + nop_us /= 5; +#else + nop_us /= 2; +#endif + while (nop_us-- > 0) { + NOP(); + } +} + +#ifdef TARGET_nrf5340_app +void hal_net_core(int hold) /* 1=hold, 0=release */ +{ + if (hold) { + /* stop the network core from booting */ + NETWORK_FORCEOFF = NETWORK_FORCEOFF_HOLD; + } + else { + /* release network core - errata 161 network core release */ + NETWORK_ERRATA_161 = 1; + NETWORK_FORCEOFF = NETWORK_FORCEOFF_RELEASE; + sleep_us(5); + NETWORK_FORCEOFF = NETWORK_FORCEOFF_HOLD; + sleep_us(1); + NETWORK_FORCEOFF = NETWORK_FORCEOFF_RELEASE; + NETWORK_ERRATA_161 = 0; + } +} +#endif + +#define IMAGE_IS_NET_CORE(img) ( \ + (img->type & HDR_IMG_TYPE_PART_MASK) == PART_NET_ID && \ + img->fw_size < FLASH_SIZE_NET) +static int hal_net_get_image(struct wolfBoot_image* img) +{ + /* check the update partition for a network core update */ + int ret = wolfBoot_open_image(img, PART_UPDATE); + if (ret == 0 && IMAGE_IS_NET_CORE(img)) { + return 0; + } + /* if external flash is enabled, try an alternate location */ +#ifdef EXT_FLASH + ret = wolfBoot_open_image_external(img, PART_UPDATE, PART_NET_ADDR); + if (ret == 0 && IMAGE_IS_NET_CORE(img)) { + return 0; + } +#endif + return (ret != 0) ? ret : -1; +} + +static void hal_net_check_version(void) +{ + int ret; + struct wolfBoot_image img; + uint32_t timeout; + +#ifdef TARGET_nrf5340_app + /* check the network core version */ + ret = hal_net_get_image(&img); + if (ret == 0) { + shm->app.version = img.fw_ver; + shm->app.size = img.fw_size; + wolfBoot_printf("Network: Ver 0x%x, Size %d\n", + shm->app.version, shm->app.size); + } + else { + wolfBoot_printf("Failed finding net core update on ext flash 0x%x\n", + PART_NET_ADDR); + } + shm->app.magic = SHAREM_MEM_MAGIC; + shm->app.status = SHARED_STATUS_READY; + + /* release network core - issue boot command */ + hal_net_core(0); + + /* wait for ready status from network core */ + timeout = 1000000; + while (shm->net.magic != SHAREM_MEM_MAGIC && + shm->net.status != SHARED_STATUS_READY && + --timeout > 0) { + /* wait */ + }; + if (timeout == 0) { + wolfBoot_printf("Timeout: network core ready!\n"); + } + + /* check if network core can continue booting or needs to wait for update */ + if (shm->app.version == shm->net.version) { + shm->app.status = SHARED_STATUS_DO_BOOT; + } +#else /* net */ + ret = wolfBoot_open_image(&img, PART_BOOT); + if (ret == 0) { + shm->net.version = img.fw_ver; + shm->net.size = img.fw_size; + wolfBoot_printf("Network: Ver 0x%x, Size %d\n", + shm->net.version, shm->net.size); + } + else { + wolfBoot_printf("Error getting boot partition info\n"); + } + shm->net.magic = SHAREM_MEM_MAGIC; + shm->net.status = SHARED_STATUS_READY; + + wolfBoot_printf("Network version: 0x%x\n", shm->net.version); + + /* wait for do_boot or update */ + timeout = 1000000; + while (shm->app.magic == SHAREM_MEM_MAGIC && + shm->app.status == SHARED_STATUS_READY && + --timeout > 0) { + /* wait */ + }; + if (timeout == 0) { + wolfBoot_printf("Timeout: app core boot signal!\n"); + } +#endif +exit: + wolfBoot_printf("Status: App %d (ver %d), Net %d (ver %d)\n", + shm->app.status, shm->app.version, shm->net.status, shm->net.version); +} + +#ifdef TARGET_nrf5340_app +void hal_net_check_update(void) +{ + int ret; + uint32_t timeout; + struct wolfBoot_image img; + + /* handle update for network core */ + ret = hal_net_get_image(&img); + if (ret == 0 && img.fw_ver > shm->net.version) { + /* validate the update is valid */ + if (wolfBoot_verify_integrity(&img) == 0 && + wolfBoot_verify_authenticity(&img) == 0) + { + /* relocate image to ram */ + ret = spi_flash_read(PART_NET_ADDR, shm->data, img.fw_size); + if (ret >= 0) { + /* signal network core to do update */ + shm->app.status = SHARED_STATUS_UPDATE_START; + + /* wait for update_done */ + timeout = 1000000; + while (shm->net.magic == SHAREM_MEM_MAGIC && + shm->net.status < SHARED_STATUS_UPDATE_DONE && + --timeout > 0) { + sleep_us(1); + }; + if (timeout == 0) { + wolfBoot_printf("Timeout: net core update done!\n"); + } + } + } + else { + wolfBoot_printf("Network image failed: Hdr %d, Hash %d, Sig %d\n", + img.hdr_ok, img.sha_ok, img.signature_ok); + } + } + /* inform network core to boot */ + shm->app.status = SHARED_STATUS_DO_BOOT; +} +#endif + +void hal_init(void) +{ +#ifdef DEBUG_UART + const char* bootStr = "wolfBoot HAL Init (" CORE_STR " core)\n"; +#endif + + clock_init(); + +#ifdef DEBUG_UART + uart_init(); + uart_write(bootStr, strlen(bootStr)); +#endif + +#ifdef TARGET_nrf5340_app + /* Allow the network core to access shared SDRAM at 0x2000_0000 */ + SPU_EXTDOMAIN_PERM(0) = + (SPU_EXTDOMAIN_PERM_SECATTR_SECURE | SPU_EXTDOMAIN_PERM_UNLOCK); +#endif + + spi_flash_probe(); + + hal_net_check_version(); + +#ifdef TEST_FLASH + if (test_flash() != 0) { + wolfBoot_printf("Internal flash Test Failed!\n"); + } +#endif +} + + +void hal_prepare_boot(void) +{ + /* TODO: Protect bootloader region of flash using SPU_FLASHREGION_PERM */ + //WOLFBOOT_ORIGIN + //BOOTLOADER_PARTITION_SIZE + +#ifdef TARGET_nrf5340_app + hal_net_check_update(); + + /* Restore defaults preventing network core from accessing shared SDRAM */ + SPU_EXTDOMAIN_PERM(0) = + (SPU_EXTDOMAIN_PERM_SECATTR_NONSECURE | SPU_EXTDOMAIN_PERM_UNLOCK); +#endif +} + +/* Test for internal flash erase/write */ +/* Use TEST_EXT_FLASH to test external QSPI flash (see qspi_flash.c) */ +#ifdef TEST_FLASH + +#ifndef TEST_ADDRESS + #define TEST_ADDRESS (FLASH_BASE_ADDR + (FLASH_SIZE - WOLFBOOT_SECTOR_SIZE)) +#endif + +/* #define TEST_FLASH_READONLY */ + +static int test_flash(void) +{ + int ret = 0; + uint32_t i, len; + uint8_t* pagePtr = (uint8_t*)TEST_ADDRESS; + static uint8_t pageData[WOLFBOOT_SECTOR_SIZE]; + + wolfBoot_printf("Internal flash test at 0x%x\n", TEST_ADDRESS); + + /* Setup test data */ + for (i=0; i FLASH + + .edidx : + { + . = ALIGN(4); + *(.ARM.exidx*) + } > FLASH + + _stored_data = .; + + .data : AT (_stored_data) + { + _start_data = .; + KEEP(*(.data*)) + . = ALIGN(4); + _end_data = .; + } > RAM + + .bss (NOLOAD) : + { + _start_bss = .; + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _end_bss = .; + __bss_end__ = .; + _end = .; + } > RAM + . = ALIGN(4); +} + +END_STACK = ORIGIN(RAM) + LENGTH(RAM); diff --git a/hal/nrf5340_net.c b/hal/nrf5340_net.c new file mode 100644 index 0000000000..bce3e01ba0 --- /dev/null +++ b/hal/nrf5340_net.c @@ -0,0 +1,28 @@ +/* nrf5340_net.c + * + * Copyright (C) 2024 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 + */ + +#ifdef TARGET_nrf5340_net + +/* use code from nrf5340.c */ +#define TARGET_nrf5340 +#include "nrf5340.c" + +#endif /* TARGET_* */ diff --git a/hal/nrf5340_net.ld b/hal/nrf5340_net.ld new file mode 100644 index 0000000000..8882538757 --- /dev/null +++ b/hal/nrf5340_net.ld @@ -0,0 +1,51 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = @ARCH_FLASH_OFFSET@, LENGTH = @BOOTLOADER_PARTITION_SIZE@ + RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 64K +} + +SECTIONS +{ + .text : + { + _start_text = .; + KEEP(*(.isr_vector)) + *(.text*) + *(.rodata*) + *(.init*) + *(.fini*) + . = ALIGN(4); + _end_text = .; + } > FLASH + + .edidx : + { + . = ALIGN(4); + *(.ARM.exidx*) + } > FLASH + + _stored_data = .; + + .data : AT (_stored_data) + { + _start_data = .; + KEEP(*(.data*)) + . = ALIGN(4); + _end_data = .; + } > RAM + + .bss (NOLOAD) : + { + _start_bss = .; + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _end_bss = .; + __bss_end__ = .; + _end = .; + } > RAM + . = ALIGN(4); +} + +END_STACK = ORIGIN(RAM) + LENGTH(RAM); diff --git a/hal/spi/spi_drv_nrf52.c b/hal/spi/spi_drv_nrf52.c index 67d160073b..6844589672 100644 --- a/hal/spi/spi_drv_nrf52.c +++ b/hal/spi/spi_drv_nrf52.c @@ -28,37 +28,10 @@ #include "spi_drv.h" #ifdef TARGET_nrf52 -#if defined(SPI_FLASH) || defined(WOLFBOOT_TPM) - -#define SPI0 (0x40003000) -#define SPI1 (0x40004000) -#define SPI2 (0x40023000) -#define SPI SPI0 -#define SPI_TASKS_START *((volatile uint32_t *)(SPI + 0x10)) -#define SPI_TASKS_STOP *((volatile uint32_t *)(SPI + 0x14)) -#define SPI_EVENTS_ENDRX *((volatile uint32_t *)(SPI + 0x110)) -#define SPI_EVENTS_END *((volatile uint32_t *)(SPI + 0x118)) -#define SPI_EVENTS_ENDTX *((volatile uint32_t *)(SPI + 0x120)) -#define SPI_EV_RDY *((volatile uint32_t *)(SPI + 0x108)) -#define SPI_INTENSET *((volatile uint32_t *)(SPI + 0x304)) -#define SPI_INTENCLR *((volatile uint32_t *)(SPI + 0x308)) -#define SPI_ENABLE *((volatile uint32_t *)(SPI + 0x500)) -#define SPI_PSEL_SCK *((volatile uint32_t *)(SPI + 0x508)) -#define SPI_PSEL_MOSI *((volatile uint32_t *)(SPI + 0x50C)) -#define SPI_PSEL_MISO *((volatile uint32_t *)(SPI + 0x510)) -#define SPI_RXDATA *((volatile uint32_t *)(SPI + 0x518)) -#define SPI_TXDATA *((volatile uint32_t *)(SPI + 0x51C)) -#define SPI_FREQUENCY *((volatile uint32_t *)(SPI + 0x524)) -#define SPI_CONFIG *((volatile uint32_t *)(SPI + 0x554)) +#if defined(SPI_FLASH) || defined(WOLFBOOT_TPM) -#define K125 0x02000000 -#define K250 0x04000000 -#define K500 0x08000000 -#define M1 0x10000000 -#define M2 0x20000000 -#define M4 0x40000000 -#define M8 0x80000000 +#include "hal/nrf52.h" void RAMFUNCTION spi_cs_off(uint32_t base, int pin) { diff --git a/hal/spi/spi_drv_nrf52.h b/hal/spi/spi_drv_nrf52.h index e23c2b99d1..33d31b7fd4 100644 --- a/hal/spi/spi_drv_nrf52.h +++ b/hal/spi/spi_drv_nrf52.h @@ -17,22 +17,12 @@ #ifndef SPI_DRV_NRF52_H_INCLUDED #define SPI_DRV_NRF52_H_INCLUDED -#include -/** SPI settings **/ - - -#define GPIO_BASE (0x50000000) -#define GPIO_OUT *((volatile uint32_t *)(GPIO_BASE + 0x504)) -#define GPIO_OUTSET *((volatile uint32_t *)(GPIO_BASE + 0x508)) -#define GPIO_OUTCLR *((volatile uint32_t *)(GPIO_BASE + 0x50C)) -#define GPIO_DIRSET *((volatile uint32_t *)(GPIO_BASE + 0x518)) -#define GPIO_PIN_CNF ((volatile uint32_t *)(GPIO_BASE + 0x700)) // Array -#define GPIO_CNF_IN 0 -#define GPIO_CNF_OUT 3 +#include +#include "hal/nrf52.h" -/* Pinout (P0.x) */ +/* SPI Pin Configuration (P0.x) */ #if 1 #define SPI_CS_PIN 13 #define SPI_MOSI_PIN 4 @@ -50,5 +40,4 @@ #define SPI_CS_FLASH SPI_CS_PIN #define SPI_CS_PIO_BASE GPIO_BASE - #endif diff --git a/hal/spi/spi_drv_nrf5340.c b/hal/spi/spi_drv_nrf5340.c new file mode 100644 index 0000000000..7789997a8c --- /dev/null +++ b/hal/spi/spi_drv_nrf5340.c @@ -0,0 +1,301 @@ +/* spi_drv_nrf5340.c + * + * Driver for the SPI back-end of the SPI_FLASH module. + * + * Example implementation for nrf52F4. + * + * Pinout: see spi_drv_nrf5340.h + * + * Copyright (C) 2024 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 "spi_drv.h" +#include "spi_flash.h" +#include "string.h" +#include "printf.h" + +#ifdef TARGET_nrf5340 + +#if defined(QSPI_FLASH) || defined(SPI_FLASH) || defined(WOLFBOOT_TPM) + +#if defined(SPI_FLASH) || defined(WOLFBOOT_TPM) +void spi_cs_off(uint32_t base, int pin) +{ + GPIO_OUTSET(base) = (1 << pin); + while ((GPIO_OUT(base) & (1 << pin)) == 0) + ; +} + +void spi_cs_on(uint32_t base, int pin) +{ + GPIO_OUTCLR(base) = (1 << pin); + while ((GPIO_OUT(base) & (1 << pin)) != 0) + ; +} + +uint8_t spi_read(void) +{ + volatile uint32_t reg = SPI_EV_RDY(SPI_PORT); + while (!reg) + reg = SPI_EV_RDY(SPI_PORT); + reg = SPI_RXDATA(SPI_PORT); + SPI_EV_RDY(SPI_PORT) = 0; + return reg; +} + +void spi_write(const char byte) +{ + uint32_t reg; + SPI_EV_RDY(SPI_PORT) = 0; + SPI_TXDATA(SPI_PORT) = (uint32_t)byte; + reg = SPI_EV_RDY(SPI_PORT); + while (!reg) + reg = SPI_EV_RDY(SPI_PORT); +} +#endif + +#ifdef QSPI_FLASH + +void qspi_wait_ready(void) +{ + int timeout = 1000000; + while (QSPI_EVENTS_READY == 0 && --timeout > 0) { + NOP(); + } + if (timeout == 0) { + #ifdef DEBUG_QSPI + wolfBoot_printf("QSPI Wait timeout!\n"); + #endif + } +} + +int qspi_transfer(uint8_t fmode, const uint8_t cmd, + uint32_t addr, uint32_t addrSz, uint32_t addrMode, + uint32_t alt, uint32_t altSz, uint32_t altMode, + uint32_t dummySz, + uint8_t* data, uint32_t dataSz, uint32_t dataMode) +{ + uint32_t cintData[2] = {0, 0}; + + QSPI_EVENTS_READY = 0; /* clear events */ + + if (addrSz == 0) { /* command only operation */ + if (dataSz > sizeof(cintData)) + dataSz = sizeof(cintData); + if (fmode == QSPI_MODE_WRITE) { + memcpy(cintData, data, dataSz); + if (dataSz >= 4) + QSPI_CINSTRDAT1 = cintData[1]; + if (dataSz > 0) + QSPI_CINSTRDAT0 = cintData[0]; + } + QSPI_CINSTRCONF = ( + QSPI_CINSTRCONF_OPCODE(cmd) | + QSPI_CINSTRCONF_LENGTH(1 + dataSz) | + QSPI_CINSTRCONF_LIO2 | + QSPI_CINSTRCONF_LIO3 /* IO3 high (not reset) */ + ); + } + else if (fmode == QSPI_MODE_WRITE && dataSz == 0) { /* erase */ + QSPI_ERASE_PTR = addr; + QSPI_ERASE_LEN = SPI_FLASH_SECTOR_SIZE; + + QSPI_TASKS_ERASESTART = 1; + } + else if (fmode == QSPI_MODE_WRITE) { /* write */ + QSPI_WRITE_DST = addr; + QSPI_WRITE_SRC = (uint32_t)data; + QSPI_WRITE_CNT = dataSz; + QSPI_TASKS_WRITESTART = 1; + } + else { /* read */ + QSPI_READ_DST = (uint32_t)data; + QSPI_READ_SRC = addr; + QSPI_READ_CNT = dataSz; + QSPI_TASKS_READSTART = 1; + } + + /* wait for generated ready event */ + qspi_wait_ready(); + + /* command only read */ + if (addrSz == 0 && fmode == QSPI_MODE_READ) { + cintData[1] = QSPI_CINSTRDAT1; + cintData[0] = QSPI_CINSTRDAT0; + memcpy(data, cintData, dataSz); + } + + return 0; +} +#endif /* QSPI_FLASH */ + +static int spi_initialized = 0; +void spi_init(int polarity, int phase) +{ + uint32_t reg; + + if (spi_initialized) { + return; + } + spi_initialized++; + +#if defined(SPI_FLASH) || defined(WOLFBOOT_TPM) + GPIO_PIN_CNF(SPI_CS_PIO_BASE, SPI_CS_FLASH) = GPIO_CNF_OUT; + GPIO_PIN_CNF(SPI_CS_PIO_BASE, SPI_SCLK_PIN) = GPIO_CNF_OUT; + GPIO_PIN_CNF(SPI_CS_PIO_BASE, SPI_MOSI_PIN) = GPIO_CNF_OUT; + GPIO_PIN_CNF(SPI_CS_PIO_BASE, SPI_MISO_PIN) = GPIO_CNF_IN; + GPIO_OUTSET(SPI_CS_PIO_BASE) = (1 << SPI_CS_FLASH); + GPIO_OUTCLR(SPI_CS_PIO_BASE) = (1 << SPI_MOSI_PIN) | (1 << SPI_SCLK_PIN); + + SPI_PSEL_MISO(SPI_PORT) = SPI_MISO_PIN; + SPI_PSEL_MOSI(SPI_PORT) = SPI_MOSI_PIN; + SPI_PSEL_SCK(SPI_PORT) = SPI_SCLK_PIN; + + SPI_FREQUENCY(SPI_PORT) = SPI_FREQ_M1; + SPI_CONFIG(SPI_PORT) = 0; /* mode 0,0 default */ + SPI_ENABLE(SPI_PORT) = 1; + (void)reg; +#endif /* SPI_FLASH || WOLFBOOT_TPM */ + +#ifdef QSPI_FLASH + /* Enable QSPI Clock */ + CLOCK_HFCLK192MSRC = 0; /* internal osc */ + CLOCK_HFCLK192MCTRL = QSPI_CLK_DIV; + CLOCK_HFCLK192MSTART = 1; + while (CLOCK_HFCLK192MSTARTED == 0); + + /* Configure QSPI Pins */ + QSPI_PSEL_SCK = PSEL_PORT(QSPI_CLK_PORT) | QSPI_CLK_PIN; + QSPI_PSEL_CSN = PSEL_PORT(QSPI_CS_PORT) | QSPI_CS_PIN; + QSPI_PSEL_IO0 = PSEL_PORT(QSPI_IO0_PORT) | QSPI_IO0_PIN; + QSPI_PSEL_IO1 = PSEL_PORT(QSPI_IO1_PORT) | QSPI_IO1_PIN; + QSPI_PSEL_IO2 = PSEL_PORT(QSPI_IO2_PORT) | QSPI_IO2_PIN; + QSPI_PSEL_IO3 = PSEL_PORT(QSPI_IO3_PORT) | QSPI_IO3_PIN; + + /* Configure all pins for GPIO input */ + GPIO_PIN_CNF(QSPI_CLK_PORT, QSPI_CLK_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); + GPIO_PIN_CNF(QSPI_CS_PORT, QSPI_CS_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); + GPIO_PIN_CNF(QSPI_IO0_PORT, QSPI_IO0_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); + GPIO_PIN_CNF(QSPI_IO1_PORT, QSPI_IO1_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); + GPIO_PIN_CNF(QSPI_IO2_PORT, QSPI_IO2_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); + GPIO_PIN_CNF(QSPI_IO3_PORT, QSPI_IO3_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); + + reg = QSPI_IFCONFIG0; + reg &= ~(QSPI_IFCONFIG0_READOC_MASK | QSPI_IFCONFIG0_WRITEOC_MASK); +#if QSPI_DATA_MODE == QSPI_DATA_MODE_QSPI + reg |= QSPI_IFCONFIG0_READOC_READ4O | QSPI_IFCONFIG0_WRITEOC_PP4O; +#elif QSPI_DATA_MODE == QSPI_DATA_MODE_DSPI + reg |= QSPI_IFCONFIG0_READOC_READ2O | QSPI_IFCONFIG0_WRITEOC_PP2O; +#else + reg |= QSPI_IFCONFIG0_READOC_FASTREAD | QSPI_IFCONFIG0_WRITEOC_PP; +#endif +#if QSPI_ADDR_SZ == 4 + reg |= QSPI_IFCONFIG0_ADDRMODE_32BIT; +#else + reg &= ~QSPI_IFCONFIG0_ADDRMODE_32BIT; +#endif +#if SPI_FLASH_PAGE_SIZE == 512 + reg |= QSPI_IFCONFIG0_PPSIZE_512; +#else + reg &= ~QSPI_IFCONFIG0_PPSIZE_512; +#endif + QSPI_IFCONFIG0 = reg; + +#if 1 /* errata 121 */ + reg = QSPI_IFCONFIG0; + #if QSPI_CLK_FREQ_DIV == 0 /* DIV1 */ + reg |= (1 << 16) | (1<<17); + #else + reg &= ~(1 << 17); + reg |= (1 << 16); + #endif + QSPI_IFCONFIG0 = reg; + QSPI_IFTIMING = QSPI_IFTIMING_RXDELAY(6); +#endif /* errata 121 */ + + reg = QSPI_IFCONFIG1; + reg &= ~QSPI_IFCONFIG1_SCKDELAY_MASK; + reg |= QSPI_IFCONFIG1_SCKDELAY(5); + /* SCK = 96MHz / (SCKFREQ + 1) */ + reg &= ~QSPI_IFCONFIG1_SCKFREQ_MASK; + reg |= QSPI_IFCONFIG1_SCKFREQ(QSPI_CLK_FREQ_DIV); + if (polarity == 0 && phase == 0) + reg &= ~QSPI_IFCONFIG1_SPIMODE3; + else + reg |= QSPI_IFCONFIG1_SPIMODE3; + QSPI_IFCONFIG1 = reg; + + QSPI_ENABLE = 1; + + /* make sure interrupts are disabled */ + QSPI_INTENCLR = 1; /* write "1" to disable READY interrupt */ + +#ifdef DEBUG_QSPI + /* Display QSPI config */ + reg = QSPI_IFCONFIG0; + wolfBoot_printf( + "QSPI Freq=%dMHz (Div Clk=%d/Sck=%d), Addr=%d-bits, PageSz=%d\n", + QSPI_CLOCK_MHZ/1000000, + (QSPI_CLK_DIV == 3) ? 4 : QSPI_CLK_DIV+1, + QSPI_CLK_FREQ_DIV+1, + (reg & QSPI_IFCONFIG0_ADDRMODE_32BIT) ? 32 : 24, + (reg & QSPI_IFCONFIG0_PPSIZE_512) ? 512 : 256); +#endif + + /* Activate QSPI */ +#ifdef DEBUG_QSPI + wolfBoot_printf("QSPI Activate\n"); +#endif + QSPI_EVENTS_READY = 0; /* clear events */ + QSPI_TASKS_ACTIVATE = 1; + qspi_wait_ready(); +#endif /* QSPI_FLASH */ + (void)polarity; + (void)phase; +} + +void spi_release(void) +{ + if (spi_initialized) { + spi_initialized--; + + /* Disable QSPI Clock to save power */ + QSPI_ENABLE = 0; + CLOCK_HFCLK192MSTOP = 1; + } +} + +#ifdef WOLFBOOT_TPM +int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz, int flags) +{ + uint32_t i; + spi_cs_on(SPI_CS_PIO_BASE, cs); + for (i = 0; i < sz; i++) { + spi_write((const char)tx[i]); + rx[i] = spi_read(); + } + if (!(flags & SPI_XFER_FLAG_CONTINUE)) { + spi_cs_off(SPI_CS_PIO_BASE, cs); + } + return 0; +} +#endif /* WOLFBOOT_TPM */ + +#endif /* QSPI_FLASH || SPI_FLASH || WOLFBOOT_TPM */ +#endif /* TARGET_ */ diff --git a/hal/spi/spi_drv_nrf5340.h b/hal/spi/spi_drv_nrf5340.h new file mode 100644 index 0000000000..686ac59e2e --- /dev/null +++ b/hal/spi/spi_drv_nrf5340.h @@ -0,0 +1,103 @@ +/* spi_drv_nrf5340.h + * + * 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 SPI_DRV_NRF53_H_INCLUDED +#define SPI_DRV_NRF53_H_INCLUDED + +#include + +#include "hal/nrf5340.h" + +/* Default SPI interface (0-2) */ +#ifndef SPI_PORT +#define SPI_PORT 0 +#endif + +/* SPI Pin Configuration (P1.x) */ +/* Default for nRF5340-DK is Arduino shield P4 P1.12-15 */ +/* CLK=P1.15, CS=P1.12, MOSI=P1.13, MISO=P1.14 */ +#ifndef SPI_CS_PIO_BASE + #define SPI_CS_PIO_BASE 1 +#endif +#ifndef SPI_CS_TPM + #define SPI_CS_TPM 11 +#endif +#ifndef SPI_CS_FLASH + #define SPI_CS_FLASH 12 +#endif +#ifndef SPI_MOSI_PIN + #define SPI_MOSI_PIN 13 +#endif +#ifndef SPI_MISO_PIN + #define SPI_MISO_PIN 14 +#endif +#ifndef SPI_CLK_PIN + #define SPI_CLK_PIN 15 +#endif + + +/* QSPI Pin Configuration */ +/* Default is nRF5340-DK QSPI connected to MX25R6435F */ +/* CLK=P0.17, CS=P0.18, IO0=P0.13, IO1=P0.14, IO2=P0.15, IO3=P0.16 */ +/* QSPI CLK PB2 (alt OCTOSPIM_P1_CLK)*/ +#ifndef QSPI_CLK_PIN + #define QSPI_CLK_PORT 0 + #define QSPI_CLK_PIN 17 +#endif +#ifndef QSPI_CS_PIN + #define QSPI_CS_PORT 0 + #define QSPI_CS_PIN 18 +#endif +#ifndef QSPI_IO0_PIN + #define QSPI_IO0_PORT 0 + #define QSPI_IO0_PIN 13 +#endif +#ifndef QSPI_IO1_PIN + #define QSPI_IO1_PORT 0 + #define QSPI_IO1_PIN 14 +#endif +#ifndef QSPI_IO2_PIN + #define QSPI_IO2_PORT 0 + #define QSPI_IO2_PIN 15 +#endif +#ifndef QSPI_IO3_PIN + #define QSPI_IO3_PORT 0 + #define QSPI_IO3_PIN 16 +#endif + +#ifndef QSPI_CLOCK_MHZ /* default 24MHz (up to 96MHz) */ + #define QSPI_CLOCK_MHZ 24000000UL +#endif + +/* MX25R6435F */ +#define QSPI_NO_SR2 + +#define QSPI_CLK 96000000UL +#if QSPI_CLOCK_MHZ <= 24000000 + #define QSPI_CLK_DIV CLOCK_HFCLK192MCTRL_DIV4 +#elif QSPI_CLOCK_MHZ <= 48000000 + /* Note: Power consumption higher for DIV2/DIV1 */ + #define QSPI_CLK_DIV CLOCK_HFCLK192MCTRL_DIV2 +#else + /* Note: Power consumption higher for DIV2/DIV1 */ + #define QSPI_CLK_DIV CLOCK_HFCLK192MCTRL_DIV1 +#endif + +/* Calculate the IFCONFIG1_SCKFREG divisor */ +#define QSPI_CLK_FREQ_DIV ((QSPI_CLK / (QSPI_CLK_DIV+1) / QSPI_CLOCK_MHZ) - 1) + +#endif /* !SPI_DRV_NRF53_H_INCLUDED */ diff --git a/include/image.h b/include/image.h index 327ac63f15..61c7f54a22 100644 --- a/include/image.h +++ b/include/image.h @@ -97,6 +97,8 @@ struct wolfBoot_image { uint8_t *sha_hash; uint8_t *fw_base; uint32_t fw_size; + uint32_t fw_ver; + uint32_t type; uint32_t part; uint32_t hdr_ok; uint32_t canary_FEED4567; @@ -514,6 +516,8 @@ struct wolfBoot_image { uint8_t *sha_hash; uint8_t *fw_base; uint32_t fw_size; + uint32_t fw_ver; + uint16_t type; uint8_t part; uint8_t hdr_ok : 1; uint8_t signature_ok : 1; @@ -562,6 +566,9 @@ static void wolfBoot_image_confirm_signature_ok(struct wolfBoot_image *img) /* Defined in image.c */ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part); +#ifdef EXT_FLASH +int wolfBoot_open_image_external(struct wolfBoot_image* img, uint8_t part, uint32_t addr); +#endif int wolfBoot_open_image_address(struct wolfBoot_image* img, uint8_t* image); int wolfBoot_verify_integrity(struct wolfBoot_image *img); int wolfBoot_verify_authenticity(struct wolfBoot_image *img); diff --git a/include/spi_drv.h b/include/spi_drv.h index 3348fb1b4b..205a3d6c50 100644 --- a/include/spi_drv.h +++ b/include/spi_drv.h @@ -55,6 +55,10 @@ #include "hal/spi/spi_drv_nrf52.h" #endif +#if defined(TARGET_nrf5340) +#include "hal/spi/spi_drv_nrf5340.h" +#endif + #if defined(TARGET_nxp_p1021) || defined(TARGET_nxp_t1024) #include "hal/spi/spi_drv_nxp.h" #endif @@ -90,12 +94,27 @@ int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz, int flags); #define QSPI_DATA_MODE_DSPI 2 #define QSPI_DATA_MODE_QSPI 3 +/* QSPI Configuration */ +#ifndef QSPI_ADDR_MODE /* address uses single SPI mode */ + #define QSPI_ADDR_MODE QSPI_DATA_MODE_SPI +#endif +#ifndef QSPI_ADDR_SZ /* default to 24-bit address */ + #define QSPI_ADDR_SZ 3 +#endif +#ifndef QSPI_DATA_MODE /* data defaults to Quad mode */ + #define QSPI_DATA_MODE QSPI_DATA_MODE_QSPI +#endif + int qspi_transfer(uint8_t fmode, const uint8_t cmd, uint32_t addr, uint32_t addrSz, uint32_t addrMode, uint32_t alt, uint32_t altSz, uint32_t altMode, uint32_t dummySz, uint8_t* data, uint32_t dataSz, uint32_t dataMode ); + +#if !defined(DEBUG_QSPI) && defined(DEBUG_UART) + #define DEBUG_QSPI 1 +#endif #endif /* QSPI_FLASH || OCTOSPI_FLASH */ #ifndef SPI_CS_FLASH diff --git a/include/spi_flash.h b/include/spi_flash.h index 12fcb1ed9b..32d2639498 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -28,6 +28,7 @@ #ifndef SPI_FLASH_DRI_H #define SPI_FLASH_DRI_H +/* SPI Configuration */ #ifndef SPI_FLASH_SECTOR_SIZE #define SPI_FLASH_SECTOR_SIZE (4096) #endif diff --git a/src/image.c b/src/image.c index fba364a4bd..02b6f9ca03 100644 --- a/src/image.c +++ b/src/image.c @@ -881,12 +881,12 @@ int wolfBoot_open_image_address(struct wolfBoot_image *img, uint8_t *image) #endif img->hdr_ok = 1; img->fw_base = img->hdr + IMAGE_HEADER_SIZE; + img->fw_ver = wolfBoot_get_blob_version(image); + img->type = wolfBoot_get_blob_type(image); - wolfBoot_printf("%s partition: %p (size %d, version 0x%x)\n", + wolfBoot_printf("%s partition: %p (sz %d, ver 0x%x, type 0x%d)\n", (img->part == PART_BOOT) ? "Boot" : "Update", - img->hdr, - (unsigned int)img->fw_size, - wolfBoot_get_blob_version(image)); + img->hdr, (unsigned int)img->fw_size, img->fw_ver, img->type); return 0; } @@ -988,6 +988,27 @@ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part) return wolfBoot_open_image_address(img, image); } + + +#ifdef EXT_FLASH +int wolfBoot_open_image_external(struct wolfBoot_image* img, uint8_t part, + uint32_t addr) +{ + uint8_t *image; + + if (img == NULL) + return -1; + + memset(img, 0, sizeof(struct wolfBoot_image)); + img->part = part; + img->hdr = (void*)addr; + img->hdr_ok = 1; + hdr_cpy_done = 0; /* reset hdr "open" flag */ + image = fetch_hdr_cpy(img); + return wolfBoot_open_image_address(img, image); +} +#endif /* EXT_FLASH */ + #endif /* WOLFBOOT_FIXED_PARTITIONS */ /** @@ -1078,7 +1099,7 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) if (image_type_size != sizeof(uint16_t)) return -1; image_type = (uint16_t)(image_type_buf[0] + (image_type_buf[1] << 8)); - if ((image_type & 0xFF00) != HDR_IMG_TYPE_AUTH) + if ((image_type & HDR_IMG_TYPE_AUTH_MASK) != HDR_IMG_TYPE_AUTH) return -1; if (img->sha_hash == NULL) { if (image_hash(img, digest) != 0) diff --git a/src/libwolfboot.c b/src/libwolfboot.c index f69925b497..22b7dfcbe5 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -1204,11 +1204,9 @@ uint32_t wolfBoot_get_diffbase_version(uint8_t part) uint16_t wolfBoot_get_image_type(uint8_t part) { uint8_t *image = wolfBoot_get_image_from_part(part); - if (image) { - return wolfBoot_get_blob_type(image); + return wolfBoot_get_blob_type(image); } - return 0; } #endif /* WOLFBOOT_FIXED_PARTITIONS */ diff --git a/src/qspi_flash.c b/src/qspi_flash.c index 1bea1fc493..3e271446cb 100644 --- a/src/qspi_flash.c +++ b/src/qspi_flash.c @@ -31,9 +31,6 @@ #include "string.h" #include "printf.h" -#ifdef DEBUG_UART -#define DEBUG_QSPI 1 -#endif /* Flash Parameters: * Winbond W25Q128FV 128Mbit serial flash @@ -49,14 +46,6 @@ #endif #define FLASH_NUM_SECTORS (FLASH_DEVICE_SIZE/FLASH_SECTOR_SIZE) - -/* QSPI Configuration - Use single/dual/quad mode for data transfers */ -#ifndef QSPI_DATA_MODE -#define QSPI_DATA_MODE QSPI_DATA_MODE_SPI -#endif -#ifndef QSPI_ADDR_SZ -#define QSPI_ADDR_SZ 3 -#endif #ifndef QSPI_DUMMY_READ #define QSPI_DUMMY_READ 8 /* Number of dummy clock cycles for reads */ #endif @@ -100,6 +89,7 @@ #define RESET_ENABLE_CMD 0x66U #define RESET_MEMORY_CMD 0x99U +#define FLASH_SR_QE 0x40 #define FLASH_SR_WRITE_EN 0x02 /* 1=Write Enabled, 0=Write Disabled */ #define FLASH_SR_BUSY 0x01 /* 1=Busy, 0=Ready */ @@ -107,20 +97,19 @@ /* Read Command */ #if QSPI_DATA_MODE == QSPI_DATA_MODE_QSPI && QSPI_ADDR_SZ == 4 -#define FLASH_READ_CMD QUAD_READ_4B_CMD + #define FLASH_READ_CMD QUAD_READ_4B_CMD #elif QSPI_DATA_MODE == QSPI_DATA_MODE_DSPI && QSPI_ADDR_SZ == 4 -#define FLASH_READ_CMD DUAL_READ_4B_CMD + #define FLASH_READ_CMD DUAL_READ_4B_CMD #elif QSPI_ADDR_SZ == 4 -#define FLASH_READ_CMD FAST_READ_4B_CMD + #define FLASH_READ_CMD FAST_READ_4B_CMD #elif QSPI_DATA_MODE == QSPI_DATA_MODE_QSPI -#define FLASH_READ_CMD QUAD_READ_CMD -#undef QSPI_DUMMY_READ -#define QSPI_DUMMY_READ 4 -#define QSPI_ADDR_MODE QSPI_DATA_MODE_QSPI + #define FLASH_READ_CMD QUAD_READ_CMD + #undef QSPI_DUMMY_READ + #define QSPI_DUMMY_READ 4 #elif QSPI_DATA_MODE == QSPI_DATA_MODE_DSPI -#define FLASH_READ_CMD DUAL_READ_CMD + #define FLASH_READ_CMD DUAL_READ_CMD #else -#define FLASH_READ_CMD FAST_READ_CMD + #define FLASH_READ_CMD FAST_READ_CMD #endif /* Write Command */ @@ -132,11 +121,6 @@ #define FLASH_WRITE_CMD PAGE_PROG_CMD #endif -/* default to single SPI mode for address */ -#ifndef QSPI_ADDR_MODE -#define QSPI_ADDR_MODE QSPI_DATA_MODE_SPI -#endif - /* forward declarations */ static int qspi_wait_ready(void); @@ -170,7 +154,7 @@ static int qspi_flash_read_id(uint8_t* id, uint32_t idSz) ret = qspi_command_simple(QSPI_MODE_READ, READ_ID_CMD, data, 3); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash ID (ret %d): 0x%02x 0x%02x 0x%02x\n", + wolfBoot_printf("QSPI Flash ID (ret %d): 0x%02x 0x%02x 0x%02x\n", ret, data[0], data[1], data[2]); #endif @@ -193,7 +177,7 @@ static int qspi_write_enable(void) /* send write enable */ ret = qspi_command_simple(QSPI_MODE_WRITE, WRITE_ENABLE_CMD, NULL, 0); #if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 - wolfBoot_printf("Write Enable: Ret %d\n", ret); + wolfBoot_printf("QSPI Write Enable: Ret %d\n", ret); #endif /* wait until write enabled and not busy */ @@ -207,13 +191,13 @@ static int qspi_write_enable(void) } if (timeout >= QSPI_FLASH_READY_TRIES) { #ifdef DEBUG_QSPI - wolfBoot_printf("Flash WE Timeout!\n"); + wolfBoot_printf("QSPI Flash WE Timeout!\n"); #endif return -1; /* timeout */ } #if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 - wolfBoot_printf("Write Enabled: %s\n", + wolfBoot_printf("QSPI Write Enabled: %s\n", (status & FLASH_SR_WRITE_EN) ? "yes" : "no"); #endif @@ -224,7 +208,7 @@ static int qspi_write_disable(void) { int ret = qspi_command_simple(QSPI_MODE_WRITE, WRITE_DISABLE_CMD, NULL, 0); #if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 - wolfBoot_printf("Write Disable: Ret %d\n", ret); + wolfBoot_printf("QSPI Write Disable: Ret %d\n", ret); #endif return ret; } @@ -241,7 +225,7 @@ static int qspi_status(uint8_t* status) ret = qspi_command_simple(QSPI_MODE_READ, READ_SR_CMD, data, 1); #if defined(DEBUG_QSPI) && DEBUG_QSPI > 1 if (status == NULL || last_status != data[0]) { - wolfBoot_printf("Status (ret %d): %02x -> %02x\n", + wolfBoot_printf("QSPI Status (ret %d): %02x -> %02x\n", ret, last_status, data[0]); } last_status = data[0]; @@ -267,7 +251,7 @@ static int qspi_wait_ready(void) } #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Ready Timeout!\n"); + wolfBoot_printf("QSPI Flash Ready Timeout!\n"); #endif return -1; } @@ -278,20 +262,30 @@ static int qspi_quad_enable(void) int ret; uint8_t data[4]; /* size multiple of uint32_t */ +#ifndef QSPI_NO_SR2 + #define QE_SR_READ READ_SR2_CMD + #define QE_SR_BIT FLASH_SR2_QE + #define QE_SR_WRITE WRITE_SR2_CMD +#else + #define QE_SR_READ READ_SR_CMD + #define QE_SR_BIT FLASH_SR_QE + #define QE_SR_WRITE WRITE_SR_CMD +#endif + memset(data, 0, sizeof(data)); - ret = qspi_command_simple(QSPI_MODE_READ, READ_SR2_CMD, data, 1); + ret = qspi_command_simple(QSPI_MODE_READ, QE_SR_READ, data, 1); #ifdef DEBUG_QSPI - wolfBoot_printf("Status Reg 2: Ret %d, 0x%x (Quad Enabled: %s)\n", - ret, data[0], (data[0] & FLASH_SR2_QE) ? "Yes" : "No"); + wolfBoot_printf("Status Reg: Ret %d, 0x%x (Quad Enabled: %s)\n", + ret, data[0], (data[0] & QE_SR_BIT) ? "Yes" : "No"); #endif - if (ret == 0 && (data[0] & FLASH_SR2_QE) == 0) { + if (ret == 0 && (data[0] & QE_SR_BIT) == 0) { ret = qspi_write_enable(); if (ret == 0) { memset(data, 0, sizeof(data)); - data[0] |= FLASH_SR2_QE; - ret = qspi_command_simple(QSPI_MODE_WRITE, WRITE_SR2_CMD, data, 1); + data[0] |= QE_SR_BIT; + ret = qspi_command_simple(QSPI_MODE_WRITE, QE_SR_WRITE, data, 1); #ifdef DEBUG_QSPI - wolfBoot_printf("Setting Quad Enable: Ret %d, SR2 0x%x\n", + wolfBoot_printf("Setting Quad Enable: Ret %d, SR 0x%x\n", ret, data[0]); #endif @@ -310,7 +304,7 @@ static int qspi_enter_4byte_addr(void) if (ret == 0) { ret = qspi_command_simple(QSPI_MODE_WRITE, ENTER_4B_ADDR_MODE_CMD, NULL, 0); #ifdef DEBUG_QSPI - wolfBoot_printf("Enter 4-byte address mode: Ret %d\n", ret); + wolfBoot_printf("QSPI: Enter 4-byte address mode: Ret %d\n", ret); #endif if (ret == 0) { ret = qspi_wait_ready(); /* Wait for not busy */ @@ -325,7 +319,7 @@ static int qspi_exit_4byte_addr(void) if (ret == 0) { ret = qspi_command_simple(QSPI_MODE_WRITE, EXIT_4B_ADDR_MODE_CMD, NULL, 0); #ifdef DEBUG_QSPI - wolfBoot_printf("Enter 4-byte address mode: Ret %d\n", ret); + wolfBoot_printf("QSPI: Enter 4-byte address mode: Ret %d\n", ret); #endif if (ret == 0) { ret = qspi_wait_ready(); /* Wait for not busy */ @@ -350,7 +344,9 @@ uint16_t spi_flash_probe(void) #endif #ifdef TEST_EXT_FLASH - test_ext_flash(); + if (test_ext_flash() < 0) { + wolfBoot_printf("QSPI flash test failed!\n"); + } #endif return 0; } @@ -372,7 +368,7 @@ int spi_flash_sector_erase(uint32_t address) NULL, 0, QSPI_DATA_MODE_NONE /* Data */ ); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Erase: Ret %d, Address 0x%x\n", ret, address); + wolfBoot_printf("QSPI Flash Erase: Ret %d, Address 0x%x\n", ret, address); #endif if (ret == 0) { ret = qspi_wait_ready(); /* Wait for not busy */ @@ -397,7 +393,7 @@ int spi_flash_read(uint32_t address, void *data, int len) if (address > FLASH_DEVICE_SIZE) { #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Read: Invalid address (0x%x > 0x%x max)\n", + wolfBoot_printf("QSPI Flash Read: Invalid address (0x%x > 0x%x max)\n", address, FLASH_DEVICE_SIZE); #endif return -1; @@ -412,8 +408,8 @@ int spi_flash_read(uint32_t address, void *data, int len) ); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Read: Ret %d, Address 0x%x, Len %d, Cmd 0x%x\n", - ret, address, len, FLASH_READ_CMD); + wolfBoot_printf("QSPI Flash Read: Ret %d, Cmd 0x%x, Len %d , 0x%x -> %p\n", + ret, FLASH_READ_CMD, len, address, data); #endif /* external flash read expects length returned */ @@ -431,23 +427,25 @@ int spi_flash_write(uint32_t address, const void *data, int len) for (page = 0; page < pages; page++) { ret = qspi_write_enable(); if (ret == 0) { + uint8_t* ptr; xferSz = len; if (xferSz > FLASH_PAGE_SIZE) xferSz = FLASH_PAGE_SIZE; addr = address + (page * FLASH_PAGE_SIZE); + ptr = ((uint8_t*)data + (page * FLASH_PAGE_SIZE)); /* ------ Write Flash (page at a time) ------ */ ret = qspi_transfer(QSPI_MODE_WRITE, FLASH_WRITE_CMD, addr, QSPI_ADDR_SZ, QSPI_DATA_MODE_SPI, /* Address */ 0, 0, QSPI_DATA_MODE_NONE, /* Alternate Bytes */ 0, /* Dummy */ - ((uint8_t*)data + (page * FLASH_PAGE_SIZE)), + ptr, /* Destination Ptr */ xferSz, QSPI_DATA_MODE /* Data */ ); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash Write: Ret %d, Addr 0x%x, Len %d, Cmd 0x%x\n", - ret, addr, xferSz, FLASH_WRITE_CMD); + wolfBoot_printf("QSPI Flash Write: Ret %d, Cmd 0x%x, Len %d , 0x%x -> %p\n", + ret, FLASH_WRITE_CMD, xferSz, address, ptr); #endif if (ret != 0) break; @@ -475,11 +473,12 @@ void spi_flash_release(void) #endif /* QSPI_FLASH || OCTOSPI_FLASH */ +/* Test for external QSPI flash */ #ifdef TEST_EXT_FLASH #ifndef TEST_EXT_ADDRESS /* Start Address for test - 2MB */ - #define TEST_EXT_ADDRESS (2 * 1024 * 1024) + #define TEST_EXT_ADDRESS (2UL * 1024UL * 1024UL) #endif static int test_ext_flash(void) @@ -489,6 +488,8 @@ static int test_ext_flash(void) uint8_t pageData[FLASH_PAGE_SIZE]; uint32_t wait = 0; + wolfBoot_printf("QSPI Flash Test at 0x%x\n", TEST_EXT_ADDRESS); + #ifndef TEST_FLASH_READONLY /* Erase sector */ ret = ext_flash_erase(TEST_EXT_ADDRESS, FLASH_SECTOR_SIZE); @@ -507,7 +508,6 @@ static int test_ext_flash(void) ret = ext_flash_read(TEST_EXT_ADDRESS, pageData, sizeof(pageData)); wolfBoot_printf("Page Read: Ret %d\n", ret); - wolfBoot_printf("Checking...\n"); /* Check data */ for (i=0; i 1 @@ -515,11 +515,11 @@ static int test_ext_flash(void) #endif if (pageData[i] != (i & 0xff)) { wolfBoot_printf("Check Data @ %d failed\n", i); - return -1; + return -i; } } - wolfBoot_printf("Flash Test Passed\n"); + wolfBoot_printf("QSPI Flash Test Passed\n"); return ret; } #endif /* TEST_EXT_FLASH */ diff --git a/src/string.c b/src/string.c index 0eeae87c6d..d8de8178c7 100644 --- a/src/string.c +++ b/src/string.c @@ -294,22 +294,33 @@ void *memmove(void *dst, const void *src, size_t n) #endif /* WOLFBOOT_USE_STDLIBC */ #if defined(PRINTF_ENABLED) && defined(DEBUG_UART) -void uart_writenum(int num, int base) +void uart_writenum(int num, int base, int zeropad, int maxdigits) { int i = 0; char buf[sizeof(int)*2+1]; const char* kDigitLut = "0123456789ABCDEF"; unsigned int val = (unsigned int)num; int sz = 0; + if (maxdigits == 0) + maxdigits = 8; + if (maxdigits > (int)sizeof(buf)) + maxdigits = (int)sizeof(buf); + memset(buf, 0, sizeof(buf)); if (base == 10 && num < 0) { /* handle negative */ buf[i++] = '-'; val = -num; } + if (zeropad) { + memset(&buf[i], '0', maxdigits); + } do { buf[sizeof(buf)-sz-1] = kDigitLut[(val % base)]; sz++; val /= base; } while (val > 0U); + if (zeropad && sz < maxdigits) { + i += maxdigits-sz; + } memmove(&buf[i], &buf[sizeof(buf)-sz], sz); i+=sz; uart_write(buf, i); @@ -318,6 +329,7 @@ void uart_writenum(int num, int base) void uart_vprintf(const char* fmt, va_list argp) { char* fmtp = (char*)fmt; + int zeropad, maxdigits; while (fmtp != NULL && *fmtp != '\0') { /* print non formatting characters */ if (*fmtp != '%') { @@ -327,9 +339,15 @@ void uart_vprintf(const char* fmt, va_list argp) fmtp++; /* skip % */ /* find formatters */ + zeropad = maxdigits = 0; while (*fmtp != '\0') { if (*fmtp >= '0' && *fmtp <= '9') { - /* length formatter - skip */ + /* length formatter */ + if (*fmtp == '0') { + zeropad = 1; + } + maxdigits <<= 8; + maxdigits += (*fmtp - '0'); fmtp++; } else if (*fmtp == 'l') { @@ -354,7 +372,7 @@ void uart_vprintf(const char* fmt, va_list argp) case 'd': { int n = (int)va_arg(argp, int); - uart_writenum(n, 10); + uart_writenum(n, 10, zeropad, maxdigits); break; } case 'p': @@ -363,7 +381,7 @@ void uart_vprintf(const char* fmt, va_list argp) case 'x': { int n = (int)va_arg(argp, int); - uart_writenum(n, 16); + uart_writenum(n, 16, zeropad, maxdigits); break; } case 's': diff --git a/test-app/ARM-nrf5340_net.ld b/test-app/ARM-nrf5340_net.ld new file mode 100644 index 0000000000..44a862e52c --- /dev/null +++ b/test-app/ARM-nrf5340_net.ld @@ -0,0 +1,57 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ + RAM (rwx) : ORIGIN = 0x21000000, LENGTH = 16K /* Run in lowmem */ +} + +SECTIONS +{ + .text : + { + _start_text = .; + KEEP(*(.isr_vector)) + *(.init) + *(.fini) + *(.text*) + KEEP(*(.rodata*)) + . = ALIGN(4); + _end_text = .; + } > FLASH + + .ARM : + { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } > FLASH + + _stored_data = .; + + .data : AT (_stored_data) + { + _start_data = .; + KEEP(*(.data*)) + . = ALIGN(4); + KEEP(*(.ramcode)) + . = ALIGN(4); + _end_data = .; + } > RAM + + .bss : + { + _start_bss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _end_bss = .; + _end = .; + } > RAM +} + +_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@; + +PROVIDE(_start_heap = _end); +PROVIDE(_end_stack = ORIGIN(RAM) + LENGTH(RAM)); diff --git a/test-app/Makefile b/test-app/Makefile index 47b8acae29..4b05adc94f 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -118,7 +118,6 @@ endif ifeq ($(ARCH),ARM) APP_OBJS+=startup_arm.o - CFLAGS+=-DSTM32 endif ifeq ($(ARCH),ARM_BE) APP_OBJS+=startup_arm.o @@ -132,6 +131,7 @@ endif ENTRY_POINT=`cat .entry-point-address` LSCRIPT:=../config/target-app.ld LSCRIPT_TEMPLATE:=$(ARCH).ld + ifeq ($(TARGET),stm32f7) LSCRIPT_TEMPLATE=ARM-stm32f7.ld CFLAGS+=-DDUALBANK_SWAP @@ -210,6 +210,10 @@ ifeq ($(TARGET),stm32u5) LDFLAGS+=-mcpu=cortex-m33 endif +ifeq ($(TARGET),nrf5340_net) + LSCRIPT_TEMPLATE=ARM-nrf5340_net.ld +endif + ifeq ($(TARGET),ti_hercules) LSCRIPT_TEMPLATE=ARM-r5be.ld # Override linker flags diff --git a/test-app/app_nrf52.c b/test-app/app_nrf52.c index 67fc20b250..ad7c60b8e2 100644 --- a/test-app/app_nrf52.c +++ b/test-app/app_nrf52.c @@ -23,26 +23,8 @@ #include #include #include "wolfboot/wolfboot.h" - - -#define GPIO_BASE (0x50000000) -#define GPIO_OUT *((volatile uint32_t *)(GPIO_BASE + 0x504)) -#define GPIO_OUTSET *((volatile uint32_t *)(GPIO_BASE + 0x508)) -#define GPIO_OUTCLR *((volatile uint32_t *)(GPIO_BASE + 0x50C)) -#define GPIO_PIN_CNF ((volatile uint32_t *)(GPIO_BASE + 0x700)) // Array - - -#define BAUD_115200 0x01D7E000 - -#define UART0_BASE (0x40002000) -#define UART0_TASK_STARTTX *((volatile uint32_t *)(UART0_BASE + 0x008)) -#define UART0_TASK_STOPTX *((volatile uint32_t *)(UART0_BASE + 0x00C)) -#define UART0_EVENT_ENDTX *((volatile uint32_t *)(UART0_BASE + 0x120)) -#define UART0_ENABLE *((volatile uint32_t *)(UART0_BASE + 0x500)) -#define UART0_TXD_PTR *((volatile uint32_t *)(UART0_BASE + 0x544)) -#define UART0_TXD_MAXCOUNT *((volatile uint32_t *)(UART0_BASE + 0x548)) -#define UART0_BAUDRATE *((volatile uint32_t *)(UART0_BASE + 0x524)) - +#include "hal/nrf52.h" +#include "printf.h" static const char extradata[1024 * 16] = "hi!"; @@ -53,26 +35,7 @@ static void gpiotoggle(uint32_t pin) GPIO_OUTSET = (~reg_val) & (1 << pin); } - -void uart_init(void) -{ - UART0_BAUDRATE = BAUD_115200; - UART0_ENABLE = 1; - -} - -void uart_write(char c) -{ - UART0_EVENT_ENDTX = 0; - - UART0_TXD_PTR = (uint32_t)(&c); - UART0_TXD_MAXCOUNT = 1; - UART0_TASK_STARTTX = 1; - while(UART0_EVENT_ENDTX == 0) - ; -} - -static const char START='*'; +static const char* START="*"; void main(void) { //uint32_t pin = 19; @@ -86,13 +49,13 @@ void main(void) version = wolfBoot_current_firmware_version(); uart_init(); - uart_write(START); + uart_write(START, 1); for (i = 3; i >= 0; i--) { - uart_write(v_array[i]); + uart_write((const char*)&v_array[i], 1); } - while(1) { + while (1) { gpiotoggle(pin); - for (i = 0; i < 800000; i++) // Wait a bit. + for (i = 0; i < 800000; i++) /* Wait a bit. */ asm volatile ("nop"); } } diff --git a/test-app/app_nrf5340.c b/test-app/app_nrf5340.c new file mode 100644 index 0000000000..e20183441c --- /dev/null +++ b/test-app/app_nrf5340.c @@ -0,0 +1,70 @@ +/* nrf5340.c + * + * Copyright (C) 2024 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 +#include +#include "wolfboot/wolfboot.h" +#include "hal/nrf5340.h" +#include "printf.h" + +void gpiotoggle(uint32_t port, uint32_t pin) +{ + uint32_t reg_val = GPIO_OUT(port); + GPIO_OUTCLR(port) = reg_val & (1 << pin); + GPIO_OUTSET(port) = (~reg_val) & (1 << pin); +} + +void main(void) +{ + int i; + /* nRF5340-DK LEDs: + * LED1 P0.28 + * LED2 P0.29 + * LED3 P0.30 + * LED4 P0.31 */ + uint32_t port = 0; + uint32_t pin = 28; + uint32_t app_version; + + GPIO_PIN_CNF(port, pin) = 1; /* Output */ + + app_version = wolfBoot_current_firmware_version(); + + uart_init(); + + wolfBoot_printf("========================\n"); + wolfBoot_printf("nRF5340 wolfBoot (app core)\n"); + wolfBoot_printf("Copyright 2024 wolfSSL Inc\n"); + wolfBoot_printf("GPL v3\n"); + wolfBoot_printf("Version : 0x%lx\r\n", app_version); + wolfBoot_printf("========================\n"); + + /* mark boot successful */ + wolfBoot_success(); + + /* Toggle LED loop */ + while (1) { + gpiotoggle(port, pin); + + sleep_us(100 * 1000); + } +} diff --git a/test-app/app_nrf5340_net.c b/test-app/app_nrf5340_net.c new file mode 100644 index 0000000000..2a6605a6e5 --- /dev/null +++ b/test-app/app_nrf5340_net.c @@ -0,0 +1,70 @@ +/* nrf5340.c + * + * Copyright (C) 2024 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 +#include +#include "wolfboot/wolfboot.h" +#include "hal/nrf5340.h" +#include "printf.h" + +void gpiotoggle(uint32_t port, uint32_t pin) +{ + uint32_t reg_val = GPIO_OUT(port); + GPIO_OUTCLR(port) = reg_val & (1 << pin); + GPIO_OUTSET(port) = (~reg_val) & (1 << pin); +} + +void main(void) +{ + int i; + /* nRF5340-DK LEDs: + * LED1 P0.28 + * LED2 P0.29 + * LED3 P0.30 + * LED4 P0.31 */ + uint32_t port = 0; + uint32_t pin = 28; + uint32_t app_version; + + GPIO_PIN_CNF(port, pin) = 1; /* Output */ + + app_version = wolfBoot_current_firmware_version(); + + uart_init(); + + wolfBoot_printf("========================\n"); + wolfBoot_printf("nRF5340 wolfBoot (net core)\n"); + wolfBoot_printf("Copyright 2024 wolfSSL Inc\n"); + wolfBoot_printf("GPL v3\n"); + wolfBoot_printf("Version : 0x%lx\r\n", app_version); + wolfBoot_printf("========================\n"); + + /* mark boot successful */ + wolfBoot_success(); + + /* Toggle LED loop */ + while (1) { + gpiotoggle(port, pin); + + sleep_us(100 * 1000); + } +} diff --git a/test-app/startup_arm.c b/test-app/startup_arm.c index cb122867bb..68d41adf69 100644 --- a/test-app/startup_arm.c +++ b/test-app/startup_arm.c @@ -29,7 +29,7 @@ extern unsigned int _end_bss; extern unsigned int _end_stack; extern unsigned int _start_heap; -#ifdef STM32 +#ifdef TARGET_stm32f4 extern void isr_tim2(void); #endif diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh new file mode 100755 index 0000000000..7fdbcf1477 --- /dev/null +++ b/tools/scripts/nrf5340/build_flash.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# run from wolfBoot root +# ./tools/scripts/nrf5340/build_flash.sh + +rm -f ./tools/scripts/nrf5340/*.bin +rm -f ./tools/scripts/nrf5340/*.hex + +# Build internal flash images for both cores + +# Build net +cp config/examples/nrf5340_net.config .config +make clean +make DEBUG=1 +cp factory.bin tools/scripts/nrf5340/factory_net.bin +# Sign flash update for testing (use partition type 2 for network update) +tools/keytools/sign --ecc256 --id 2 test-app/image.bin wolfboot_signing_private_key.der 2 +cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_net.bin + +# Build app +cp config/examples/nrf5340.config .config +make clean +make DEBUG=1 +cp factory.bin tools/scripts/nrf5340/factory_app.bin +# Sign flash update for testing +tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 2 +cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_app.bin + +# Convert to HEX format for programmer tool +arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x00000000 tools/scripts/nrf5340/factory_app.bin tools/scripts/nrf5340/factory_app.hex +arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x01000000 tools/scripts/nrf5340/factory_net.bin tools/scripts/nrf5340/factory_net.hex + +arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/image_v2_signed_app.bin tools/scripts/nrf5340/image_v2_signed_app.hex +arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10100000 tools/scripts/nrf5340/image_v2_signed_net.bin tools/scripts/nrf5340/image_v2_signed_net.hex + +# Program Internal Flash +#nrfjprog -f nrf53 --recover +#nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_app.hex --verify +#nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_net.hex --verify --coprocessor CP_NETWORK +JLinkExe -CommandFile tools/scripts/nrf5340/flash_net.jlink +JLinkExe -CommandFile tools/scripts/nrf5340/flash_app.jlink + +# Program external flash +nrfjprog -f nrf53 --qspieraseall +nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_app.hex --verify +nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_net.hex --verify diff --git a/tools/scripts/nrf5340/flash_app.jlink b/tools/scripts/nrf5340/flash_app.jlink new file mode 100644 index 0000000000..2194fbff2c --- /dev/null +++ b/tools/scripts/nrf5340/flash_app.jlink @@ -0,0 +1,7 @@ +device nRF5340_xxAA_APP +si SWD +speed 4000 +jtagconf -1,-1 +connect +loadbin tools/scripts/nrf5340/factory_app.bin 0x0 +quit diff --git a/tools/scripts/nrf5340/flash_net.jlink b/tools/scripts/nrf5340/flash_net.jlink new file mode 100644 index 0000000000..2c41207a48 --- /dev/null +++ b/tools/scripts/nrf5340/flash_net.jlink @@ -0,0 +1,7 @@ +device nRF5340_xxAA_NET +si SWD +speed 4000 +jtagconf -1,-1 +connect +loadbin tools/scripts/nrf5340/factory_net.bin 0x01000000 +quit From d45ec98bb366cad0b84464f65ecd63472b2d2f29 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 27 Sep 2024 12:49:29 -0700 Subject: [PATCH 02/19] Improve network core firmware update. --- config/examples/nrf5340_net.config | 2 +- hal/nrf5340.c | 203 ++++++++++++++++----------- include/image.h | 12 +- src/image.c | 16 ++- tools/scripts/nrf5340/build_flash.sh | 19 ++- 5 files changed, 152 insertions(+), 100 deletions(-) diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config index 821033eea5..81010a008c 100644 --- a/config/examples/nrf5340_net.config +++ b/config/examples/nrf5340_net.config @@ -17,7 +17,7 @@ RAM_CODE?=1 DUALBANK_SWAP?=0 FLAGS_HOME=0 -DISABLE_BACKUP=0 +DISABLE_BACKUP=1 EXT_FLASH?=0 SPI_FLASH?=0 QSPI_FLASH?=0 diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 41f12720bf..5030b2967c 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -51,18 +51,17 @@ static int test_flash(void); #define PART_NET_ADDR 0x100000UL #endif -/* Shared Memory between network and application cores */ +/* SHM: Shared Memory between network and application cores */ /* first 64KB (0x10000) is used by wolfBoot and limited in nrf5340.ld */ #ifndef SHARED_MEM_ADDR #define SHARED_MEM_ADDR (0x20000000UL + (64 * 1024)) - #define SHARED_MEM_SIZE (256 * 1024) /* enable access to full 256KB for entire network update image */ #endif -/* Shared memory states */ +/* Shared memory states (mask, easier to check) */ #define SHARED_STATUS_UNKNOWN 0 #define SHARED_STATUS_READY 1 #define SHARED_STATUS_UPDATE_START 2 -#define SHARED_STATUS_UPDATE_DONE 3 -#define SHARED_STATUS_DO_BOOT 4 +#define SHARED_STATUS_UPDATE_DONE 4 +#define SHARED_STATUS_DO_BOOT 8 #define SHAREM_MEM_MAGIC 0x5753484D /* WSHM */ @@ -78,11 +77,12 @@ typedef struct { ShmInfo_t app; /* application core write location */ /* application places firmware here */ - uint8_t data[0]; + uint8_t data[FLASH_SIZE_NET]; } SharedMem_t; static SharedMem_t* shm = (SharedMem_t*)SHARED_MEM_ADDR; +/* UART */ #ifdef DEBUG_UART #ifndef UART_SEL #define UART_SEL 0 /* select UART 0 or 1 */ @@ -280,24 +280,77 @@ void hal_net_core(int hold) /* 1=hold, 0=release */ } #endif +static uint8_t* get_image_hdr(struct wolfBoot_image* img) +{ +#ifdef EXT_FLASH + return img->hdr_cache; +#else + return img->hdr; +#endif +} +static uint16_t get_image_partition_id(struct wolfBoot_image* img) +{ + return wolfBoot_get_blob_type(get_image_hdr(img)) & HDR_IMG_TYPE_PART_MASK; +} + #define IMAGE_IS_NET_CORE(img) ( \ - (img->type & HDR_IMG_TYPE_PART_MASK) == PART_NET_ID && \ - img->fw_size < FLASH_SIZE_NET) -static int hal_net_get_image(struct wolfBoot_image* img) + (get_image_partition_id(img) == PART_NET_ID) && \ + (img->fw_size < (FLASH_SIZE_NET - IMAGE_HEADER_SIZE))) +static int hal_net_get_image(struct wolfBoot_image* img, ShmInfo_t* info) { + int ret; +#ifdef TARGET_nrf5340_app /* check the update partition for a network core update */ - int ret = wolfBoot_open_image(img, PART_UPDATE); - if (ret == 0 && IMAGE_IS_NET_CORE(img)) { - return 0; + ret = wolfBoot_open_image(img, PART_UPDATE); + if (ret == 0 && !IMAGE_IS_NET_CORE(img)) { + ret = -1; } /* if external flash is enabled, try an alternate location */ -#ifdef EXT_FLASH - ret = wolfBoot_open_image_external(img, PART_UPDATE, PART_NET_ADDR); - if (ret == 0 && IMAGE_IS_NET_CORE(img)) { - return 0; + #ifdef EXT_FLASH + if (ret != 0) { + ret = wolfBoot_open_image_external(img, PART_UPDATE, + (uint8_t*)PART_NET_ADDR); + if (ret == 0 && !IMAGE_IS_NET_CORE(img)) { + ret = -1; + } } -#endif - return (ret != 0) ? ret : -1; + #endif +#else /* TARGET_nrf5340_net */ + ret = wolfBoot_open_image(img, PART_BOOT); +#endif /* TARGET_nrf5340_* */ + if (ret == 0) { + info->version = wolfBoot_get_blob_version(get_image_hdr(img)); + info->size = img->fw_size; + wolfBoot_printf("Network Image: Ver 0x%x, Size %d\n", + info->version, info->size); + } + else { + info->version = 0; /* not known */ + wolfBoot_printf("Network Image: Update not found\n"); + } + return ret; +} + +static void hal_shm_status_set(ShmInfo_t* info, uint32_t status) +{ + info->magic = SHAREM_MEM_MAGIC; + info->status = status; +} + +static int hal_shm_status_wait(ShmInfo_t* info, uint32_t status, + uint32_t timeout_us) +{ + int ret = 0; + uint32_t timeout = timeout_us; + while ((info->magic != SHAREM_MEM_MAGIC || (info->status & status) == 0) + && --timeout > 0) { + sleep_us(1); + }; + if (timeout == 0) { + wolfBoot_printf("Timeout: status 0x%x\n", status); + ret = -1; /* timeout */ + } + return ret; } static void hal_net_check_version(void) @@ -308,65 +361,49 @@ static void hal_net_check_version(void) #ifdef TARGET_nrf5340_app /* check the network core version */ - ret = hal_net_get_image(&img); - if (ret == 0) { - shm->app.version = img.fw_ver; - shm->app.size = img.fw_size; - wolfBoot_printf("Network: Ver 0x%x, Size %d\n", - shm->app.version, shm->app.size); - } - else { - wolfBoot_printf("Failed finding net core update on ext flash 0x%x\n", - PART_NET_ADDR); - } - shm->app.magic = SHAREM_MEM_MAGIC; - shm->app.status = SHARED_STATUS_READY; + hal_net_get_image(&img, &shm->app); + hal_shm_status_set(&shm->app, SHARED_STATUS_READY); /* release network core - issue boot command */ hal_net_core(0); /* wait for ready status from network core */ - timeout = 1000000; - while (shm->net.magic != SHAREM_MEM_MAGIC && - shm->net.status != SHARED_STATUS_READY && - --timeout > 0) { - /* wait */ - }; - if (timeout == 0) { - wolfBoot_printf("Timeout: network core ready!\n"); - } + ret = hal_shm_status_wait(&shm->net, SHARED_STATUS_READY, 1000000); /* check if network core can continue booting or needs to wait for update */ - if (shm->app.version == shm->net.version) { - shm->app.status = SHARED_STATUS_DO_BOOT; - } -#else /* net */ - ret = wolfBoot_open_image(&img, PART_BOOT); - if (ret == 0) { - shm->net.version = img.fw_ver; - shm->net.size = img.fw_size; - wolfBoot_printf("Network: Ver 0x%x, Size %d\n", - shm->net.version, shm->net.size); + if (ret != 0 || shm->app.version <= shm->net.version) { + wolfBoot_printf("Network Core: Releasing for boot\n"); + hal_shm_status_set(&shm->app, SHARED_STATUS_DO_BOOT); } else { - wolfBoot_printf("Error getting boot partition info\n"); + wolfBoot_printf("Network Core: Holding for update\n"); } - shm->net.magic = SHAREM_MEM_MAGIC; - shm->net.status = SHARED_STATUS_READY; - - wolfBoot_printf("Network version: 0x%x\n", shm->net.version); - - /* wait for do_boot or update */ - timeout = 1000000; - while (shm->app.magic == SHAREM_MEM_MAGIC && - shm->app.status == SHARED_STATUS_READY && - --timeout > 0) { - /* wait */ - }; - if (timeout == 0) { - wolfBoot_printf("Timeout: app core boot signal!\n"); +#else /* TARGET_nrf5340_net */ + hal_net_get_image(&img, &shm->net); + hal_shm_status_set(&shm->net, SHARED_STATUS_READY); + + /* wait for do_boot or update from app core */ + ret = hal_shm_status_wait(&shm->app, + (SHARED_STATUS_UPDATE_START | SHARED_STATUS_DO_BOOT), 1000000); + /* are we updating? */ + if (ret == 0 && shm->app.status == SHARED_STATUS_UPDATE_START) { + wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", + shm->net.version, shm->app.version, shm->net.size, shm->net.size); + /* Erase network core boot flash */ + wb_flash_erase(&img, 0, WOLFBOOT_PARTITION_SIZE); + /* Write new firmware to internal flash */ + wb_flash_write(&img, 0, shm->data, shm->app.size); + + /* Reopen image and refresh information */ + wolfBoot_open_image(&img, PART_BOOT); + wolfBoot_printf("Network version (after update): 0x%x\n", + shm->net.version); + hal_net_get_image(&img, &shm->net); + hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); + + /* continue booting */ } -#endif +#endif /* TARGET_nrf5340_* */ exit: wolfBoot_printf("Status: App %d (ver %d), Net %d (ver %d)\n", shm->app.status, shm->app.version, shm->net.status, shm->net.version); @@ -380,28 +417,32 @@ void hal_net_check_update(void) struct wolfBoot_image img; /* handle update for network core */ - ret = hal_net_get_image(&img); - if (ret == 0 && img.fw_ver > shm->net.version) { + ret = hal_net_get_image(&img, &shm->app); + if (ret == 0 && shm->app.version > shm->net.version) { + wolfBoot_printf("Found Network Core update: Ver %d->%d, Size %d->%d\n", + shm->net.version, shm->app.version, shm->net.size, shm->net.size); + /* validate the update is valid */ if (wolfBoot_verify_integrity(&img) == 0 && wolfBoot_verify_authenticity(&img) == 0) { - /* relocate image to ram */ - ret = spi_flash_read(PART_NET_ADDR, shm->data, img.fw_size); + uint32_t fw_size = IMAGE_HEADER_SIZE + img.fw_size; + wolfBoot_printf("Network image valid, loading into shared mem\n"); + /* relocate image to shared ram */ + #ifdef EXT_FLASH + ret = ext_flash_read(PART_NET_ADDR, shm->data, fw_size); + #else + memcpy(shm->data, img.hdr, fw_size); + #endif if (ret >= 0) { /* signal network core to do update */ - shm->app.status = SHARED_STATUS_UPDATE_START; + hal_shm_status_set(&shm->app, SHARED_STATUS_UPDATE_START); /* wait for update_done */ - timeout = 1000000; - while (shm->net.magic == SHAREM_MEM_MAGIC && - shm->net.status < SHARED_STATUS_UPDATE_DONE && - --timeout > 0) { - sleep_us(1); - }; - if (timeout == 0) { - wolfBoot_printf("Timeout: net core update done!\n"); - } + ret = hal_shm_status_wait(&shm->net, + SHARED_STATUS_UPDATE_DONE, 1000000); + if (ret == 0) + wolfBoot_printf("Network core firmware update sent\n"); } } else { @@ -410,7 +451,7 @@ void hal_net_check_update(void) } } /* inform network core to boot */ - shm->app.status = SHARED_STATUS_DO_BOOT; + hal_shm_status_set(&shm->app, SHARED_STATUS_DO_BOOT); } #endif diff --git a/include/image.h b/include/image.h index 61c7f54a22..952df6daf1 100644 --- a/include/image.h +++ b/include/image.h @@ -93,12 +93,13 @@ int wolfBot_get_dts_size(void *dts_addr); struct wolfBoot_image { uint8_t *hdr; +#ifdef EXT_FLASH + uint8_t *hdr_cache; +#endif uint8_t *trailer; uint8_t *sha_hash; uint8_t *fw_base; uint32_t fw_size; - uint32_t fw_ver; - uint32_t type; uint32_t part; uint32_t hdr_ok; uint32_t canary_FEED4567; @@ -512,12 +513,13 @@ static void __attribute__((noinline)) wolfBoot_image_confirm_signature_ok( struct wolfBoot_image { uint8_t *hdr; +#ifdef EXT_FLASH + uint8_t *hdr_cache; +#endif uint8_t *trailer; uint8_t *sha_hash; uint8_t *fw_base; uint32_t fw_size; - uint32_t fw_ver; - uint16_t type; uint8_t part; uint8_t hdr_ok : 1; uint8_t signature_ok : 1; @@ -567,7 +569,7 @@ static void wolfBoot_image_confirm_signature_ok(struct wolfBoot_image *img) /* Defined in image.c */ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part); #ifdef EXT_FLASH -int wolfBoot_open_image_external(struct wolfBoot_image* img, uint8_t part, uint32_t addr); +int wolfBoot_open_image_external(struct wolfBoot_image* img, uint8_t part, uint8_t* addr); #endif int wolfBoot_open_image_address(struct wolfBoot_image* img, uint8_t* image); int wolfBoot_verify_integrity(struct wolfBoot_image *img); diff --git a/src/image.c b/src/image.c index 02b6f9ca03..08c178d8e2 100644 --- a/src/image.c +++ b/src/image.c @@ -881,12 +881,15 @@ int wolfBoot_open_image_address(struct wolfBoot_image *img, uint8_t *image) #endif img->hdr_ok = 1; img->fw_base = img->hdr + IMAGE_HEADER_SIZE; - img->fw_ver = wolfBoot_get_blob_version(image); - img->type = wolfBoot_get_blob_type(image); +#ifdef EXT_FLASH + img->hdr_cache = image; +#endif wolfBoot_printf("%s partition: %p (sz %d, ver 0x%x, type 0x%d)\n", (img->part == PART_BOOT) ? "Boot" : "Update", - img->hdr, (unsigned int)img->fw_size, img->fw_ver, img->type); + img->hdr, (unsigned int)img->fw_size, + wolfBoot_get_blob_version(image), + wolfBoot_get_blob_type(image)); return 0; } @@ -992,16 +995,15 @@ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part) #ifdef EXT_FLASH int wolfBoot_open_image_external(struct wolfBoot_image* img, uint8_t part, - uint32_t addr) + uint8_t* addr) { - uint8_t *image; - + uint8_t* image; if (img == NULL) return -1; memset(img, 0, sizeof(struct wolfBoot_image)); img->part = part; - img->hdr = (void*)addr; + img->hdr = addr; img->hdr_ok = 1; hdr_cpy_done = 0; /* reset hdr "open" flag */ image = fetch_hdr_cpy(img); diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index 7fdbcf1477..0f0327db58 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -1,5 +1,7 @@ #!/bin/bash +# nRF5340 dual core: Creates internal and external flash images for testing + # run from wolfBoot root # ./tools/scripts/nrf5340/build_flash.sh @@ -33,14 +35,19 @@ arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x01000000 tools/scri arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/image_v2_signed_app.bin tools/scripts/nrf5340/image_v2_signed_app.hex arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10100000 tools/scripts/nrf5340/image_v2_signed_net.bin tools/scripts/nrf5340/image_v2_signed_net.hex + +if [ "$1" == "erase" ]; then + nrfjprog -f nrf53 --recover + nrfjprog -f nrf53 --qspieraseall +fi + +# Program external flash +nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_app.hex --verify +nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_net.hex --verify + + # Program Internal Flash -#nrfjprog -f nrf53 --recover #nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_app.hex --verify #nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_net.hex --verify --coprocessor CP_NETWORK JLinkExe -CommandFile tools/scripts/nrf5340/flash_net.jlink JLinkExe -CommandFile tools/scripts/nrf5340/flash_app.jlink - -# Program external flash -nrfjprog -f nrf53 --qspieraseall -nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_app.hex --verify -nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_net.hex --verify From 680b9b410031db65c8833c174af292d7bf8f4eb7 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 27 Sep 2024 15:28:16 -0700 Subject: [PATCH 03/19] Fixes for properly functioning network core updates. --- docs/Targets.md | 63 ++++++++++++++++++++++++++++++++-------------- hal/nrf5340.c | 55 ++++++++++++++++++++++------------------ include/spi_drv.h | 2 +- src/image.c | 2 +- src/update_flash.c | 13 +++++----- 5 files changed, 82 insertions(+), 53 deletions(-) diff --git a/docs/Targets.md b/docs/Targets.md index 304166f2e7..30ad290ab3 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -2202,18 +2202,33 @@ QSPI Freq=24MHz (Div Clk=3/Sck=1), Addr=24-bits, PageSz=256 QSPI Activate QSPI Flash ID (ret 0): 0xC2 0x28 0x17 Status Reg: Ret 0, 0x40 (Quad Enabled: Yes) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x2000022C -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x2000022C -Boot partition: 0xC000 (size 7428, version 0x1) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x20000128 -Update partition: 0x0 (size 7428, version 0x2) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x2000022C -Boot partition: 0xC000 (size 7428, version 0x1) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x2000012C +Update partition: 0x0 (sz 7864, ver 0x2, type 0x201) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x100000 -> 0x2000012C +Update partition: 0x100000 (sz 5780, ver 0x2, type 0x202) +Network Image: Ver 0x2, Size 5780 +Network Core: Holding for update +Status: App 1 (ver 2), Net 1 (ver 1) +QSPI Flash ID (ret 0): 0xC2 0x28 0x17 +Status Reg: Ret 0, 0x40 (Quad Enabled: Yes) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x20000230 +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x20000230 +Boot partition: 0xC000 (sz 7864, ver 0x1, type 0x201) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x2000012C +Update partition: 0x0 (sz 7864, ver 0x2, type 0x201) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x20000230 +Boot partition: 0xC000 (sz 7864, ver 0x1, type 0x201) Booting version: 0x1 -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x100000 -> 0x20000128 -Update partition: 0x100000 (size 5492, version 0x2) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x20000230 -Network version: 0x2 +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x2000012C +Update partition: 0x0 (sz 7864, ver 0x2, type 0x201) +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x100000 -> 0x2000012C +Update partition: 0x100000 (sz 5780, ver 0x2, type 0x202) +Network Image: Ver 0x2, Size 5780 +Found Network Core update: Ver 1->2, Size 6036->6036 +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x101700 -> 0x2000002C +Network image valid, loading into shared mem +QSPI Flash Read: Ret 0, Cmd 0xEB, Len 6036 , 0x100000 -> 0x20010020 +Network core firmware update done ======================== nRF5340 wolfBoot (app core) Copyright 2024 wolfSSL Inc @@ -2228,15 +2243,25 @@ Network Core: ``` wolfBoot HAL Init (net core) -Boot partition: 0x100C000 (size 5492, version 0x1) -Update partition: 0x100C000 (size 5492, version 0x1) -Boot partition: 0x100C000 (size 5492, version 0x1) -Booting version: 0x1 +Boot partition: 0x100C000 (sz 5780, ver 0x1, type 0x201) +Network Image: Ver 0x1, Size 5780 +Starting update: Ver 1->2, Size 6036->6036 +Internal Flash Erase: addr 0x100C000, len 6036 +Internal Flash Erase: page 0x100C000 +Internal Flash Erase: page 0x100C800 +Internal Flash Erase: page 0x100D000 +Internal Flash Write: addr 0x100C000, len 6036 +Boot partition: 0x100C000 (sz 5780, ver 0x2, type 0x202) +Network Image: Ver 0x2, Size 5780 +Network version (after update): 0x2 +Status: App 2 (ver 2), Net 4 (ver 2) +Boot partition: 0x100C000 (sz 5780, ver 0x2, type 0x202) +Booting version: 0x2 ======================== nRF5340 wolfBoot (net core) Copyright 2024 wolfSSL Inc GPL v3 -Version : 0x1 +Version : 0x2 ======================== Internal Flash Write: addr 0x1039FFC, len 4 Internal Flash Write: addr 0x1039FFB, len 1 @@ -3050,8 +3075,8 @@ repository that can be directly flashed into the BIOS flash of the board. ## Infineon AURIX TC3xx -wolfBoot supports the AURIX TC3xx family of devices, and provides a demo application targeting the TC375 AURIX LiteKit-V2. +wolfBoot supports the AURIX TC3xx family of devices, and provides a demo application targeting the TC375 AURIX LiteKit-V2. -For detailed instructions on using wolfBoot with the AURIX TC3xx, please refer to [IDE/AURIX/README.md](../IDE/AURIX/README.md) +For detailed instructions on using wolfBoot with the AURIX TC3xx, please refer to [IDE/AURIX/README.md](../IDE/AURIX/README.md) -wolfBoot can also integrate with [wolfHSM](https://www.wolfssl.com/products/wolfhsm/) on AURIX TC3xx devices, offloading cryptographic operations and key storage to the AURIX HSM core. For more information on using wolfBoot with wolfHSM on AURIX devices, please contact us at facts@wolfssl.com. +wolfBoot can also integrate with [wolfHSM](https://www.wolfssl.com/products/wolfhsm/) on AURIX TC3xx devices, offloading cryptographic operations and key storage to the AURIX HSM core. For more information on using wolfBoot with wolfHSM on AURIX devices, please contact us at facts@wolfssl.com. diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 5030b2967c..48c3b6c86b 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -209,19 +209,21 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { uint32_t end = address + len - 1; uint32_t p; - uint32_t page_sz = (address < FLASH_BASE_NET) ? - FLASH_PAGESZ_APP : - FLASH_PAGESZ_NET; #ifdef DEBUG_FLASH wolfBoot_printf("Internal Flash Erase: addr 0x%x, len %d\n", address, len); #endif - for (p = address; p <= end; p += page_sz) { + /* mask to page start address */ + address &= ~(FLASH_PAGE_SIZE-1); + for (p = address; p <= end; p += FLASH_PAGE_SIZE) { /* set both secure and non-secure registers */ NVMC_CONFIG = NVMC_CONFIG_EEN; NVMC_CONFIGNS = NVMC_CONFIG_EEN; while (NVMC_READY == 0); *(volatile uint32_t *)p = 0xFFFFFFFF; while (NVMC_READY == 0); + #ifdef DEBUG_FLASH + wolfBoot_printf("Internal Flash Erase: page 0x%x\n", p); + #endif } return 0; } @@ -319,10 +321,13 @@ static int hal_net_get_image(struct wolfBoot_image* img, ShmInfo_t* info) ret = wolfBoot_open_image(img, PART_BOOT); #endif /* TARGET_nrf5340_* */ if (ret == 0) { - info->version = wolfBoot_get_blob_version(get_image_hdr(img)); - info->size = img->fw_size; + uint32_t ver = wolfBoot_get_blob_version(get_image_hdr(img)); + /* Note: network core fault writing to shared memory means application + * core did not enable access at run-time yet */ + info->version = ver; + info->size = IMAGE_HEADER_SIZE + img->fw_size; wolfBoot_printf("Network Image: Ver 0x%x, Size %d\n", - info->version, info->size); + ver, img->fw_size); } else { info->version = 0; /* not known */ @@ -390,18 +395,17 @@ static void hal_net_check_version(void) wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", shm->net.version, shm->app.version, shm->net.size, shm->net.size); /* Erase network core boot flash */ - wb_flash_erase(&img, 0, WOLFBOOT_PARTITION_SIZE); + hal_flash_erase((uintptr_t)img.hdr, shm->app.size); /* Write new firmware to internal flash */ - wb_flash_write(&img, 0, shm->data, shm->app.size); + hal_flash_write((uintptr_t)img.hdr, shm->data, shm->app.size); /* Reopen image and refresh information */ - wolfBoot_open_image(&img, PART_BOOT); + hal_net_get_image(&img, &shm->net); wolfBoot_printf("Network version (after update): 0x%x\n", shm->net.version); - hal_net_get_image(&img, &shm->net); hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); - /* continue booting */ + /* continue booting - boot process will validate image hash/signature */ } #endif /* TARGET_nrf5340_* */ exit: @@ -420,19 +424,18 @@ void hal_net_check_update(void) ret = hal_net_get_image(&img, &shm->app); if (ret == 0 && shm->app.version > shm->net.version) { wolfBoot_printf("Found Network Core update: Ver %d->%d, Size %d->%d\n", - shm->net.version, shm->app.version, shm->net.size, shm->net.size); + shm->net.version, shm->app.version, shm->net.size, shm->app.size); /* validate the update is valid */ if (wolfBoot_verify_integrity(&img) == 0 && wolfBoot_verify_authenticity(&img) == 0) { - uint32_t fw_size = IMAGE_HEADER_SIZE + img.fw_size; wolfBoot_printf("Network image valid, loading into shared mem\n"); /* relocate image to shared ram */ #ifdef EXT_FLASH - ret = ext_flash_read(PART_NET_ADDR, shm->data, fw_size); + ret = ext_flash_read(PART_NET_ADDR, shm->data, shm->app.size); #else - memcpy(shm->data, img.hdr, fw_size); + memcpy(shm->data, img.hdr, shm->app.size); #endif if (ret >= 0) { /* signal network core to do update */ @@ -441,8 +444,9 @@ void hal_net_check_update(void) /* wait for update_done */ ret = hal_shm_status_wait(&shm->net, SHARED_STATUS_UPDATE_DONE, 1000000); - if (ret == 0) - wolfBoot_printf("Network core firmware update sent\n"); + if (ret == 0) { + wolfBoot_printf("Network core firmware update done\n"); + } } } else { @@ -474,15 +478,15 @@ void hal_init(void) (SPU_EXTDOMAIN_PERM_SECATTR_SECURE | SPU_EXTDOMAIN_PERM_UNLOCK); #endif - spi_flash_probe(); - - hal_net_check_version(); - #ifdef TEST_FLASH if (test_flash() != 0) { wolfBoot_printf("Internal flash Test Failed!\n"); } #endif + + spi_flash_probe(); + + hal_net_check_version(); } @@ -506,7 +510,8 @@ void hal_prepare_boot(void) #ifdef TEST_FLASH #ifndef TEST_ADDRESS - #define TEST_ADDRESS (FLASH_BASE_ADDR + (FLASH_SIZE - WOLFBOOT_SECTOR_SIZE)) + #define TEST_SZ (WOLFBOOT_SECTOR_SIZE * 2) + #define TEST_ADDRESS (FLASH_BASE_ADDR + (FLASH_SIZE - TEST_SZ)) #endif /* #define TEST_FLASH_READONLY */ @@ -516,7 +521,7 @@ static int test_flash(void) int ret = 0; uint32_t i, len; uint8_t* pagePtr = (uint8_t*)TEST_ADDRESS; - static uint8_t pageData[WOLFBOOT_SECTOR_SIZE]; + static uint8_t pageData[TEST_SZ]; wolfBoot_printf("Internal flash test at 0x%x\n", TEST_ADDRESS); @@ -528,7 +533,7 @@ static int test_flash(void) #ifndef TEST_FLASH_READONLY /* Erase sector */ hal_flash_unlock(); - ret = hal_flash_erase(TEST_ADDRESS, WOLFBOOT_SECTOR_SIZE); + ret = hal_flash_erase(TEST_ADDRESS, sizeof(pageData)); hal_flash_lock(); if (ret != 0) { wolfBoot_printf("Erase Sector failed: Ret %d\n", ret); diff --git a/include/spi_drv.h b/include/spi_drv.h index 205a3d6c50..4eee576795 100644 --- a/include/spi_drv.h +++ b/include/spi_drv.h @@ -99,7 +99,7 @@ int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz, int flags); #define QSPI_ADDR_MODE QSPI_DATA_MODE_SPI #endif #ifndef QSPI_ADDR_SZ /* default to 24-bit address */ - #define QSPI_ADDR_SZ 3 + #define QSPI_ADDR_SZ 3 #endif #ifndef QSPI_DATA_MODE /* data defaults to Quad mode */ #define QSPI_DATA_MODE QSPI_DATA_MODE_QSPI diff --git a/src/image.c b/src/image.c index 08c178d8e2..2464d635d3 100644 --- a/src/image.c +++ b/src/image.c @@ -885,7 +885,7 @@ int wolfBoot_open_image_address(struct wolfBoot_image *img, uint8_t *image) img->hdr_cache = image; #endif - wolfBoot_printf("%s partition: %p (sz %d, ver 0x%x, type 0x%d)\n", + wolfBoot_printf("%s partition: %p (sz %d, ver 0x%x, type 0x%x)\n", (img->part == PART_BOOT) ? "Boot" : "Update", img->hdr, (unsigned int)img->fw_size, wolfBoot_get_blob_version(image), diff --git a/src/update_flash.c b/src/update_flash.c index ec43c0ffc1..427e2a7f37 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -526,22 +526,22 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) * checks on the firmware update * before starting the swap */ - update_type = wolfBoot_get_image_type(PART_UPDATE); wolfBoot_get_update_sector_flag(0, &flag); /* Check the first sector to detect interrupted update */ if (flag == SECT_FLAG_NEW) { - if (((update_type & 0x000F) != HDR_IMG_TYPE_APP) || - ((update_type & 0xFF00) != HDR_IMG_TYPE_AUTH)) { - wolfBoot_printf("Invalid update type %d\n", update_type); + if (((update_type & HDR_IMG_TYPE_PART_MASK) != HDR_IMG_TYPE_APP) || + ((update_type & HDR_IMG_TYPE_AUTH_MASK) != HDR_IMG_TYPE_AUTH)) { + wolfBoot_printf("Invalid update type 0x%x\n", update_type); return -1; } if (update.fw_size > MAX_UPDATE_SIZE - 1) { wolfBoot_printf("Invalid update size %u\n", update.fw_size); return -1; } - if (!update.hdr_ok || (wolfBoot_verify_integrity(&update) < 0) + if (!update.hdr_ok + || (wolfBoot_verify_integrity(&update) < 0) || (wolfBoot_verify_authenticity(&update) < 0)) { wolfBoot_printf("Update integrity/verification failed!\n"); return -1; @@ -872,10 +872,9 @@ void RAMFUNCTION wolfBoot_start(void) wolfBoot_check_self_update(); #endif - bootRet = wolfBoot_get_partition_state(PART_BOOT, &bootState); + bootRet = wolfBoot_get_partition_state(PART_BOOT, &bootState); updateRet = wolfBoot_get_partition_state(PART_UPDATE, &updateState); - #if !defined(DISABLE_BACKUP) /* resume the final erase in case the power failed before it finished */ resumedFinalErase = wolfBoot_swap_and_final_erase(1); From 69a95e89f0657cd01da86fe8414da1d32a75123f Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 27 Sep 2024 15:31:49 -0700 Subject: [PATCH 04/19] Consolidate duplicate TEST_FLASH code. --- Makefile | 1 + hal/hal.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ hal/imx_rt.c | 55 ++-------------------------------- hal/nrf5340.c | 63 +-------------------------------------- hal/nxp_p1021.c | 56 ----------------------------------- hal/nxp_t1024.c | 55 ---------------------------------- hal/renesas-rx.c | 62 -------------------------------------- include/hal.h | 4 +++ src/loader.c | 3 ++ 9 files changed, 88 insertions(+), 288 deletions(-) create mode 100644 hal/hal.c diff --git a/Makefile b/Makefile index 2bc191e937..829b3bce4c 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ OBJS:= \ ./src/string.o \ ./src/image.o \ ./src/libwolfboot.o \ + ./hal/hal.o \ ./hal/$(TARGET).o ifeq ($(SIGN),NONE) diff --git a/hal/hal.c b/hal/hal.c new file mode 100644 index 0000000000..a29793944e --- /dev/null +++ b/hal/hal.c @@ -0,0 +1,77 @@ +/* hal.c + * + * Copyright (C) 2024 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 + */ + +/* Code shared between all HAL's */ + +#include +#include "hal.h" +#include "string.h" +#include "printf.h" + +/* Test for internal flash erase/write */ +/* Use TEST_EXT_FLASH to test ext flash (see spi_flash.c or qspi_flash.c) */ +#ifdef TEST_FLASH + +#ifndef TEST_ADDRESS + #define TEST_SZ WOLFBOOT_SECTOR_SIZE + #define TEST_ADDRESS WOLFBOOT_PARTITION_UPDATE_ADDRESS +#endif + +int hal_flash_test(void) +{ + int ret = 0; + uint32_t i, len; + uint8_t* pagePtr = (uint8_t*)TEST_ADDRESS; + static uint8_t pageData[TEST_SZ]; + + wolfBoot_printf("Internal flash test at 0x%x\n", TEST_ADDRESS); + + /* Setup test data */ + for (i=0; i Date: Mon, 30 Sep 2024 14:41:29 -0700 Subject: [PATCH 05/19] Fix for the `set_trailer_at` with external flash to use 32-bit write using cached value (Many QSPI hardware peripherals do not support a single byte write). Fix delta build error with DISABLE_BACKUP. Added tests for updating both cores in build_flash.sh. --- config/examples/nrf5340.config | 5 ++ config/examples/nrf5340_net.config | 1 + hal/nrf5340.c | 89 ++++++++++++---------------- hal/spi/spi_drv_nrf5340.h | 4 +- include/spi_drv.h | 3 - src/libwolfboot.c | 12 +++- src/qspi_flash.c | 10 +++- src/update_flash.c | 2 + tools/scripts/nrf5340/build_flash.sh | 12 +++- 9 files changed, 75 insertions(+), 63 deletions(-) diff --git a/config/examples/nrf5340.config b/config/examples/nrf5340.config index d12984ccd8..c92b5bc842 100644 --- a/config/examples/nrf5340.config +++ b/config/examples/nrf5340.config @@ -11,6 +11,7 @@ NO_ASM?=0 NO_MPU=1 ALLOW_DOWNGRADE?=0 NVM_FLASH_WRITEONCE?=0 +DELTA_UPDATES?=1 SPMATH?=1 RAM_CODE?=1 @@ -44,4 +45,8 @@ DEBUG?=0 DEBUG_UART?=1 USE_GCC=1 +# Use larger block size for swapping sectors +CFLAGS_EXTRA+=-DFLASHBUFFER_SIZE=0x1000 + CFLAGS_EXTRA+=-DDEBUG_FLASH +CFLAGS_EXTRA+=-DDEBUG_QSPI=1 diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config index 81010a008c..f4dd88b411 100644 --- a/config/examples/nrf5340_net.config +++ b/config/examples/nrf5340_net.config @@ -11,6 +11,7 @@ NO_ASM?=1 NO_MPU=1 ALLOW_DOWNGRADE?=0 NVM_FLASH_WRITEONCE?=0 +DELTA_UPDATES?=1 SPMATH?=1 RAM_CODE?=1 diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 9ed31f3ff3..32b9215ffb 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -53,11 +53,11 @@ #define SHARED_MEM_ADDR (0x20000000UL + (64 * 1024)) #endif /* Shared memory states (mask, easier to check) */ -#define SHARED_STATUS_UNKNOWN 0 -#define SHARED_STATUS_READY 1 -#define SHARED_STATUS_UPDATE_START 2 -#define SHARED_STATUS_UPDATE_DONE 4 -#define SHARED_STATUS_DO_BOOT 8 +#define SHARED_STATUS_UNKNOWN 0x00 +#define SHARED_STATUS_READY 0x01 +#define SHARED_STATUS_UPDATE_START 0x02 +#define SHARED_STATUS_UPDATE_DONE 0x04 +#define SHARED_STATUS_DO_BOOT 0x08 #define SHAREM_MEM_MAGIC 0x5753484D /* WSHM */ @@ -205,7 +205,7 @@ int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { uint32_t end = address + len - 1; uint32_t p; -#ifdef DEBUG_FLASH +#if defined(DEBUG_FLASH) && DEBUG_FLASH > 1 wolfBoot_printf("Internal Flash Erase: addr 0x%x, len %d\n", address, len); #endif /* mask to page start address */ @@ -354,6 +354,7 @@ static int hal_shm_status_wait(ShmInfo_t* info, uint32_t status, return ret; } +/* Handles network core updates */ static void hal_net_check_version(void) { int ret; @@ -374,51 +375,8 @@ static void hal_net_check_version(void) /* check if network core can continue booting or needs to wait for update */ if (ret != 0 || shm->app.version <= shm->net.version) { wolfBoot_printf("Network Core: Releasing for boot\n"); - hal_shm_status_set(&shm->app, SHARED_STATUS_DO_BOOT); } else { - wolfBoot_printf("Network Core: Holding for update\n"); - } -#else /* TARGET_nrf5340_net */ - hal_net_get_image(&img, &shm->net); - hal_shm_status_set(&shm->net, SHARED_STATUS_READY); - - /* wait for do_boot or update from app core */ - ret = hal_shm_status_wait(&shm->app, - (SHARED_STATUS_UPDATE_START | SHARED_STATUS_DO_BOOT), 1000000); - /* are we updating? */ - if (ret == 0 && shm->app.status == SHARED_STATUS_UPDATE_START) { - wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", - shm->net.version, shm->app.version, shm->net.size, shm->net.size); - /* Erase network core boot flash */ - hal_flash_erase((uintptr_t)img.hdr, shm->app.size); - /* Write new firmware to internal flash */ - hal_flash_write((uintptr_t)img.hdr, shm->data, shm->app.size); - - /* Reopen image and refresh information */ - hal_net_get_image(&img, &shm->net); - wolfBoot_printf("Network version (after update): 0x%x\n", - shm->net.version); - hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); - - /* continue booting - boot process will validate image hash/signature */ - } -#endif /* TARGET_nrf5340_* */ -exit: - wolfBoot_printf("Status: App %d (ver %d), Net %d (ver %d)\n", - shm->app.status, shm->app.version, shm->net.status, shm->net.version); -} - -#ifdef TARGET_nrf5340_app -void hal_net_check_update(void) -{ - int ret; - uint32_t timeout; - struct wolfBoot_image img; - - /* handle update for network core */ - ret = hal_net_get_image(&img, &shm->app); - if (ret == 0 && shm->app.version > shm->net.version) { wolfBoot_printf("Found Network Core update: Ver %d->%d, Size %d->%d\n", shm->net.version, shm->app.version, shm->net.size, shm->app.size); @@ -452,8 +410,37 @@ void hal_net_check_update(void) } /* inform network core to boot */ hal_shm_status_set(&shm->app, SHARED_STATUS_DO_BOOT); +#else /* TARGET_nrf5340_net */ + hal_net_get_image(&img, &shm->net); + hal_shm_status_set(&shm->net, SHARED_STATUS_READY); + + /* wait for do_boot or update from app core */ + wolfBoot_printf("Waiting for status from app core...\n"); + ret = hal_shm_status_wait(&shm->app, + (SHARED_STATUS_UPDATE_START | SHARED_STATUS_DO_BOOT), 1000000); + + /* are we updating? */ + if (ret == 0 && shm->app.status == SHARED_STATUS_UPDATE_START) { + wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", + shm->net.version, shm->app.version, shm->net.size, shm->net.size); + /* Erase network core boot flash */ + hal_flash_erase((uintptr_t)img.hdr, shm->app.size); + /* Write new firmware to internal flash */ + hal_flash_write((uintptr_t)img.hdr, shm->data, shm->app.size); + + /* Reopen image and refresh information */ + hal_net_get_image(&img, &shm->net); + wolfBoot_printf("Network version (after update): 0x%x\n", + shm->net.version); + hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); + + /* continue booting - boot process will validate image hash/signature */ + } +#endif /* TARGET_nrf5340_* */ +exit: + wolfBoot_printf("Status: App %d (ver %d), Net %d (ver %d)\n", + shm->app.status, shm->app.version, shm->net.status, shm->net.version); } -#endif void hal_init(void) { @@ -488,8 +475,6 @@ void hal_prepare_boot(void) //BOOTLOADER_PARTITION_SIZE #ifdef TARGET_nrf5340_app - hal_net_check_update(); - /* Restore defaults preventing network core from accessing shared SDRAM */ SPU_EXTDOMAIN_PERM(0) = (SPU_EXTDOMAIN_PERM_SECATTR_NONSECURE | SPU_EXTDOMAIN_PERM_UNLOCK); diff --git a/hal/spi/spi_drv_nrf5340.h b/hal/spi/spi_drv_nrf5340.h index 686ac59e2e..961dfe50c6 100644 --- a/hal/spi/spi_drv_nrf5340.h +++ b/hal/spi/spi_drv_nrf5340.h @@ -79,8 +79,8 @@ #define QSPI_IO3_PIN 16 #endif -#ifndef QSPI_CLOCK_MHZ /* default 24MHz (up to 96MHz) */ - #define QSPI_CLOCK_MHZ 24000000UL +#ifndef QSPI_CLOCK_MHZ /* default 48MHz (up to 96MHz) */ + #define QSPI_CLOCK_MHZ 48000000UL #endif /* MX25R6435F */ diff --git a/include/spi_drv.h b/include/spi_drv.h index 4eee576795..332f136a7c 100644 --- a/include/spi_drv.h +++ b/include/spi_drv.h @@ -112,9 +112,6 @@ int qspi_transfer(uint8_t fmode, const uint8_t cmd, uint8_t* data, uint32_t dataSz, uint32_t dataMode ); -#if !defined(DEBUG_QSPI) && defined(DEBUG_UART) - #define DEBUG_QSPI 1 -#endif #endif /* QSPI_FLASH || OCTOSPI_FLASH */ #ifndef SPI_CS_FLASH diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 22b7dfcbe5..e078b39dc0 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -453,8 +453,12 @@ static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val) if (part == PART_BOOT) { #ifdef EXT_FLASH if (FLAGS_BOOT_EXT()) { + /* use ext_cache and 32-bit writes to avoid any underlying hardware + * issues with 1-byte write */ + ext_cache &= ~0xFF; + ext_cache |= val; ext_flash_check_write(PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at), - (void *)&val, 1); + (void *)&ext_cache, sizeof(uint32_t)); } else #endif @@ -465,8 +469,12 @@ static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val) else if (part == PART_UPDATE) { #ifdef EXT_FLASH if (FLAGS_UPDATE_EXT()) { + /* use ext_cache and 32-bit writes to avoid any underlying hardware + * issues with 1-byte write */ + ext_cache &= ~0xFF; + ext_cache |= val; ext_flash_check_write(PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at), - (void *)&val, 1); + (void *)&ext_cache, sizeof(uint32_t)); } else #endif diff --git a/src/qspi_flash.c b/src/qspi_flash.c index 3e271446cb..b30419efa7 100644 --- a/src/qspi_flash.c +++ b/src/qspi_flash.c @@ -422,6 +422,11 @@ int spi_flash_write(uint32_t address, const void *data, int len) uint32_t xferSz, page, pages, idx = 0; uintptr_t addr; +#ifdef DEBUG_QSPI + wolfBoot_printf("QSPI Flash Write: Len %d, %p -> 0x%x\n", + len, data, address); +#endif + /* write by page */ pages = ((len + (FLASH_PAGE_SIZE-1)) / FLASH_PAGE_SIZE); for (page = 0; page < pages; page++) { @@ -444,8 +449,9 @@ int spi_flash_write(uint32_t address, const void *data, int len) xferSz, QSPI_DATA_MODE /* Data */ ); #ifdef DEBUG_QSPI - wolfBoot_printf("QSPI Flash Write: Ret %d, Cmd 0x%x, Len %d , 0x%x -> %p\n", - ret, FLASH_WRITE_CMD, xferSz, address, ptr); + wolfBoot_printf("QSPI Flash Sector Write: " + "Ret %d, Cmd 0x%x, Len %d, %p -> 0x%x\n", + ret, FLASH_WRITE_CMD, xferSz, ptr, address); #endif if (ret != 0) break; diff --git a/src/update_flash.c b/src/update_flash.c index 427e2a7f37..c04196eeac 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -438,9 +438,11 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, wb_flash_erase(boot, sector * WOLFBOOT_SECTOR_SIZE, WOLFBOOT_SECTOR_SIZE); sector++; } +#ifndef DISABLE_BACKUP /* start re-entrant final erase, return code is only for resumption in * wolfBoot_start*/ wolfBoot_swap_and_final_erase(0); +#endif out: #ifdef EXT_FLASH ext_flash_lock(); diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index 0f0327db58..6fe7d8bac3 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -28,11 +28,19 @@ cp factory.bin tools/scripts/nrf5340/factory_app.bin tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 2 cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_app.bin +# Create a bin footer with wolfBoot trailer "BOOT" and "p" (ASCII for 0x70 == IMG_STATE_UPDATING): +echo -n "pBOOT" > tools/scripts/nrf5340/trigger_magic.bin +./tools/bin-assemble/bin-assemble \ + tools/scripts/nrf5340/update_app_v2.bin \ + 0x0 tools/scripts/nrf5340/image_v2_signed_app.bin \ + 0xEDFFB tools/scripts/nrf5340/trigger_magic.bin + + # Convert to HEX format for programmer tool arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x00000000 tools/scripts/nrf5340/factory_app.bin tools/scripts/nrf5340/factory_app.hex arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x01000000 tools/scripts/nrf5340/factory_net.bin tools/scripts/nrf5340/factory_net.hex -arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/image_v2_signed_app.bin tools/scripts/nrf5340/image_v2_signed_app.hex +arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/update_app_v2.bin tools/scripts/nrf5340/update_app_v2.hex arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10100000 tools/scripts/nrf5340/image_v2_signed_net.bin tools/scripts/nrf5340/image_v2_signed_net.hex @@ -42,7 +50,7 @@ if [ "$1" == "erase" ]; then fi # Program external flash -nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_app.hex --verify +nrfjprog -f nrf53 --program tools/scripts/nrf5340/update_app_v2.hex --verify nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_net.hex --verify From eb9b549694b7bfb647295233781a0f4f52d45b07 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 1 Oct 2024 07:06:02 -0700 Subject: [PATCH 06/19] QSPI Power control (active low). --- config/examples/nrf5340.config | 3 +++ hal/spi/spi_drv_nrf5340.c | 7 +++++++ hal/spi/spi_drv_nrf5340.h | 4 ++++ 3 files changed, 14 insertions(+) diff --git a/config/examples/nrf5340.config b/config/examples/nrf5340.config index c92b5bc842..707fe33861 100644 --- a/config/examples/nrf5340.config +++ b/config/examples/nrf5340.config @@ -48,5 +48,8 @@ USE_GCC=1 # Use larger block size for swapping sectors CFLAGS_EXTRA+=-DFLASHBUFFER_SIZE=0x1000 +# Enable optional power control pin (active low) P1.00 +CFLAGS_EXTRA+=-DQSPI_PWR_CTRL_PORT=1 -DQSPI_PWR_CTRL_PIN=0 + CFLAGS_EXTRA+=-DDEBUG_FLASH CFLAGS_EXTRA+=-DDEBUG_QSPI=1 diff --git a/hal/spi/spi_drv_nrf5340.c b/hal/spi/spi_drv_nrf5340.c index 7789997a8c..dcbbe3aa1c 100644 --- a/hal/spi/spi_drv_nrf5340.c +++ b/hal/spi/spi_drv_nrf5340.c @@ -195,6 +195,10 @@ void spi_init(int polarity, int phase) GPIO_PIN_CNF(QSPI_IO1_PORT, QSPI_IO1_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); GPIO_PIN_CNF(QSPI_IO2_PORT, QSPI_IO2_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); GPIO_PIN_CNF(QSPI_IO3_PORT, QSPI_IO3_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); +#if defined(QSPI_PWR_CTRL_PORT) && defined(QSPI_PWR_CTRL_PIN) + GPIO_PIN_CNF(QSPI_PWR_CTRL_PORT, QSPI_PWR_CTRL_PIN) = (GPIO_CNF_IN_DIS | GPIO_CNF_HIGH_DRIVE); + GPIO_OUTCLR(QSPI_PWR_CTRL_PORT) = (1 << QSPI_PWR_CTRL_PIN); /* active low */ +#endif reg = QSPI_IFCONFIG0; reg &= ~(QSPI_IFCONFIG0_READOC_MASK | QSPI_IFCONFIG0_WRITEOC_MASK); @@ -278,6 +282,9 @@ void spi_release(void) /* Disable QSPI Clock to save power */ QSPI_ENABLE = 0; CLOCK_HFCLK192MSTOP = 1; + #if defined(QSPI_PWR_CTRL_PORT) && defined(QSPI_PWR_CTRL_PIN) + GPIO_OUTSET(QSPI_PWR_CTRL_PORT) = (1 << QSPI_PWR_CTRL_PIN); + #endif } } diff --git a/hal/spi/spi_drv_nrf5340.h b/hal/spi/spi_drv_nrf5340.h index 961dfe50c6..01d7967840 100644 --- a/hal/spi/spi_drv_nrf5340.h +++ b/hal/spi/spi_drv_nrf5340.h @@ -83,6 +83,10 @@ #define QSPI_CLOCK_MHZ 48000000UL #endif +/* Optional power pin for QSPI enable */ +//#define QSPI_PWR_CTRL_PORT 1 +//#define QSPI_PWR_CTRL_PIN 0 + /* MX25R6435F */ #define QSPI_NO_SR2 From c8b0d74e1da5919fd082350d95e3003f89f38ad5 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 1 Oct 2024 08:15:22 -0700 Subject: [PATCH 07/19] Switch network core to use external flash HAL, but map to shared memory. Allows using update_flash logic including encrypted and delta updates. --- config/examples/nrf5340_net.config | 11 ++-- hal/nrf5340.c | 97 +++++++++++++++++++++++++++--- src/qspi_flash.c | 2 +- 3 files changed, 94 insertions(+), 16 deletions(-) diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config index f4dd88b411..6ae30c77cf 100644 --- a/config/examples/nrf5340_net.config +++ b/config/examples/nrf5340_net.config @@ -19,7 +19,8 @@ RAM_CODE?=1 DUALBANK_SWAP?=0 FLAGS_HOME=0 DISABLE_BACKUP=1 -EXT_FLASH?=0 +# Implementation maps to shared application core memory +EXT_FLASH?=1 SPI_FLASH?=0 QSPI_FLASH?=0 @@ -35,11 +36,11 @@ WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x0100C000 # Application Partition Size (184KB) WOLFBOOT_PARTITION_SIZE?=0x2E000 -# Flash offset for update (not used - handled by application core) -WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x0100C000 +# Flash offset for update (provided by application core to shared memory) +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x100000 -# Flash offset for swap (not used - handled by application core) -WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x103A800 +# Flash offset for swap (uses shared memory) +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x12E000 V?=0 DEBUG?=0 diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 32b9215ffb..8515f22326 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -74,9 +74,15 @@ typedef struct { /* application places firmware here */ uint8_t data[FLASH_SIZE_NET]; + /* used as "swap" */ + uint8_t swap[FLASH_PAGESZ_NET]; } SharedMem_t; static SharedMem_t* shm = (SharedMem_t*)SHARED_MEM_ADDR; +#ifdef TARGET_nrf5340_net +static int do_update = 0; +#endif + /* UART */ #ifdef DEBUG_UART @@ -232,6 +238,71 @@ void RAMFUNCTION hal_flash_lock(void) { } +#ifdef TARGET_nrf5340_net +/* external flash is access application core shared memory directly */ + +/* calculates location in shared memory */ +static uintptr_t ext_flash_addr_calc(uintptr_t address) +{ + if (address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) { + if (address >= WOLFBOOT_PARTITION_SWAP_ADDRESS) { + address -= WOLFBOOT_PARTITION_SWAP_ADDRESS; + } + else { /* update */ + address -= WOLFBOOT_PARTITION_UPDATE_ADDRESS; + } + } + /* check address */ + if (address >= (FLASH_SIZE_NET + FLASH_PAGESZ_NET)) { + address = 0; + } + return address; +} + +int ext_flash_write(uintptr_t address, const uint8_t *data, int len) +{ + uintptr_t addr = ext_flash_addr_calc(address); +#ifdef DEBUG_FLASH + wolfBoot_printf("Ext Write: Len %d, Addr 0x%x (off 0x%x) -> 0x%x\n", + len, address, addr, data); +#endif + memcpy(shm->data + addr, data, len); + return 0; +} + +int ext_flash_read(uintptr_t address, uint8_t *data, int len) +{ + uintptr_t addr = ext_flash_addr_calc(address); +#ifdef DEBUG_FLASH + wolfBoot_printf("Ext Read: Len %d, Addr 0x%x (off 0x%x) -> %p\n", + len, address, addr, data); +#endif + + memcpy(data, shm->data + addr, len); + return len; +} + +int ext_flash_erase(uintptr_t address, int len) +{ + uintptr_t addr = ext_flash_addr_calc(address); +#ifdef DEBUG_FLASH + wolfBoot_printf("Ext Erase: Len %d, Addr 0x%x (off 0x%x)\n", + len, address, addr); +#endif + memset(shm->data + addr, FLASH_BYTE_ERASED, len); + return 0; +} + +void ext_flash_lock(void) +{ + /* no op */ +} +void ext_flash_unlock(void) +{ + /* no op */ +} +#endif /* TARGET_nrf5340_net */ + static void clock_init(void) { #ifndef TARGET_nrf5340_net @@ -423,18 +494,12 @@ static void hal_net_check_version(void) if (ret == 0 && shm->app.status == SHARED_STATUS_UPDATE_START) { wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", shm->net.version, shm->app.version, shm->net.size, shm->net.size); - /* Erase network core boot flash */ - hal_flash_erase((uintptr_t)img.hdr, shm->app.size); - /* Write new firmware to internal flash */ - hal_flash_write((uintptr_t)img.hdr, shm->data, shm->app.size); + do_update = 1; - /* Reopen image and refresh information */ - hal_net_get_image(&img, &shm->net); - wolfBoot_printf("Network version (after update): 0x%x\n", - shm->net.version); - hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); + /* trigger update */ + wolfBoot_set_partition_state(PART_UPDATE, IMG_STATE_UPDATING); - /* continue booting - boot process will validate image hash/signature */ + /* proceed to update_flash routines */ } #endif /* TARGET_nrf5340_* */ exit: @@ -474,6 +539,18 @@ void hal_prepare_boot(void) //WOLFBOOT_ORIGIN //BOOTLOADER_PARTITION_SIZE +#ifdef TARGET_nrf5340_net + if (do_update) { + /* signal application core of update */ + /* Reopen image and refresh information */ + struct wolfBoot_image img; + hal_net_get_image(&img, &shm->net); + wolfBoot_printf("Network version (after update): 0x%x\n", + shm->net.version); + hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); + } +#endif + #ifdef TARGET_nrf5340_app /* Restore defaults preventing network core from accessing shared SDRAM */ SPU_EXTDOMAIN_PERM(0) = diff --git a/src/qspi_flash.c b/src/qspi_flash.c index b30419efa7..20ebf078a6 100644 --- a/src/qspi_flash.c +++ b/src/qspi_flash.c @@ -408,7 +408,7 @@ int spi_flash_read(uint32_t address, void *data, int len) ); #ifdef DEBUG_QSPI - wolfBoot_printf("QSPI Flash Read: Ret %d, Cmd 0x%x, Len %d , 0x%x -> %p\n", + wolfBoot_printf("QSPI Flash Read: Ret %d, Cmd 0x%x, Len %d, 0x%x -> %p\n", ret, FLASH_READ_CMD, len, address, data); #endif From 77dde99962b32964b18aa1909a1e106ea00d5dba Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 1 Oct 2024 09:38:06 -0700 Subject: [PATCH 08/19] Example for using custom UART port/pin. Additional debug output on erase of unused flash sectors. --- config/examples/nrf5340.config | 5 ++++- docs/Targets.md | 5 +---- hal/nrf5340.c | 4 +++- src/update_flash.c | 4 +++- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/config/examples/nrf5340.config b/config/examples/nrf5340.config index 707fe33861..5a7ba646e1 100644 --- a/config/examples/nrf5340.config +++ b/config/examples/nrf5340.config @@ -49,7 +49,10 @@ USE_GCC=1 CFLAGS_EXTRA+=-DFLASHBUFFER_SIZE=0x1000 # Enable optional power control pin (active low) P1.00 -CFLAGS_EXTRA+=-DQSPI_PWR_CTRL_PORT=1 -DQSPI_PWR_CTRL_PIN=0 +#CFLAGS_EXTRA+=-DQSPI_PWR_CTRL_PORT=1 -DQSPI_PWR_CTRL_PIN=0 + +# Use UART0 on P0.22 +#CFLAGS_EXTRA+=-DUART_PORT=0 -DUART_PIN=22 CFLAGS_EXTRA+=-DDEBUG_FLASH CFLAGS_EXTRA+=-DDEBUG_QSPI=1 diff --git a/docs/Targets.md b/docs/Targets.md index 30ad290ab3..845f3daa59 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -2186,11 +2186,8 @@ Tested with the Nordic nRF5340-DK. This device has two cores: 1) Application core: Cortex-M33 at 128MHz, w/TrustZone, 1MB flash, 512KB RAM 2) Network core: Cortex-M33 at 64MHz, 256KB Flash and 64KB RAM -The cores communicate using the IPC peripheral. - -The network core can access application core resources (flash, RAM, and peripherals) when granted permission through the application's DCNF and SPU settings. A small portion of the application core RAM is dedicated to the exchange of messages between the application and network cores. - The DK board has two virtual COM ports. Application core and Network core will each output to different VCOM ports. +The cores communicate firmware updates using shared memory hosted on application core. Example Boot Output: diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 8515f22326..a6c8f2b928 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -466,9 +466,11 @@ static void hal_net_check_version(void) /* signal network core to do update */ hal_shm_status_set(&shm->app, SHARED_STATUS_UPDATE_START); + wolfBoot_printf("Waiting for net core update to finish...\n"); + /* wait for update_done */ ret = hal_shm_status_wait(&shm->net, - SHARED_STATUS_UPDATE_DONE, 1000000); + SHARED_STATUS_UPDATE_DONE, 5000000); if (ret == 0) { wolfBoot_printf("Network core firmware update done\n"); } diff --git a/src/update_flash.c b/src/update_flash.c index c04196eeac..072698446f 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -265,6 +265,7 @@ static int wolfBoot_swap_and_final_erase(int resume) wb_flash_write(boot, tmpBootPos, (void*)tmpBuffer, sizeof(tmpBuffer)); } /* erase the last boot sector(s) */ + wolfBoot_printf("Erasing unused boot sectors...\n"); wb_flash_erase(boot, WOLFBOOT_PARTITION_SIZE - eraseLen, eraseLen); /* set the encryption key */ #ifdef EXT_ENCRYPTED @@ -281,6 +282,7 @@ static int wolfBoot_swap_and_final_erase(int resume) /* mark boot as TESTING */ wolfBoot_set_partition_state(PART_BOOT, IMG_STATE_TESTING); /* erase the last sector(s) of update */ + wolfBoot_printf("Erasing unused update sectors...\n"); wb_flash_erase(update, WOLFBOOT_PARTITION_SIZE - eraseLen, eraseLen); return 0; } @@ -440,7 +442,7 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, } #ifndef DISABLE_BACKUP /* start re-entrant final erase, return code is only for resumption in - * wolfBoot_start*/ + * wolfBoot_start */ wolfBoot_swap_and_final_erase(0); #endif out: From f832f746de84c435d055f4c3b8b48a0be47df717 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 1 Oct 2024 11:50:08 -0700 Subject: [PATCH 09/19] Fixed and improved erase of remainder of partition logic and logging. Added support for nRF5340 core synchronization (`NRF_SYNC_CORES`). Added test for `WOLFBOOT_FLASH_MULTI_SECTOR_ERASE`. --- .github/workflows/test-configs.yml | 8 +++++ config/examples/nrf5340.config | 5 ++- hal/nrf5340.c | 16 ++++++++-- src/update_flash.c | 49 +++++++++++++----------------- 4 files changed, 46 insertions(+), 32 deletions(-) diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 5cc2c51151..b34ba299df 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -208,6 +208,14 @@ jobs: config-file: ./config/examples/sim.config make-args: SPMATH=1 WOLFBOOT_SMALL_STACK=0 WOLFBOOT_HUGE_STACK=1 + sim_multi_sector_erase: + uses: ./.github/workflows/test-build.yml + with: + arch: host + config-file: ./config/examples/sim.config + make-args: CFLAGS_EXTRA=-DWOLFBOOT_FLASH_MULTI_SECTOR_ERASE + + # TODO: SP math with small stack has issues stm32c0: diff --git a/config/examples/nrf5340.config b/config/examples/nrf5340.config index 5a7ba646e1..1c2480e7fa 100644 --- a/config/examples/nrf5340.config +++ b/config/examples/nrf5340.config @@ -45,7 +45,10 @@ DEBUG?=0 DEBUG_UART?=1 USE_GCC=1 -# Use larger block size for swapping sectors +# Optionally wait for network core to boot before starting application core +CFLAGS_EXTRA+=-DNRF_SYNC_CORES + +# Use larger block size for swapping sectors (performance improvement) CFLAGS_EXTRA+=-DFLASHBUFFER_SIZE=0x1000 # Enable optional power control pin (active low) P1.00 diff --git a/hal/nrf5340.c b/hal/nrf5340.c index a6c8f2b928..cf85cf0873 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -468,7 +468,7 @@ static void hal_net_check_version(void) wolfBoot_printf("Waiting for net core update to finish...\n"); - /* wait for update_done */ + /* wait for update_done - note longer wait */ ret = hal_shm_status_wait(&shm->net, SHARED_STATUS_UPDATE_DONE, 5000000); if (ret == 0) { @@ -543,17 +543,27 @@ void hal_prepare_boot(void) #ifdef TARGET_nrf5340_net if (do_update) { - /* signal application core of update */ - /* Reopen image and refresh information */ + /* signal application core update done */ struct wolfBoot_image img; + /* Reopen image and refresh information */ hal_net_get_image(&img, &shm->net); wolfBoot_printf("Network version (after update): 0x%x\n", shm->net.version); hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); } + else { + hal_shm_status_set(&shm->net, SHARED_STATUS_DO_BOOT); + } #endif #ifdef TARGET_nrf5340_app +#ifdef NRF_SYNC_CORES + /* if core synchronization enabled, then wait for update_done or do_boot */ + wolfBoot_printf("Waiting for network core...\n"); + (void)hal_shm_status_wait(&shm->net, + (SHARED_STATUS_UPDATE_DONE | SHARED_STATUS_DO_BOOT), 1000000); +#endif + /* Restore defaults preventing network core from accessing shared SDRAM */ SPU_EXTDOMAIN_PERM(0) = (SPU_EXTDOMAIN_PERM_SECATTR_NONSECURE | SPU_EXTDOMAIN_PERM_UNLOCK); diff --git a/src/update_flash.c b/src/update_flash.c index 072698446f..d63f573c4d 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -265,7 +265,6 @@ static int wolfBoot_swap_and_final_erase(int resume) wb_flash_write(boot, tmpBootPos, (void*)tmpBuffer, sizeof(tmpBuffer)); } /* erase the last boot sector(s) */ - wolfBoot_printf("Erasing unused boot sectors...\n"); wb_flash_erase(boot, WOLFBOOT_PARTITION_SIZE - eraseLen, eraseLen); /* set the encryption key */ #ifdef EXT_ENCRYPTED @@ -282,7 +281,6 @@ static int wolfBoot_swap_and_final_erase(int resume) /* mark boot as TESTING */ wolfBoot_set_partition_state(PART_BOOT, IMG_STATE_TESTING); /* erase the last sector(s) of update */ - wolfBoot_printf("Erasing unused update sectors...\n"); wb_flash_erase(update, WOLFBOOT_PARTITION_SIZE - eraseLen, eraseLen); return 0; } @@ -509,9 +507,6 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) uint32_t up_v; #endif uint32_t cur_ver, upd_ver; -#ifdef WOLFBOOT_FLASH_MULTI_SECTOR_ERASE - size_t remainderBytes; -#endif wolfBoot_printf("Staring Update (fallback allowed %d)\n", fallback_allowed); @@ -668,37 +663,30 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) } } -#ifdef WOLFBOOT_FLASH_MULTI_SECTOR_ERASE -/* Performant option: Erase remainder of flash sectors in one HAL command */ - #ifdef NVM_FLASH_WRITEONCE - /* erase up until the start of the second-to-last sector for writeonce */ - remainderBytes = - WOLFBOOT_PARTITION_SIZE - (sector * sector_size) - (2 * sector_size); + /* erase up until the start of the second-to-last sector for writeonce */ + size = WOLFBOOT_PARTITION_SIZE - (sector * sector_size) - (2 * sector_size); #else - /* erase up until the start of the last sector */ - remainderBytes = - WOLFBOOT_PARTITION_SIZE - (sector * sector_size) - sector_size; + /* erase up until the start of the last sector */ + size = WOLFBOOT_PARTITION_SIZE - (sector * sector_size) - sector_size; #endif - wb_flash_erase(&boot, sector * sector_size, remainderBytes); - wb_flash_erase(&update, sector * sector_size, remainderBytes); -#else /* WOLFBOOT_FLASH_MULTI_SECTOR_ERASE */ -/* Smaller code size option: Iterate over every remaining sector and erase it - * individually. Required on some targets (stm32f4) to pass code size check */ + wolfBoot_printf("Erasing remainder of partition (%d sectors)...\n", + size/sector_size); - /* erase to the last sector, writeonce has 2 sectors */ - while((sector * sector_size) < WOLFBOOT_PARTITION_SIZE - - sector_size - #ifdef NVM_FLASH_WRITEONCE - * 2 - #endif - ) { +#ifdef WOLFBOOT_FLASH_MULTI_SECTOR_ERASE + /* Performant option: Erase remainder of flash sectors in one HAL command */ + wb_flash_erase(&boot, sector * sector_size, size); + wb_flash_erase(&update, sector * sector_size, size); +#else + /* Smaller code size option: Iterate over every remaining sector and erase + * individually. Required on some targets (like stm32f4) due to code size */ + while (size >= sector_size) { wb_flash_erase(&boot, sector * sector_size, sector_size); wb_flash_erase(&update, sector * sector_size, sector_size); sector++; + size -= sector_size; } - #endif /* !WOLFBOOT_FLASH_MULTI_SECTOR_ERASE */ /* start re-entrant final erase, return code is only for resumption in @@ -728,9 +716,14 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) wolfBoot_copy_sector(&update, &boot, sector); sector++; } - while ((sector * sector_size) < WOLFBOOT_PARTITION_SIZE) { + /* erase remainder of partition */ + size = WOLFBOOT_PARTITION_SIZE - (sector * sector_size); + wolfBoot_printf("Erasing remainder of partition (%d sectors)...\n", + size/sector_size); + while (size >= sector_size) { wb_flash_erase(&boot, sector * sector_size, sector_size); sector++; + size -= sector_size; } wolfBoot_set_partition_state(PART_BOOT, IMG_STATE_SUCCESS); From e45124c554b810738a642537cd56f7eb1a829a97 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 1 Oct 2024 13:08:38 -0700 Subject: [PATCH 10/19] Attempt to not grow code size with end of partition sector erase changes. --- src/update_flash.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/update_flash.c b/src/update_flash.c index d63f573c4d..ecc37e5d41 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -663,31 +663,38 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) } } + /* calculate number of remaining bytes */ + /* reserve 1 sector for status (2 sectors for NV write once) */ +#if defined(WOLFBOOT_FLASH_MULTI_SECTOR_ERASE) || defined(PRINTF_ENABLED) #ifdef NVM_FLASH_WRITEONCE - /* erase up until the start of the second-to-last sector for writeonce */ size = WOLFBOOT_PARTITION_SIZE - (sector * sector_size) - (2 * sector_size); #else - /* erase up until the start of the last sector */ size = WOLFBOOT_PARTITION_SIZE - (sector * sector_size) - sector_size; #endif - wolfBoot_printf("Erasing remainder of partition (%d sectors)...\n", + wolfBoot_printf("Erasing remainder of partitions (%d sectors)...\n", size/sector_size); +#endif #ifdef WOLFBOOT_FLASH_MULTI_SECTOR_ERASE /* Performant option: Erase remainder of flash sectors in one HAL command */ + /* If the HAL supports erase of multiple sectors this could improve performance */ wb_flash_erase(&boot, sector * sector_size, size); wb_flash_erase(&update, sector * sector_size, size); #else - /* Smaller code size option: Iterate over every remaining sector and erase - * individually. Required on some targets (like stm32f4) due to code size */ - while (size >= sector_size) { + /* Iterate over every remaining sector and erase individually. */ + /* This loop is smallest code size */ + while ((sector * sector_size) < WOLFBOOT_PARTITION_SIZE - + sector_size + #ifdef NVM_FLASH_WRITEONCE + * 2 + #endif + ) { wb_flash_erase(&boot, sector * sector_size, sector_size); wb_flash_erase(&update, sector * sector_size, sector_size); sector++; - size -= sector_size; } -#endif /* !WOLFBOOT_FLASH_MULTI_SECTOR_ERASE */ +#endif /* WOLFBOOT_FLASH_MULTI_SECTOR_ERASE */ /* start re-entrant final erase, return code is only for resumption in * wolfBoot_start*/ @@ -699,7 +706,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) hal_flash_lock(); #else /* DISABLE_BACKUP */ - /* Direct Swap without power fail saftey */ + /* Direct Swap without power fail safety */ hal_flash_unlock(); #ifdef EXT_FLASH @@ -717,13 +724,14 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) sector++; } /* erase remainder of partition */ +#ifdef PRINTF_ENABLED size = WOLFBOOT_PARTITION_SIZE - (sector * sector_size); wolfBoot_printf("Erasing remainder of partition (%d sectors)...\n", size/sector_size); - while (size >= sector_size) { +#endif + while ((sector * sector_size) < WOLFBOOT_PARTITION_SIZE) { wb_flash_erase(&boot, sector * sector_size, sector_size); sector++; - size -= sector_size; } wolfBoot_set_partition_state(PART_BOOT, IMG_STATE_SUCCESS); From 7445d8601925be7167a270a7672954259731059f Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 1 Oct 2024 14:24:32 -0700 Subject: [PATCH 11/19] Enable backup for network core, so the last known image will still be in shared ram. Fixed bug with swap offset on network core external memory map and "erase" init. --- config/examples/nrf5340_net.config | 5 ++++- hal/nrf5340.c | 23 ++++++++++++++--------- include/wolfboot/wolfboot.h | 2 ++ src/update_flash.c | 10 ++++++---- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config index 6ae30c77cf..45d4d8944f 100644 --- a/config/examples/nrf5340_net.config +++ b/config/examples/nrf5340_net.config @@ -18,7 +18,7 @@ RAM_CODE?=1 DUALBANK_SWAP?=0 FLAGS_HOME=0 -DISABLE_BACKUP=1 +DISABLE_BACKUP=0 # Implementation maps to shared application core memory EXT_FLASH?=1 SPI_FLASH?=0 @@ -42,6 +42,9 @@ WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x100000 # Flash offset for swap (uses shared memory) WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x12E000 +# Network core uses partition ID 2 +CFLAGS_EXTRA+=-DHDR_IMG_TYPE_APP=0x2 + V?=0 DEBUG?=0 DEBUG_UART?=1 diff --git a/hal/nrf5340.c b/hal/nrf5340.c index cf85cf0873..aa3a0dfd6d 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -40,9 +40,17 @@ /* Network updates can be signed with "--id 2" and placed into the normal update partition, * or they can be placed into the external flash at offset 0x100000 */ +/* Partition ID should be set HDR_IMG_TYPE_APP=2 */ #ifndef PART_NET_ID -#define PART_NET_ID 2 +#ifdef HDR_IMG_TYPE_APP + #define PART_NET_ID HDR_IMG_TYPE_APP +#else + #define PART_NET_ID 2 /* default */ +#endif #endif + +/* Offset in external QSPI flash for network update + * Comes from nrf5340_net.config WOLFBOOT_PARTITION_UPDATE_ADDRESS) */ #ifndef PART_NET_ADDR #define PART_NET_ADDR 0x100000UL #endif @@ -244,14 +252,8 @@ void RAMFUNCTION hal_flash_lock(void) /* calculates location in shared memory */ static uintptr_t ext_flash_addr_calc(uintptr_t address) { - if (address >= WOLFBOOT_PARTITION_UPDATE_ADDRESS) { - if (address >= WOLFBOOT_PARTITION_SWAP_ADDRESS) { - address -= WOLFBOOT_PARTITION_SWAP_ADDRESS; - } - else { /* update */ - address -= WOLFBOOT_PARTITION_UPDATE_ADDRESS; - } - } + /* offset external flash addresses by the update partition address */ + address -= WOLFBOOT_PARTITION_UPDATE_ADDRESS; /* check address */ if (address >= (FLASH_SIZE_NET + FLASH_PAGESZ_NET)) { address = 0; @@ -456,6 +458,9 @@ static void hal_net_check_version(void) wolfBoot_verify_authenticity(&img) == 0) { wolfBoot_printf("Network image valid, loading into shared mem\n"); + /* initialize remainder of shared memory with 0xFF (erased) */ + memset(shm->data + shm->app.size, FLASH_BYTE_ERASED, + sizeof(shm->data) - shm->app.size); /* relocate image to shared ram */ #ifdef EXT_FLASH ret = ext_flash_read(PART_NET_ADDR, shm->data, shm->app.size); diff --git a/include/wolfboot/wolfboot.h b/include/wolfboot/wolfboot.h index b8bcfda814..c082ad7ad9 100644 --- a/include/wolfboot/wolfboot.h +++ b/include/wolfboot/wolfboot.h @@ -112,7 +112,9 @@ extern "C" { #define HDR_IMG_TYPE_PART_MASK 0x000F #define HDR_IMG_TYPE_WOLFBOOT 0x0000 +#ifndef HDR_IMG_TYPE_APP #define HDR_IMG_TYPE_APP 0x0001 +#endif #define KEYSTORE_PUBKEY_SIZE_NONE 0 #define KEYSTORE_PUBKEY_SIZE_ED25519 32 diff --git a/src/update_flash.c b/src/update_flash.c index ecc37e5d41..886742c339 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -486,7 +486,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) const uint32_t sector_size = WOLFBOOT_SECTOR_SIZE; uint32_t sector = 0; /* we need to pre-set flag to SECT_FLAG_NEW in case magic hasn't been set - * on the update partion as part of the delta update direction check. if + * on the update partition as part of the delta update direction check. if * magic has not been set flag will have an un-determined value when we go * to check it */ uint8_t flag = SECT_FLAG_NEW; @@ -663,9 +663,10 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) } } + /* Erase remainder of partitions */ +#if defined(WOLFBOOT_FLASH_MULTI_SECTOR_ERASE) || defined(PRINTF_ENABLED) /* calculate number of remaining bytes */ /* reserve 1 sector for status (2 sectors for NV write once) */ -#if defined(WOLFBOOT_FLASH_MULTI_SECTOR_ERASE) || defined(PRINTF_ENABLED) #ifdef NVM_FLASH_WRITEONCE size = WOLFBOOT_PARTITION_SIZE - (sector * sector_size) - (2 * sector_size); #else @@ -677,8 +678,9 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) #endif #ifdef WOLFBOOT_FLASH_MULTI_SECTOR_ERASE - /* Performant option: Erase remainder of flash sectors in one HAL command */ - /* If the HAL supports erase of multiple sectors this could improve performance */ + /* Erase remainder of flash sectors in one HAL command. */ + /* This can improve performance if the HAL supports erase of + * multiple sectors */ wb_flash_erase(&boot, sector * sector_size, size); wb_flash_erase(&update, sector * sector_size, size); #else From 55e9efe2c5b73deb6fc8a1d8ca9c5e910df22fe4 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 2 Oct 2024 15:33:10 -0700 Subject: [PATCH 12/19] Fix for nRF5340 `uart_write` issue with memchr args, which caused occasional corrupt characters to be printed. Improve core state description in logging. Enabled network core test app GPIO work on `LED2 P0.29`. --- config/examples/nrf5340.config | 4 +- config/examples/nrf5340_net.config | 2 +- docs/Targets.md | 148 ++++++++++++++++++--------- hal/nrf5340.c | 49 ++++++--- hal/nrf5340.h | 1 + test-app/app_nrf5340.c | 6 +- test-app/app_nrf5340_net.c | 6 +- tools/scripts/nrf5340/build_flash.sh | 18 +++- 8 files changed, 165 insertions(+), 69 deletions(-) diff --git a/config/examples/nrf5340.config b/config/examples/nrf5340.config index 1c2480e7fa..18b4c5b21b 100644 --- a/config/examples/nrf5340.config +++ b/config/examples/nrf5340.config @@ -57,5 +57,5 @@ CFLAGS_EXTRA+=-DFLASHBUFFER_SIZE=0x1000 # Use UART0 on P0.22 #CFLAGS_EXTRA+=-DUART_PORT=0 -DUART_PIN=22 -CFLAGS_EXTRA+=-DDEBUG_FLASH -CFLAGS_EXTRA+=-DDEBUG_QSPI=1 +#CFLAGS_EXTRA+=-DDEBUG_FLASH +#CFLAGS_EXTRA+=-DDEBUG_QSPI=1 diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config index 45d4d8944f..15381049da 100644 --- a/config/examples/nrf5340_net.config +++ b/config/examples/nrf5340_net.config @@ -50,4 +50,4 @@ DEBUG?=0 DEBUG_UART?=1 USE_GCC=1 -CFLAGS_EXTRA+=-DDEBUG_FLASH +#CFLAGS_EXTRA+=-DDEBUG_FLASH diff --git a/docs/Targets.md b/docs/Targets.md index 845f3daa59..de433d72da 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -2195,73 +2195,129 @@ Application Core: ``` wolfBoot HAL Init (app core) -QSPI Freq=24MHz (Div Clk=3/Sck=1), Addr=24-bits, PageSz=256 -QSPI Activate -QSPI Flash ID (ret 0): 0xC2 0x28 0x17 -Status Reg: Ret 0, 0x40 (Quad Enabled: Yes) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x2000012C -Update partition: 0x0 (sz 7864, ver 0x2, type 0x201) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x100000 -> 0x2000012C -Update partition: 0x100000 (sz 5780, ver 0x2, type 0x202) -Network Image: Ver 0x2, Size 5780 -Network Core: Holding for update -Status: App 1 (ver 2), Net 1 (ver 1) -QSPI Flash ID (ret 0): 0xC2 0x28 0x17 -Status Reg: Ret 0, 0x40 (Quad Enabled: Yes) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x20000230 -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x20000230 -Boot partition: 0xC000 (sz 7864, ver 0x1, type 0x201) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x2000012C -Update partition: 0x0 (sz 7864, ver 0x2, type 0x201) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 4 , 0xEDFFC -> 0x20000230 -Boot partition: 0xC000 (sz 7864, ver 0x1, type 0x201) +Boot header magic 0x00000000 invalid at 0x20000128 +Update partition: 0x100000 (sz 4120, ver 0x1, type 0x202) +Network Image: Update not found +Network Core: Releasing for boot +Status: App 8 (ver 0), Net 1 (ver 1) +Boot partition: 0xC000 (sz 4832, ver 0x1, type 0x201) +Boot header magic 0x00000000 invalid at 0x20000128 +Boot partition: 0xC000 (sz 4832, ver 0x1, type 0x201) Booting version: 0x1 -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x0 -> 0x2000012C -Update partition: 0x0 (sz 7864, ver 0x2, type 0x201) -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x100000 -> 0x2000012C -Update partition: 0x100000 (sz 5780, ver 0x2, type 0x202) -Network Image: Ver 0x2, Size 5780 -Found Network Core update: Ver 1->2, Size 6036->6036 -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 256 , 0x101700 -> 0x2000002C +Waiting for network core... +======================== +nRF5340 wolfBoot (app core) +Copyright 2024 wolfSSL Inc +GPL v3 +Version : 0x1 +======================== +``` + +Network Core: + +``` +wolfBoot HAL Init (net core) +Boot partition: 0x100C000 (sz 4120, ver 0x1, type 0x202) +Network Image: Ver 0x1, Size 4120 +Waiting for status from app core... +Status: App 8 (ver 0), Net 1 (ver 2) +Boot partition: 0x100C000 (sz 4120, ver 0x1, type 0x202) +Boot header magic 0xF7E99810 invalid at 0x21000128 +Boot partition: 0x100C000 (sz 4120, ver 0x1, type 0x202) +Booting version: 0x1 +======================== +nRF5340 wolfBoot (net core) +Copyright 2024 wolfSSL Inc +GPL v3 +Version : 0x1 +======================== +``` + +Example output when doing an update: + +Application Core: + +``` +wolfBoot HAL Init (app core) +Update partition: 0x0 (sz 4832, ver 0x2, type 0x201) +Network Image: Ver 0x2, Size 4832 +Found Network Core update: Ver 1->2, Size 4376->5088 Network image valid, loading into shared mem -QSPI Flash Read: Ret 0, Cmd 0xEB, Len 6036 , 0x100000 -> 0x20010020 +Waiting for net core update to finish... Network core firmware update done +Status: App 8 (ver 2), Net 4 (ver 2) +Update partition: 0x0 (sz 4832, ver 0x2, type 0x201) +Boot partition: 0xC000 (sz 4832, ver 0x1, type 0x201) +Update partition: 0x0 (sz 4832, ver 0x2, type 0x201) +Staring Update (fallback allowed 0) +Update partition: 0x0 (sz 4832, ver 0x2, type 0x201) +Boot partition: 0xC000 (sz 4832, 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) +Boot partition: 0xC000 (sz 4832, ver 0x2, type 0x201) +Boot header magic 0x00000000 invalid at 0x20000128 +Copy sector 1 (part 1->2) +Copy sector 1 (part 0->1) +Copy sector 1 (part 2->0) +Erasing remainder of partitions (235 sectors)... +Boot partition: 0xC000 (sz 4832, ver 0x2, type 0x201) +Boot header magic 0x00000000 invalid at 0x20000128 +Copy sector 236 (part 0->2) +Boot partition: 0xC000 (sz 4832, ver 0x2, type 0x201) +Booting version: 0x2 +Waiting for network core... ======================== nRF5340 wolfBoot (app core) Copyright 2024 wolfSSL Inc GPL v3 -Version : 0x1 +Version : 0x2 ======================== -Internal Flash Write: addr 0xF9FFC, len 4 -Internal Flash Write: addr 0xF9FFB, len 1 ``` Network Core: ``` wolfBoot HAL Init (net core) -Boot partition: 0x100C000 (sz 5780, ver 0x1, type 0x201) -Network Image: Ver 0x1, Size 5780 -Starting update: Ver 1->2, Size 6036->6036 -Internal Flash Erase: addr 0x100C000, len 6036 -Internal Flash Erase: page 0x100C000 -Internal Flash Erase: page 0x100C800 -Internal Flash Erase: page 0x100D000 -Internal Flash Write: addr 0x100C000, len 6036 -Boot partition: 0x100C000 (sz 5780, ver 0x2, type 0x202) -Network Image: Ver 0x2, Size 5780 -Network version (after update): 0x2 -Status: App 2 (ver 2), Net 4 (ver 2) -Boot partition: 0x100C000 (sz 5780, ver 0x2, type 0x202) +Boot partition: 0x100C000 (sz 4120, ver 0x1, type 0x201) +Network Image: Ver 0x1, Size 4120 +Waiting for status from app core... +Starting update: Ver 1->2, Size 4376->4376 +Status: App 2 (ver 2), Net 1 (ver 1) +Update partition: 0x100000 (sz 4120, ver 0x2, type 0x202) +Boot partition: 0x100C000 (sz 4120, ver 0x1, type 0x201) +Update partition: 0x100000 (sz 4120, ver 0x2, type 0x202) +Staring Update (fallback allowed 0) +Update partition: 0x100000 (sz 4120, ver 0x2, type 0x202) +Boot partition: 0x100C000 (sz 4120, 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) +Boot partition: 0x100C000 (sz 4120, ver 0x2, type 0x202) +Update partition: 0x100000 (sz 4120, ver 0x1, type 0x201) +Copy sector 1 (part 1->2) +Copy sector 1 (part 0->1) +Copy sector 1 (part 2->0) +Copy sector 2 (part 1->2) +Copy sector 2 (part 0->1) +Copy sector 2 (part 2->0) +Erasing remainder of partitions (88 sectors)... +Boot partition: 0x100C000 (sz 4120, ver 0x2, type 0x202) +Update partition: 0x100000 (sz 4120, ver 0x1, type 0x201) +Copy sector 90 (part 0->2) +Boot partition: 0x100C000 (sz 4120, ver 0x2, type 0x202) Booting version: 0x2 +Boot partition: 0x100C000 (sz 4120, ver 0x2, type 0x202) +Network Image: Ver 0x2, Size 4120 +Network version (after update): 0x2 ======================== nRF5340 wolfBoot (net core) Copyright 2024 wolfSSL Inc GPL v3 Version : 0x2 ======================== -Internal Flash Write: addr 0x1039FFC, len 4 -Internal Flash Write: addr 0x1039FFB, len 1 ``` ### Building / Flashing Nordic nRF5340 diff --git a/hal/nrf5340.c b/hal/nrf5340.c index aa3a0dfd6d..aece46105d 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -98,9 +98,11 @@ static int do_update = 0; #define UART_SEL 0 /* select UART 0 or 1 */ #endif #if !defined(UART_PORT) && !defined(UART_PIN) - #if UART_SEL == 0 && !defined(TARGET_nrf5340_net) + #if defined(TARGET_nrf5340_app) #define UART_PORT 0 #define UART_PIN 20 + #define UART_NET_PORT 1 + #define UART_NET_PIN 1 #else #define UART_PORT 1 #define UART_PIN 1 @@ -109,8 +111,9 @@ static int do_update = 0; void uart_init(void) { - /* nRF5340-DK: - * App: UART0=P1.01, UART1=P0.20 */ + /* nRF5340-DK: (P0.20 or P1.01) + * App: UART0=P0.20 + * Net: UART0=P1.01 */ UART_ENABLE(UART_SEL) = 0; GPIO_PIN_CNF(UART_PORT, UART_PIN) = (GPIO_CNF_OUT #ifdef TARGET_nrf5340_net @@ -122,9 +125,11 @@ void uart_init(void) UART_CONFIG(UART_SEL) = 0; /* Flow=Diabled, Stop=1-bit, Parity exclude */ UART_ENABLE(UART_SEL) = 8; - /* allow network core access to P1.01 - must be set from application core */ -#ifdef TARGET_nrf5340_app - GPIO_PIN_CNF(1, 1) = (GPIO_CNF_OUT | GPIO_CNF_MCUSEL(1)); + /* allow network core access to UART pin - must be set from app core */ +#if defined(TARGET_nrf5340_app) && \ + defined(UART_NET_PORT) && defined(UART_NET_PIN) + GPIO_PIN_CNF(UART_NET_PORT, UART_NET_PIN) = + (GPIO_CNF_OUT | GPIO_CNF_MCUSEL(1)); #endif } @@ -160,18 +165,20 @@ void uart_write(const char* buf, unsigned int sz) unsigned int lineSz; do { /* find `\n` */ - line = memchr(buf, sz, '\n'); + line = memchr(buf, '\n', sz); if (line == NULL) { uart_write_sz(buf, sz); break; } lineSz = line - buf; + if (lineSz > sz-1) + lineSz = sz-1; - uart_write_sz(line, lineSz); - uart_write_sz("\r", 1); /* handle CRLF */ + uart_write_sz(buf, lineSz); + uart_write_sz("\r\n", 2); /* handle CRLF */ buf = line; - sz -= lineSz; + sz -= lineSz + 1; /* skip \n, already sent */ } while ((int)sz > 0); } #endif /* DEBUG_UART */ @@ -427,6 +434,23 @@ static int hal_shm_status_wait(ShmInfo_t* info, uint32_t status, return ret; } +static const char* hal_shm_status_string(uint32_t status) +{ + switch (status) { + case SHARED_STATUS_READY: + return "Ready"; + case SHARED_STATUS_UPDATE_START: + return "Update Start"; + case SHARED_STATUS_UPDATE_DONE: + return "Update Done"; + case SHARED_STATUS_DO_BOOT: + return "Do boot"; + default: + break; + } + return "Unknown"; +} + /* Handles network core updates */ static void hal_net_check_version(void) { @@ -510,8 +534,9 @@ static void hal_net_check_version(void) } #endif /* TARGET_nrf5340_* */ exit: - wolfBoot_printf("Status: App %d (ver %d), Net %d (ver %d)\n", - shm->app.status, shm->app.version, shm->net.status, shm->net.version); + wolfBoot_printf("Status: App %s (ver %d), Net %s (ver %d)\n", + hal_shm_status_string(shm->app.status), shm->app.version, + hal_shm_status_string(shm->net.status), shm->net.version); } void hal_init(void) diff --git a/hal/nrf5340.h b/hal/nrf5340.h index 750aece53c..535c0fe529 100644 --- a/hal/nrf5340.h +++ b/hal/nrf5340.h @@ -236,6 +236,7 @@ void sleep_us(unsigned int us); #endif #define UART_TASK_STARTTX(n) *((volatile uint32_t *)(UART_BASE(n) + 0x008)) #define UART_TASK_STOPTX(n) *((volatile uint32_t *)(UART_BASE(n) + 0x00C)) +#define UART_EVENT_TXDRDY(n) *((volatile uint32_t *)(UART_BASE(n) + 0x11C)) #define UART_EVENT_ENDTX(n) *((volatile uint32_t *)(UART_BASE(n) + 0x120)) #define UART_ENABLE(n) *((volatile uint32_t *)(UART_BASE(n) + 0x500)) #define UART_PSEL_TXD(n) *((volatile uint32_t *)(UART_BASE(n) + 0x50C)) diff --git a/test-app/app_nrf5340.c b/test-app/app_nrf5340.c index e20183441c..67d35fd20b 100644 --- a/test-app/app_nrf5340.c +++ b/test-app/app_nrf5340.c @@ -45,7 +45,9 @@ void main(void) uint32_t pin = 28; uint32_t app_version; - GPIO_PIN_CNF(port, pin) = 1; /* Output */ + GPIO_PIN_CNF(port, pin) = GPIO_CNF_OUT; + /* Allow network core access to P0.29 GPIO */ + GPIO_PIN_CNF(0, 29) = (GPIO_CNF_OUT | GPIO_CNF_MCUSEL(1)); app_version = wolfBoot_current_firmware_version(); @@ -55,7 +57,7 @@ void main(void) wolfBoot_printf("nRF5340 wolfBoot (app core)\n"); wolfBoot_printf("Copyright 2024 wolfSSL Inc\n"); wolfBoot_printf("GPL v3\n"); - wolfBoot_printf("Version : 0x%lx\r\n", app_version); + wolfBoot_printf("Version : 0x%lx\n", app_version); wolfBoot_printf("========================\n"); /* mark boot successful */ diff --git a/test-app/app_nrf5340_net.c b/test-app/app_nrf5340_net.c index 2a6605a6e5..806d5b7f83 100644 --- a/test-app/app_nrf5340_net.c +++ b/test-app/app_nrf5340_net.c @@ -42,10 +42,10 @@ void main(void) * LED3 P0.30 * LED4 P0.31 */ uint32_t port = 0; - uint32_t pin = 28; + uint32_t pin = 29; uint32_t app_version; - GPIO_PIN_CNF(port, pin) = 1; /* Output */ + GPIO_PIN_CNF(port, pin) = GPIO_CNF_OUT; app_version = wolfBoot_current_firmware_version(); @@ -55,7 +55,7 @@ void main(void) wolfBoot_printf("nRF5340 wolfBoot (net core)\n"); wolfBoot_printf("Copyright 2024 wolfSSL Inc\n"); wolfBoot_printf("GPL v3\n"); - wolfBoot_printf("Version : 0x%lx\r\n", app_version); + wolfBoot_printf("Version : 0x%lx\n", app_version); wolfBoot_printf("========================\n"); /* mark boot successful */ diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index 6fe7d8bac3..c8eebe941c 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -4,6 +4,17 @@ # run from wolfBoot root # ./tools/scripts/nrf5340/build_flash.sh +# optionally run with "erase" argument to rease both internal and external flash +# or provide make arguments "DEBUG=1" + + +if [ "$1" == "erase" ]; then + DO_ERASE=1 + MAKE_ARGS="$2" +else + DO_ERASE=0 + MAKE_ARGS="$1" +fi rm -f ./tools/scripts/nrf5340/*.bin rm -f ./tools/scripts/nrf5340/*.hex @@ -13,7 +24,7 @@ rm -f ./tools/scripts/nrf5340/*.hex # Build net cp config/examples/nrf5340_net.config .config make clean -make DEBUG=1 +make $MAKE_ARGS cp factory.bin tools/scripts/nrf5340/factory_net.bin # Sign flash update for testing (use partition type 2 for network update) tools/keytools/sign --ecc256 --id 2 test-app/image.bin wolfboot_signing_private_key.der 2 @@ -22,7 +33,8 @@ cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_net.bin # Build app cp config/examples/nrf5340.config .config make clean -make DEBUG=1 +make $MAKE_ARGS + cp factory.bin tools/scripts/nrf5340/factory_app.bin # Sign flash update for testing tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 2 @@ -44,7 +56,7 @@ arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scri arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10100000 tools/scripts/nrf5340/image_v2_signed_net.bin tools/scripts/nrf5340/image_v2_signed_net.hex -if [ "$1" == "erase" ]; then +if [ "$DO_ERASE" == "1" ]; then nrfjprog -f nrf53 --recover nrfjprog -f nrf53 --qspieraseall fi From c0688efbd25a1fadd838b5404bbb9bc1d1dd15ef Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 2 Oct 2024 15:57:25 -0700 Subject: [PATCH 13/19] Improve the nRF5340 build script to support arguments. --- tools/scripts/nrf5340/build_flash.sh | 170 ++++++++++++++++++--------- 1 file changed, 114 insertions(+), 56 deletions(-) diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index c8eebe941c..59c011ffd8 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -4,70 +4,128 @@ # run from wolfBoot root # ./tools/scripts/nrf5340/build_flash.sh -# optionally run with "erase" argument to rease both internal and external flash -# or provide make arguments "DEBUG=1" - -if [ "$1" == "erase" ]; then +# optionally run with "--erase" argument to rease both internal and external flash + +# Defaults +MAKE_ARGS= +DO_BUILD=0 +DO_BUILD_DEBUG=0 +DO_ERASE=0 +DO_PROGRAM=0 +if [[ $# -eq 0 ]] ; then + DO_BUILD=1 + DO_BUILD_DEBUG=0 DO_ERASE=1 - MAKE_ARGS="$2" -else - DO_ERASE=0 - MAKE_ARGS="$1" + DO_PROGRAM=1 + echo "Build release with symbols, erase and program" fi -rm -f ./tools/scripts/nrf5340/*.bin -rm -f ./tools/scripts/nrf5340/*.hex - -# Build internal flash images for both cores - -# Build net -cp config/examples/nrf5340_net.config .config -make clean -make $MAKE_ARGS -cp factory.bin tools/scripts/nrf5340/factory_net.bin -# Sign flash update for testing (use partition type 2 for network update) -tools/keytools/sign --ecc256 --id 2 test-app/image.bin wolfboot_signing_private_key.der 2 -cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_net.bin - -# Build app -cp config/examples/nrf5340.config .config -make clean -make $MAKE_ARGS - -cp factory.bin tools/scripts/nrf5340/factory_app.bin -# Sign flash update for testing -tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 2 -cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_app.bin - -# Create a bin footer with wolfBoot trailer "BOOT" and "p" (ASCII for 0x70 == IMG_STATE_UPDATING): -echo -n "pBOOT" > tools/scripts/nrf5340/trigger_magic.bin -./tools/bin-assemble/bin-assemble \ - tools/scripts/nrf5340/update_app_v2.bin \ - 0x0 tools/scripts/nrf5340/image_v2_signed_app.bin \ - 0xEDFFB tools/scripts/nrf5340/trigger_magic.bin - - -# Convert to HEX format for programmer tool -arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x00000000 tools/scripts/nrf5340/factory_app.bin tools/scripts/nrf5340/factory_app.hex -arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x01000000 tools/scripts/nrf5340/factory_net.bin tools/scripts/nrf5340/factory_net.hex - -arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/update_app_v2.bin tools/scripts/nrf5340/update_app_v2.hex -arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10100000 tools/scripts/nrf5340/image_v2_signed_net.bin tools/scripts/nrf5340/image_v2_signed_net.hex - +while test $# -gt 0; do + case "$1" in + -h|--help|-?) + echo "nRF5340 build / flash script" + echo " " + echo "default: build, erase and program" + echo " " + echo "options:" + echo "-h, --help show brief help" + echo "-b, --build build release with symbols" + echo "-d, --debug build debug" + echo "-v, --verbose build verbose" + echo "-e, --erase do erase of internal/external flash" + echo "-p, --program program images built" + exit 0 + ;; + -b|--build) + DO_BUILD=1 + MAKE_ARGS+=" DEBUG_SYMBOLS=1" + echo "Build release with symbols" + shift + ;; + -d|--debug) + DO_BUILD=1 + MAKE_ARGS+=" DEBUG=1" + echo "Build with debug" + shift + ;; + -v|--verbose) + DO_BUILD=1 + MAKE_ARGS+=" V=1" + echo "Build with verbose output" + shift + ;; + -e|--erase) + DO_ERASE=1 + echo "Do erase" + shift + ;; + -p|--program) + DO_PROGRAM=1 + echo "Do program" + shift + ;; + *) + break + ;; + esac +done + +if [[ $DO_BUILD == 1 ]]; then + rm -f ./tools/scripts/nrf5340/*.bin + rm -f ./tools/scripts/nrf5340/*.hex + + # Build internal flash images for both cores + + # Build net + cp config/examples/nrf5340_net.config .config + make clean + make $MAKE_ARGS + cp factory.bin tools/scripts/nrf5340/factory_net.bin + # Sign flash update for testing (use partition type 2 for network update) + tools/keytools/sign --ecc256 --id 2 test-app/image.bin wolfboot_signing_private_key.der 2 + cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_net.bin + + # Build app + cp config/examples/nrf5340.config .config + make clean + make $MAKE_ARGS + + cp factory.bin tools/scripts/nrf5340/factory_app.bin + # Sign flash update for testing + tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 2 + cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_app.bin + + # Create a bin footer with wolfBoot trailer "BOOT" and "p" (ASCII for 0x70 == IMG_STATE_UPDATING): + echo -n "pBOOT" > tools/scripts/nrf5340/trigger_magic.bin + ./tools/bin-assemble/bin-assemble \ + tools/scripts/nrf5340/update_app_v2.bin \ + 0x0 tools/scripts/nrf5340/image_v2_signed_app.bin \ + 0xEDFFB tools/scripts/nrf5340/trigger_magic.bin + + + # Convert to HEX format for programmer tool + arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x00000000 tools/scripts/nrf5340/factory_app.bin tools/scripts/nrf5340/factory_app.hex + arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x01000000 tools/scripts/nrf5340/factory_net.bin tools/scripts/nrf5340/factory_net.hex + + arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/update_app_v2.bin tools/scripts/nrf5340/update_app_v2.hex + arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10100000 tools/scripts/nrf5340/image_v2_signed_net.bin tools/scripts/nrf5340/image_v2_signed_net.hex +fi -if [ "$DO_ERASE" == "1" ]; then +if [[ $DO_ERASE == 1 ]]; then nrfjprog -f nrf53 --recover nrfjprog -f nrf53 --qspieraseall fi -# Program external flash -nrfjprog -f nrf53 --program tools/scripts/nrf5340/update_app_v2.hex --verify -nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_net.hex --verify +if [[ $DO_PROGRAM == 1 ]]; then + # Program external flash + nrfjprog -f nrf53 --program tools/scripts/nrf5340/update_app_v2.hex --verify + nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_net.hex --verify -# Program Internal Flash -#nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_app.hex --verify -#nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_net.hex --verify --coprocessor CP_NETWORK -JLinkExe -CommandFile tools/scripts/nrf5340/flash_net.jlink -JLinkExe -CommandFile tools/scripts/nrf5340/flash_app.jlink + # Program Internal Flash + #nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_app.hex --verify + #nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_net.hex --verify --coprocessor CP_NETWORK + JLinkExe -CommandFile tools/scripts/nrf5340/flash_net.jlink + JLinkExe -CommandFile tools/scripts/nrf5340/flash_app.jlink +fi From f04d36f9866a778118965f5cc0ff8b6f3906d870 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 3 Oct 2024 16:50:57 -0700 Subject: [PATCH 14/19] Enable ECC384 and SHA384. Fix sleep_us. Add Cortex-M hard-fault handler support. --- config/examples/nrf5340.config | 8 ++- config/examples/nrf5340_net.config | 11 +++- hal/nrf5340.c | 28 +++++++-- hal/nrf5340.ld | 1 + hal/nrf5340_net.ld | 1 + include/loader.h | 2 + src/boot_arm.c | 87 ++++++++++++++++++++++++++++ src/loader.c | 2 + test-app/app_nrf5340.c | 2 +- test-app/app_nrf5340_net.c | 2 +- tools/scripts/nrf5340/build_flash.sh | 7 ++- 11 files changed, 137 insertions(+), 14 deletions(-) diff --git a/config/examples/nrf5340.config b/config/examples/nrf5340.config index 18b4c5b21b..83be6bdaae 100644 --- a/config/examples/nrf5340.config +++ b/config/examples/nrf5340.config @@ -1,8 +1,8 @@ ARCH?=ARM TZEN?=0 TARGET?=nrf5340 -SIGN?=ECC256 -HASH?=SHA256 +SIGN?=ECC384 +HASH?=SHA384 WOLFBOOT_VERSION?=1 VTOR?=1 CORTEX_M0?=0 @@ -44,6 +44,7 @@ V?=0 DEBUG?=0 DEBUG_UART?=1 USE_GCC=1 +OPTIMIZATION_LEVEL=2 # Optionally wait for network core to boot before starting application core CFLAGS_EXTRA+=-DNRF_SYNC_CORES @@ -59,3 +60,6 @@ CFLAGS_EXTRA+=-DFLASHBUFFER_SIZE=0x1000 #CFLAGS_EXTRA+=-DDEBUG_FLASH #CFLAGS_EXTRA+=-DDEBUG_QSPI=1 + +# Hard fault debugging +#CFLAGS_EXTRA+=-DDEBUG_HARDFAULT diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config index 15381049da..cefe4ad2fd 100644 --- a/config/examples/nrf5340_net.config +++ b/config/examples/nrf5340_net.config @@ -1,8 +1,8 @@ ARCH?=ARM TZEN?=0 TARGET?=nrf5340_net -SIGN?=ECC256 -HASH?=SHA256 +SIGN?=ECC384 +HASH?=SHA384 WOLFBOOT_VERSION?=1 VTOR?=1 CORTEX_M0?=0 @@ -49,5 +49,12 @@ V?=0 DEBUG?=0 DEBUG_UART?=1 USE_GCC=1 +OPTIMIZATION_LEVEL=2 #CFLAGS_EXTRA+=-DDEBUG_FLASH + +# If debugging network core disable the shared memory, since app core has not enabled access to it +#CFLAGS_EXTRA+=-DDISABLE_SHARED_MEM + +# Hard fault debugging +#CFLAGS_EXTRA+=-DDEBUG_HARDFAULT diff --git a/hal/nrf5340.c b/hal/nrf5340.c index aece46105d..cf3cd3886e 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -85,7 +85,9 @@ typedef struct { /* used as "swap" */ uint8_t swap[FLASH_PAGESZ_NET]; } SharedMem_t; +#ifndef DISABLE_SHARED_MEM static SharedMem_t* shm = (SharedMem_t*)SHARED_MEM_ADDR; +#endif /* !DISABLE_SHARED_MEM */ #ifdef TARGET_nrf5340_net static int do_update = 0; @@ -275,7 +277,9 @@ int ext_flash_write(uintptr_t address, const uint8_t *data, int len) wolfBoot_printf("Ext Write: Len %d, Addr 0x%x (off 0x%x) -> 0x%x\n", len, address, addr, data); #endif +#ifndef DISABLE_SHARED_MEM memcpy(shm->data + addr, data, len); +#endif return 0; } @@ -286,8 +290,9 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len) wolfBoot_printf("Ext Read: Len %d, Addr 0x%x (off 0x%x) -> %p\n", len, address, addr, data); #endif - +#ifndef DISABLE_SHARED_MEM memcpy(data, shm->data + addr, len); +#endif return len; } @@ -298,7 +303,9 @@ int ext_flash_erase(uintptr_t address, int len) wolfBoot_printf("Ext Erase: Len %d, Addr 0x%x (off 0x%x)\n", len, address, addr); #endif +#ifndef DISABLE_SHARED_MEM memset(shm->data + addr, FLASH_BYTE_ERASED, len); +#endif return 0; } @@ -325,13 +332,13 @@ static void clock_init(void) void sleep_us(unsigned int us) { /* Calculate ops per us (128MHz=128 instructions per 1us */ - unsigned long nop_us = (CPU_CLOCK / 10000000); + unsigned long nop_us = (CPU_CLOCK / 1000000); nop_us *= us; /* instruction for each iteration */ #ifdef DEBUG - nop_us /= 5; + nop_us /= 30; #else - nop_us /= 2; + nop_us /= 5; #endif while (nop_us-- > 0) { NOP(); @@ -358,6 +365,7 @@ void hal_net_core(int hold) /* 1=hold, 0=release */ } #endif +#ifndef DISABLE_SHARED_MEM static uint8_t* get_image_hdr(struct wolfBoot_image* img) { #ifdef EXT_FLASH @@ -538,6 +546,8 @@ static void hal_net_check_version(void) hal_shm_status_string(shm->app.status), shm->app.version, hal_shm_status_string(shm->net.status), shm->net.version); } +#endif /* !DISABLE_SHARED_MEM */ + void hal_init(void) { @@ -561,7 +571,9 @@ void hal_init(void) /* need early init of external flash to support checking network core */ spi_flash_probe(); +#ifndef DISABLE_SHARED_MEM hal_net_check_version(); +#endif } @@ -571,6 +583,7 @@ void hal_prepare_boot(void) //WOLFBOOT_ORIGIN //BOOTLOADER_PARTITION_SIZE +#ifndef DISABLE_SHARED_MEM #ifdef TARGET_nrf5340_net if (do_update) { /* signal application core update done */ @@ -591,9 +604,12 @@ void hal_prepare_boot(void) /* if core synchronization enabled, then wait for update_done or do_boot */ wolfBoot_printf("Waiting for network core...\n"); (void)hal_shm_status_wait(&shm->net, - (SHARED_STATUS_UPDATE_DONE | SHARED_STATUS_DO_BOOT), 1000000); -#endif + (SHARED_STATUS_UPDATE_DONE | SHARED_STATUS_DO_BOOT), 2000000); +#endif /* NRF_SYNC_CORES */ +#endif /* TARGET_nrf5340_app */ +#endif /* !DISABLE_SHARED_MEM */ +#ifdef TARGET_nrf5340_app /* Restore defaults preventing network core from accessing shared SDRAM */ SPU_EXTDOMAIN_PERM(0) = (SPU_EXTDOMAIN_PERM_SECATTR_NONSECURE | SPU_EXTDOMAIN_PERM_UNLOCK); diff --git a/hal/nrf5340.ld b/hal/nrf5340.ld index 9f1c9809e6..c65e9c5748 100644 --- a/hal/nrf5340.ld +++ b/hal/nrf5340.ld @@ -11,6 +11,7 @@ SECTIONS { _start_text = .; KEEP(*(.isr_vector)) + *(.boot*) *(.text*) *(.rodata*) *(.init*) diff --git a/hal/nrf5340_net.ld b/hal/nrf5340_net.ld index 8882538757..9f842bfdab 100644 --- a/hal/nrf5340_net.ld +++ b/hal/nrf5340_net.ld @@ -10,6 +10,7 @@ SECTIONS { _start_text = .; KEEP(*(.isr_vector)) + *(.boot*) *(.text*) *(.rodata*) *(.init*) diff --git a/include/loader.h b/include/loader.h index 0c55f819ed..d9a8e930d4 100644 --- a/include/loader.h +++ b/include/loader.h @@ -102,8 +102,10 @@ static inline void wolfBoot_panic(void) wolfBoot_panicked++; } #else +#include "printf.h" static inline void wolfBoot_panic(void) { + wolfBoot_printf("wolfBoot: PANIC!\n"); while(1) ; } diff --git a/src/boot_arm.c b/src/boot_arm.c index b64fde4450..d975365c04 100644 --- a/src/boot_arm.c +++ b/src/boot_arm.c @@ -23,6 +23,7 @@ #include "image.h" #include "loader.h" +#include "printf.h" #include "wolfboot/wolfboot.h" extern unsigned int _start_text; @@ -296,11 +297,97 @@ asm( #endif /* CORTEX_R5 */ +#ifdef DEBUG_HARDFAULT +__attribute__((section(".boot"))) __attribute__((used)) +void HardFault_HandlerC( uint32_t *hardfault_args ) +{ + /* Using volatile to prevent the compiler/linker optimizing them out */ + volatile uint32_t stacked_r0; + volatile uint32_t stacked_r1; + volatile uint32_t stacked_r2; + volatile uint32_t stacked_r3; + volatile uint32_t stacked_r12; + volatile uint32_t stacked_lr; + volatile uint32_t stacked_pc; + volatile uint32_t stacked_psr; + volatile uint32_t _CFSR; + volatile uint32_t _HFSR; + volatile uint32_t _DFSR; + volatile uint32_t _AFSR; + volatile uint32_t _BFAR; + volatile uint32_t _MMAR; + + stacked_r0 = ((uint32_t)hardfault_args[0]); + stacked_r1 = ((uint32_t)hardfault_args[1]); + stacked_r2 = ((uint32_t)hardfault_args[2]); + stacked_r3 = ((uint32_t)hardfault_args[3]); + stacked_r12 = ((uint32_t)hardfault_args[4]); + stacked_lr = ((uint32_t)hardfault_args[5]); + stacked_pc = ((uint32_t)hardfault_args[6]); + stacked_psr = ((uint32_t)hardfault_args[7]); + + /* Configurable Fault Status Register */ + /* Consists of MMSR, BFSR and UFSR */ + _CFSR = (*((volatile uint32_t *)(0xE000ED28))); + /* Hard Fault Status Register */ + _HFSR = (*((volatile uint32_t *)(0xE000ED2C))); + /* Debug Fault Status Register */ + _DFSR = (*((volatile uint32_t *)(0xE000ED30))); + /* Auxiliary Fault Status Register */ + _AFSR = (*((volatile uint32_t *)(0xE000ED3C))); + /* MemManage Fault Address Register */ + _MMAR = (*((volatile uint32_t *)(0xE000ED34))); + /* Bus Fault Address Register */ + _BFAR = (*((volatile uint32_t *)(0xE000ED38))); + + wolfBoot_printf("\n\nHard fault handler (all numbers in hex):\n"); + wolfBoot_printf("R0 = %lx\n", stacked_r0); + wolfBoot_printf("R1 = %lx\n", stacked_r1); + wolfBoot_printf("R2 = %lx\n", stacked_r2); + wolfBoot_printf("R3 = %lx\n", stacked_r3); + wolfBoot_printf("R12 = %lx\n", stacked_r12); + wolfBoot_printf("LR [R14] = %lx subroutine call return address\n", + stacked_lr); + wolfBoot_printf("PC [R15] = %lx program counter\n", stacked_pc); + wolfBoot_printf("PSR = %lx\n", stacked_psr); + wolfBoot_printf("CFSR = %lx\n", _CFSR); + wolfBoot_printf("HFSR = %lx\n", _HFSR); + wolfBoot_printf("DFSR = %lx\n", _DFSR); + wolfBoot_printf("AFSR = %lx\n", _AFSR); + wolfBoot_printf("MMAR = %lx\n", _MMAR); + wolfBoot_printf("BFAR = %lx\n", _BFAR); + + /* Break into the debugger */ + __asm("BKPT #0\n"); +} + +__attribute__((section(".boot"))) __attribute__((naked)) +void isr_fault(void) +{ + __asm volatile + ( + " movs r0,#4 \n" /* load bit mask into R0 */ + " mov r1, lr \n" /* load link register into R1 */ + " tst r0, r1 \n" /* compare with bitmask */ + " beq _MSP \n" /* if bitmask is set: stack pointer is in PSP. Otherwise in MSP */ + " mrs r0, psp \n" /* otherwise: stack pointer is in PSP */ + " b _GetPC \n" /* go to part which loads the PC */ + "_MSP: \n" /* stack pointer is in MSP register */ + " mrs r0, msp \n" /* load stack pointer into R0 */ + "_GetPC: \n" /* find out where the hard fault happened */ + " ldr r1,[r0,#20] \n" /* load program counter into R1. R1 contains address of the next instruction where the hard fault happened */ + " ldr r2, =HardFault_HandlerC \n" + " bx r2 \n" + " bx lr \n" /* decode more information. R0 contains pointer to stack frame */ + ); +} +#else void isr_fault(void) { /* Panic. */ wolfBoot_panic(); } +#endif /* DEBUG_HARDFAULT */ void isr_empty(void) { diff --git a/src/loader.c b/src/loader.c index 797a77ca8d..f9fe865e3d 100644 --- a/src/loader.c +++ b/src/loader.c @@ -33,7 +33,9 @@ #include "image.h" #include "hal.h" #include "spi_flash.h" +#ifdef UART_FLASH #include "uart_flash.h" +#endif #include "wolfboot/wolfboot.h" #ifdef WOLFBOOT_TPM diff --git a/test-app/app_nrf5340.c b/test-app/app_nrf5340.c index 67d35fd20b..49a1644391 100644 --- a/test-app/app_nrf5340.c +++ b/test-app/app_nrf5340.c @@ -67,6 +67,6 @@ void main(void) while (1) { gpiotoggle(port, pin); - sleep_us(100 * 1000); + sleep_us(500 * 1000); } } diff --git a/test-app/app_nrf5340_net.c b/test-app/app_nrf5340_net.c index 806d5b7f83..90fb0a762b 100644 --- a/test-app/app_nrf5340_net.c +++ b/test-app/app_nrf5340_net.c @@ -65,6 +65,6 @@ void main(void) while (1) { gpiotoggle(port, pin); - sleep_us(100 * 1000); + sleep_us(500 * 1000); } } diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index 59c011ffd8..d3a81243b1 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -1,11 +1,14 @@ #!/bin/bash # nRF5340 dual core: Creates internal and external flash images for testing +# Signs each with a new version 2 and places into external flash, +# with flag to trigger update (like calling wolfBoot_update_trigger) # run from wolfBoot root # ./tools/scripts/nrf5340/build_flash.sh # optionally run with "--erase" argument to rease both internal and external flash +# example: ./tools/scripts/nrf5340/build_flash.sh --debug --erase --program # Defaults MAKE_ARGS= @@ -83,7 +86,7 @@ if [[ $DO_BUILD == 1 ]]; then make $MAKE_ARGS cp factory.bin tools/scripts/nrf5340/factory_net.bin # Sign flash update for testing (use partition type 2 for network update) - tools/keytools/sign --ecc256 --id 2 test-app/image.bin wolfboot_signing_private_key.der 2 + tools/keytools/sign --ecc384 --sha384 --id 2 test-app/image.bin wolfboot_signing_private_key.der 2 cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_net.bin # Build app @@ -93,7 +96,7 @@ if [[ $DO_BUILD == 1 ]]; then cp factory.bin tools/scripts/nrf5340/factory_app.bin # Sign flash update for testing - tools/keytools/sign --ecc256 test-app/image.bin wolfboot_signing_private_key.der 2 + tools/keytools/sign --ecc384 --sha384 test-app/image.bin wolfboot_signing_private_key.der 2 cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_app.bin # Create a bin footer with wolfBoot trailer "BOOT" and "p" (ASCII for 0x70 == IMG_STATE_UPDATING): From 03190286a43364060acfae02d0c631870576d505 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 4 Oct 2024 13:47:49 -0700 Subject: [PATCH 15/19] Fix `sleep_us` logic to use RTC. Resolves issue with different optimization levels breaking sleep. Also demonstrates synchronized boot and LED's matching from both cores. --- hal/nrf5340.c | 66 ++++++++++++++++++++++++++++++--------------------- hal/nrf5340.h | 41 +++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 28 deletions(-) diff --git a/hal/nrf5340.c b/hal/nrf5340.c index cf3cd3886e..175082606c 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -38,6 +38,8 @@ * Any key size greater than 128 bits must be divided and distributed over multiple key slot instances. */ +#define USE_RTC 0 /* Use RTC0 for sleep */ + /* Network updates can be signed with "--id 2" and placed into the normal update partition, * or they can be placed into the external flash at offset 0x100000 */ /* Partition ID should be set HDR_IMG_TYPE_APP=2 */ @@ -321,28 +323,38 @@ void ext_flash_unlock(void) static void clock_init(void) { -#ifndef TARGET_nrf5340_net +#ifdef TARGET_nrf5340_app CLOCK_HFCLKSRC = 1; /* use external high frequency clock */ CLOCK_HFCLKSTART = 1; /* wait for high frequency clock startup */ while (CLOCK_HFCLKSTARTED == 0); #endif + /* Start low frequency clock - used by RTC */ + CLOCK_LFCLKSRC = 0; /* internal low power */ + CLOCK_LFCLKSTART = 1; + /* wait for high frequency clock startup */ + while (CLOCK_LFCLKSTARTED == 0); + + RTC_PRESCALER(USE_RTC) = 0; /* 32768 per second */ } -void sleep_us(unsigned int us) +void sleep_us(uint32_t usec) { - /* Calculate ops per us (128MHz=128 instructions per 1us */ - unsigned long nop_us = (CPU_CLOCK / 1000000); - nop_us *= us; - /* instruction for each iteration */ -#ifdef DEBUG - nop_us /= 30; -#else - nop_us /= 5; -#endif - while (nop_us-- > 0) { - NOP(); - } + /* Calculate number ticks to wait */ + uint32_t comp = ((usec * 32768UL) / 1000000); + if (comp == 0) + comp = 1; /* wait at least 1 tick */ + if (comp > RTC_OVERFLOW) + comp = RTC_OVERFLOW; /* max wait (512 seconds with prescaler=0) */ + + RTC_CLEAR(USE_RTC) = 1; + RTC_EVTENSET(USE_RTC) = RTC_EVTENSET_CC0; + RTC_EVENT_CC(USE_RTC, 0) = 0; /* clear compare event */ + RTC_CC(USE_RTC, 0) = comp; + RTC_START(USE_RTC) = 1; + /* wait for compare event */ + while (RTC_EVENT_CC(USE_RTC, 0) == 0); + RTC_STOP(USE_RTC) = 1; } #ifdef TARGET_nrf5340_app @@ -427,15 +439,14 @@ static void hal_shm_status_set(ShmInfo_t* info, uint32_t status) } static int hal_shm_status_wait(ShmInfo_t* info, uint32_t status, - uint32_t timeout_us) + uint32_t timeout_ms) { int ret = 0; - uint32_t timeout = timeout_us; while ((info->magic != SHAREM_MEM_MAGIC || (info->status & status) == 0) - && --timeout > 0) { - sleep_us(1); + && --timeout_ms > 0) { + sleep_us(1000); }; - if (timeout == 0) { + if (timeout_ms == 0) { wolfBoot_printf("Timeout: status 0x%x\n", status); ret = -1; /* timeout */ } @@ -474,8 +485,8 @@ static void hal_net_check_version(void) /* release network core - issue boot command */ hal_net_core(0); - /* wait for ready status from network core */ - ret = hal_shm_status_wait(&shm->net, SHARED_STATUS_READY, 1000000); + /* wait for ready status from network core - 2 seconds */ + ret = hal_shm_status_wait(&shm->net, SHARED_STATUS_READY, 2*1000); /* check if network core can continue booting or needs to wait for update */ if (ret != 0 || shm->app.version <= shm->net.version) { @@ -505,9 +516,9 @@ static void hal_net_check_version(void) wolfBoot_printf("Waiting for net core update to finish...\n"); - /* wait for update_done - note longer wait */ + /* wait for update_done - note longer wait - 10 seconds */ ret = hal_shm_status_wait(&shm->net, - SHARED_STATUS_UPDATE_DONE, 5000000); + SHARED_STATUS_UPDATE_DONE, 10*1000); if (ret == 0) { wolfBoot_printf("Network core firmware update done\n"); } @@ -524,10 +535,10 @@ static void hal_net_check_version(void) hal_net_get_image(&img, &shm->net); hal_shm_status_set(&shm->net, SHARED_STATUS_READY); - /* wait for do_boot or update from app core */ + /* wait for do_boot or update from app core - 2 seconds */ wolfBoot_printf("Waiting for status from app core...\n"); ret = hal_shm_status_wait(&shm->app, - (SHARED_STATUS_UPDATE_START | SHARED_STATUS_DO_BOOT), 1000000); + (SHARED_STATUS_UPDATE_START | SHARED_STATUS_DO_BOOT), 2*1000); /* are we updating? */ if (ret == 0 && shm->app.status == SHARED_STATUS_UPDATE_START) { @@ -601,10 +612,11 @@ void hal_prepare_boot(void) #ifdef TARGET_nrf5340_app #ifdef NRF_SYNC_CORES - /* if core synchronization enabled, then wait for update_done or do_boot */ + /* if core synchronization enabled, + * then wait for update_done or do_boot (5 seconds) */ wolfBoot_printf("Waiting for network core...\n"); (void)hal_shm_status_wait(&shm->net, - (SHARED_STATUS_UPDATE_DONE | SHARED_STATUS_DO_BOOT), 2000000); + (SHARED_STATUS_UPDATE_DONE | SHARED_STATUS_DO_BOOT), 5*1000); #endif /* NRF_SYNC_CORES */ #endif /* TARGET_nrf5340_app */ #endif /* !DISABLE_SHARED_MEM */ diff --git a/hal/nrf5340.h b/hal/nrf5340.h index 535c0fe529..3534a0fac6 100644 --- a/hal/nrf5340.h +++ b/hal/nrf5340.h @@ -70,7 +70,7 @@ #define ISB() __asm__ volatile ("isb") #define NOP() __asm__ volatile ("nop") -void sleep_us(unsigned int us); +void sleep_us(uint32_t usec); /* PSEL Port (bit 5) - Used for various PSEL (UART,SPI,QSPI,I2C,NFC) */ #define PSEL_PORT(n) (((n) & 0x1) << 5) @@ -194,6 +194,16 @@ void sleep_us(unsigned int us); #define CLOCK_HFCLK192MCTRL_DIV2 1 #define CLOCK_HFCLK192MCTRL_DIV4 2 +/* Low frequency: 32.768 kHz */ +#define CLOCK_LFCLKSTART *((volatile uint32_t *)(CLOCK_BASE + 0x008)) +#define CLOCK_LFCLKSTOP *((volatile uint32_t *)(CLOCK_BASE + 0x00C)) +#define CLOCK_LFCLKSTARTED *((volatile uint32_t *)(CLOCK_BASE + 0x104)) +#define CLOCK_LFCLKSRC *((volatile uint32_t *)(CLOCK_BASE + 0x518)) +#define CLOCK_LFCLKSRC_LFULP 0 /* ultra-low power RC oscillator */ +#define CLOCK_LFCLKSRC_LFRC 1 /* RC oscillator */ +#define CLOCK_LFCLKSRC_LFXO 2 /* crystal oscillator */ +#define CLOCK_LFCLKSRC_LFSYNT 3 /* synthesized from HFCLK */ + /* GPIO Port (0-1) */ #ifdef TARGET_nrf5340_app @@ -387,4 +397,33 @@ void uart_write_sz(const char* c, unsigned int sz); #define IPC_RECEIVE_CNF(n) *((volatile uint32_t *)(IPC_BASE + 0x590 + (((n) & 0xF) * 0x4))) #define IPC_GPMEM(n) *((volatile uint32_t *)(IPC_BASE + 0x610 + (((n) & 0x1) * 0x4))) +/* RTC - uses LFCLK - 24-bit counter/compare */ +#ifdef TARGET_nrf5340_app + #ifdef TZEN + #define RTC_BASE(n) ((0x50014000) + (((n) & 0x1) * 0x1000)) + #else + #define RTC_BASE(n) ((0x40014000) + (((n) & 0x1) * 0x1000)) + #endif +#else + #define RTC_BASE(n) (0x41011000) /* network core */ +#endif +#define RTC_START(n) *((volatile uint32_t *)(RTC_BASE(n) + 0x000)) +#define RTC_STOP(n) *((volatile uint32_t *)(RTC_BASE(n) + 0x004)) +#define RTC_CLEAR(n) *((volatile uint32_t *)(RTC_BASE(n) + 0x008)) +#define RTC_EVENT_TICK(n) *((volatile uint32_t *)(RTC_BASE(n) + 0x100)) +#define RTC_EVENT_OVRFLW(n) *((volatile uint32_t *)(RTC_BASE(n) + 0x104)) +#define RTC_EVENT_CC(n,i) *((volatile uint32_t *)(RTC_BASE(n) + 0x140 + ((i) & 0x3) * 0x4)) +#define RTC_EVTENSET(n) *((volatile uint32_t *)(RTC_BASE(n) + 0x344)) +#define RTC_EVTENSET_TICK (1 << 0) +#define RTC_EVTENSET_OVRFLW (1 << 1) +#define RTC_EVTENSET_CC0 (1 << 16) +#define RTC_EVTENSET_CC1 (1 << 17) +#define RTC_EVTENSET_CC2 (1 << 18) +#define RTC_EVTENSET_CC3 (1 << 19) +#define RTC_COUNTER(n) *((volatile uint32_t *)(RTC_BASE(n) + 0x504)) +#define RTC_PRESCALER(n) *((volatile uint32_t *)(RTC_BASE(n) + 0x508)) /* default=0 or 32768 per second (12-bit) up to 0xFFF */ +#define RTC_CC(n,i) *((volatile uint32_t *)(RTC_BASE(n) + 0x540 + ((i) & 0x3) * 0x4)) +#define RTC_OVERFLOW 0xFFFFFFUL + + #endif /* !_HAL_NRF5340_H_ */ From cecb813596242c3cfaff11eb5d44a310dc5c5837 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 4 Oct 2024 16:16:11 -0700 Subject: [PATCH 16/19] Added tests for delta updates. Added logging for delta version errors. Added `SIGN_OPTIONS_EXTRA`. --- config/examples/nrf5340_net.config | 2 + hal/nrf5340.c | 6 +- options.mk | 3 + src/update_flash.c | 5 + test-app/app_nrf5340.c | 1 + test-app/app_nrf5340_net.c | 1 + tools/scripts/nrf5340/build_flash.sh | 161 +++++++++++++++++++++------ 7 files changed, 139 insertions(+), 40 deletions(-) diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config index cefe4ad2fd..cfcd2b9120 100644 --- a/config/examples/nrf5340_net.config +++ b/config/examples/nrf5340_net.config @@ -51,6 +51,8 @@ DEBUG_UART?=1 USE_GCC=1 OPTIMIZATION_LEVEL=2 +SIGN_OPTIONS_EXTRA=--id 2 + #CFLAGS_EXTRA+=-DDEBUG_FLASH # If debugging network core disable the shared memory, since app core has not enabled access to it diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 175082606c..8ad2ca8da3 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -516,9 +516,9 @@ static void hal_net_check_version(void) wolfBoot_printf("Waiting for net core update to finish...\n"); - /* wait for update_done - note longer wait - 10 seconds */ + /* wait for update_done - 30 seconds */ ret = hal_shm_status_wait(&shm->net, - SHARED_STATUS_UPDATE_DONE, 10*1000); + SHARED_STATUS_UPDATE_DONE, 30*1000); if (ret == 0) { wolfBoot_printf("Network core firmware update done\n"); } @@ -543,7 +543,7 @@ static void hal_net_check_version(void) /* are we updating? */ if (ret == 0 && shm->app.status == SHARED_STATUS_UPDATE_START) { wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", - shm->net.version, shm->app.version, shm->net.size, shm->net.size); + shm->net.version, shm->app.version, shm->net.size, shm->app.size); do_update = 1; /* trigger update */ diff --git a/options.mk b/options.mk index 584b65e3e7..166929b1f4 100644 --- a/options.mk +++ b/options.mk @@ -853,3 +853,6 @@ ifneq ($(KEYVAULT_MAX_ITEMS),) CFLAGS+=-DKEYVAULT_MAX_ITEMS=$(KEYVAULT_MAX_ITEMS) endif +ifneq ($(SIGN_OPTIONS_EXTRA),) + SIGN_OPTIONS+=$(SIGN_OPTIONS_EXTRA) +endif diff --git a/src/update_flash.c b/src/update_flash.c index 886742c339..a3e186b0a9 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -338,11 +338,16 @@ static int wolfBoot_delta_update(struct wolfBoot_image *boot, ret = wb_patch_init(&ctx, boot->hdr, boot->fw_size + IMAGE_HEADER_SIZE, update->hdr + *img_offset, *img_size); } else { + wolfBoot_printf("Delta version check failed! " + "Cur 0x%x, Upd 0x%x, Delta 0x%x\n", + cur_v, upd_v, delta_base_v); ret = -1; } } else { if (!resume && (cur_v != delta_base_v)) { /* Wrong base image, cannot apply delta patch */ + wolfBoot_printf("Delta Base 0x%x != Cur 0x%x\n", + cur_v, delta_base_v); ret = -1; } else { ret = wb_patch_init(&ctx, boot->hdr, boot->fw_size + IMAGE_HEADER_SIZE, diff --git a/test-app/app_nrf5340.c b/test-app/app_nrf5340.c index 49a1644391..1042f70c49 100644 --- a/test-app/app_nrf5340.c +++ b/test-app/app_nrf5340.c @@ -58,6 +58,7 @@ void main(void) wolfBoot_printf("Copyright 2024 wolfSSL Inc\n"); wolfBoot_printf("GPL v3\n"); wolfBoot_printf("Version : 0x%lx\n", app_version); + wolfBoot_printf("Compiled: " __DATE__ ":" __TIME__ "\n"); wolfBoot_printf("========================\n"); /* mark boot successful */ diff --git a/test-app/app_nrf5340_net.c b/test-app/app_nrf5340_net.c index 90fb0a762b..8325d754ad 100644 --- a/test-app/app_nrf5340_net.c +++ b/test-app/app_nrf5340_net.c @@ -56,6 +56,7 @@ void main(void) wolfBoot_printf("Copyright 2024 wolfSSL Inc\n"); wolfBoot_printf("GPL v3\n"); wolfBoot_printf("Version : 0x%lx\n", app_version); + wolfBoot_printf("Compiled: " __DATE__ ":" __TIME__ "\n"); wolfBoot_printf("========================\n"); /* mark boot successful */ diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index d3a81243b1..97744c6bb7 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -5,23 +5,39 @@ # with flag to trigger update (like calling wolfBoot_update_trigger) # run from wolfBoot root +# Example use: +# Clean build and program factory version 1 # ./tools/scripts/nrf5340/build_flash.sh -# optionally run with "--erase" argument to rease both internal and external flash -# example: ./tools/scripts/nrf5340/build_flash.sh --debug --erase --program +# Build full update version 2 and flash to external (also reprograms internal flash) +# ./tools/scripts/nrf5340/build_flash.sh --update + +# Build dela update version 3 and flash to external (also reprograms internal flash) +# ./tools/scripts/nrf5340/build_flash.sh --delta # Defaults -MAKE_ARGS= +MAKE_ARGS=" DEBUG_SYMBOLS=1" +DO_CLEAN=0 DO_BUILD=0 +DO_UPDATE=0 DO_BUILD_DEBUG=0 -DO_ERASE=0 -DO_PROGRAM=0 +DO_ERASE_INT=0 +DO_ERASE_EXT=0 +DO_PROGRAM_INT=0 +DO_PROGRAM_EXT=0 +DO_DELTA=0 +UPDATE_VERSION=1 + +SIGN_ARGS="--ecc384 --sha384" +#SIGN_ARGS="--ecc256 --sha256" + +# Default with no arguments if [[ $# -eq 0 ]] ; then + DO_CLEAN=1 DO_BUILD=1 - DO_BUILD_DEBUG=0 - DO_ERASE=1 - DO_PROGRAM=1 - echo "Build release with symbols, erase and program" + DO_ERASE_INT=1 + DO_PROGRAM_INT=1 + echo "Clean build release, erase and program (internal flash only)" fi while test $# -gt 0; do @@ -33,99 +49,170 @@ while test $# -gt 0; do echo " " echo "options:" echo "-h, --help show brief help" + echo "-c, --clean cleanup build artifacts" echo "-b, --build build release with symbols" echo "-d, --debug build debug" echo "-v, --verbose build verbose" + echo "--version use custom version" echo "-e, --erase do erase of internal/external flash" echo "-p, --program program images built" + echo "-u, --update build update, sign and program external flash" + echo "-t, --delta build update, sign delta and program external flash" exit 0 ;; + -c|--clean) + DO_CLEAN=1 + echo "Cleaning build artifacts" + shift + ;; -b|--build) DO_BUILD=1 - MAKE_ARGS+=" DEBUG_SYMBOLS=1" echo "Build release with symbols" shift ;; -d|--debug) DO_BUILD=1 MAKE_ARGS+=" DEBUG=1" - echo "Build with debug" + echo "Add debug option" shift ;; -v|--verbose) DO_BUILD=1 MAKE_ARGS+=" V=1" - echo "Build with verbose output" + echo "Add verbose output" shift ;; -e|--erase) - DO_ERASE=1 + DO_ERASE_INT=1 + DO_ERASE_EXT=1 echo "Do erase" shift ;; -p|--program) - DO_PROGRAM=1 + DO_PROGRAM_INT=1 + DO_PROGRAM_EXT=1 echo "Do program" shift ;; + --version) + UPDATE_VERSION="$2" + echo "Use version ${UPDATE_VERSION}" + shift + shift + ;; + -u|--update) + DO_UPDATE=1 + UPDATE_VERSION=2 + DO_BUILD=1 + DO_ERASE_INT=1 + DO_ERASE_EXT=1 + DO_PROGRAM_INT=1 + DO_PROGRAM_EXT=1 + echo "Do update build and program" + shift + ;; + -t|--delta) + DO_DELTA=1 + UPDATE_VERSION=3 + DO_BUILD=1 + DO_UPDATE=0 + DO_CLEAN=0 + DO_ERASE_INT=1 + DO_ERASE_EXT=1 + DO_PROGRAM_INT=1 + DO_PROGRAM_EXT=1 + echo "Do delta build and program" + shift + ;; *) break ;; esac done -if [[ $DO_BUILD == 1 ]]; then +if [[ $DO_CLEAN == 1 ]]; then rm -f ./tools/scripts/nrf5340/*.bin rm -f ./tools/scripts/nrf5340/*.hex +fi +if [[ $DO_BUILD == 1 ]]; then # Build internal flash images for both cores # Build net cp config/examples/nrf5340_net.config .config make clean make $MAKE_ARGS - cp factory.bin tools/scripts/nrf5340/factory_net.bin - # Sign flash update for testing (use partition type 2 for network update) - tools/keytools/sign --ecc384 --sha384 --id 2 test-app/image.bin wolfboot_signing_private_key.der 2 - cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_net.bin + cp test-app/image.bin tools/scripts/nrf5340/image_net.bin + if [ ! -f tools/scripts/nrf5340/factory_net.bin ]; then + cp test-app/image_v1_signed.bin tools/scripts/nrf5340/image_net_v1_signed.bin + cp factory.bin tools/scripts/nrf5340/factory_net.bin + fi # Build app cp config/examples/nrf5340.config .config make clean make $MAKE_ARGS + cp test-app/image.bin tools/scripts/nrf5340/image_app.bin + cp test-app/image.bin tools/scripts/nrf5340/image_app_v${UPDATE_VERSION}.bin + if [ ! -f tools/scripts/nrf5340/factory_app.bin ]; then + cp test-app/image_v1_signed.bin tools/scripts/nrf5340/image_app_v1_signed.bin + cp factory.bin tools/scripts/nrf5340/factory_app.bin + fi +fi - cp factory.bin tools/scripts/nrf5340/factory_app.bin - # Sign flash update for testing - tools/keytools/sign --ecc384 --sha384 test-app/image.bin wolfboot_signing_private_key.der 2 - cp test-app/image_v2_signed.bin tools/scripts/nrf5340/image_v2_signed_app.bin +if [[ $DO_UPDATE == 1 ]]; then + # Sign flash update for testing (for network partition using --id 2) + tools/keytools/sign $SIGN_ARGS --id 2 tools/scripts/nrf5340/image_net.bin wolfboot_signing_private_key.der $UPDATE_VERSION + tools/keytools/sign $SIGN_ARGS tools/scripts/nrf5340/image_app.bin wolfboot_signing_private_key.der $UPDATE_VERSION # Create a bin footer with wolfBoot trailer "BOOT" and "p" (ASCII for 0x70 == IMG_STATE_UPDATING): echo -n "pBOOT" > tools/scripts/nrf5340/trigger_magic.bin ./tools/bin-assemble/bin-assemble \ - tools/scripts/nrf5340/update_app_v2.bin \ - 0x0 tools/scripts/nrf5340/image_v2_signed_app.bin \ + tools/scripts/nrf5340/update_app.bin \ + 0x0 tools/scripts/nrf5340/image_app_v${UPDATE_VERSION}_signed.bin \ 0xEDFFB tools/scripts/nrf5340/trigger_magic.bin + # Net update does not need triggered + cp tools/scripts/nrf5340/image_net_v${UPDATE_VERSION}_signed.bin tools/scripts/nrf5340/update_net.bin +fi - # Convert to HEX format for programmer tool - arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x00000000 tools/scripts/nrf5340/factory_app.bin tools/scripts/nrf5340/factory_app.hex - arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x01000000 tools/scripts/nrf5340/factory_net.bin tools/scripts/nrf5340/factory_net.hex +if [[ $DO_DELTA == 1 ]]; then + # Sign flash update for testing (for network partition using --id 2) delta between v1 and v3 + tools/keytools/sign $SIGN_ARGS --id 2 --delta tools/scripts/nrf5340/image_net_v1_signed.bin tools/scripts/nrf5340/image_net.bin wolfboot_signing_private_key.der $UPDATE_VERSION + tools/keytools/sign $SIGN_ARGS --delta tools/scripts/nrf5340/image_app_v1_signed.bin tools/scripts/nrf5340/image_app.bin wolfboot_signing_private_key.der $UPDATE_VERSION - arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/update_app_v2.bin tools/scripts/nrf5340/update_app_v2.hex - arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10100000 tools/scripts/nrf5340/image_v2_signed_net.bin tools/scripts/nrf5340/image_v2_signed_net.hex + # Create a bin footer with wolfBoot trailer "BOOT" and "p" (ASCII for 0x70 == IMG_STATE_UPDATING): + echo -n "pBOOT" > tools/scripts/nrf5340/trigger_magic.bin + ./tools/bin-assemble/bin-assemble \ + tools/scripts/nrf5340/update_app.bin \ + 0x0 tools/scripts/nrf5340/image_app_v${UPDATE_VERSION}_signed_diff.bin \ + 0xEDFFB tools/scripts/nrf5340/trigger_magic.bin + + # Net update does not need triggered + cp tools/scripts/nrf5340/image_net_v${UPDATE_VERSION}_signed_diff.bin tools/scripts/nrf5340/update_net.bin fi -if [[ $DO_ERASE == 1 ]]; then - nrfjprog -f nrf53 --recover - nrfjprog -f nrf53 --qspieraseall +if [[ $DO_ERASE_INT == 1 ]]; then + nrfjprog -f nrf53 --recover +fi +if [[ $DO_ERASE_EXT == 1 ]]; then + # QSPI Erase/Write doesn't work without a --recover + nrfjprog -f nrf53 --qspieraseall fi -if [[ $DO_PROGRAM == 1 ]]; then +if [[ $DO_PROGRAM_EXT == 1 ]]; then + # Convert to HEX format for programmer tool + arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10000000 tools/scripts/nrf5340/update_app.bin tools/scripts/nrf5340/update_app.hex + arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x10100000 tools/scripts/nrf5340/update_net.bin tools/scripts/nrf5340/update_net.hex # Program external flash - nrfjprog -f nrf53 --program tools/scripts/nrf5340/update_app_v2.hex --verify - nrfjprog -f nrf53 --program tools/scripts/nrf5340/image_v2_signed_net.hex --verify - + nrfjprog -f nrf53 --program tools/scripts/nrf5340/update_app.hex --verify + nrfjprog -f nrf53 --program tools/scripts/nrf5340/update_net.hex --verify +fi +if [[ $DO_PROGRAM_INT == 1 ]]; then + # Convert to HEX format for programmer tool + arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x00000000 tools/scripts/nrf5340/factory_app.bin tools/scripts/nrf5340/factory_app.hex + arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x01000000 tools/scripts/nrf5340/factory_net.bin tools/scripts/nrf5340/factory_net.hex # Program Internal Flash #nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_app.hex --verify #nrfjprog -f nrf53 --program tools/scripts/nrf5340/factory_net.hex --verify --coprocessor CP_NETWORK From 3e3d44b8a21c5939669a7b25cf59b3837c016896 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 7 Oct 2024 21:20:43 -0700 Subject: [PATCH 17/19] Switch to using IPC for communicating state. Prevents possible hard fault on network core reset. Cleanup make logic for using custom partition id (WOLFBOOT_PART_ID). On net update allow app core to continue booting if synchronization is enabled. --- config/examples/nrf5340_net.config | 7 +- hal/nrf5340.c | 319 ++++++++++++++++++--------- hal/nrf5340.h | 2 +- options.mk | 6 +- src/update_flash.c | 6 +- tools/scripts/nrf5340/build_flash.sh | 1 - 6 files changed, 223 insertions(+), 118 deletions(-) diff --git a/config/examples/nrf5340_net.config b/config/examples/nrf5340_net.config index cfcd2b9120..bc18a07606 100644 --- a/config/examples/nrf5340_net.config +++ b/config/examples/nrf5340_net.config @@ -43,7 +43,7 @@ WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x100000 WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x12E000 # Network core uses partition ID 2 -CFLAGS_EXTRA+=-DHDR_IMG_TYPE_APP=0x2 +WOLFBOOT_PART_ID=2 V?=0 DEBUG?=0 @@ -51,12 +51,7 @@ DEBUG_UART?=1 USE_GCC=1 OPTIMIZATION_LEVEL=2 -SIGN_OPTIONS_EXTRA=--id 2 - #CFLAGS_EXTRA+=-DDEBUG_FLASH -# If debugging network core disable the shared memory, since app core has not enabled access to it -#CFLAGS_EXTRA+=-DDISABLE_SHARED_MEM - # Hard fault debugging #CFLAGS_EXTRA+=-DDEBUG_HARDFAULT diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 8ad2ca8da3..9510dcb714 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -38,17 +38,15 @@ * Any key size greater than 128 bits must be divided and distributed over multiple key slot instances. */ -#define USE_RTC 0 /* Use RTC0 for sleep */ +#ifndef USE_RTC + #define USE_RTC 0 /* Use RTC0 for sleep */ +#endif /* Network updates can be signed with "--id 2" and placed into the normal update partition, * or they can be placed into the external flash at offset 0x100000 */ -/* Partition ID should be set HDR_IMG_TYPE_APP=2 */ +/* Set Partition ID in .config using WOLFBOOT_PART_ID=2 */ #ifndef PART_NET_ID -#ifdef HDR_IMG_TYPE_APP - #define PART_NET_ID HDR_IMG_TYPE_APP -#else - #define PART_NET_ID 2 /* default */ -#endif +#define PART_NET_ID 2 /* default */ #endif /* Offset in external QSPI flash for network update @@ -57,17 +55,31 @@ #define PART_NET_ADDR 0x100000UL #endif +/* IPC Channels 0/1 */ +/* Channel 0: APP Send -> NET Recv + * Channel 1: NET Send -> APP Recv */ +#ifdef TARGET_nrf5340_app + #define USE_IPC_SEND 0 + #define USE_IPC_RECV 1 +#else + #define USE_IPC_SEND 1 + #define USE_IPC_RECV 0 +#endif + /* SHM: Shared Memory between network and application cores */ /* first 64KB (0x10000) is used by wolfBoot and limited in nrf5340.ld */ #ifndef SHARED_MEM_ADDR #define SHARED_MEM_ADDR (0x20000000UL + (64 * 1024)) #endif + /* Shared memory states (mask, easier to check) */ #define SHARED_STATUS_UNKNOWN 0x00 #define SHARED_STATUS_READY 0x01 -#define SHARED_STATUS_UPDATE_START 0x02 -#define SHARED_STATUS_UPDATE_DONE 0x04 -#define SHARED_STATUS_DO_BOOT 0x08 +#define SHARED_STATUS_VERSION 0x02 +#define SHARED_STATUS_UPDATE_START 0x04 +#define SHARED_STATUS_UPDATE_DONE 0x08 +#define SHARED_STATUS_DO_BOOT 0x10 +#define SHARED_STATUS_TIMEOUT 0x80 #define SHAREM_MEM_MAGIC 0x5753484D /* WSHM */ @@ -81,18 +93,26 @@ typedef struct { typedef struct { ShmInfo_t net; /* network core write location */ ShmInfo_t app; /* application core write location */ +} SharedCores_t; + +typedef struct { + SharedCores_t core; + /* Note: If enableShm=0 do not access below */ /* application places firmware here */ uint8_t data[FLASH_SIZE_NET]; /* used as "swap" */ uint8_t swap[FLASH_PAGESZ_NET]; } SharedMem_t; -#ifndef DISABLE_SHARED_MEM -static SharedMem_t* shm = (SharedMem_t*)SHARED_MEM_ADDR; -#endif /* !DISABLE_SHARED_MEM */ -#ifdef TARGET_nrf5340_net -static int do_update = 0; +static int enableShm = 0; +static int doUpdateNet = 0; + +#ifdef TARGET_nrf5340_app +static SharedMem_t* shm = (SharedMem_t*)SHARED_MEM_ADDR; +#else +static SharedCores_t shm_shadow; +static SharedMem_t* shm = (SharedMem_t*)&shm_shadow; #endif @@ -279,9 +299,8 @@ int ext_flash_write(uintptr_t address, const uint8_t *data, int len) wolfBoot_printf("Ext Write: Len %d, Addr 0x%x (off 0x%x) -> 0x%x\n", len, address, addr, data); #endif -#ifndef DISABLE_SHARED_MEM - memcpy(shm->data + addr, data, len); -#endif + if (enableShm) + memcpy(shm->data + addr, data, len); return 0; } @@ -292,9 +311,10 @@ int ext_flash_read(uintptr_t address, uint8_t *data, int len) wolfBoot_printf("Ext Read: Len %d, Addr 0x%x (off 0x%x) -> %p\n", len, address, addr, data); #endif -#ifndef DISABLE_SHARED_MEM - memcpy(data, shm->data + addr, len); -#endif + if (enableShm) + memcpy(data, shm->data + addr, len); + else + memset(data, FLASH_BYTE_ERASED, len); return len; } @@ -305,9 +325,8 @@ int ext_flash_erase(uintptr_t address, int len) wolfBoot_printf("Ext Erase: Len %d, Addr 0x%x (off 0x%x)\n", len, address, addr); #endif -#ifndef DISABLE_SHARED_MEM - memset(shm->data + addr, FLASH_BYTE_ERASED, len); -#endif + if (enableShm) + memset(shm->data + addr, FLASH_BYTE_ERASED, len); return 0; } @@ -377,7 +396,6 @@ void hal_net_core(int hold) /* 1=hold, 0=release */ } #endif -#ifndef DISABLE_SHARED_MEM static uint8_t* get_image_hdr(struct wolfBoot_image* img) { #ifdef EXT_FLASH @@ -432,25 +450,69 @@ static int hal_net_get_image(struct wolfBoot_image* img, ShmInfo_t* info) return ret; } +static void hal_shm_init(void) +{ + IPC_SEND_CNF(USE_IPC_SEND) = (1 << USE_IPC_SEND); + IPC_RECEIVE_CNF(USE_IPC_RECV) = (1 << USE_IPC_RECV); + IPC_EVENTS_RECEIVE(USE_IPC_SEND) = 0; + IPC_EVENTS_RECEIVE(USE_IPC_RECV) = 0; + +#ifdef TARGET_nrf5340_app + /* Allow the network core to access shared SDRAM at 0x2000_0000 */ + SPU_EXTDOMAIN_PERM(0) = + (SPU_EXTDOMAIN_PERM_SECATTR_SECURE | SPU_EXTDOMAIN_PERM_UNLOCK); +#endif +} + static void hal_shm_status_set(ShmInfo_t* info, uint32_t status) { - info->magic = SHAREM_MEM_MAGIC; - info->status = status; + IPC_TASKS_SEND(USE_IPC_SEND) = 1; + if (info != NULL) { + info->magic = SHAREM_MEM_MAGIC; + info->status = status; + } } -static int hal_shm_status_wait(ShmInfo_t* info, uint32_t status, +static uint32_t hal_shm_status_wait(ShmInfo_t* info, uint32_t status, uint32_t timeout_ms) { + uint32_t status_ret = SHARED_STATUS_UNKNOWN; int ret = 0; - while ((info->magic != SHAREM_MEM_MAGIC || (info->status & status) == 0) - && --timeout_ms > 0) { - sleep_us(1000); - }; - if (timeout_ms == 0) { - wolfBoot_printf("Timeout: status 0x%x\n", status); - ret = -1; /* timeout */ - } - return ret; + + do { + /* see if status shared already */ + if (info != NULL && (info->magic == SHAREM_MEM_MAGIC && + (info->status & status) != 0)) { + status_ret = info->status; + break; + } + /* Wait for event */ + while (IPC_EVENTS_RECEIVE(USE_IPC_RECV) == 0 && --timeout_ms > 0) { + sleep_us(1000); + } + if (timeout_ms == 0) { + status_ret = SHARED_STATUS_TIMEOUT; + break; + } + /* clear event */ + IPC_EVENTS_RECEIVE(USE_IPC_RECV) = 0; + /* if we got an event and "info" not provided, just return status to + * signal event occurred */ + if (info == NULL) { + status_ret = status; + break; + } + } while (1); + return status_ret; +} + +static void hal_shm_cleanup(void) +{ +#ifdef TARGET_nrf5340_app + /* Restore defaults preventing network core from accessing shared SDRAM */ + SPU_EXTDOMAIN_PERM(0) = + (SPU_EXTDOMAIN_PERM_SECATTR_NONSECURE | SPU_EXTDOMAIN_PERM_UNLOCK); +#endif } static const char* hal_shm_status_string(uint32_t status) @@ -458,43 +520,75 @@ static const char* hal_shm_status_string(uint32_t status) switch (status) { case SHARED_STATUS_READY: return "Ready"; + case SHARED_STATUS_VERSION: + return "Version"; case SHARED_STATUS_UPDATE_START: return "Update Start"; case SHARED_STATUS_UPDATE_DONE: return "Update Done"; case SHARED_STATUS_DO_BOOT: return "Do boot"; + case SHARED_STATUS_TIMEOUT: + return "Timeout"; default: break; } return "Unknown"; } +static int hal_net_signal_wait_ready(uint32_t timeout_ms) +{ + int ret = 0; + uint32_t status; + + /* wait for network core ready */ + do { + hal_shm_status_set(NULL, SHARED_STATUS_READY); + status = hal_shm_status_wait(NULL, SHARED_STATUS_READY, 1); + } while (status == SHARED_STATUS_TIMEOUT && --timeout_ms > 0); + if (timeout_ms == 0 && status == SHARED_STATUS_TIMEOUT) { + ret = -1; + } + return ret; +} /* Handles network core updates */ static void hal_net_check_version(void) { int ret; struct wolfBoot_image img; - uint32_t timeout; + uint32_t timeout, status = 0; #ifdef TARGET_nrf5340_app /* check the network core version */ - hal_net_get_image(&img, &shm->app); - hal_shm_status_set(&shm->app, SHARED_STATUS_READY); + hal_net_get_image(&img, &shm->core.app); /* release network core - issue boot command */ hal_net_core(0); - /* wait for ready status from network core - 2 seconds */ - ret = hal_shm_status_wait(&shm->net, SHARED_STATUS_READY, 2*1000); + wolfBoot_printf("Waiting for ready from net core...\n"); + + /* wait for ready status from network core */ + ret = hal_net_signal_wait_ready(500); + if (ret == 0) { + enableShm = 1; + wolfBoot_printf("Net core ready\n"); + + /* wait for version */ + status = hal_shm_status_wait(&shm->core.net, + SHARED_STATUS_VERSION, 2*1000); + } + else { + wolfBoot_printf("Net core timeout, disable shared mem\n"); + } /* check if network core can continue booting or needs to wait for update */ - if (ret != 0 || shm->app.version <= shm->net.version) { + if (ret != 0 || shm->core.app.version <= shm->core.net.version) { wolfBoot_printf("Network Core: Releasing for boot\n"); } else { wolfBoot_printf("Found Network Core update: Ver %d->%d, Size %d->%d\n", - shm->net.version, shm->app.version, shm->net.size, shm->app.size); + shm->core.net.version, shm->core.app.version, + shm->core.net.size, shm->core.app.size); /* validate the update is valid */ if (wolfBoot_verify_integrity(&img) == 0 && @@ -502,26 +596,32 @@ static void hal_net_check_version(void) { wolfBoot_printf("Network image valid, loading into shared mem\n"); /* initialize remainder of shared memory with 0xFF (erased) */ - memset(shm->data + shm->app.size, FLASH_BYTE_ERASED, - sizeof(shm->data) - shm->app.size); + memset(shm->data + shm->core.app.size, FLASH_BYTE_ERASED, + sizeof(shm->data) - shm->core.app.size); /* relocate image to shared ram */ #ifdef EXT_FLASH - ret = ext_flash_read(PART_NET_ADDR, shm->data, shm->app.size); + ret = ext_flash_read(PART_NET_ADDR, shm->data, shm->core.app.size); #else - memcpy(shm->data, img.hdr, shm->app.size); + memcpy(shm->data, img.hdr, shm->core.app.size); #endif if (ret >= 0) { + doUpdateNet = 1; + /* signal network core to do update */ - hal_shm_status_set(&shm->app, SHARED_STATUS_UPDATE_START); + hal_shm_status_set(&shm->core.app, SHARED_STATUS_UPDATE_START); + #ifndef NRF_SYNC_CORES wolfBoot_printf("Waiting for net core update to finish...\n"); /* wait for update_done - 30 seconds */ - ret = hal_shm_status_wait(&shm->net, + status = hal_shm_status_wait(&shm->core.net, SHARED_STATUS_UPDATE_DONE, 30*1000); - if (ret == 0) { + if (status == SHARED_STATUS_UPDATE_DONE) { wolfBoot_printf("Network core firmware update done\n"); } + #else + wolfBoot_printf("Continuing boot while network core updates\n"); + #endif } } else { @@ -530,34 +630,51 @@ static void hal_net_check_version(void) } } /* inform network core to boot */ - hal_shm_status_set(&shm->app, SHARED_STATUS_DO_BOOT); + hal_shm_status_set(&shm->core.app, SHARED_STATUS_DO_BOOT); #else /* TARGET_nrf5340_net */ - hal_net_get_image(&img, &shm->net); - hal_shm_status_set(&shm->net, SHARED_STATUS_READY); + /* wait for IPC event indicating application core exists */ + ret = hal_net_signal_wait_ready(500); + if (ret == 0) { + /* enable use of shared memory */ + shm = (SharedMem_t*)SHARED_MEM_ADDR; + enableShm = 1; + } + else { + wolfBoot_printf("App core timeout, disable shared mem\n"); + } + + /* inform application core we are ready */ + hal_shm_status_set(&shm->core.net, SHARED_STATUS_READY); - /* wait for do_boot or update from app core - 2 seconds */ - wolfBoot_printf("Waiting for status from app core...\n"); - ret = hal_shm_status_wait(&shm->app, - (SHARED_STATUS_UPDATE_START | SHARED_STATUS_DO_BOOT), 2*1000); + if (enableShm) { + wolfBoot_printf("App core ready\n"); - /* are we updating? */ - if (ret == 0 && shm->app.status == SHARED_STATUS_UPDATE_START) { - wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", - shm->net.version, shm->app.version, shm->net.size, shm->app.size); - do_update = 1; + hal_net_get_image(&img, &shm->core.net); + hal_shm_status_set(&shm->core.net, SHARED_STATUS_VERSION); - /* trigger update */ - wolfBoot_set_partition_state(PART_UPDATE, IMG_STATE_UPDATING); + /* wait for do_boot or update from app core - 2 seconds */ + wolfBoot_printf("Waiting for update or boot from app core...\n"); + status = hal_shm_status_wait(&shm->core.app, + (SHARED_STATUS_UPDATE_START | SHARED_STATUS_DO_BOOT), 2*1000); - /* proceed to update_flash routines */ + /* are we updating? */ + if (status == SHARED_STATUS_UPDATE_START) { + wolfBoot_printf("Starting update: Ver %d->%d, Size %d->%d\n", + shm->core.net.version, shm->core.app.version, + shm->core.net.size, shm->core.app.size); + doUpdateNet = 1; + + /* trigger update */ + wolfBoot_set_partition_state(PART_UPDATE, IMG_STATE_UPDATING); + } } + /* proceed to update_flash routines */ #endif /* TARGET_nrf5340_* */ exit: wolfBoot_printf("Status: App %s (ver %d), Net %s (ver %d)\n", - hal_shm_status_string(shm->app.status), shm->app.version, - hal_shm_status_string(shm->net.status), shm->net.version); + hal_shm_status_string(shm->core.app.status), shm->core.app.version, + hal_shm_status_string(shm->core.net.status), shm->core.net.version); } -#endif /* !DISABLE_SHARED_MEM */ void hal_init(void) @@ -573,18 +690,12 @@ void hal_init(void) uart_write(bootStr, strlen(bootStr)); #endif -#ifdef TARGET_nrf5340_app - /* Allow the network core to access shared SDRAM at 0x2000_0000 */ - SPU_EXTDOMAIN_PERM(0) = - (SPU_EXTDOMAIN_PERM_SECATTR_SECURE | SPU_EXTDOMAIN_PERM_UNLOCK); -#endif + hal_shm_init(); /* need early init of external flash to support checking network core */ spi_flash_probe(); -#ifndef DISABLE_SHARED_MEM hal_net_check_version(); -#endif } @@ -593,39 +704,35 @@ void hal_prepare_boot(void) /* TODO: Protect bootloader region of flash using SPU_FLASHREGION_PERM */ //WOLFBOOT_ORIGIN //BOOTLOADER_PARTITION_SIZE + //FLASHREGION[n].PERM -#ifndef DISABLE_SHARED_MEM -#ifdef TARGET_nrf5340_net - if (do_update) { - /* signal application core update done */ - struct wolfBoot_image img; - /* Reopen image and refresh information */ - hal_net_get_image(&img, &shm->net); - wolfBoot_printf("Network version (after update): 0x%x\n", - shm->net.version); - hal_shm_status_set(&shm->net, SHARED_STATUS_UPDATE_DONE); - } - else { - hal_shm_status_set(&shm->net, SHARED_STATUS_DO_BOOT); - } -#endif + if (enableShm) { + #ifdef TARGET_nrf5340_net + if (doUpdateNet) { + /* signal application core update done */ + struct wolfBoot_image img; + /* Reopen image and refresh information */ + hal_net_get_image(&img, &shm->core.net); + wolfBoot_printf("Network version (after update): 0x%x\n", + shm->core.net.version); + hal_shm_status_set(&shm->core.net, SHARED_STATUS_UPDATE_DONE); + } + else { + hal_shm_status_set(&shm->core.net, SHARED_STATUS_DO_BOOT); + } + #endif -#ifdef TARGET_nrf5340_app -#ifdef NRF_SYNC_CORES - /* if core synchronization enabled, - * then wait for update_done or do_boot (5 seconds) */ - wolfBoot_printf("Waiting for network core...\n"); - (void)hal_shm_status_wait(&shm->net, - (SHARED_STATUS_UPDATE_DONE | SHARED_STATUS_DO_BOOT), 5*1000); -#endif /* NRF_SYNC_CORES */ -#endif /* TARGET_nrf5340_app */ -#endif /* !DISABLE_SHARED_MEM */ + #if defined(TARGET_nrf5340_app) && defined(NRF_SYNC_CORES) + /* if core synchronization enabled, + * then wait for update_done or do_boot (5 seconds, 30 for update) */ + wolfBoot_printf("Waiting for network core...\n"); + (void)hal_shm_status_wait(&shm->core.net, + (SHARED_STATUS_UPDATE_DONE | SHARED_STATUS_DO_BOOT), + doUpdateNet ? 30*1000 : 5*1000); + #endif + } -#ifdef TARGET_nrf5340_app - /* Restore defaults preventing network core from accessing shared SDRAM */ - SPU_EXTDOMAIN_PERM(0) = - (SPU_EXTDOMAIN_PERM_SECATTR_NONSECURE | SPU_EXTDOMAIN_PERM_UNLOCK); -#endif + hal_shm_cleanup(); } #endif /* TARGET_* */ diff --git a/hal/nrf5340.h b/hal/nrf5340.h index 3534a0fac6..5713af15a0 100644 --- a/hal/nrf5340.h +++ b/hal/nrf5340.h @@ -387,7 +387,7 @@ void uart_write_sz(const char* c, unsigned int sz); #define IPC_BASE (0x4002A000) #endif #else - #define IPC_BASE (0x4002A000) /* network core */ + #define IPC_BASE (0x41012000) /* network core */ #endif #define IPC_TASKS_SEND(n) *((volatile uint32_t *)(IPC_BASE + 0x000 + (((n) & 0xF) * 0x4))) #define IPC_SUBSCRIBE_SEND(n) *((volatile uint32_t *)(IPC_BASE + 0x080 + (((n) & 0xF) * 0x4))) diff --git a/options.mk b/options.mk index 166929b1f4..4de595f9b0 100644 --- a/options.mk +++ b/options.mk @@ -853,6 +853,8 @@ ifneq ($(KEYVAULT_MAX_ITEMS),) CFLAGS+=-DKEYVAULT_MAX_ITEMS=$(KEYVAULT_MAX_ITEMS) endif -ifneq ($(SIGN_OPTIONS_EXTRA),) - SIGN_OPTIONS+=$(SIGN_OPTIONS_EXTRA) +# Support for using a custom partition ID +ifneq ($(WOLFBOOT_PART_ID),) + CFLAGS+=-DHDR_IMG_TYPE_APP=$(WOLFBOOT_PART_ID) + SIGN_OPTIONS+=--id $(WOLFBOOT_PART_ID) endif diff --git a/src/update_flash.c b/src/update_flash.c index a3e186b0a9..174eddc516 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -537,7 +537,8 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) if (flag == SECT_FLAG_NEW) { if (((update_type & HDR_IMG_TYPE_PART_MASK) != HDR_IMG_TYPE_APP) || ((update_type & HDR_IMG_TYPE_AUTH_MASK) != HDR_IMG_TYPE_AUTH)) { - wolfBoot_printf("Invalid update type 0x%x\n", update_type); + wolfBoot_printf("Update type invalid 0x%x!=0x%x\n", + update_type, HDR_IMG_TYPE_AUTH); return -1; } if (update.fw_size > MAX_UPDATE_SIZE - 1) { @@ -547,7 +548,8 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed) if (!update.hdr_ok || (wolfBoot_verify_integrity(&update) < 0) || (wolfBoot_verify_authenticity(&update) < 0)) { - wolfBoot_printf("Update integrity/verification failed!\n"); + wolfBoot_printf("Update verify failed: Hdr %d, Hash %d, Sig %d\n", + update.hdr_ok, update.sha_ok, update.signature_ok); return -1; } PART_SANITY_CHECK(&update); diff --git a/tools/scripts/nrf5340/build_flash.sh b/tools/scripts/nrf5340/build_flash.sh index 97744c6bb7..f339b004bb 100755 --- a/tools/scripts/nrf5340/build_flash.sh +++ b/tools/scripts/nrf5340/build_flash.sh @@ -153,7 +153,6 @@ if [[ $DO_BUILD == 1 ]]; then make clean make $MAKE_ARGS cp test-app/image.bin tools/scripts/nrf5340/image_app.bin - cp test-app/image.bin tools/scripts/nrf5340/image_app_v${UPDATE_VERSION}.bin if [ ! -f tools/scripts/nrf5340/factory_app.bin ]; then cp test-app/image_v1_signed.bin tools/scripts/nrf5340/image_app_v1_signed.bin cp factory.bin tools/scripts/nrf5340/factory_app.bin From bd1215a57509f4a8a09deb68471612b169143d24 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 8 Oct 2024 12:33:29 -0700 Subject: [PATCH 18/19] Fix issue with network core update when not a multiple of 4 bytes. The QSPI driver requires READ.CNT to be a multiple of 4 bytes (so read a bit more if odd remainder). --- hal/nrf5340.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hal/nrf5340.c b/hal/nrf5340.c index 9510dcb714..cd76dddb4d 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -595,15 +595,17 @@ static void hal_net_check_version(void) wolfBoot_verify_authenticity(&img) == 0) { wolfBoot_printf("Network image valid, loading into shared mem\n"); - /* initialize remainder of shared memory with 0xFF (erased) */ - memset(shm->data + shm->core.app.size, FLASH_BYTE_ERASED, - sizeof(shm->data) - shm->core.app.size); /* relocate image to shared ram */ #ifdef EXT_FLASH - ret = ext_flash_read(PART_NET_ADDR, shm->data, shm->core.app.size); + /* must be multiple of 4 (READ.CNT length must be multiple of 4) */ + ret = ext_flash_read(PART_NET_ADDR, shm->data, + (shm->core.app.size + 3) & ~3); #else memcpy(shm->data, img.hdr, shm->core.app.size); #endif + /* initialize remainder of shared memory with 0xFF (erased) */ + memset(shm->data + shm->core.app.size, FLASH_BYTE_ERASED, + sizeof(shm->data) - shm->core.app.size); if (ret >= 0) { doUpdateNet = 1; From 422f9e8da018c0f494616a118c5308b20e5cf694 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 8 Oct 2024 16:31:46 -0700 Subject: [PATCH 19/19] Support for SPU to write protect bootloader flash region on application startup. --- Makefile | 2 +- hal/nrf5340.c | 35 +++++++++++++++++++++++++++++++---- hal/nrf5340.h | 10 +++++----- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 829b3bce4c..4c9f618c69 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ BIG_ENDIAN?=0 USE_GCC?=1 USE_GCC_HEADLESS?=1 FLASH_OTP_KEYSTORE?=0 +BOOTLOADER_PARTITION_SIZE?=$$(( $(WOLFBOOT_PARTITION_BOOT_ADDRESS) - $(ARCH_FLASH_OFFSET))) OBJS:= \ ./src/string.o \ @@ -141,7 +142,6 @@ ifeq ($(FLASH_OTP_KEYSTORE),1) endif ASFLAGS:=$(CFLAGS) -BOOTLOADER_PARTITION_SIZE?=$$(( $(WOLFBOOT_PARTITION_BOOT_ADDRESS) - $(ARCH_FLASH_OFFSET))) all: $(MAIN_TARGET) diff --git a/hal/nrf5340.c b/hal/nrf5340.c index cd76dddb4d..1365bf85d6 100644 --- a/hal/nrf5340.c +++ b/hal/nrf5340.c @@ -700,13 +700,40 @@ void hal_init(void) hal_net_check_version(); } +/* enable write protection for the region of flash specified */ +int hal_flash_protect(uint32_t start, uint32_t len) +{ + /* only application core supports SPU */ +#ifdef TARGET_nrf5340_app + uint32_t region, n, i; + + /* limit check */ + if (start > FLASH_SIZE) + return -1; + /* truncate if exceeds flash size */ + if (start + len > FLASH_SIZE) + len = FLASH_SIZE - start; + + region = (start / SPU_BLOCK_SIZE); + n = (len / SPU_BLOCK_SIZE); + + for (i = 0; i < n; i++) { + /* do not allow write to this region and lock till next reset */ + SPU_FLASHREGION_PERM(region+i) = ( + SPU_FLASHREGION_PERM_EXEC | + SPU_FLASHREGION_PERM_READ | + SPU_FLASHREGION_PERM_SECATTR | + SPU_FLASHREGION_PERM_LOCK + ); + } +#endif + return 0; +} void hal_prepare_boot(void) { - /* TODO: Protect bootloader region of flash using SPU_FLASHREGION_PERM */ - //WOLFBOOT_ORIGIN - //BOOTLOADER_PARTITION_SIZE - //FLASHREGION[n].PERM + /* Write protect bootloader region of flash */ + hal_flash_protect(WOLFBOOT_ORIGIN, BOOTLOADER_PARTITION_SIZE); if (enableShm) { #ifdef TARGET_nrf5340_net diff --git a/hal/nrf5340.h b/hal/nrf5340.h index 5713af15a0..2024c9fce0 100644 --- a/hal/nrf5340.h +++ b/hal/nrf5340.h @@ -106,11 +106,11 @@ void sleep_us(uint32_t usec); #define SPU_BLOCK_SIZE (16 * 1024) #define SPU_FLASHREGION_PERM(n) *((volatile uint32_t *)(SPU_BASE + 0x600 + (((n) & 0x3F) * 0x4))) - #define SPU_FLASHREGION_PERM_EXEC (1 << 0) - #define SPU_FLASHREGION_PERM_WRITE (1 << 1) - #define SPU_FLASHREGION_PERM_READ (1 << 2) - #define SPU_FLASHREGION_PERM_SECATTR (1 << 4) - #define SPU_FLASHREGION_PERM_LOCK (1 << 8) + #define SPU_FLASHREGION_PERM_EXEC (1 << 0) /* Allow instruction fetches from flash region */ + #define SPU_FLASHREGION_PERM_WRITE (1 << 1) /* Allow write operation to region */ + #define SPU_FLASHREGION_PERM_READ (1 << 2) /* Allow read operation from flash region */ + #define SPU_FLASHREGION_PERM_SECATTR (1 << 4) /* Flash region n security attribute is secure */ + #define SPU_FLASHREGION_PERM_LOCK (1 << 8) /* The content of this register can't be changed until the next reset */ #endif /* OTP */