Skip to content

Commit c193a3b

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

File tree

14 files changed

+724
-9
lines changed

14 files changed

+724
-9
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: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ export WOLFBOOT_LIB_WOLFHSM
170170
## Architecture/CPU configuration
171171
include arch.mk
172172

173+
ifeq ($(TARGET),wolfhal)
174+
OBJS+=./hal/boards/$(BOARD)/board.o
175+
include hal/boards/$(BOARD)/board.mk
176+
endif
177+
173178
# Parse config options
174179
include options.mk
175180

@@ -534,7 +539,10 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE
534539
sed -e "s/@IMAGE_HEADER_SIZE@/$(IMAGE_HEADER_SIZE)/g" | \
535540
sed -e "s/@FSP_S_LOAD_BASE@/$(FSP_S_LOAD_BASE)/g" | \
536541
sed -e "s/@WOLFBOOT_L2LIM_SIZE@/$(WOLFBOOT_L2LIM_SIZE)/g" | \
537-
sed -e "s/@L2SRAM_ADDR@/$(L2SRAM_ADDR)/g" \
542+
sed -e "s/@L2SRAM_ADDR@/$(L2SRAM_ADDR)/g" | \
543+
sed -e 's/@WOLFHAL_FLASH_EXCLUDE_TEXT@/$(WOLFHAL_FLASH_EXCLUDE_TEXT)/g' | \
544+
sed -e 's/@WOLFHAL_FLASH_EXCLUDE_RODATA@/$(WOLFHAL_FLASH_EXCLUDE_RODATA)/g' | \
545+
sed -e 's/@WOLFHAL_FLASH_RAM_SECTIONS@/$(WOLFHAL_FLASH_RAM_SECTIONS)/g' \
538546
> $@
539547

