Skip to content

Commit 2805c69

Browse files
committed
Create STM32WB wolfHAL example. GC sections on all test apps
1 parent 993b4f4 commit 2805c69

File tree

15 files changed

+668
-10
lines changed

15 files changed

+668
-10
lines changed

.github/workflows/test-configs.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,12 @@ jobs:
604604
arch: arm
605605
config-file: ./config/examples/stm32wb.config
606606

607+
wolfhal_stm32wb_test:
608+
uses: ./.github/workflows/test-build.yml
609+
with:
610+
arch: arm
611+
config-file: ./config/examples/wolfhal_stm32wb_nucleo.config
612+
607613
# TODO: ti-tms570lc435.config requires F021 Flash API (Windows installer only)
608614
# ti_tms570lc435_test:
609615
# uses: ./.github/workflows/test-build-ti-hercules.yml

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@
1313
[submodule "lib/wolfPSA"]
1414
path = lib/wolfPSA
1515
url = https://github.com/wolfSSL/wolfPSA.git
16+
[submodule "lib/wolfHAL"]
17+
path = lib/wolfHAL
18+
url = https://github.com/wolfSSL/wolfHAL.git

Makefile

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,14 @@ export WOLFBOOT_LIB_WOLFHSM
170170
## Architecture/CPU configuration
171171
include arch.mk
172172

173+
ifeq ($(TARGET),wolfhal)
174+
ifeq ($(strip $(BOARD)),)
175+
$(error TARGET=wolfhal requires BOARD to be set, e.g. BOARD=stm32wb_nucleo)
176+
endif
177+
OBJS+=./hal/boards/$(BOARD)/board.o
178+
include hal/boards/$(BOARD)/board.mk
179+
endif
180+
173181
# Parse config options
174182
include options.mk
175183

@@ -534,7 +542,10 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE
534542
sed -e "s/@IMAGE_HEADER_SIZE@/$(IMAGE_HEADER_SIZE)/g" | \
535543
sed -e "s/@FSP_S_LOAD_BASE@/$(FSP_S_LOAD_BASE)/g" | \
536544
sed -e "s/@WOLFBOOT_L2LIM_SIZE@/$(WOLFBOOT_L2LIM_SIZE)/g" | \
537-
sed -e "s/@L2SRAM_ADDR@/$(L2SRAM_ADDR)/g" \
545+
sed -e "s/@L2SRAM_ADDR@/$(L2SRAM_ADDR)/g" | \
546+
sed -e 's/@WOLFHAL_FLASH_EXCLUDE_TEXT@/$(WOLFHAL_FLASH_EXCLUDE_TEXT)/g' | \
547+
sed -e 's/@WOLFHAL_FLASH_EXCLUDE_RODATA@/$(WOLFHAL_FLASH_EXCLUDE_RODATA)/g' | \
548+
sed -e 's/@WOLFHAL_FLASH_RAM_SECTIONS@/$(WOLFHAL_FLASH_RAM_SECTIONS)/g' \
538549
> $@
539550

540551
hex: wolfboot.hex

arch.mk

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ ifeq ($(ARCH),ARM)
214214
SPI_TARGET=stm32
215215
endif
216216

217+
# Defaults for linker script placeholders (overridden by wolfhal target)
218+
WOLFHAL_FLASH_EXCLUDE_TEXT?=*(.text*)
219+
WOLFHAL_FLASH_EXCLUDE_RODATA?=*(.rodata*)
220+
WOLFHAL_FLASH_RAM_SECTIONS?=
221+
217222
ifeq ($(TARGET),stm32wb)
218223
ARCH_FLASH_OFFSET=0x08000000
219224
SPI_TARGET=stm32
@@ -229,6 +234,10 @@ ifeq ($(ARCH),ARM)
229234
endif
230235
endif
231236

237+
ifeq ($(TARGET),wolfhal)
238+
WOLFHAL_ROOT?=$(WOLFBOOT_ROOT)/lib/wolfHAL
239+
CFLAGS+=-I$(WOLFHAL_ROOT) -DWHAL_CFG_NO_TIMEOUT -Ihal/boards/$(BOARD)
240+
endif
232241

