Create STM32WB wolfHAL example. GC sections on all test apps

pull/801/head
Alex Lanzano 2026-03-04 17:10:51 -05:00 committed by Daniele Lacamera
parent b1ad603363
commit 125872c571
15 changed files with 690 additions and 15 deletions

View File

@ -667,6 +667,12 @@ jobs:
arch: arm
config-file: ./config/examples/stm32wb.config
wolfhal_stm32wb_test:
uses: ./.github/workflows/test-build.yml
with:
arch: arm
config-file: ./config/examples/wolfhal_stm32wb_nucleo.config
# TODO: ti-tms570lc435.config requires F021 Flash API (Windows installer only)
# ti_tms570lc435_test:
# uses: ./.github/workflows/test-build-ti-hercules.yml

3
.gitmodules vendored
View File

@ -13,3 +13,6 @@
[submodule "lib/wolfPSA"]
path = lib/wolfPSA
url = https://github.com/wolfSSL/wolfPSA.git
[submodule "lib/wolfHAL"]
path = lib/wolfHAL
url = https://github.com/wolfSSL/wolfHAL.git

View File

@ -174,6 +174,17 @@ export WOLFBOOT_LIB_WOLFHSM
## Architecture/CPU configuration
include arch.mk
ifeq ($(TARGET),wolfhal)
ifeq ($(strip $(BOARD)),)
$(error TARGET=wolfhal requires BOARD to be set, e.g. BOARD=stm32wb_nucleo)
endif
# wolfHAL target: hal/wolfhal.o is added by the per-TARGET rule
# above. The board's board.c provides hal_init/hal_prepare_boot and
# the wolfHAL device handles; board.mk pulls in chip drivers.
OBJS+=./hal/boards/$(BOARD)/board.o
include hal/boards/$(BOARD)/board.mk
endif
# Parse config options
include options.mk
@ -567,7 +578,10 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE
sed -e "s/@WOLFBOOT_LOAD_ADDRESS@/$(WOLFBOOT_LOAD_ADDRESS)/g" | \
sed -e "s/@FSP_S_LOAD_BASE@/$(FSP_S_LOAD_BASE)/g" | \
sed -e "s/@WOLFBOOT_L2LIM_SIZE@/$(WOLFBOOT_L2LIM_SIZE)/g" | \
sed -e "s/@L2SRAM_ADDR@/$(L2SRAM_ADDR)/g" \
sed -e "s/@L2SRAM_ADDR@/$(L2SRAM_ADDR)/g" | \
sed -e 's/@WOLFHAL_FLASH_EXCLUDE_TEXT@/$(WOLFHAL_FLASH_EXCLUDE_TEXT)/g' | \
sed -e 's/@WOLFHAL_FLASH_EXCLUDE_RODATA@/$(WOLFHAL_FLASH_EXCLUDE_RODATA)/g' | \
sed -e 's/@WOLFHAL_FLASH_RAM_SECTIONS@/$(WOLFHAL_FLASH_RAM_SECTIONS)/g' \
> $@
hex: wolfboot.hex

11
arch.mk
View File

@ -223,6 +223,11 @@ ifeq ($(ARCH),ARM)
SPI_TARGET=stm32
endif
# Defaults for linker script placeholders (overridden by wolfhal target)
WOLFHAL_FLASH_EXCLUDE_TEXT?=*(.text*)
WOLFHAL_FLASH_EXCLUDE_RODATA?=*(.rodata*)
WOLFHAL_FLASH_RAM_SECTIONS?=
ifeq ($(TARGET),stm32wb)
ARCH_FLASH_OFFSET=0x08000000
SPI_TARGET=stm32
@ -238,7 +243,6 @@ ifeq ($(ARCH),ARM)
endif
endif
ifeq ($(TARGET),stm32l5)
CORTEX_M33=1
CFLAGS+=-Ihal
@ -570,6 +574,11 @@ endif
endif
endif
ifeq ($(TARGET),wolfhal)
WOLFHAL_ROOT?=$(WOLFBOOT_ROOT)/lib/wolfHAL
CFLAGS+=-I$(WOLFHAL_ROOT) -Ihal/boards/$(BOARD)
endif
## Renesas RX
ifeq ($(ARCH),RENESAS_RX)