540548
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: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
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 consists of four parts:
17+
18+
1. **Generic HAL shim** (`hal/wolfhal.c`) — implements the wolfBoot HAL API
19+
(`hal_flash_write`, `hal_flash_erase`, etc.) by calling `Board_*` macros. This
20+
file is shared across all wolfHAL boards.
21+
22+
2. **Board directory** (`hal/boards/<board>/`) — contains three files that fully
23+
describe a board:
24+
- `board.h``#define` macros mapping generic `Board_*` APIs to chip-specific
25+
wolfHAL driver functions.
26+
- `board.c` — device instances (clock, flash, GPIO, UART), configuration
27+
structs, and `hal_init`/`hal_prepare_boot` implementations.
28+
- `board.mk` — build variables (`ARCH_FLASH_OFFSET`, `LSCRIPT_IN`, wolfHAL
29+
driver objects, `RAM_CODE` linker rules).
30+
31+
3. **Generic test application** (`test-app/app_wolfhal.c`) — demonstrates using
32+
wolfHAL peripherals (GPIO, UART) beyond what the bootloader needs, using the same
33+
`Board_*` API.
34+
35+
4. **wolfHAL library** (`lib/wolfHAL/`) — the wolfHAL submodule containing the
36+
platform drivers.
37+
38+
### How It Fits Together
39+
40+
```
41+
config/examples/wolfhal_<board>.config
42+
└─ TARGET=wolfhal BOARD=<board>
43+
44+
arch.mk
45+
└─ Sets WOLFHAL_ROOT, CFLAGS += -Ihal/boards/$(BOARD)
46+
47+
Makefile
48+
└─ OBJS += hal/boards/$(BOARD)/board.o
49+
└─ include hal/boards/$(BOARD)/board.mk
50+
51+
hal/wolfhal.c (generic — calls Board_Flash_Write, Board_Uart_Send, etc.)
52+
└─ #include "board.h" (resolved via -I to the board directory)
53+
54+
hal/boards/<board>/
55+
├─ board.h (#define Board_Flash_Write → whal_<family>Flash_Write)
56+
├─ board.c (device instances, hal_init, hal_prepare_boot)
57+
└─ board.mk (ARCH_FLASH_OFFSET, LSCRIPT_IN, driver objects, RAM_CODE rules)
58+
```
59+
60+
The `board.h` macros resolve `Board_*` calls directly to the chip-specific wolfHAL
61+
driver functions at compile time. This avoids vtable indirection and allows the
62+
linker to garbage-collect unused driver code (with `-Wl,--gc-sections`).
63+
64+
## Configuration
65+
66+
A wolfHAL-based config requires two variables beyond the standard wolfBoot settings:
67+
68+
```
69+
TARGET=wolfhal
70+
BOARD=stm32wb_nucleo
71+
```
72+
73+
- `TARGET=wolfhal` selects the generic wolfHAL HAL shim and build path.
74+
- `BOARD` selects the board directory under `hal/boards/`.
75+
76+
See `config/examples/wolfhal_*.config` for complete examples.
77+
78+
## Adding a New Board
79+
80+
To add a new board, create a directory `hal/boards/<board_name>/` with three files:
81+
82+
### 1. `board.h` — API Mappings
83+
84+
Map each generic `Board_*` macro to the appropriate wolfHAL driver function for your
85+
MCU family. The required mappings are:
86+
87+
```c
88+
#ifndef WOLFHAL_BOARD_H
89+
#define WOLFHAL_BOARD_H
90+
91+
#include <wolfHAL/clock/<family>_clock.h>
92+
#include <wolfHAL/flash/<family>_flash.h>
93+
#include <wolfHAL/gpio/<family>_gpio.h>
94+
#include <wolfHAL/uart/<family>_uart.h>
95+
96+
/* Clock */
97+
#define Board_Clock_Init whal_<Family>Clock_Init
98+
#define Board_Clock_Deinit whal_<Family>Clock_Deinit
99+
#define Board_Clock_Enable whal_<Family>Clock_Enable
100+
#define Board_Clock_Disable whal_<Family>Clock_Disable
101+
102+
/* Flash */
103+
#define Board_Flash_Init whal_<Family>Flash_Init
104+
#define Board_Flash_Deinit whal_<Family>Flash_Deinit
105+
#define Board_Flash_Lock whal_<Family>Flash_Lock
106+
#define Board_Flash_Unlock whal_<Family>Flash_Unlock
107+
#define Board_Flash_Write whal_<Family>Flash_Write
108+
#define Board_Flash_Erase whal_<Family>Flash_Erase
109+
110+
/* GPIO */
111+
#define Board_Gpio_Init whal_<Family>Gpio_Init
112+
#define Board_Gpio_Deinit whal_<Family>Gpio_Deinit
113+
#define Board_Gpio_Set whal_<Family>Gpio_Set
114+
#define Board_Gpio_Get whal_<Family>Gpio_Get
115+
116+
/* UART */
117+
#define Board_Uart_Init whal_<Family>Uart_Init
118+
#define Board_Uart_Deinit whal_<Family>Uart_Deinit
119+
#define Board_Uart_Send whal_<Family>Uart_Send
120+
#define Board_Uart_Recv whal_<Family>Uart_Recv
121+
122+
#endif /* WOLFHAL_BOARD_H */
123+
```
124+
125+
### 2. `board.c` — Device Instances and Initialization
126+
127+
Define the wolfHAL device instances and implement `hal_init` and `hal_prepare_boot`.
128+
The file must export `g_wbFlash` (and `g_wbUart` when `DEBUG_UART` is enabled) as
129+
non-static globals — these are referenced by `hal/wolfhal.c` via `extern`.
130+
131+
```c
132+
#include "hal.h"
133+
#include "board.h"
134+
135+
/* Clock controller */
136+
whal_Clock g_wbClock = {
137+
.regmap = { .base = ..., .size = 0x400 },
138+
.cfg = &(<family>_clock_cfg) { ... },
139+
};
140+
141+
/* Flash */
142+
whal_Flash g_wbFlash = {
143+
.regmap = { .base = ..., .size = 0x400 },
144+
.cfg = &(<family>_flash_cfg) {
145+
.startAddr = 0x08000000,
146+
.size = ...,
147+
},
148+
};
149+
150+
#ifdef DEBUG_UART
151+
whal_Gpio g_wbGpio = { ... };
152+
whal_Uart g_wbUart = { ... };
153+
#endif
154+
155+
void hal_init(void)
156+
{
157+
/* Initialize clock tree, flash, and optionally GPIO/UART */
158+
Board_Clock_Init(&g_wbClock);
159+
Board_Flash_Init(&g_wbFlash);
160+
#ifdef DEBUG_UART
161+
Board_Gpio_Init(&g_wbGpio);
162+
Board_Uart_Init(&g_wbUart);
163+
#endif
164+
}
165+
166+
void hal_prepare_boot(void)
167+
{
168+
#ifdef DEBUG_UART
169+
Board_Uart_Deinit(&g_wbUart);
170+
Board_Gpio_Deinit(&g_wbGpio);
171+
#endif
172+
Board_Flash_Deinit(&g_wbFlash);
173+
Board_Clock_Deinit(&g_wbClock);
174+
}
175+
```
176+
177+
### 3. `board.mk` — Build Variables
178+
179+
Provide the build-time configuration: flash offset, linker script, and the wolfHAL
180+
driver objects needed for your MCU family.
181+
182+
```makefile
183+
ARCH_FLASH_OFFSET=0x08000000
184+
LSCRIPT_IN=hal/<family>.ld
185+
186+
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/clock/<family>_clock.o
187+
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/flash/<family>_flash.o
188+
ifeq ($(DEBUG_UART),1)
189+
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/gpio/<family>_gpio.o
190+
WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/uart/<family>_uart.o
191+
endif
192+
193+
OBJS+=$(WOLFHAL_OBJS)
194+
APP_OBJS+=$(WOLFHAL_OBJS)
195+
196+
ifeq ($(RAM_CODE),1)
197+
WOLFHAL_FLASH_EXCLUDE_TEXT=*(EXCLUDE_FILE(*<family>_flash.o) .text*)
198+
WOLFHAL_FLASH_EXCLUDE_RODATA=*(EXCLUDE_FILE(*<family>_flash.o) .rodata*)
199+
WOLFHAL_FLASH_RAM_SECTIONS=*<family>_flash.o(.text* .rodata*)
200+
endif
201+
```
202+
203+
### 4. Config File
204+
205+
Create `config/examples/wolfhal_<board_name>.config`:
206+
207+
```
208+
TARGET=wolfhal
209+
BOARD=<board_name>
210+
SIGN=ECC256
211+
HASH=SHA256
212+
WOLFBOOT_SECTOR_SIZE=0x1000
213+
WOLFBOOT_PARTITION_SIZE=0x20000
214+
WOLFBOOT_PARTITION_BOOT_ADDRESS=0x08008000
215+
WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x08028000
216+
WOLFBOOT_PARTITION_SWAP_ADDRESS=0x08048000
217+
NVM_FLASH_WRITEONCE=1
218+
```
219+
220+
Adjust partition addresses and sector sizes for your board's flash layout. Optionally
221+
add `DEBUG_UART=1` to enable UART debug output.
222+
223+
## RAM_CODE
224+
225+
When `RAM_CODE=1` is set, wolfBoot's core flash update functions are placed in RAM
226+
via the `RAMFUNCTION` attribute. For wolfHAL boards, the `board.mk` defines
227+
`EXCLUDE_FILE` rules that also place the wolfHAL flash driver into RAM. This ensures
228+
all flash operations execute from RAM, which is required on MCUs that stall or fault
229+
when code executes from the same flash bank being programmed.
230+
231+
The linker script uses `@WOLFHAL_FLASH_EXCLUDE_TEXT@`,
232+
`@WOLFHAL_FLASH_EXCLUDE_RODATA@`, and `@WOLFHAL_FLASH_RAM_SECTIONS@` placeholders
233+
that are substituted at build time. When `RAM_CODE=1`, these expand to
234+
`EXCLUDE_FILE` rules that move the flash driver's `.text` and `.rodata` sections from
235+
flash into the `.data` section (loaded to RAM at startup). When `RAM_CODE` is not
236+
set, all code remains in flash as normal.
237+
238+
## Test Application
239+
240+
The generic test application (`test-app/app_wolfhal.c`) demonstrates using wolfHAL
241+
peripherals beyond what the bootloader needs. It initializes GPIO and UART via the
242+
`Board_*` API, then exercises the wolfBoot update mechanism.
243+
244+
The test app re-uses the board's clock instance via `extern whal_Clock g_wbClock` to
245+
enable peripheral clocks for its own devices (e.g. GPIO for an LED, UART for serial
246+
output).
247+
248+
The test-app Makefile compiles its own copy of the board file (`board_<board>.o`)
249+
with `DEBUG_UART=1` always defined, since the app needs UART and GPIO regardless of
250+
the bootloader's `DEBUG_UART` setting.

0 commit comments

Comments
 (0)