Skip to content

Commit 5b8c68f

Browse files
committed
Create STM32WB wolfHAL example. GC sections on all test apps
1 parent 1c0c379 commit 5b8c68f

File tree

12 files changed

+659
-9
lines changed

12 files changed

+659
-9
lines changed

.github/workflows/test-configs.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,12 @@ jobs:
571571
arch: arm
572572
config-file: ./config/examples/stm32wb.config
573573

574+
wolfhal_stm32wb_test:
575+
uses: ./.github/workflows/test-build.yml
576+
with:
577+
arch: arm
578+
config-file: ./config/examples/wolfhal_stm32wb_nucleo.config
579+
574580
# TODO: ti-tms570lc435.config requires F021 Flash API (Windows installer only)
575581
# ti_tms570lc435_test:
576582
# 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: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,10 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE
522522
sed -e "s/@BOOTLOADER_START@/$(BOOTLOADER_START)/g" | \
523523
sed -e "s/@IMAGE_HEADER_SIZE@/$(IMAGE_HEADER_SIZE)/g" | \
524524
sed -e "s/@FSP_S_LOAD_BASE@/$(FSP_S_LOAD_BASE)/g" | \
525-
sed -e "s/@WOLFBOOT_L2LIM_SIZE@/$(WOLFBOOT_L2LIM_SIZE)/g" \
525+
sed -e "s/@WOLFBOOT_L2LIM_SIZE@/$(WOLFBOOT_L2LIM_SIZE)/g" | \
526+
sed -e 's/@WOLFHAL_FLASH_EXCLUDE_TEXT@/$(WOLFHAL_FLASH_EXCLUDE_TEXT)/g' | \
527+
sed -e 's/@WOLFHAL_FLASH_EXCLUDE_RODATA@/$(WOLFHAL_FLASH_EXCLUDE_RODATA)/g' | \
528+
sed -e 's/@WOLFHAL_FLASH_RAM_SECTIONS@/$(WOLFHAL_FLASH_RAM_SECTIONS)/g' \
526529
> $@
527530

528531
hex: wolfboot.hex

arch.mk

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,11 @@ ifeq ($(ARCH),ARM)
206206
SPI_TARGET=stm32
207207
endif
208208

209+
# Defaults for linker script placeholders (overridden by wolfhal target)
210+
WOLFHAL_FLASH_EXCLUDE_TEXT?=*(.text*)
211+
WOLFHAL_FLASH_EXCLUDE_RODATA?=*(.rodata*)
212+
WOLFHAL_FLASH_RAM_SECTIONS?=
213+
209214
ifeq ($(TARGET),stm32wb)
210215
ARCH_FLASH_OFFSET=0x08000000
211216
SPI_TARGET=stm32
@@ -221,6 +226,24 @@ ifeq ($(ARCH),ARM)
221226
endif
222227
endif
223228

229+
ifeq ($(TARGET),wolfhal_stm32wb)
230+
ARCH_FLASH_OFFSET=0x08000000
231+
LSCRIPT_IN=hal/stm32wb.ld
232+
WOLFHAL_ROOT?=$(WOLFBOOT_ROOT)/lib/wolfHAL
233+
CFLAGS+=-I$(WOLFHAL_ROOT) -DWHAL_CFG_DIRECT_CALLBACKS
234+
OBJS+=./hal/boards/$(BOARD).o
235+
OBJS+=$(WOLFHAL_ROOT)/src/clock/stm32wb_rcc.o
236+
OBJS+=$(WOLFHAL_ROOT)/src/flash/stm32wb_flash.o
237+
ifeq ($(DEBUG_UART),1)
238+
OBJS+=$(WOLFHAL_ROOT)/src/gpio/stm32wb_gpio.o
239+
OBJS+=$(WOLFHAL_ROOT)/src/uart/stm32wb_uart.o
240+
endif
241+
ifeq ($(RAM_CODE),1)
242+
WOLFHAL_FLASH_EXCLUDE_TEXT=*(EXCLUDE_FILE(*stm32wb_flash.o) .text*)
243+
WOLFHAL_FLASH_EXCLUDE_RODATA=*(EXCLUDE_FILE(*stm32wb_flash.o) .rodata*)
244+
WOLFHAL_FLASH_RAM_SECTIONS=*stm32wb_flash.o(.text* .rodata*)
245+
endif
246+
endif
224247

