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.
pull/507/head
David Garske 2024-09-26 15:37:18 -07:00 committed by Daniele Lacamera
parent b6b77f01e0
commit 6db7de6a75
34 changed files with 2226 additions and 183 deletions

View File

@ -1,6 +1,7 @@
file wolfboot.elf
tar rem:3333
add-symbol-file test-app/image.elf
set pagination off
foc c

View File

@ -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:

View File

@ -203,7 +203,9 @@ else
CFLAGS+=-mcpu=cortex-m33 -DCORTEX_M33
LDFLAGS+=-mcpu=cortex-m33
ifeq ($(TZEN),1)
ifneq (,$(findstring stm32,$(TARGET)))
OBJS+=hal/stm32_tz.o
endif
CFLAGS+=-mcmse
ifeq ($(WOLFCRYPT_TZ),1)
SECURE_OBJS+=./src/wc_callable.o

View File

@ -3,6 +3,7 @@ TARGET?=nrf52
SIGN?=ECC256
HASH?=SHA256
DEBUG?=0
DEBUG_UART?=1
VTOR?=1
CORTEX_M0?=0
NO_ASM?=0

View File

@ -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

View File

@ -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

View File

@ -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 <qspi_content.hex> --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

View File

@ -19,32 +19,42 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifdef TARGET_nrf52
#include <stdint.h>
#include "image.h"
#include "nrf52.h"
/* Assembly helpers */
#define DMB() __asm__ volatile ("dmb")
#ifdef DEBUG_UART
void uart_init(void)
{
UART0_BAUDRATE = BAUD_115200;
UART0_ENABLE = 1;
}
static void uart_write_char(char c)
{
UART0_EVENT_ENDTX = 0;
/* Instantiation */
#define CLOCK_CONTROL_BASE (0x40000000)
#define NVMC_BASE (0x4001E000)
UART0_TXD_PTR = (uint32_t)(&c);
UART0_TXD_MAXCOUNT = 1;
UART0_TASK_STARTTX = 1;
while(UART0_EVENT_ENDTX == 0)
;
}
/* 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))
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 */

102
hal/nrf52.h 100644
View File

@ -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_ */

514
hal/nrf5340.c 100644
View File

@ -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 <stdint.h>
#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<sizeof(pageData); i++) {
((uint8_t*)pageData)[i] = (i & 0xff);
}
#ifndef TEST_FLASH_READONLY
/* Erase sector */
hal_flash_unlock();
ret = hal_flash_erase(TEST_ADDRESS, WOLFBOOT_SECTOR_SIZE);
hal_flash_lock();
if (ret != 0) {
wolfBoot_printf("Erase Sector failed: Ret %d\n", ret);
return ret;
}
/* Write Page */
ret = hal_flash_write(TEST_ADDRESS, (uint8_t*)pageData, sizeof(pageData));
wolfBoot_printf("Write Page: Ret %d\n", ret);
#endif /* !TEST_FLASH_READONLY */
/* Compare Page */
ret = memcmp((void*)TEST_ADDRESS, pageData, sizeof(pageData));
if (ret != 0) {
wolfBoot_printf("Check Data @ %d failed\n", ret);
return ret;
}
wolfBoot_printf("Internal Flash Test Passed\n");
return ret;
}
#endif /* TEST_FLASH */
#endif /* TARGET_* */

389
hal/nrf5340.h 100644
View File