View File

@ -0,0 +1,11 @@
TARGET=wolfhal
BOARD=stm32wb_nucleo
PKA=0
SIGN=ECC256
HASH=SHA256
WOLFBOOT_SECTOR_SIZE=0x1000
WOLFBOOT_PARTITION_SIZE=0x20000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x08008000
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x08028000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x08048000
NVM_FLASH_WRITEONCE=1

256
docs/wolfHAL.md 100644
View File

@ -0,0 +1,256 @@
# wolfHAL Integration
wolfBoot supports [wolfHAL](https://github.com/wolfSSL/wolfHAL) as an alternative
hardware abstraction layer backend. wolfHAL provides portable drivers for common MCU
peripherals (clock, flash, GPIO, UART, SPI, etc.) with a consistent API across
platforms.
## Overview
The wolfHAL integration uses a single generic `TARGET=wolfhal` with a per-board
abstraction layer. All board-specific details — device instances, driver bindings,
build flags, and linker scripts — live in a self-contained board directory. Adding
support for a new board or MCU family requires no changes to the core build system or
HAL shim.
The integration uses wolfHAL's **direct API mapping** feature. Each platform
driver source provides an optional `#ifdef` block that renames its driver
functions to the top-level API names. When the corresponding
`WHAL_CFG_<TYPE>_API_MAPPING_<VARIANT>` flag is defined, the driver file
itself provides the definition of the top-level API — no wrapper, no vtable
indirection, no runtime null-check. Calling `whal_Flash_Write(&dev, ...)` links
directly to the platform driver's implementation.
The integration consists of four parts:
1. **Generic HAL shim** (`hal/wolfhal.c`) — implements the wolfBoot HAL API
(`hal_flash_write`, `hal_flash_erase`, etc.) by calling the top-level wolfHAL
API (`whal_Flash_Write`, `whal_Uart_Send`, etc.). This file is shared across
all wolfHAL boards.
2. **Board directory** (`hal/boards/<board>/`) — contains three files that fully
describe a board:
- `board.h` — includes the chip-specific wolfHAL driver headers and defines
any board-level pin/peripheral enums.
- `board.c` — device instances (clock, flash, GPIO, UART), configuration
structs, and `hal_init`/`hal_prepare_boot` implementations.
- `board.mk` — build variables (`ARCH_FLASH_OFFSET`, `LSCRIPT_IN`, the
`WHAL_CFG_*_API_MAPPING_*` flags, wolfHAL driver objects, `RAM_CODE`
linker rules).
3. **Generic test application** (`test-app/app_wolfhal.c`) — demonstrates using
wolfHAL peripherals (GPIO, UART) beyond what the bootloader needs, using the
same top-level wolfHAL API.
4. **wolfHAL library** (`lib/wolfHAL/`) — the wolfHAL submodule containing the
platform drivers.
### How It Fits Together
```
config/examples/wolfhal_<board>.config
└─ TARGET=wolfhal BOARD=<board>
arch.mk
└─ Sets WOLFHAL_ROOT, CFLAGS += -Ihal/boards/$(BOARD)
Makefile
└─ OBJS += hal/boards/$(BOARD)/board.o
└─ include hal/boards/$(BOARD)/board.mk
hal/wolfhal.c (generic — calls whal_Flash_Write, whal_Uart_Send, etc.)
└─ #include "board.h" (resolved via -I to the board directory)
hal/boards/<board>/
├─ board.h (includes wolfHAL driver headers, pin enums)
├─ board.c (device instances, hal_init, hal_prepare_boot)
└─ board.mk (WHAL_CFG_*_API_MAPPING_*, driver objects, RAM_CODE rules)
```
The `WHAL_CFG_*_API_MAPPING_*` flags cause each wolfHAL driver source to emit
its functions under the top-level API name. Since only one driver source per
device type is compiled, there is no conflict — and since no dispatch source
(e.g., `src/flash/flash.c`) is included, there is no vtable indirection. The
linker can garbage-collect any unused symbols with `-Wl,--gc-sections`.
## Configuration
A wolfHAL-based config requires two variables beyond the standard wolfBoot settings:
```
TARGET=wolfhal
BOARD=stm32wb_nucleo
```
- `TARGET=wolfhal` selects the generic wolfHAL HAL shim and build path.
- `BOARD` selects the board directory under `hal/boards/`.
See `config/examples/wolfhal_*.config` for complete examples.
## Adding a New Board
To add a new board, create a directory `hal/boards/<board_name>/` with three files:
### 1. `board.h` — Driver Headers and Pin Enums
Include the chip-specific wolfHAL driver headers and declare any board-level
enums (pin indices, peripheral identifiers):
```c
#ifndef WOLFHAL_BOARD_H
#define WOLFHAL_BOARD_H
#include <wolfHAL/clock/<family>_rcc.h>
#include <wolfHAL/flash/<family>_flash.h>
#include <wolfHAL/gpio/<family>_gpio.h>
#include <wolfHAL/uart/<family>_uart.h>
/* GPIO pin indices (matches pin array in board.c) */
enum {
BOARD_LED_PIN,
BOARD_UART_TX_PIN,
BOARD_UART_RX_PIN,
BOARD_PIN_COUNT,
};
#endif /* WOLFHAL_BOARD_H */
```
### 2. `board.c` — Device Instances and Initialization
Define the wolfHAL device instances and implement `hal_init` and `hal_prepare_boot`
using the top-level wolfHAL API. The file must export `g_wbFlash` (and `g_wbUart`
when `DEBUG_UART` is enabled) as non-static globals — these are referenced by
`hal/wolfhal.c` via `extern`.
```c
#include "hal.h"
#include "board.h"
/* Clock controller */
whal_Clock g_wbClock = {
.regmap = { .base = ..., .size = 0x400 },
.cfg = &(whal_<Family>Rcc_Cfg) { ... },
};
/* Flash */
whal_Flash g_wbFlash = {
.regmap = { .base = ..., .size = 0x400 },
.cfg = &(whal_<Family>Flash_Cfg) {
.startAddr = 0x08000000,
.size = ...,
},
};
#ifdef DEBUG_UART
whal_Gpio g_wbGpio = { ... };
whal_Uart g_wbUart = { ... };
#endif
void hal_init(void)
{
whal_Clock_Init(&g_wbClock);
whal_Flash_Init(&g_wbFlash);
#ifdef DEBUG_UART
whal_Gpio_Init(&g_wbGpio);
whal_Uart_Init(&g_wbUart);
#endif
}
void hal_prepare_boot(void)
{
#ifdef DEBUG_UART
whal_Uart_Deinit(&g_wbUart);
whal_Gpio_Deinit(&g_wbGpio);
#endif
whal_Flash_Deinit(&g_wbFlash);
whal_Clock_Deinit(&g_wbClock);
}
```
Note: the device instance's `.driver` field is intentionally left unset. With
API mapping, the top-level `whal_*_Init`/etc. symbols are the driver functions
themselves — there is no dispatch through a vtable.
### 3. `board.mk` — Build Variables
Provide the build-time configuration: API mapping flags, flash offset, linker
script, and the wolfHAL driver objects needed for your MCU family. **Do not
compile the dispatch source (`src/<type>/<type>.c`)** — it would provide a
duplicate definition of the top-level API symbols.
```makefile
ARCH_FLASH_OFFSET=0x08000000
LSCRIPT_IN=hal/<family>.ld
# Bind wolfHAL driver sources directly to the top-level API symbols.
CFLAGS+=-DWHAL_CFG_CLOCK_API_MAPPING_<FAMILY>
CFLAGS+=-DWHAL_CFG_FLASH_API_MAPPING_<FAMILY>
CFLAGS+=-DWHAL_CFG_GPIO_API_MAPPING_<FAMILY>
CFLAGS+=-DWHAL_CFG_UART_API_MAPPING_<FAMILY>
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/clock/<family>_rcc.o
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/flash/<family>_flash.o
ifeq ($(DEBUG_UART),1)
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/gpio/<family>_gpio.o
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/uart/<family>_uart.o
endif
OBJS+=$(WOLFHAL_OBJS)
APP_OBJS+=$(WOLFHAL_OBJS)
ifeq ($(RAM_CODE),1)
WOLFHAL_FLASH_EXCLUDE_TEXT=*(EXCLUDE_FILE(*<family>_flash.o) .text*)
WOLFHAL_FLASH_EXCLUDE_RODATA=*(EXCLUDE_FILE(*<family>_flash.o) .rodata*)
WOLFHAL_FLASH_RAM_SECTIONS=*<family>_flash.o(.text* .rodata*)
endif
```
Only one API mapping flag may be active per device type per build.
### 4. Config File
Create `config/examples/wolfhal_<board_name>.config`:
```
TARGET=wolfhal
BOARD=<board_name>
SIGN=ECC256
HASH=SHA256
WOLFBOOT_SECTOR_SIZE=0x1000
WOLFBOOT_PARTITION_SIZE=0x20000
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x08008000
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x08028000
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x08048000
NVM_FLASH_WRITEONCE=1
```
Adjust partition addresses and sector sizes for your board's flash layout. Optionally
add `DEBUG_UART=1` to enable UART debug output.
## RAM_CODE
When `RAM_CODE=1` is set, wolfBoot's core flash update functions are placed in RAM
via the `RAMFUNCTION` attribute. For wolfHAL boards, the `board.mk` defines
`EXCLUDE_FILE` rules that also place the wolfHAL flash driver into RAM. This ensures
all flash operations execute from RAM, which is required on MCUs that stall or fault
when code executes from the same flash bank being programmed.
The linker script uses `@WOLFHAL_FLASH_EXCLUDE_TEXT@`,
`@WOLFHAL_FLASH_EXCLUDE_RODATA@`, and `@WOLFHAL_FLASH_RAM_SECTIONS@` placeholders
that are substituted at build time. When `RAM_CODE=1`, these expand to
`EXCLUDE_FILE` rules that move the flash driver's `.text` and `.rodata` sections from
flash into the `.data` section (loaded to RAM at startup). When `RAM_CODE` is not
set, all code remains in flash as normal.
## Test Application
The generic test application (`test-app/app_wolfhal.c`) demonstrates using wolfHAL
peripherals beyond what the bootloader needs. It accesses the board-provided GPIO and
UART instances (`g_wbGpio`, `g_wbUart`) via `extern`, using the top-level wolfHAL
API (`whal_Gpio_Set`, `whal_Uart_Send`) to toggle an LED and send serial output,
then exercises the wolfBoot update mechanism.
The test-app Makefile compiles its own copy of the board file (`board_<board>.o`)
with `DEBUG_UART=1` always defined, since the app needs UART and GPIO regardless of
the bootloader's `DEBUG_UART` setting.

View File

@ -0,0 +1,86 @@
/* board.c
*
* STM32WB55 Nucleo board configuration using upstream wolfHAL drivers.
* Gpio/Flash/Uart singletons are instantiated by the driver .c files
* from WHAL_CFG_STM32WB_*_DEV initializer macros in board.h; board.c
* uses the BOARD_*_DEV handles for the rest. RCC is header-inlined and
* hardcodes WHAL_STM32WB_RCC_BASE no dev pointer needed.
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stddef.h>
#include "hal.h"
#include "board.h"
#ifdef DEBUG_UART
static const whal_Stm32wb_Rcc_PeriphClk g_periphClks[] = {
{WHAL_STM32WB55_GPIOB_GATE},
{WHAL_STM32WB55_UART1_GATE},
};
#define PERIPH_CLK_COUNT (sizeof(g_periphClks) / sizeof(g_periphClks[0]))
#endif
/* MSI 4 MHz -> PLL VCO 128 MHz -> PLLR /2 = 64 MHz -> SYSCLK */
static void pll_clock_on(void)
{
whal_Stm32wb_Flash_Ext_SetLatency(BOARD_FLASH_DEV, WHAL_STM32WB_FLASH_LATENCY_3);
whal_Stm32wb_Rcc_EnablePll(&(whal_Stm32wb_Rcc_PllCfg){
.clkSrc = WHAL_STM32WB_RCC_PLLCLK_SRC_MSI,
.n = 32, .m = 0, .r = 1, .q = 0, .p = 0,
});
whal_Stm32wb_Rcc_SetSysClock(WHAL_STM32WB_RCC_SYSCLK_SRC_PLL);
}
static void pll_clock_off(void)
{
whal_Stm32wb_Rcc_SetSysClock(WHAL_STM32WB_RCC_SYSCLK_SRC_MSI);
whal_Stm32wb_Rcc_DisablePll();
whal_Stm32wb_Flash_Ext_SetLatency(BOARD_FLASH_DEV, WHAL_STM32WB_FLASH_LATENCY_0);
}
void hal_init(void)
{
pll_clock_on();
whal_Flash_Init(BOARD_FLASH_DEV);
#ifdef DEBUG_UART
for (size_t i = 0; i < PERIPH_CLK_COUNT; i++) {
whal_Stm32wb_Rcc_EnablePeriphClk(&g_periphClks[i]);
}
whal_Gpio_Init(BOARD_GPIO_DEV);
whal_Uart_Init(BOARD_UART_DEV);
#endif
}
void hal_prepare_boot(void)
{
#ifdef DEBUG_UART
whal_Uart_Deinit(BOARD_UART_DEV);
whal_Gpio_Deinit(BOARD_GPIO_DEV);
for (size_t i = PERIPH_CLK_COUNT; i-- > 0; ) {
whal_Stm32wb_Rcc_DisablePeriphClk(&g_periphClks[i]);
}
#endif
whal_Flash_Deinit(BOARD_FLASH_DEV);
pll_clock_off();
}

View File

@ -0,0 +1,101 @@
/* board.h
*
* STM32WB55 Nucleo wolfHAL board header. Provides the WHAL_CFG_STM32WB_X_DEV
* initializer macros that the upstream chip drivers use to instantiate the
* whal_Stm32wb_X_Dev singletons (in their own .c file), plus the BOARD_X_DEV
* handles that the wolfBoot adapter (hal/wolfhal.c) and board.c pass into
* the wolfHAL API.
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef WOLFHAL_BOARD_H
#define WOLFHAL_BOARD_H
#include <wolfHAL/wolfHAL.h>
#include <wolfHAL/platform/st/stm32wb55xx.h>
#include <wolfHAL/clock/stm32wb_rcc.h>
#include <wolfHAL/flash/stm32wb_flash.h>
#include <wolfHAL/gpio/stm32wb_gpio.h>
#include <wolfHAL/uart/stm32wb_uart.h>
/* GPIO pin indices used by the runtime-addressable pinCfg table. */
enum {
BOARD_LED_PIN,
BOARD_UART_TX_PIN,
BOARD_UART_RX_PIN,
BOARD_PIN_COUNT,
};
/* Singletons owned by the upstream driver .c files. Declared here so
* BOARD_FLASH_DEV can take its address. */
extern const whal_Gpio whal_Stm32wb_Gpio_Dev;
extern const whal_Flash whal_Stm32wb_Flash_Dev;
extern const whal_Uart whal_Stm32wb_Uart_Dev;
/* Device handles passed into the wolfHAL API. GPIO/UART use the
* INTERNAL_DEV sentinel (the SINGLE_INSTANCE drivers ignore the dev
* pointer and read from their static singleton); FLASH takes the
* address so it could coexist with another flash driver in the future
* without API churn. */
#define BOARD_GPIO_DEV WHAL_INTERNAL_DEV
#define BOARD_UART_DEV WHAL_INTERNAL_DEV
#define BOARD_FLASH_DEV WHAL_INTERNAL_DEV
/* GPIO singleton initializer — instantiated by stm32wb_gpio.c. */
#define WHAL_CFG_STM32WB_GPIO_DEV { \
.base = WHAL_STM32WB55_GPIO_BASE, \
.cfg = (void *)&(const whal_Stm32wb_Gpio_Cfg){ \
.pinCfg = (const whal_Stm32wb_Gpio_PinCfg[BOARD_PIN_COUNT]){ \
[BOARD_LED_PIN] = WHAL_STM32WB_GPIO_PIN( \
WHAL_STM32WB_GPIO_PORT_B, 5, WHAL_STM32WB_GPIO_MODE_OUT, \
WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB_GPIO_SPEED_LOW, \
WHAL_STM32WB_GPIO_PULL_UP, 0), \
[BOARD_UART_TX_PIN] = WHAL_STM32WB_GPIO_PIN( \
WHAL_STM32WB_GPIO_PORT_B, 6, WHAL_STM32WB_GPIO_MODE_ALTFN, \
WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB_GPIO_SPEED_FAST, \
WHAL_STM32WB_GPIO_PULL_UP, 7), \
[BOARD_UART_RX_PIN] = WHAL_STM32WB_GPIO_PIN( \
WHAL_STM32WB_GPIO_PORT_B, 7, WHAL_STM32WB_GPIO_MODE_ALTFN, \
WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB_GPIO_SPEED_FAST, \
WHAL_STM32WB_GPIO_PULL_UP, 7), \
}, \
.pinCount = BOARD_PIN_COUNT, \
}, \
}
/* Flash singleton initializer — instantiated by stm32wb_flash.c. */
#define WHAL_CFG_STM32WB_FLASH_DEV { \
.base = WHAL_STM32WB55_FLASH_BASE, \
.cfg = (void *)&(const whal_Stm32wb_Flash_Cfg){ \
.startAddr = 0x08000000, \
.size = 0x100000, \
}, \
}
/* UART singleton initializer — instantiated by stm32wb_uart.c when
* WHAL_CFG_STM32WB_UART_SINGLE_INSTANCE is defined. */
#define WHAL_CFG_STM32WB_UART_DEV { \
.base = WHAL_STM32WB55_UART1_BASE, \
.cfg = (void *)&(const whal_Stm32wb_Uart_Cfg){ \
.brr = WHAL_STM32WB_UART_BRR(64000000, 115200), \
}, \
}
#endif /* WOLFHAL_BOARD_H */

