diff --git a/.gdbinit b/.gdbinit index 676e54df9..f2124937d 100644 --- a/.gdbinit +++ b/.gdbinit @@ -1,6 +1,7 @@ tar rem:3333 file wolfboot.elf 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 1df9275be..c86b5b0ef 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -116,6 +116,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 92dbe8319..79ce9b7f6 100644 --- a/arch.mk +++ b/arch.mk @@ -181,7 +181,9 @@ ifeq ($(CORTEX_M33),1) 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 97398b39d..4f3cc99bf 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 000000000..d12984ccd --- /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 000000000..821033eea --- /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 c100d4526..d0f148d5a 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -4,24 +4,27 @@ 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 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) @@ -33,7 +36,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) @@ -2122,6 +2124,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 @@ -2864,8 +2995,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 33ed1f4b7..f15ae4f28 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 000000000..622963cb6 --- /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 000000000..41f12720b --- /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 000000000..bce3e01ba --- /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 000000000..888253875 --- /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 67d160073..684458967 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 e23c2b99d..33d31b7fd 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 000000000..7789997a8 --- /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 000000000..686ac59e2 --- /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 327ac63f1..61c7f54a2 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 3348fb1b4..205a3d6c5 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 12fcb1ed9..32d263949 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 fba364a4b..02b6f9ca0 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 f69925b49..22b7dfcbe 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 1bea1fc49..3e271446c 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 0eeae87c6..d8de8178c 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 000000000..44a862e52 --- /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 7e095197f..e6672ea46 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -117,7 +117,6 @@ endif ifeq ($(ARCH),ARM) APP_OBJS+=startup_arm.o - CFLAGS+=-DSTM32 endif ifeq ($(ARCH),ARM_BE) APP_OBJS+=startup_arm.o @@ -131,6 +130,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 @@ -204,6 +204,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 67fc20b25..ad7c60b8e 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 000000000..e20183441 --- /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 000000000..2a6605a6e --- /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 cb122867b..68d41adf6 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 000000000..7fdbcf147 --- /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 000000000..2194fbff2 --- /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 000000000..2c41207a4 --- /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