@ -0,0 +1,389 @@
/* 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
*/
#ifndef _HAL_NRF5340_H_
#define _HAL_NRF5340_H_
/* Build-time gate for secure or non-secure peripherals.
* At boot-time peripherals are secure */
#ifdef TARGET_nrf5340_net
/* Network core */
#undef QSPI_FLASH /* not supported on network core */
#define CORE_STR "net"
#else
/* Application core */
#define TARGET_nrf5340_app
#define CORE_STR "app"
#ifndef TZEN
/* at reset/power on wolfBoot is using secure bases */
#define TZEN
#endif
#endif
/* Clock */
#ifdef TARGET_nrf5340_app
#define CPU_CLOCK 128000000UL /* 128MHz */
#else
#define CPU_CLOCK 64000000UL /* 64MHz */
#endif
/* Flash */
#define FLASH_PAGESZ_APP (4096) /* 4KB Page */
#define FLASH_BASE_APP (0x00000000)
#define FLASH_SIZE_APP (1024UL * 1024UL) /* 1MB Flash */
#define FLASH_PAGESZ_NET (2048) /* 2KB Page */
#define FLASH_BASE_NET (0x01000000)
#define FLASH_SIZE_NET (256UL * 1024UL) /* 256KB Flash */
#ifdef TARGET_nrf5340_app
#define FLASH_PAGE_SIZE FLASH_PAGESZ_APP
#define FLASH_BASE_ADDR FLASH_BASE_APP
#define FLASH_SIZE FLASH_SIZE_APP
#else
#define FLASH_PAGE_SIZE FLASH_PAGESZ_NET
#define FLASH_BASE_ADDR FLASH_BASE_NET
#define FLASH_SIZE FLASH_SIZE_NET
#endif
/* Assembly helpers */
#define DMB() __asm__ volatile ("dmb")
#define DSB() __asm__ volatile ("dsb")
#define ISB() __asm__ volatile ("isb")
#define NOP() __asm__ volatile ("nop")
void sleep_us(unsigned int us);
/* PSEL Port (bit 5) - Used for various PSEL (UART,SPI,QSPI,I2C,NFC) */
#define PSEL_PORT(n) (((n) & 0x1) << 5)
/* Domain Configuration */
#ifdef TARGET_nrf5340_app
#ifdef TZEN
#define DCNF_BASE (0x50000000)
#else
#define DCNF_BASE (0x40000000)
#endif
#else
#define DCNF_BASE (0x41000000)
#endif
#define DCNF_CPUID *((volatile uint32_t *)(DCNF_BASE + 0x420))
#ifdef TARGET_nrf5340_app
/* allows blocking of network cores ability to resources on application core */
#define DCNF_EXTPERI0_PROT *((volatile uint32_t *)(DCNF_BASE + 0x440))
#define DCNF_EXTRAM0_PROT *((volatile uint32_t *)(DCNF_BASE + 0x460)) /* Eight 64KB slaves bit 0=0x20000000-0x20010000 (64KB) */
#define DCNF_EXTCODE0_PROT *((volatile uint32_t *)(DCNF_BASE + 0x480))
#endif
#ifdef TARGET_nrf5340_app
/* SPU */
#define SPU_BASE 0x50003000UL
#define SPU_EXTDOMAIN_PERM(n) *((volatile uint32_t *)(SPU_BASE + 0x440 + (((n) & 0x0) * 0x4)))
#define SPU_EXTDOMAIN_PERM_SECATTR_NONSECURE 0
#define SPU_EXTDOMAIN_PERM_SECATTR_SECURE (1 << 4)
#define SPU_EXTDOMAIN_PERM_UNLOCK 0
#define SPU_EXTDOMAIN_PERM_LOCK (1 << 8)
#define SPU_EXTDOMAIN_PERM_SECUREMAPPING_MASK (0x3)
#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)
#endif
/* OTP */
#define UICR_BASE (0x00FF8000UL)
#define UICR_USER (UICR_BASE)
#define UICR_OTP (UICR_BASE + 0x100)
/* Reset */
#ifdef TARGET_nrf5340_app
#ifdef TZEN
#define RESET_BASE (0x50005000)
#else
#define RESET_BASE (0x40005000)
#endif
#else
#define RESET_BASE (0x41005000)
#endif
#define NETWORK_RESETREAS *((volatile uint32_t *)(RESET_BASE + 0x400))
#define NETWORK_RESETREAS_RESETPIN (1 << 0)
#define NETWORK_RESETREAS_DOG0 (1 << 1) /* watchdog timer 0 */
#define NETWORK_RESETREAS_SREQ (1 << 3) /* soft reset */
#define NETWORK_RESETREAS_OFF (1 << 5) /* wake from off */
#define NETWORK_RESETREAS_MFORCEOFF (1 << 23)
#define NETWORK_FORCEOFF *((volatile uint32_t *)(RESET_BASE + 0x614))
#define NETWORK_FORCEOFF_RELEASE 0
#define NETWORK_FORCEOFF_HOLD 1
#define NETWORK_ERRATA_161 *((volatile uint32_t *)(RESET_BASE + 0x618))
/* Non-volatile memory controller */
#ifdef TARGET_nrf5340_app
#ifdef TZEN
#define NVMC_BASE (0x50039000)
#else
#define NVMC_BASE (0x40039000)
#endif
#else
#define NVMC_BASE (0x41080000)
#endif
#define NVMC_READY *((volatile uint32_t *)(NVMC_BASE + 0x400))
#define NVMC_READYNEXT *((volatile uint32_t *)(NVMC_BASE + 0x408))
#define NVMC_CONFIG *((volatile uint32_t *)(NVMC_BASE + 0x504))
#define NVMC_CONFIGNS *((volatile uint32_t *)(NVMC_BASE + 0x584))
#define NVMC_WRITEUICRNS *((volatile uint32_t *)(NVMC_BASE + 0x588)) /* User information configuration registers (UICR) */
#define NVMC_CONFIG_REN 0 /* read only access */
#define NVMC_CONFIG_WEN 1 /* write enable */
#define NVMC_CONFIG_EEN 2 /* erase enable */
#define NVMC_CONFIG_PEE 3 /* partial erase enable - secure only */
#define NVMC_WRITEUICRNS_SET 1
#define NVMC_WRITEUICRNS_KEY 0xAFBE5A70
/* Clock control */
#ifdef TARGET_nrf5340_app
#ifdef TZEN
#define CLOCK_BASE (0x50005000)
#else
#define CLOCK_BASE (0x40005000)
#endif
#else
#define CLOCK_BASE (0x41005000) /* network core */
#endif
#define CLOCK_HFCLKSTART *((volatile uint32_t *)(CLOCK_BASE + 0x000))
#define CLOCK_HFCLKSTOP *((volatile uint32_t *)(CLOCK_BASE + 0x004))
#define CLOCK_HFCLKSTARTED *((volatile uint32_t *)(CLOCK_BASE + 0x100))
#define CLOCK_HFCLKSTAT *((volatile uint32_t *)(CLOCK_BASE + 0x40C))
#define CLOCK_HFCLKSRC *((volatile uint32_t *)(CLOCK_BASE + 0x514))
#define CLOCK_HFCLKSRC_HFXO 1
#define CLOCK_HFCLKCTRL *((volatile uint32_t *)(CLOCK_BASE + 0x558))
#define CLOCK_HFCLKCTRL_DIV1 0
#define CLOCK_HFCLKCTRL_DIV2 1
#define CLOCK_HFCLK192MSTART *((volatile uint32_t *)(CLOCK_BASE + 0x020))
#define CLOCK_HFCLK192MSTOP *((volatile uint32_t *)(CLOCK_BASE + 0x024))
#define CLOCK_HFCLK192MSTARTED *((volatile uint32_t *)(CLOCK_BASE + 0x124))
#define CLOCK_HFCLK192MSRC *((volatile uint32_t *)(CLOCK_BASE + 0x580))
#define CLOCK_HFCLK192MSRC_HFXO 1
#define CLOCK_HFCLK192MCTRL *((volatile uint32_t *)(CLOCK_BASE + 0x5B8))
#define CLOCK_HFCLK192MCTRL_DIV1 0
#define CLOCK_HFCLK192MCTRL_DIV2 1
#define CLOCK_HFCLK192MCTRL_DIV4 2
/* GPIO Port (0-1) */
#ifdef TARGET_nrf5340_app
#ifdef TZEN
#define GPIO_BASE(n) (0x50842500 + (((n) & 0x1) * 0x300))
#else
#define GPIO_BASE(n) (0x40842500 + (((n) & 0x1) * 0x300))
#endif
#else
#define GPIO_BASE(n) (0x418C0500 + (((n) & 0x1) * 0x300))
#endif
#define GPIO_OUT(n) *((volatile uint32_t *)(GPIO_BASE(n) + 0x004))
#define GPIO_OUTSET(n) *((volatile uint32_t *)(GPIO_BASE(n) + 0x008))
#define GPIO_OUTCLR(n) *((volatile uint32_t *)(GPIO_BASE(n) + 0x00C))
#define GPIO_IN(n) *((volatile uint32_t *)(GPIO_BASE(n) + 0x010))
#define GPIO_DIRSET(n) *((volatile uint32_t *)(GPIO_BASE(n) + 0x018))
#define GPIO_PIN_CNF(n,p) *((volatile uint32_t *)(GPIO_BASE(n) + 0x200 + ((p) * 0x4)))
#define GPIO_CNF_IN 0
#define GPIO_CNF_IN_DIS 2
#define GPIO_CNF_OUT 3
#define GPIO_CNF_PULL_DIS 0
#define GPIO_CNF_PULL_UP (3UL << 2)
#define GPIO_CNF_PULL_DOWN (1UL << 2)
#define GPIO_CNF_STD_DRIVE 0
#define GPIO_CNF_HIGH_DRIVE (3UL << 8)
#define GPIO_CNF_SENSE_NONE 0
#define GPIO_CNF_MCUSEL(n) (((n) & 0x7) << 28)
/* UART (0-1) */
#ifdef TARGET_nrf5340_app
#ifdef TZEN
#define UART_BASE(n) (0x50008000 + (((n) & 0x1) * 0x1000))
#else
#define UART_BASE(n) (0x40008000 + (((n) & 0x1) * 0x1000))
#endif
#else
#define UART_BASE(n) (0x41013000) /* UARTE0 only */
#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_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))
#define UART_PSEL_RXD(n) *((volatile uint32_t *)(UART_BASE(n) + 0x514))
#define UART_BAUDRATE(n) *((volatile uint32_t *)(UART_BASE(n) + 0x524))
#define UART_TXD_PTR(n) *((volatile uint32_t *)(UART_BASE(n) + 0x544))
#define UART_TXD_MAXCOUNT(n) *((volatile uint32_t *)(UART_BASE(n) + 0x548))
#define UART_CONFIG(n) *((volatile uint32_t *)(UART_BASE(n) + 0x56C))
#define BAUD_115200 0x01D60000UL
void uart_write_sz(const char* c, unsigned int sz);
/* SPI (0-2) */
#ifdef TARGET_nrf5340_app
#ifdef TZEN
#define SPI_BASE(n) (0x50008000 + (((n) & 0x3) * 0x1000))
#else
#define SPI_BASE(n) (0x40008000 + (((n) & 0x3) * 0x1000))
#endif
#else
#define SPI_BASE(n) (0x41013000) /* SPIM0 only */
#endif
#define SPI_TASKS_START(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x010))
#define SPI_TASKS_STOP(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x014))
#define SPI_EVENTS_ENDRX(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x110))
#define SPI_EVENTS_END(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x118))
#define SPI_EVENTS_ENDTX(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x120))
#define SPI_EV_RDY(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x108))
#define SPI_INTENSET(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x304))
#define SPI_INTENCLR(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x308))
#define SPI_ENABLE(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x500))
#define SPI_PSEL_SCK(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x508))
#define SPI_PSEL_MOSI(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x50C))
#define SPI_PSEL_MISO(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x510))
#define SPI_RXDATA(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x518))
#define SPI_TXDATA(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x51C))
#define SPI_FREQUENCY(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x524))
#define SPI_CONFIG(n) *((volatile uint32_t *)(SPI_BASE(n) + 0x554))
#define SPI_FREQ_K125 0x02000000
#define SPI_FREQ_K250 0x04000000
#define SPI_FREQ_K500 0x08000000
#define SPI_FREQ_M1 0x10000000
#define SPI_FREQ_M2 0x20000000
#define SPI_FREQ_M4 0x40000000
#define SPI_FREQ_M8 0x80000000
#define SPI_FREQ_M16 0x0A000000
#define SPI_FREQ_M32 0x14000000
/* QSPI */
#ifdef TARGET_nrf5340_app
#ifdef TZEN
#define QSPI_BASE (0x5002B000)
#else
#define QSPI_BASE (0x4002B000)
#endif
#define QSPI_TASKS_ACTIVATE *((volatile uint32_t *)(QSPI_BASE + 0x000))
#define QSPI_TASKS_READSTART *((volatile uint32_t *)(QSPI_BASE + 0x004))
#define QSPI_TASKS_WRITESTART *((volatile uint32_t *)(QSPI_BASE + 0x008))
#define QSPI_TASKS_ERASESTART *((volatile uint32_t *)(QSPI_BASE + 0x00C))
#define QSPI_TASKS_DEACTIVATE *((volatile uint32_t *)(QSPI_BASE + 0x010))
#define QSPI_EVENTS_READY *((volatile uint32_t *)(QSPI_BASE + 0x100))
#define QSPI_INTEN *((volatile uint32_t *)(QSPI_BASE + 0x300))
#define QSPI_INTENSET *((volatile uint32_t *)(QSPI_BASE + 0x304))
#define QSPI_INTENCLR *((volatile uint32_t *)(QSPI_BASE + 0x308))
#define QSPI_ENABLE *((volatile uint32_t *)(QSPI_BASE + 0x500))
#define QSPI_READ_SRC *((volatile uint32_t *)(QSPI_BASE + 0x504))
#define QSPI_READ_DST *((volatile uint32_t *)(QSPI_BASE + 0x508))
#define QSPI_READ_CNT *((volatile uint32_t *)(QSPI_BASE + 0x50C))
#define QSPI_WRITE_DST *((volatile uint32_t *)(QSPI_BASE + 0x510))
#define QSPI_WRITE_SRC *((volatile uint32_t *)(QSPI_BASE + 0x514))
#define QSPI_WRITE_CNT *((volatile uint32_t *)(QSPI_BASE + 0x518))
#define QSPI_ERASE_PTR *((volatile uint32_t *)(QSPI_BASE + 0x51C))
#define QSPI_ERASE_LEN *((volatile uint32_t *)(QSPI_BASE + 0x520))
#define QSPI_PSEL_SCK *((volatile uint32_t *)(QSPI_BASE + 0x524))
#define QSPI_PSEL_CSN *((volatile uint32_t *)(QSPI_BASE + 0x528))
#define QSPI_PSEL_IO0 *((volatile uint32_t *)(QSPI_BASE + 0x530))
#define QSPI_PSEL_IO1 *((volatile uint32_t *)(QSPI_BASE + 0x534))
#define QSPI_PSEL_IO2 *((volatile uint32_t *)(QSPI_BASE + 0x538))
#define QSPI_PSEL_IO3 *((volatile uint32_t *)(QSPI_BASE + 0x53C))
#define QSPI_IFCONFIG0 *((volatile uint32_t *)(QSPI_BASE + 0x544))
#define QSPI_IFCONFIG1 *((volatile uint32_t *)(QSPI_BASE + 0x600))
#define QSPI_STATUS *((volatile uint32_t *)(QSPI_BASE + 0x604))
#define QSPI_ADDRCONF *((volatile uint32_t *)(QSPI_BASE + 0x624))
#define QSPI_CINSTRCONF *((volatile uint32_t *)(QSPI_BASE + 0x634))
#define QSPI_CINSTRDAT0 *((volatile uint32_t *)(QSPI_BASE + 0x638))
#define QSPI_CINSTRDAT1 *((volatile uint32_t *)(QSPI_BASE + 0x63C))
#define QSPI_IFTIMING *((volatile uint32_t *)(QSPI_BASE + 0x640))
#define QSPI_IFCONFIG0_READOC_MASK 0x7
#define QSPI_IFCONFIG0_READOC_FASTREAD (0) /* opcode 0x0B */
#define QSPI_IFCONFIG0_READOC_READ2O (1) /* opcode 0x3B */
#define QSPI_IFCONFIG0_READOC_READ2IO (2) /* opcode 0xBB */
#define QSPI_IFCONFIG0_READOC_READ4O (3) /* opcode 0x6B */
#define QSPI_IFCONFIG0_READOC_READ4IO (4) /* opcode 0xEB */
#define QSPI_IFCONFIG0_WRITEOC_MASK ((0x7) << 3)
#define QSPI_IFCONFIG0_WRITEOC_PP ((0) << 3) /* opcode 0x02 */
#define QSPI_IFCONFIG0_WRITEOC_PP2O ((1) << 3) /* opcode 0xA2 */
#define QSPI_IFCONFIG0_WRITEOC_PP4O ((2) << 3) /* opcode 0x32 */
#define QSPI_IFCONFIG0_WRITEOC_PP4IO ((3) << 3) /* opcode 0x38 */
#define QSPI_IFCONFIG0_ADDRMODE_24BIT ((0) << 6)
#define QSPI_IFCONFIG0_ADDRMODE_32BIT ((1) << 6)
#define QSPI_IFCONFIG0_DPMENABLE ((1) << 7)
#define QSPI_IFCONFIG0_PPSIZE_256 ((0) << 12)
#define QSPI_IFCONFIG0_PPSIZE_512 ((1) << 12)
#define QSPI_IFCONFIG1_SCKDELAY_MASK 0xFF
#define QSPI_IFCONFIG1_SCKDELAY(n) ((n) & QSPI_IFCONFIG1_SCKDELAY_MASK)
#define QSPI_IFCONFIG1_SPIMODE0 0
#define QSPI_IFCONFIG1_SPIMODE3 (1UL << 25)
#define QSPI_IFCONFIG1_SCKFREQ_MASK ((0xF) << 28)
#define QSPI_IFCONFIG1_SCKFREQ(n) (((n) & 0xF) << 28)
#define QSPI_CINSTRCONF_OPCODE(n) ((n) & 0xFF)
#define QSPI_CINSTRCONF_LENGTH(n) (((n) & 0xF) << 8)
#define QSPI_CINSTRCONF_LIO2 (1 << 12)
#define QSPI_CINSTRCONF_LIO3 (1 << 13)
#define QSPI_CINSTRCONF_WREN (1 << 15) /* send WREN opcode 0x6 before */
#define QSPI_IFTIMING_RXDELAY(n) (((n) & 0x7) << 8)
#else
/* Disable QSPI Flash */
#undef QSPI_FLASH
#endif
/* interprocessor communication (IPC) peripheral */
#ifdef TARGET_nrf5340_app
#ifdef TZEN
#define IPC_BASE (0x5002A000)
#else
#define IPC_BASE (0x4002A000)
#endif
#else
#define IPC_BASE (0x4002A000) /* 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)))
#define IPC_EVENTS_RECEIVE(n) *((volatile uint32_t *)(IPC_BASE + 0x100 + (((n) & 0xF) * 0x4)))
#define IPC_PUBLISH_RECEIVE(n) *((volatile uint32_t *)(IPC_BASE + 0x180 + (((n) & 0xF) * 0x4)))
#define IPC_SEND_CNF(n) *((volatile uint32_t *)(IPC_BASE + 0x510 + (((n) & 0xF) * 0x4)))
#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)))
#endif /* !_HAL_NRF5340_H_ */