233242
ifeq ($(TARGET),stm32l5)
234243
CORTEX_M33=1
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
TARGET=wolfhal
2+
BOARD=stm32wb_nucleo
3+
SIGN=ECC256
4+
HASH=SHA256
5+
WOLFBOOT_SECTOR_SIZE=0x1000
6+
WOLFBOOT_PARTITION_SIZE=0x20000
7+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x08008000
8+
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x08028000
9+
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x08048000
10+
NVM_FLASH_WRITEONCE=1

docs/wolfHAL.md

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
# wolfHAL Integration
2+
3+
wolfBoot supports [wolfHAL](https://github.com/wolfSSL/wolfHAL) as an alternative
4+
hardware abstraction layer backend. wolfHAL provides portable drivers for common MCU
5+
peripherals (clock, flash, GPIO, UART, SPI, etc.) with a consistent API across
6+
platforms.
7+
8+
## Overview
9+
10+
The wolfHAL integration uses a single generic `TARGET=wolfhal` with a per-board
11+
abstraction layer. All board-specific details — device instances, driver bindings,
12+
build flags, and linker scripts — live in a self-contained board directory. Adding
13+
support for a new board or MCU family requires no changes to the core build system or
14+
HAL shim.
15+
16+
The integration uses wolfHAL's **direct API mapping** feature. Each platform
17+
driver source provides an optional `#ifdef` block that renames its driver
18+
functions to the top-level API names. When the corresponding
19+
`WHAL_CFG_<TYPE>_API_MAPPING_<VARIANT>` flag is defined, the driver file
20+
itself provides the definition of the top-level API — no wrapper, no vtable
21+
indirection, no runtime null-check. Calling `whal_Flash_Write(&dev, ...)` links
22+
directly to the platform driver's implementation.
23+
24+
The integration consists of four parts:
25+
26+
1. **Generic HAL shim** (`hal/wolfhal.c`) — implements the wolfBoot HAL API
27+
(`hal_flash_write`, `hal_flash_erase`, etc.) by calling the top-level wolfHAL
28+
API (`whal_Flash_Write`, `whal_Uart_Send`, etc.). This file is shared across
29+
all wolfHAL boards.
30+
31+
2. **Board directory** (`hal/boards/<board>/`) — contains three files that fully
32+
describe a board:
33+
- `board.h` — includes the chip-specific wolfHAL driver headers and defines
34+
any board-level pin/peripheral enums.
35+
- `board.c` — device instances (clock, flash, GPIO, UART), configuration
36+
structs, and `hal_init`/`hal_prepare_boot` implementations.
37+
- `board.mk` — build variables (`ARCH_FLASH_OFFSET`, `LSCRIPT_IN`, the
38+
`WHAL_CFG_*_API_MAPPING_*` flags, wolfHAL driver objects, `RAM_CODE`
39+
linker rules).
40+
41+
3. **Generic test application** (`test-app/app_wolfhal.c`) — demonstrates using
42+
wolfHAL peripherals (GPIO, UART) beyond what the bootloader needs, using the
43+
same top-level wolfHAL API.
44+
45+
4. **wolfHAL library** (`lib/wolfHAL/`) — the wolfHAL submodule containing the
46+
platform drivers.
47+
48+
### How It Fits Together
49+
50+
```
51+
config/examples/wolfhal_<board>.config
52+
└─ TARGET=wolfhal BOARD=<board>
53+
54+
arch.mk
55+
└─ Sets WOLFHAL_ROOT, CFLAGS += -Ihal/boards/$(BOARD)
56+
57+
Makefile
58+
└─ OBJS += hal/boards/$(BOARD)/board.o
59+
└─ include hal/boards/$(BOARD)/board.mk
60+
61+
hal/wolfhal.c (generic — calls whal_Flash_Write, whal_Uart_Send, etc.)
62+
└─ #include "board.h" (resolved via -I to the board directory)
63+
64+
hal/boards/<board>/
65+
├─ board.h (includes wolfHAL driver headers, pin enums)
66+
├─ board.c (device instances, hal_init, hal_prepare_boot)
67+
└─ board.mk (WHAL_CFG_*_API_MAPPING_*, driver objects, RAM_CODE rules)
68+
```
69+
70+
The `WHAL_CFG_*_API_MAPPING_*` flags cause each wolfHAL driver source to emit
71+
its functions under the top-level API name. Since only one driver source per
72+
device type is compiled, there is no conflict — and since no dispatch source
73+
(e.g., `src/flash/flash.c`) is included, there is no vtable indirection. The
74+
linker can garbage-collect any unused symbols with `-Wl,--gc-sections`.
75+
76+
## Configuration
77+
78+
A wolfHAL-based config requires two variables beyond the standard wolfBoot settings:
79+
80+
```
81+
TARGET=wolfhal
82+
BOARD=stm32wb_nucleo
83+
```
84+
85+
- `TARGET=wolfhal` selects the generic wolfHAL HAL shim and build path.
86+
- `BOARD` selects the board directory under `hal/boards/`.
87+
88+
See `config/examples/wolfhal_*.config` for complete examples.
89+
90+
## Adding a New Board
91+
92+
To add a new board, create a directory `hal/boards/<board_name>/` with three files:
93+
94+
### 1. `board.h` — Driver Headers and Pin Enums
95+
96+
Include the chip-specific wolfHAL driver headers and declare any board-level
97+
enums (pin indices, peripheral identifiers):
98+
99+
```c
100+
#ifndef WOLFHAL_BOARD_H
101+
#define WOLFHAL_BOARD_H
102+
103+
#include <wolfHAL/clock/<family>_rcc.h>
104+
#include <wolfHAL/flash/<family>_flash.h>
105+
#include <wolfHAL/gpio/<family>_gpio.h>
106+
#include <wolfHAL/uart/<family>_uart.h>
107+
108+
/* GPIO pin indices (matches pin array in board.c) */
109+
enum {
110+
BOARD_LED_PIN,
111+
BOARD_UART_TX_PIN,
112+
BOARD_UART_RX_PIN,
113+
BOARD_PIN_COUNT,
114+
};
115+
116+
#endif /* WOLFHAL_BOARD_H */
117+
```
118+
119+
### 2. `board.c` — Device Instances and Initialization
120+
121+
Define the wolfHAL device instances and implement `hal_init` and `hal_prepare_boot`
122+
using the top-level wolfHAL API. The file must export `g_wbFlash` (and `g_wbUart`
123+
when `DEBUG_UART` is enabled) as non-static globals — these are referenced by
124+
`hal/wolfhal.c` via `extern`.
125+
126+
```c
127+
#include "hal.h"
128+
#include "board.h"
129+
130+
/* Clock controller */
131+
whal_Clock g_wbClock = {
132+
.regmap = { .base = ..., .size = 0x400 },
133+
.cfg = &(whal_<Family>Rcc_Cfg) { ... },
134+
};
135+
136+
/* Flash */
137+
whal_Flash g_wbFlash = {
138+
.regmap = { .base = ..., .size = 0x400 },
139+
.cfg = &(whal_<Family>Flash_Cfg) {
140+
.startAddr = 0x08000000,
141+
.size = ...,
142+
},
143+
};
144+
145+
#ifdef DEBUG_UART
146+
whal_Gpio g_wbGpio = { ... };
147+
whal_Uart g_wbUart = { ... };
148+
#endif
149+
150+
void hal_init(void)
151+
{
152+
whal_Clock_Init(&g_wbClock);
153+
whal_Flash_Init(&g_wbFlash);
154+
#ifdef DEBUG_UART
155+
whal_Gpio_Init(&g_wbGpio);
156+
whal_Uart_Init(&g_wbUart);
157+
#endif
158+
}
159+
160+
void hal_prepare_boot(void)
161+
{
162+
#ifdef DEBUG_UART
163+
whal_Uart_Deinit(&g_wbUart);
164+
whal_Gpio_Deinit(&g_wbGpio);
165+
#endif
166+
whal_Flash_Deinit(&g_wbFlash);
167+
whal_Clock_Deinit(&g_wbClock);
168+
}
169+
```
170+
171+
Note: the device instance's `.driver` field is intentionally left unset. With
172+
API mapping, the top-level `whal_*_Init`/etc. symbols are the driver functions
173+
themselves — there is no dispatch through a vtable.
174+
175+
### 3. `board.mk` — Build Variables
176+
177+
Provide the build-time configuration: API mapping flags, flash offset, linker
178+
script, and the wolfHAL driver objects needed for your MCU family. **Do not
179+
compile the dispatch source (`src/<type>/<type>.c`)** — it would provide a
180+
duplicate definition of the top-level API symbols.
181+
182+
```makefile
183+
ARCH_FLASH_OFFSET=0x08000000
184+
LSCRIPT_IN=hal/<family>.ld
185+
186+
# Bind wolfHAL driver sources directly to the top-level API symbols.
187+
CFLAGS+=-DWHAL_CFG_CLOCK_API_MAPPING_<FAMILY>
188+
CFLAGS+=-DWHAL_CFG_FLASH_API_MAPPING_<FAMILY>
189+
CFLAGS+=-DWHAL_CFG_GPIO_API_MAPPING_<FAMILY>
190+
CFLAGS+=-DWHAL_CFG_UART_API_MAPPING_<FAMILY>
191+
192+
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/clock/<family>_rcc.o
193+
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/flash/<family>_flash.o
194+
ifeq ($(DEBUG_UART),1)
195+
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/gpio/<family>_gpio.o
196+
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/uart/<family>_uart.o
197+
endif
198+
199+
OBJS+=$(WOLFHAL_OBJS)
200+
APP_OBJS+=$(WOLFHAL_OBJS)
201+
202+
ifeq ($(RAM_CODE),1)
203+
WOLFHAL_FLASH_EXCLUDE_TEXT=*(EXCLUDE_FILE(*<family>_flash.o) .text*)
204+
WOLFHAL_FLASH_EXCLUDE_RODATA=*(EXCLUDE_FILE(*<family>_flash.o) .rodata*)
205+
WOLFHAL_FLASH_RAM_SECTIONS=*<family>_flash.o(.text* .rodata*)
206+
endif
207+
```
208+
209+
Only one API mapping flag may be active per device type per build.
210+
211+
### 4. Config File
212+
213+
Create `config/examples/wolfhal_<board_name>.config`:
214+
215+
```
216+
TARGET=wolfhal
217+
BOARD=<board_name>
218+
SIGN=ECC256
219+
HASH=SHA256
220+
WOLFBOOT_SECTOR_SIZE=0x1000
221+
WOLFBOOT_PARTITION_SIZE=0x20000
222+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x08008000
223+
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x08028000
224+
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x08048000
225+
NVM_FLASH_WRITEONCE=1
226+
```
227+
228+
Adjust partition addresses and sector sizes for your board's flash layout. Optionally
229+
add `DEBUG_UART=1` to enable UART debug output.
230+
231+
## RAM_CODE
232+
233+
When `RAM_CODE=1` is set, wolfBoot's core flash update functions are placed in RAM
234+
via the `RAMFUNCTION` attribute. For wolfHAL boards, the `board.mk` defines
235+
`EXCLUDE_FILE` rules that also place the wolfHAL flash driver into RAM. This ensures
236+
all flash operations execute from RAM, which is required on MCUs that stall or fault
237+
when code executes from the same flash bank being programmed.
238+
239+
The linker script uses `@WOLFHAL_FLASH_EXCLUDE_TEXT@`,
240+
`@WOLFHAL_FLASH_EXCLUDE_RODATA@`, and `@WOLFHAL_FLASH_RAM_SECTIONS@` placeholders
241+
that are substituted at build time. When `RAM_CODE=1`, these expand to
242+
`EXCLUDE_FILE` rules that move the flash driver's `.text` and `.rodata` sections from
243+
flash into the `.data` section (loaded to RAM at startup). When `RAM_CODE` is not
244+
set, all code remains in flash as normal.
245+
246+
## Test Application
247+
248+
The generic test application (`test-app/app_wolfhal.c`) demonstrates using wolfHAL
249+
peripherals beyond what the bootloader needs. It accesses the board-provided GPIO and
250+
UART instances (`g_wbGpio`, `g_wbUart`) via `extern`, using the top-level wolfHAL
251+
API (`whal_Gpio_Set`, `whal_Uart_Send`) to toggle an LED and send serial output,
252+
then exercises the wolfBoot update mechanism.
253+
254+
The test-app Makefile compiles its own copy of the board file (`board_<board>.o`)
255+
with `DEBUG_UART=1` always defined, since the app needs UART and GPIO regardless of
256+
the bootloader's `DEBUG_UART` setting.

0 commit comments

Comments
 (0)