View File

@ -0,0 +1,25 @@
ARCH_FLASH_OFFSET=0x08000000
LSCRIPT_IN=hal/stm32wb.ld
CFLAGS+=-DWHAL_CFG_NO_TIMEOUT
# Upstream wolfHAL drivers from lib/wolfHAL/src/. wolfBoot's hal_flash_*
# contract is satisfied by hal/wolfhal.c (added automatically because
# TARGET=wolfhal) calling whal_Flash_*.
CFLAGS+=-DWHAL_CFG_STM32WB_FLASH_DIRECT_API_MAPPING
CFLAGS+=-DWHAL_CFG_STM32WB_GPIO_DIRECT_API_MAPPING
CFLAGS+=-DWHAL_CFG_STM32WB_UART_DIRECT_API_MAPPING
# UART driver is single-instance — reads whal_Stm32wb_Uart_Dev from board.h
# instead of the passed dev pointer.
CFLAGS+=-DWHAL_CFG_STM32WB_UART_SINGLE_INSTANCE
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/reg.o
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/flash/stm32wb_flash.o
ifeq ($(DEBUG_UART),1)
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/gpio/stm32wb_gpio.o
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/uart/stm32wb_uart.o
endif
OBJS+=$(WOLFHAL_OBJS)
APP_OBJS+=$(WOLFHAL_OBJS)

