wolfHAL Design Review#37
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR provides a stripped-down, additive snapshot of the wolfHAL codebase for a top-to-bottom design review (not intended for merging), showcasing the core HAL abstractions, STM32 platform drivers, example boards, tests, and documentation.
Changes:
- Adds core wolfHAL public headers (GPIO/UART/Flash/Timer/IRQ + core helpers like regmap/timeout/bitops/endian) and corresponding generic dispatch implementations.
- Introduces STM32WB and STM32L1 platform/board support (drivers, board init, linker scripts, startup/IVT).
- Adds a minimal test framework plus host “core” unit tests and HW-facing board tests; includes a blinky example and onboarding docs.
Reviewed changes
Copilot reviewed 82 out of 83 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| wolfHAL/wolfHAL.h | Umbrella include header for core wolfHAL modules. |
| wolfHAL/uart/uart.h | Generic UART API + driver vtable definitions. |
| wolfHAL/uart/stm32wb_uart.h | STM32WB UART driver config + API surface. |
| wolfHAL/uart/stm32l1_uart.h | STM32L1 UART aliasing to STM32F4 UART. |
| wolfHAL/uart/stm32f4_uart.h | STM32F4 UART driver config and API surface. |
| wolfHAL/timer/timer.h | Generic timer API + driver vtable definitions. |
| wolfHAL/timer/systick.h | SysTick timer driver configuration and API. |
| wolfHAL/timeout.h | Timeout abstraction macros for polling/delays. |
| wolfHAL/regmap.h | Register access helpers (read/write/update/poll). |
| wolfHAL/power/stm32l1_pwr.h | STM32L1 power (PWR) helper API. |
| wolfHAL/power/power.h | Board-level power handle type definition. |
| wolfHAL/platform/st/stm32wb55xx.h | STM32WB55 convenience initializers/macros. |
| wolfHAL/platform/st/stm32l152re.h | STM32L152 convenience initializers/macros. |
| wolfHAL/platform/arm/cortex_m4.h | Cortex-M4 device macros (SysTick/NVIC regmaps). |
| wolfHAL/platform/arm/cortex_m3.h | Cortex-M3 device macros (SysTick/NVIC regmaps). |
| wolfHAL/irq/irq.h | Generic IRQ controller abstraction + vtable. |
| wolfHAL/irq/cortex_m4_nvic.h | NVIC driver API/config definitions. |
| wolfHAL/gpio/stm32wb_gpio.h | STM32WB GPIO pin packing + driver API/config. |
| wolfHAL/gpio/stm32l1_gpio.h | STM32L1 GPIO aliasing to STM32WB GPIO. |
| wolfHAL/gpio/gpio.h | Generic GPIO API + driver vtable definitions. |
| wolfHAL/flash/stm32wb_flash.h | STM32WB flash driver config + helpers. |
| wolfHAL/flash/stm32l1_flash.h | STM32L1 flash driver config + helpers. |
| wolfHAL/flash/flash.h | Generic flash API + driver vtable definitions. |
| wolfHAL/error.h | Shared error code definitions. |
| wolfHAL/endian.h | Endian load/store helper functions. |
| wolfHAL/clock/stm32wb_rcc.h | STM32WB RCC helper APIs/config types. |
| wolfHAL/clock/stm32l1_rcc.h | STM32L1 RCC helper APIs/config types. |
| wolfHAL/clock/clock.h | Board-level clock handle type definition. |
| wolfHAL/bitops.h | Bitfield encode/decode helpers. |
| tests/uart/test_uart.c | Generic UART API argument/NULL handling tests. |
| tests/test.h | Minimal C test framework + assertions/printf-like output. |
| tests/main.c | HW test runner (board + per-module tests). |
| tests/gpio/test_stm32wb_gpio.c | STM32WB GPIO platform register-level tests. |
| tests/gpio/test_stm32l1_gpio.c | STM32L1 GPIO platform tests via source include aliasing. |
| tests/gpio/test_gpio.c | Generic GPIO API tests. |
| tests/core/test_timeout.c | Host-side timeout macro unit tests. |
| tests/core/test_endian.c | Host-side endian helper unit tests. |
| tests/core/test_bitops.c | Host-side bitops unit tests. |
| tests/core/main.c | Host-side unit test runner. |
| tests/core/Makefile | Build rules for host-side unit tests. |
| tests/clock/test_stm32wb_clock.c | STM32WB RCC platform test(s). |
| tests/clock/test_clock.c | Placeholder for generic clock tests (none by design). |
| tests/README.md | Documentation for running HW and host-side tests. |
| tests/Makefile | HW test build orchestration (boards/tests discovery). |
| src/uart/uart.c | Generic UART vtable dispatch implementations. |
| src/uart/stm32wb_uart.c | STM32WB polled UART driver implementation. |
| src/uart/stm32l1_uart.c | STM32L1 UART driver implementation via source include aliasing. |
| src/uart/stm32f4_uart.c | STM32F4 polled UART driver implementation. |
| src/timer/timer.c | Generic timer vtable dispatch implementations. |
| src/timer/systick.c | SysTick timer driver implementation. |
| src/power/stm32l1_pwr.c | STM32L1 power helper implementation. |
| src/irq/cortex_m4_nvic.c | NVIC driver implementation. |
| src/gpio/stm32wb_gpio.c | STM32WB GPIO driver implementation. |
| src/gpio/stm32l1_gpio.c | STM32L1 GPIO driver implementation via source include aliasing. |
| src/gpio/gpio.c | Generic GPIO vtable dispatch implementations. |
| src/flash/stm32l1_flash.c | STM32L1 flash driver implementation. |
| src/flash/flash.c | Generic flash vtable dispatch implementations. |
| src/clock/stm32wb_rcc.c | STM32WB RCC helper implementation. |
| src/clock/stm32l1_rcc.c | STM32L1 RCC helper implementation. |
| examples/blinky/main.c | Simple blinky example using wolfHAL + board layer. |
| examples/blinky/Makefile | Build rules for blinky example with board integration. |
| examples/README.md | Documentation for building/running examples. |
| docs/adding_an_example.md | Guide for adding new example applications. |
| docs/adding_a_test.md | Guide for adding new tests (generic + platform-specific). |
| docs/adding_a_board.md | Guide for adding new board support packages. |
| boards/stm32wb55xx_nucleo/linker.ld | STM32WB55 linker script for demos/tests. |
| boards/stm32wb55xx_nucleo/ivt.c | STM32WB55 startup + vector table. |
| boards/stm32wb55xx_nucleo/board.mk | STM32WB55 toolchain/flags/sources for builds. |
| boards/stm32wb55xx_nucleo/board.h | STM32WB55 board API + global device instances. |
| boards/stm32wb55xx_nucleo/board.c | STM32WB55 device instantiation + Board_Init/Deinit. |
| boards/stm32l152re_nucleo/linker.ld | STM32L152 linker script for demos/tests. |
| boards/stm32l152re_nucleo/ivt.c | STM32L152 startup + vector table. |
| boards/stm32l152re_nucleo/board.mk | STM32L152 toolchain/flags/sources for builds. |
| boards/stm32l152re_nucleo/board.h | STM32L152 board API + global device instances. |
| boards/stm32l152re_nucleo/board.c | STM32L152 device instantiation + Board_Init/Deinit. |
| boards/README.md | Board BSP conventions and supported boards list. |
| README.md | Top-level repository overview and navigation. |
| .gitignore | Ignore rules for build artifacts and generated files. |
Comments suppressed due to low confidence (7)
wolfHAL/regmap.h:1
- The regmap helpers claim 32-bit register access but use
size_tfor both addresses and register values, and cast tovolatile size_t*. On 64-bit hosts or targets wheresize_tisn’t 32-bit, this can perform incorrect-width MMIO reads/writes and break hardware access. Recommend usinguintptr_tfor MMIO addresses (base,offset) anduint32_t(or explicitly sized types) for register values/pointers (e.g.,volatile uint32_t*), with separate helpers if 8/16/64-bit registers are needed.
wolfHAL/regmap.h:1 - The regmap helpers claim 32-bit register access but use
size_tfor both addresses and register values, and cast tovolatile size_t*. On 64-bit hosts or targets wheresize_tisn’t 32-bit, this can perform incorrect-width MMIO reads/writes and break hardware access. Recommend usinguintptr_tfor MMIO addresses (base,offset) anduint32_t(or explicitly sized types) for register values/pointers (e.g.,volatile uint32_t*), with separate helpers if 8/16/64-bit registers are needed.
wolfHAL/regmap.h:1 - The regmap helpers claim 32-bit register access but use
size_tfor both addresses and register values, and cast tovolatile size_t*. On 64-bit hosts or targets wheresize_tisn’t 32-bit, this can perform incorrect-width MMIO reads/writes and break hardware access. Recommend usinguintptr_tfor MMIO addresses (base,offset) anduint32_t(or explicitly sized types) for register values/pointers (e.g.,volatile uint32_t*), with separate helpers if 8/16/64-bit registers are needed.
src/uart/stm32wb_uart.c:1 - UART transmit writes are implemented as a read-modify-write (
whal_Reg_Update) targetingUART_TDR_REG, which is typically write-only on STM32 USARTv2. A RMW can read an undefined value (or fault) and is not appropriate for FIFO/data registers. Additionally, the loop never waits for TX space (e.g., TXE/TXFNF) before writing the next byte, so it can overrun/overwrite the transmit register/FIFO depending on the peripheral. Use a pure write helper for TDR, poll a ‘TX ready’ flag before each write, and (optionally) poll TC once after the entire buffer to ensure completion.
src/timer/systick.c:1 - SysTick reload semantics are typically ‘RELOAD = (ticks_per_period - 1)’. Writing
cyclesPerTickdirectly yields a period ofcyclesPerTick + 1cycles. Either rename/document the config field as the raw reload value, or programcyclesPerTick - 1(with a defined behavior forcyclesPerTick == 0) socyclesPerTickmatches the name and expected timing.
tests/test.h:1 - Negating
valcan overflow forINT_MIN(undefined behavior in C). This can corrupt output or crash when printing the most-negative int. A robust fix is to convert using an unsigned magnitude (or a wider signed type) without ever doingval = -valonint.
wolfHAL/error.h:1 - The comment states
whal_Erroris a signed 16-bit type, but the code usesint(commonly 32-bit on the embedded toolchains shown). Either update the comment to match reality (signed int) or change the typedef to an explicitly-sized type (e.g.,int16_t) if a 16-bit ABI is required.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 82 out of 83 changed files in this pull request and generated 14 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 82 out of 83 changed files in this pull request and generated 10 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
06f16b0 to
16d9eef
Compare
wolfHAL design review
This PR is not for merging. It's a simplified stripped-down version of the wolfHAL
main branch opened against an empty parent branch (
tmp) so you guys canread the codebase top-to-bottom as a single additive diff (~10k lines)
rather than navigating around an existing tree. The actual code already
lives on
main.Purpose of wolfHAL
wolfHAL is a hardware abstraction layer meant to consolidate the
driver-porting work that today gets duplicated across our codebases
wolfCrypt, wolfBoot, wolfHSM, wolfIP, and any other project in the future that needs to
talk to hardware. Right now each project carries its own porting layer,
so adding a new platform means re-implementing roughly the same drivers
multiple times in slightly different shapes. wolfHAL is the single
target for that work: port a platform once, get it everywhere.
The design requirements:
against
whal_Gpio_Set,whal_Uart_Send,whal_Flash_Read, etc.,and that source compiles unchanged whether the underlying driver
is on-chip STM32WB GPIO, an external SPI NOR, or a Linux char
device. Moving a project to a new platform is a board-config
change, not a code change.
like the STM32C0 (32 KB flash, 12 KB RAM), wolfHAL has to disappear
into a minimal footprint.
enormously. pin assignments, clock trees, power sequencing,
on-chip vs. external peripherals, OS-mediated vs. bare-metal and
a user porting wolfHAL to their hardware should not need to edit
the driver source. All board-specific choices live in the board's
board.c(device instances, configuration structs, init order),build flags, and chip-specific helpers; driver code stays vanilla
and upstreamable.
How to read this PR
docs/getting_started.mdfor the conceptual modeldocs/writing_a_driver.mdfor the driver-category breakdown(covers the full peripheral catalog — most types aren't in this PR)
boards/stm32wb55xx_nucleo/board.cto see device/board configurationsrc/gpio/stm32wb_gpio.c) to see thevtable + DIRECT_API_MAPPING pattern
src/gpio/stm32l1_gpio.c)Patterns to look at
src/gpio/gpio.c,src/uart/uart.csrc/gpio/stm32wb_gpio.csrc/clock/stm32wb_rcc.c,src/power/stm32l1_pwr.cDIRECT_API_MAPPINGsrc/gpio/stm32wb_gpio.c(#ifdefblock)#includesrc/gpio/stm32l1_gpio.c,src/uart/stm32l1_uart.cExt_helpers for non-generic opswhal_Stm32wb_Flash_Ext_SetLatencyboards/stm32wb55xx_nucleo/board.cwolfHAL/timeout.h, used throughoutWhat's included
wolfHAL/<type>/<type>.h) for the devicetypes the demo boards exercise: gpio, uart, flash, timer, plus the
board-level handles (clock, power)
stm32wb55xx_nucleo(Cortex-M4, 64 MHz via PLL)stm32l152re_nucleo(Cortex-M3, 32 MHz via PLL + voltage scaling)on both and power on L1
#include "stm32wb_gpio.c"(register-compatible). L1 UART similarlyreuses the F4 UART driver. Different from the macro-based
DIRECT_API_MAPPINGaliasing.conventions
What's intentionally excluded
To keep the diff readable, the following are dropped from this snapshot
but exist on
mainand follow the same patterns:block, eth, eth_phy, sensor, ipc
"peripheral driver" category is documented in
docs/writing_a_driver.mdbut isn't physically demonstrated here