52
hal/nrf5340.ld 100644
View File

@ -0,0 +1,52 @@
MEMORY
{
FLASH (rx) : ORIGIN = @ARCH_FLASH_OFFSET@, LENGTH = @BOOTLOADER_PARTITION_SIZE@
FLASH_NET (rx) : ORIGIN = 0x01000000, LENGTH = 256K
RAM (rwx) : ORIGIN = 0x20000000, 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);

28
hal/nrf5340_net.c 100644
View File

@ -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_* */

51
hal/nrf5340_net.ld 100644
View File

@ -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);

View File

@ -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))
#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)
{

View File

@ -17,22 +17,12 @@
#ifndef SPI_DRV_NRF52_H_INCLUDED
#define SPI_DRV_NRF52_H_INCLUDED
#include <stdint.h>
/** SPI settings **/
#include "hal/nrf52.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_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
/* 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

View File

@ -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 <stdint.h>
#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_ */

View File

@ -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 <stdint.h>
#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 */

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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 0;
}
#endif /* WOLFBOOT_FIXED_PARTITIONS */

View File

@ -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 */
@ -116,7 +106,6 @@
#define FLASH_READ_CMD QUAD_READ_CMD
#undef QSPI_DUMMY_READ
#define QSPI_DUMMY_READ 4
#define QSPI_ADDR_MODE QSPI_DATA_MODE_QSPI
#elif QSPI_DATA_MODE == QSPI_DATA_MODE_DSPI
#define FLASH_READ_CMD DUAL_READ_CMD
#else
@ -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 */
memset(data, 0, sizeof(data));
ret = qspi_command_simple(QSPI_MODE_READ, READ_SR2_CMD, 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");
#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
if (ret == 0 && (data[0] & FLASH_SR2_QE) == 0) {
memset(data, 0, sizeof(data));
ret = qspi_command_simple(QSPI_MODE_READ, QE_SR_READ, data, 1);
#ifdef DEBUG_QSPI
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] & 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<sizeof(pageData); i++) {
#if defined(DEBUG_QSPI) && DEBUG_QSPI > 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 */

View File

@ -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':

View File

@ -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));

View File

@ -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

View File

@ -23,26 +23,8 @@
#include <stdint.h>
#include <string.h>
#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) {
gpiotoggle(pin);
for (i = 0; i < 800000; i++) // Wait a bit.
for (i = 0; i < 800000; i++) /* Wait a bit. */
asm volatile ("nop");
}
}

View File

@ -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 <stdlib.h>
#include <stdint.h>
#include <string.h>
#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);
}
}

View File

@ -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 <stdlib.h>
#include <stdint.h>
#include <string.h>
#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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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