View File

@ -10,10 +10,8 @@ SECTIONS
{
_start_text = .;
KEEP(*(.isr_vector))
; *(EXCLUDE_FILE(*chacha*) .text*)
; *(EXCLUDE_FILE(*chacha*) .rodata*)
*(.text*)
*(.rodata*)
@WOLFHAL_FLASH_EXCLUDE_TEXT@
@WOLFHAL_FLASH_EXCLUDE_RODATA@
. = ALIGN(4);
_end_text = .;
} > FLASH
@ -30,9 +28,7 @@ SECTIONS
KEEP(*(.data*))
. = ALIGN(4);
KEEP(*(.ramcode))
; KEEP(*(.text.wc_Chacha*))
; KEEP(*(.rodata.sigma))
; KEEP(*(.rodata.tau))
@WOLFHAL_FLASH_RAM_SECTIONS@
. = ALIGN(4);
_end_data = .;
} > RAM

58
hal/wolfhal.c 100644
View File

@ -0,0 +1,58 @@
/* wolfhal.c
*
* Generic wolfHAL port for wolfBoot. wolfBoot's HAL contract
* (hal_flash_*, uart_write) is satisfied here by forwarding to the
* wolfHAL API. The chip drivers behind the wolfHAL API are singletons,
* instantiated by the driver .c files from initializer macros in
* board.h; this file passes the BOARD_*_DEV handles defined there.
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdint.h>
#include "hal.h"
#include "wolfboot/wolfboot.h"
#include "board.h"
void RAMFUNCTION hal_flash_unlock(void)
{
whal_Flash_Unlock(BOARD_FLASH_DEV, 0, 0);
}
void RAMFUNCTION hal_flash_lock(void)
{
whal_Flash_Lock(BOARD_FLASH_DEV, 0, 0);
}
int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len)
{
return whal_Flash_Write(BOARD_FLASH_DEV, (size_t)address, data, (size_t)len);
}
int RAMFUNCTION hal_flash_erase(uint32_t address, int len)
{
return whal_Flash_Erase(BOARD_FLASH_DEV, (size_t)address, (size_t)len);
}
#ifdef DEBUG_UART
void uart_write(const char *buf, unsigned int len)
{
whal_Uart_Send(BOARD_UART_DEV, (const uint8_t *)buf, (size_t)len);
}
#endif

1
lib/wolfHAL 160000

@ -0,0 +1 @@
Subproject commit 2bc2938b0bbcc977177153a7f38393710702bf70

View File

@ -1215,7 +1215,9 @@ OBJS+=$(SECURE_OBJS)
ifeq ($(RAM_CODE),1)
ifeq ($(ENCRYPT),1)
ifeq ($(ENCRYPT_WITH_CHACHA),1)
LSCRIPT_IN=hal/$(TARGET)_chacha_ram.ld
ifneq ($(TARGET),wolfhal)
LSCRIPT_IN=hal/$(TARGET)_chacha_ram.ld
endif
endif
endif
ifeq ($(ARCH),ARM)

View File

@ -12,6 +12,7 @@ vpath %.S $(WOLFBOOT_LIB_WOLFSSL)
vpath %.c $(WOLFBOOT_LIB_WOLFTPM)
vpath %.S $(WOLFBOOT_LIB_WOLFTPM)
WOLFBOOT_ROOT?=..
TARGET?=none
ARCH?=ARM
MCUXPRESSO_CMSIS?=$(MCUXPRESSO)/CMSIS
@ -68,7 +69,7 @@ ifeq ($(TARGET),ti_hercules)
APP_OBJS:=app_$(TARGET).o ../test-app/libwolfboot.o
CFLAGS+=-I"../include"
else
CFLAGS+=-Wall -ffreestanding -Wno-unused
CFLAGS+=-Wall -ffreestanding -Wno-unused -ffunction-sections -fdata-sections
# Stack usage computation not supported on TriCore
ifneq ($(ARCH),AURIX_TC3)
ifneq ($(USE_CLANG),1)
@ -89,6 +90,8 @@ else
APP_OBJS:=app_renesas_rx.o ../test-app/libwolfboot.o ../src/boot_renesas.o ../src/boot_renesas_start.o ../hal/renesas-rx.o
LDFLAGS+=-ffreestanding -nostartfiles
CFLAGS+=-DWOLFBOOT_RENESAS_APP
else ifeq ($(TARGET),wolfhal)
APP_OBJS:=app_wolfhal.o led.o system.o timer.o ../test-app/libwolfboot.o
else
APP_OBJS:=app_$(TARGET).o led.o system.o timer.o ../test-app/libwolfboot.o
endif
@ -682,13 +685,24 @@ ifeq ($(QSPI_FLASH),1)
endif
endif
ifeq ($(TARGET),wolfhal)
ifeq ($(strip $(BOARD)),)
$(error TARGET=wolfhal requires BOARD to be set, e.g. BOARD=stm32wb_nucleo)
endif
WOLFHAL_ROOT?=$(WOLFBOOT_ROOT)/lib/wolfHAL
CFLAGS+=-I$(WOLFHAL_ROOT) -DWHAL_CFG_NO_TIMEOUT -I$(WOLFBOOT_ROOT)/hal/boards/$(BOARD)
DEBUG_UART=1
APP_OBJS+=board_$(BOARD).o
# hal/wolfhal.o is added by the generic ../hal/$(TARGET).o rule below
# when TARGET=wolfhal, so we don't add it explicitly here.
include $(WOLFBOOT_ROOT)/hal/boards/$(BOARD)/board.mk
endif
ifeq ($(UART_FLASH),1)
CFLAGS+=-D"UART_FLASH=1"
APP_OBJS+= ../src/uart_flash.o ../hal/uart/uart_drv_$(UART_TARGET).o
else
ifeq ($(TARGET),stm32wb)
APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET).o
endif
else ifeq ($(TARGET),stm32wb)
APP_OBJS+=../hal/uart/uart_drv_$(UART_TARGET).o
endif
ifeq ($(TARGET),kinetis)
@ -1139,6 +1153,10 @@ delta-extra-data: image.bin
../hal/spi/spi_drv_$(SPI_TARGET)_ns.o: ../hal/spi/spi_drv_$(SPI_TARGET).c FORCE
$(Q)$(CC) $(CFLAGS) -c -o $(@) ../hal/spi/spi_drv_$(SPI_TARGET).c -DNONSECURE_APP
board_$(BOARD).o: ../hal/boards/$(BOARD)/board.c
@echo "\t[CC-$(ARCH)] $@"
$(Q)$(CC) $(CFLAGS) -DDEBUG_UART -c $(OUTPUT_FLAG) $@ $<
%.o:%.c
@echo "\t[CC-$(ARCH)] $@"
$(Q)$(CC) $(CFLAGS) -c $(OUTPUT_FLAG) $@ $^

View File

@ -0,0 +1,89 @@
/* app_wolfhal.c
*
* Generic test bare-metal application using wolfHAL
*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfBoot.
*
* wolfBoot is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfBoot is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "hal.h"
#include "wolfboot/wolfboot.h"
#include "target.h"
#include "board.h"
#ifdef TARGET_wolfhal
/* Chip drivers behind the wolfHAL API are singletons (configured via
* board.h). Use the BOARD_*_DEV handles defined there. */
/* Matches all keys:
* - chacha (32 + 12)
* - aes128 (16 + 16)
* - aes256 (32 + 16)
*/
char enc_key[] = "0123456789abcdef0123456789abcdef"
"0123456789abcdef";
volatile uint32_t time_elapsed = 0;
void main(void)
{
uint32_t version;
uint32_t updv;
uint8_t ver_buf[5];
hal_init();
/* LED on */
whal_Gpio_Set(BOARD_GPIO_DEV, BOARD_LED_PIN, 1);
version = wolfBoot_current_firmware_version();
updv = wolfBoot_update_firmware_version();
ver_buf[0] = '*';
ver_buf[1] = (version >> 24) & 0xFF;
ver_buf[2] = (version >> 16) & 0xFF;
ver_buf[3] = (version >> 8) & 0xFF;
ver_buf[4] = version & 0xFF;
whal_Uart_Send(BOARD_UART_DEV, ver_buf, sizeof(ver_buf));
if ((version == 1) && (updv != 8)) {
/* LED off */
whal_Gpio_Set(BOARD_GPIO_DEV, BOARD_LED_PIN, 0);
#if EXT_ENCRYPTED
wolfBoot_set_encrypt_key((uint8_t *)enc_key,
(uint8_t *)(enc_key + 32));
#endif
wolfBoot_update_trigger();
/* LED on */
whal_Gpio_Set(BOARD_GPIO_DEV, BOARD_LED_PIN, 1);
} else {
if (version != 7)
wolfBoot_success();
}
/* Wait for reboot */
while (1)
__asm__ volatile("wfi");
}
#endif /* TARGET_wolfhal */