225248
ifeq ($(TARGET),stm32l5)
226249
CORTEX_M33=1
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
TARGET=wolfhal_stm32wb
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: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
# wolfHAL Integration
2+
3+
wolfBoot supports [wolfHAL](https://github.com/wolfSSL/wolfHAL) as an alternative hardware abstraction layer backend. wolfHAL provides portable, vtable-dispatched drivers for common MCU peripherals (clock, flash, GPIO, UART, SPI, etc.) with a consistent API across platforms.
4+
5+
## Overview
6+
7+
The wolfHAL integration consists of three parts:
8+
9+
1. **HAL implementation** (`hal/wolfhal_<family>.c`) — implements the wolfBoot HAL API (`hal_init`, `hal_flash_write`, etc.) by calling wolfHAL driver functions. One file per MCU family (e.g. STM32WB).
10+
11+
2. **Board configuration** (`hal/boards/<board>.c`) — defines the wolfHAL device instances (flash, clock, and optionally GPIO/UART for `DEBUG_UART`) with board-specific register addresses, clock parameters, and flash geometry. One file per board.
12+
13+
3. **wolfHAL library** (`lib/wolfHAL/`) — the wolfHAL submodule containing the platform drivers.
14+
15+
## Configuration
16+
17+
A wolfHAL-based config requires two variables beyond the standard wolfBoot settings:
18+
19+
```
20+
TARGET=wolfhal_stm32wb
21+
BOARD=stm32wb_nucleo
22+
```
23+
24+
- `TARGET` selects the MCU family HAL implementation (`hal/wolfhal_stm32wb.c`)
25+
- `BOARD` selects the board configuration file (`hal/boards/stm32wb_nucleo.c`)
26+
27+
## Adding a New Board
28+
29+
To add a new board for an existing MCU family (e.g. a custom STM32WB board):
30+
31+
1. Create `hal/boards/<board_name>.c` with the wolfHAL device configuration:
32+
33+
```c
34+
#include <wolfHAL/clock/stm32wb_rcc.h>
35+
#include <wolfHAL/flash/stm32wb_flash.h>
36+
#ifdef DEBUG_UART
37+
#include <wolfHAL/gpio/stm32wb_gpio.h>
38+
#include <wolfHAL/uart/stm32wb_uart.h>
39+
#endif
40+
#include <wolfHAL/platform/st/stm32wb55xx.h>
41+
42+
/* Forward declarations for circular references */
43+
whal_Flash g_wbFlash;
44+
whal_Clock g_wbClock;
45+
46+
/* PLL, clock, and flash configuration for your board */
47+
static whal_Stm32wbRcc_PllClkCfg pllCfg = { ... };
48+
static whal_Stm32wbRcc_Cfg rccCfg = { .flash = &g_wbFlash, ... };
49+
static whal_Stm32wbFlash_Cfg flashCfg = { .clkCtrl = &g_wbClock, ... };
50+
51+
/* Minimal clock driver vtable: Enable/Disable are used by the flash, GPIO, and
52+
* UART drivers for peripheral clock gating. GetRate is only needed by the UART
53+
* driver for baud rate calculation. */
54+
static const whal_ClockDriver clockDriver = {
55+
.Enable = whal_Stm32wbRcc_Enable,
56+
.Disable = whal_Stm32wbRcc_Disable,
57+
#ifdef DEBUG_UART
58+
.GetRate = whal_Stm32wbRccPll_GetRate,
59+
#endif
60+
};
61+
62+
/* Device definitions */
63+
whal_Clock g_wbClock = {
64+
.regmap = { .base = 0x58000000, .size = 0x400 },
65+
.driver = &clockDriver,
66+
.cfg = &rccCfg,
67+
};
68+
69+
whal_Flash g_wbFlash = {
70+
.regmap = { .base = 0x58004000, .size = 0x400 },
71+
.cfg = &flashCfg,
72+
};
73+
74+
#ifdef DEBUG_UART
75+
/* GPIO — UART1 TX/RX pins */
76+
static whal_Stm32wbGpio_PinCfg gpioPins[] = { ... };
77+
static whal_Stm32wbGpio_Cfg gpioCfg = { .clkCtrl = &g_wbClock, ... };
78+
79+
whal_Gpio g_wbGpio = {
80+
.regmap = { .base = 0x48000000, .size = 0x400 },
81+
.cfg = &gpioCfg,
82+
};
83+
84+
/* UART1 at 115200 baud */
85+
static whal_Stm32wbUart_Cfg uartCfg = { .clkCtrl = &g_wbClock, .baud = 115200 };
86+
87+
whal_Uart g_wbUart = {
88+
.regmap = { .base = 0x40013800, .size = 0x400 },
89+
.cfg = &uartCfg,
90+
};
91+
#endif /* DEBUG_UART */
92+
```
93+
94+
The board file exports `g_wbFlash` and `g_wbClock` as non-static globals (and `g_wbGpio`/`g_wbUart` when `DEBUG_UART` is enabled). The HAL implementation references these via `extern`.
95+
96+
2. Create `config/examples/wolfhal_<target>_<board>.config`:
97+
98+
```
99+
TARGET=wolfhal_stm32wb
100+
BOARD=<board_name>
101+
SIGN=ECC256
102+
HASH=SHA256
103+
WOLFBOOT_SECTOR_SIZE=0x1000
104+
WOLFBOOT_PARTITION_SIZE=0x20000
105+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x08008000
106+
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x08028000
107+
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x08048000
108+
NVM_FLASH_WRITEONCE=1
109+
```
110+
111+
Adjust partition addresses and sizes for your board's flash layout.
112+
113+
Optionally add `DEBUG_UART=1` to enable UART debug output via wolfHAL.
114+
115+
### RAM_CODE
116+
117+
When `RAM_CODE=1` is set, wolfBoot's core flash update functions are placed in RAM
118+
via the `RAMFUNCTION` attribute. For wolfHAL targets, the wolfHAL flash driver
119+
(`stm32wb_flash.o`) is also placed in RAM using `EXCLUDE_FILE` directives in the
120+
linker script. This ensures all flash operations execute from RAM, which is required
121+
on some MCUs that stall or fault when code executes from the same flash bank being
122+
programmed.
123+
124+
```
125+
RAM_CODE=1
126+
```
127+
128+
The linker script (`hal/stm32wb.ld`) uses `@WOLFHAL_FLASH_EXCLUDE_TEXT@`,
129+
`@WOLFHAL_FLASH_EXCLUDE_RODATA@`, and `@WOLFHAL_FLASH_RAM_SECTIONS@` placeholders
130+
that are substituted at build time. When `RAM_CODE=1`, these expand to
131+
`EXCLUDE_FILE(*stm32wb_flash.o)` rules that move the flash driver's `.text` and
132+
`.rodata` sections from flash into the `.data` section (loaded to RAM at startup).
133+
When `RAM_CODE` is not set, all code remains in flash as normal.
134+
135+
## Adding a New MCU Family
136+
137+
To add support for a new MCU family (e.g. STM32H7):
138+
139+
1. Create `hal/wolfhal_<family>.c` implementing the wolfBoot HAL functions. Use the appropriate wolfHAL driver headers and call driver functions directly for minimal overhead:
140+
141+
```c
142+
#include <stdint.h>
143+
#include "hal.h"
144+
#include <wolfHAL/clock/<family>_rcc.h>
145+
#include <wolfHAL/flash/<family>_flash.h>
146+
#ifdef DEBUG_UART
147+
#include <wolfHAL/gpio/<family>_gpio.h>
148+
#include <wolfHAL/uart/<family>_uart.h>
149+
#endif
150+
151+
extern whal_Flash g_wbFlash;
152+
extern whal_Clock g_wbClock;
153+
#ifdef DEBUG_UART
154+
extern whal_Gpio g_wbGpio;
155+
extern whal_Uart g_wbUart;
156+
#endif
157+
158+
void hal_init(void)
159+
{
160+
/* Family-specific clock and flash initialization */
161+
#ifdef DEBUG_UART
162+
/* GPIO and UART initialization */
163+
#endif
164+
}
165+
166+
void hal_prepare_boot(void)
167+
{
168+
#ifdef DEBUG_UART
169+
/* UART and GPIO deinitialization */
170+
#endif
171+
/* Family-specific flash and clock deinitialization */
172+
}
173+
174+
/* hal_flash_unlock, hal_flash_lock, hal_flash_write, hal_flash_erase */
175+
176+
#ifdef DEBUG_UART
177+
void uart_write(const char *buf, unsigned int len)
178+
{
179+
/* Send via wolfHAL UART driver */
180+
}
181+
#endif
182+
```
183+
184+
2. Add the target block in `arch.mk`:
185+
186+
```makefile
187+
ifeq ($(TARGET),wolfhal_<family>)
188+
ARCH_FLASH_OFFSET=0x08000000
189+
LSCRIPT_IN=hal/<family>.ld
190+
WOLFHAL_ROOT?=$(WOLFBOOT_ROOT)/lib/wolfHAL
191+
CFLAGS+=-I$(WOLFHAL_ROOT) -DWHAL_CFG_DIRECT_CALLBACKS
192+
OBJS+=./hal/boards/$(BOARD).o
193+
OBJS+=$(WOLFHAL_ROOT)/src/<device>/<driver>.o
194+
endif
195+
```
196+
197+
3. Create at least one board configuration file in `hal/boards/`.
198+
199+
## Test Application
200+
201+
The test application (`test-app/app_wolfhal_stm32wb.c`) demonstrates using wolfHAL peripherals beyond what the bootloader needs. It initializes GPIO (LED on PB5) and UART (UART1 at 115200 baud) via wolfHAL, then exercises the wolfBoot update mechanism.
202+
203+
The test app accesses the board's clock instance via `extern whal_Clock g_wbClock` for peripheral clock gating.
204+
205+
The test-app compiles its own copy of the board file (`board_<board>.o`) with
206+
`-DDEBUG_UART` always defined, since the app needs `GetRate` in the clock vtable
207+
for UART baud rate calculation. This is independent of the bootloader's
208+
`DEBUG_UART` setting — the bootloader's board object only includes `GetRate` when
209+
`DEBUG_UART=1` is in the config.

0 commit comments

Comments
 (0)