Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .claude/skills/port-stm32-platform/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ For each device type, decide **reuse existing driver (with alias)** OR **write a

The clock driver is almost always new per family. GPIO, I2C, and IWDG/WWDG are almost always reusable. UART, flash, RNG, DMA require careful diffing.

**Clock is the architectural exception.** Unlike every other driver type, the clock subsystem has no `whal_ClockDriver` vtable and no generic `whal_Clock_Init`/`Enable`/`Disable` API. Chip clock drivers expose imperative `Enable*`/`Disable*`/`Set*` helpers (e.g. `whal_<Platform>_Rcc_EnableOsc`, `EnablePll`, `SetSysClock`, `EnablePeriphClk`) and boards call them directly. See `docs/writing_a_driver.md` "Clock" section. The platform header does NOT define a `WHAL_<PLATFORM>_RCC_DRIVER` macro, and the chip's `g_whalClock` global has only `.regmap = { ... }` — no `.driver`, no `.cfg`. Reference: `wolfHAL/clock/stm32wb_rcc.h` and `boards/stm32wb55xx_nucleo/board.c`.
**Clock is an architectural exception.** Unlike most driver types, the clock subsystem has no `whal_ClockDriver` vtable and no generic `whal_Clock_Init`/`Enable`/`Disable` API. Chip clock drivers expose imperative `Enable*`/`Disable*`/`Set*` helpers (e.g. `whal_<Platform>_Rcc_EnableOsc`, `EnablePll`, `SetSysClock`, `EnablePeriphClk`) and boards call them directly. See `docs/writing_a_driver.md` "Clock" section. The platform header does NOT define a `WHAL_<PLATFORM>_RCC_DRIVER` macro, and the chip's `g_whalClock` global has only `.base = ...` — no `.driver`, no `.cfg`. Reference: `wolfHAL/clock/stm32wb_rcc.h` and `boards/stm32wb55xx_nucleo/board.c`.

**Crypto is also an architectural exception.** Crypto uses per-algorithm device structs (`whal_AesGcm`, `whal_Sha256`, etc.) instead of a single `whal_Crypto` with generic dispatch. Each algo struct has `.crypto` (pointer to the hardware device), `.driver` (per-algo vtable with Oneshot/Start/Process/Finalize), and `.state` (driver-managed streaming state). `whal_Crypto` itself is a platform driver with just Init/Deinit for hardware lifecycle. Direct API mapping is per-algorithm (e.g. `WHAL_CFG_STM32WB_AES_GCM_DIRECT_API_MAPPING`), not per-device-type. See `docs/writing_a_driver.md` "Crypto" section. Reference: `wolfHAL/crypto/stm32wb_aes.h` and `wolfHAL/crypto/stm32wba_hash.h`.

## Phase 2 — Platform header

Expand All @@ -74,7 +76,7 @@ Skeleton:
/* ...one include per device type... */

#define WHAL_<PLATFORM>_USART1_DEVICE \
.regmap = { .base = 0x<addr>, .size = 0x400 }, \
.base = 0x<addr>, \
.driver = &whal_<Platform>Uart_Driver

#define WHAL_<PLATFORM>_USART1_CLOCK \
Expand Down Expand Up @@ -188,7 +190,7 @@ Create `boards/<board_name>/` with:
Exports `extern whal_<Type>` instances and declares `Board_Init`/`Board_Deinit`/`Board_WaitMs`. Follow `docs/adding_a_board.md`.

### `board.c`
Define each `whal_<Type>` global with its platform macro + board-specific config (pins, baud rates, timeout, DMA channel assignments). The `whal_Clock` global is just `.regmap = { ... }` (no `.driver`, no `.cfg`) since the clock subsystem has no vtable. Implement `Board_Init` in dependency order: PWR → bring up clock tree imperatively (oscillator on, PLL configure+enable, sysclk switch) → enable peripheral clocks → GPIO → UART → Timer → the rest. Keep the watchdog out of `Board_Init` (the app starts it when ready to refresh) per `docs/adding_a_board.md`. Guard DMA-specific setup under `#ifdef BOARD_DMA`, matching `boards/stm32wba55cg_nucleo/board.c`.
Define each `whal_<Type>` global with its platform macro + board-specific config (pins, baud rates, timeout, DMA channel assignments). The `whal_Clock` global is just `.base = ...` (no `.driver`, no `.cfg`) since the clock subsystem has no vtable. Implement `Board_Init` in dependency order: PWR → bring up clock tree imperatively (oscillator on, PLL configure+enable, sysclk switch) → enable peripheral clocks → GPIO → UART → Timer → the rest. Keep the watchdog out of `Board_Init` (the app starts it when ready to refresh) per `docs/adding_a_board.md`. Guard DMA-specific setup under `#ifdef BOARD_DMA`, matching `boards/stm32wba55cg_nucleo/board.c`.

### GPIO pin conflict check
After writing the `pinCfg` array in `board.c`, scan every entry pair and verify no two entries share the same physical port+pin. This is a common mistake when a pin serves double duty (e.g., PA5 used as both an LED and SPI1_SCK). If a conflict is found, consult the chip's alternate-function table in the datasheet and remap the conflicting peripheral to an alternate pin on a different port.
Expand Down
12 changes: 6 additions & 6 deletions boards/pic32cz_curiosity_ultra/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@

/* Power */
static whal_Power g_whalPower = {
.regmap = { WHAL_PIC32CZ_SUPC_REGMAP },
.base = WHAL_PIC32CZ_SUPC_BASE,
};

/* Clock */
whal_Clock g_whalClock = {
.regmap = { WHAL_PIC32CZ_CLOCK_REGMAP },
.base = WHAL_PIC32CZ_CLOCK_BASE,
};

/* Peripheral clocks */
Expand All @@ -30,7 +30,7 @@ static const whal_Pic32cz_Clock_PeriphClk g_periphClks[] = {

/* GPIO */
whal_Gpio g_whalGpio = {
.regmap = { WHAL_PIC32CZ_GPIO_REGMAP },
.base = WHAL_PIC32CZ_GPIO_BASE,
/* .driver: direct API mapping */

.cfg = &(whal_Pic32cz_Gpio_Cfg) {
Expand Down Expand Up @@ -60,7 +60,7 @@ whal_Gpio g_whalGpio = {

/* UART */
whal_Uart g_whalUart = {
.regmap = { WHAL_PIC32CZ_SERCOM4_UART_REGMAP },
.base = WHAL_PIC32CZ_SERCOM4_UART_BASE,
/* .driver: direct API mapping */

.cfg = &(whal_Pic32cz_Uart_Cfg) {
Expand All @@ -72,7 +72,7 @@ whal_Uart g_whalUart = {

/* Timer */
whal_Timer g_whalTimer = {
.regmap = { WHAL_CORTEX_M7_SYSTICK_REGMAP },
.base = WHAL_CORTEX_M7_SYSTICK_BASE,
.driver = WHAL_CORTEX_M7_SYSTICK_DRIVER,

.cfg = &(whal_SysTick_Cfg) {
Expand All @@ -84,7 +84,7 @@ whal_Timer g_whalTimer = {

/* Flash */
whal_Flash g_whalFlash = {
.regmap = { WHAL_PIC32CZ_FLASH_REGMAP },
.base = WHAL_PIC32CZ_FLASH_BASE,
.driver = WHAL_PIC32CZ_FLASH_DRIVER,
};

Expand Down
4 changes: 2 additions & 2 deletions boards/pic32cz_curiosity_ultra/board.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ GCC = $(GCC_PATH)arm-none-eabi-gcc
LD = $(GCC_PATH)arm-none-eabi-ld
OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy

CFLAGS += -Wall -Werror $(INCLUDE) -g3 \
CFLAGS += -Wall -Werror $(INCLUDE) -g3 -Os -ffunction-sections -fdata-sections \
-ffreestanding -nostdlib -mcpu=cortex-m7 \
-DPLATFORM_PIC32CZ -MMD -MP \
-DWHAL_CFG_PIC32CZ_GPIO_DIRECT_API_MAPPING \
-DWHAL_CFG_PIC32CZ_CLOCK_DIRECT_API_MAPPING \
-DWHAL_CFG_PIC32CZ_UART_DIRECT_API_MAPPING
LDFLAGS = --omagic -static
LDFLAGS = --omagic -static --gc-sections

LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld

Expand Down
12 changes: 6 additions & 6 deletions boards/stm32c031_nucleo/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ whal_Timeout g_whalTimeout = {

/* Clock */
whal_Clock g_whalClock = {
.regmap = { WHAL_STM32C031_RCC_REGMAP },
.base = WHAL_STM32C031_RCC_BASE,
};

static const whal_Stm32c0_Rcc_PeriphClk g_periphClks[] = {
Expand All @@ -46,7 +46,7 @@ static const whal_Stm32c0_Rcc_PeriphClk g_periphClks[] = {

/* GPIO */
whal_Gpio g_whalGpio = {
.regmap = { WHAL_STM32C031_GPIO_REGMAP },
.base = WHAL_STM32C031_GPIO_BASE,
/* .driver: direct API mapping */

.cfg = &(whal_Stm32c0_Gpio_Cfg) {
Expand Down Expand Up @@ -88,7 +88,7 @@ whal_Gpio g_whalGpio = {

/* Timer */
whal_Timer g_whalTimer = {
.regmap = { WHAL_CORTEX_M0PLUS_SYSTICK_REGMAP },
.base = WHAL_CORTEX_M0PLUS_SYSTICK_BASE,
.driver = WHAL_CORTEX_M0PLUS_SYSTICK_DRIVER,

.cfg = &(whal_SysTick_Cfg) {
Expand All @@ -100,7 +100,7 @@ whal_Timer g_whalTimer = {

/* UART */
whal_Uart g_whalUart = {
.regmap = { WHAL_STM32C031_USART2_REGMAP },
.base = WHAL_STM32C031_USART2_BASE,
/* .driver: direct API mapping */

.cfg = &(whal_Stm32c0_Uart_Cfg) {
Expand All @@ -111,7 +111,7 @@ whal_Uart g_whalUart = {

/* SPI */
whal_Spi g_whalSpi = {
.regmap = { WHAL_STM32C031_SPI1_REGMAP },
.base = WHAL_STM32C031_SPI1_BASE,
/* .driver: direct API mapping */

.cfg = &(whal_Stm32c0_Spi_Cfg) {
Expand All @@ -122,7 +122,7 @@ whal_Spi g_whalSpi = {

/* Flash */
whal_Flash g_whalFlash = {
.regmap = { WHAL_STM32C031_FLASH_REGMAP },
.base = WHAL_STM32C031_FLASH_BASE,
.driver = WHAL_STM32C031_FLASH_DRIVER,

.cfg = &(whal_Stm32c0_Flash_Cfg) {
Expand Down
4 changes: 2 additions & 2 deletions boards/stm32c031_nucleo/board.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ GCC = $(GCC_PATH)arm-none-eabi-gcc
LD = $(GCC_PATH)arm-none-eabi-gcc
OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy

CFLAGS += -Wall -Werror $(INCLUDE) -g3 \
CFLAGS += -Wall -Werror $(INCLUDE) -g3 -Os -ffunction-sections -fdata-sections \
-ffreestanding -nostdlib -mcpu=cortex-m0plus -mthumb \
-DPLATFORM_STM32C0 -MMD -MP \
-DWHAL_CFG_STM32C0_GPIO_DIRECT_API_MAPPING \
-DWHAL_CFG_STM32C0_RCC_DIRECT_API_MAPPING \
-DWHAL_CFG_STM32C0_UART_DIRECT_API_MAPPING \
-DWHAL_CFG_STM32C0_SPI_DIRECT_API_MAPPING
LDFLAGS = -mcpu=cortex-m0plus -mthumb -ffreestanding -nostartfiles \
-Wl,--omagic -static
-Wl,--omagic -Wl,--gc-sections -static

LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld

Expand Down
16 changes: 8 additions & 8 deletions boards/stm32f091rc_nucleo/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ whal_Timeout g_whalTimeout = {

/* Clock — PLL at 48 MHz (HSI/2 * 12) */
whal_Clock g_whalClock = {
.regmap = { WHAL_STM32F091_RCC_REGMAP },
.base = WHAL_STM32F091_RCC_BASE,
};

static const whal_Stm32f0_Rcc_PeriphClk g_periphClks[] = {
Expand All @@ -44,7 +44,7 @@ static const whal_Stm32f0_Rcc_PeriphClk g_periphClks[] = {

/* GPIO */
whal_Gpio g_whalGpio = {
.regmap = { WHAL_STM32F091_GPIO_REGMAP },
.base = WHAL_STM32F091_GPIO_BASE,

.cfg = &(whal_Stm32f0_Gpio_Cfg) {
.pinCfg = (whal_Stm32f0_Gpio_PinCfg[PIN_COUNT]) {
Expand Down Expand Up @@ -100,7 +100,7 @@ whal_Gpio g_whalGpio = {

/* Timer — SysTick at 1 ms */
whal_Timer g_whalTimer = {
.regmap = { WHAL_CORTEX_M0_SYSTICK_REGMAP },
.base = WHAL_CORTEX_M0_SYSTICK_BASE,
.driver = WHAL_CORTEX_M0_SYSTICK_DRIVER,

.cfg = &(whal_SysTick_Cfg) {
Expand All @@ -112,7 +112,7 @@ whal_Timer g_whalTimer = {

/* UART — USART2 at 115200 baud */
whal_Uart g_whalUart = {
.regmap = { WHAL_STM32F091_USART2_REGMAP },
.base = WHAL_STM32F091_USART2_BASE,

.cfg = &(whal_Stm32f0_Uart_Cfg) {
.timeout = &g_whalTimeout,
Expand All @@ -122,7 +122,7 @@ whal_Uart g_whalUart = {

/* SPI */
whal_Spi g_whalSpi = {
.regmap = { WHAL_STM32F091_SPI1_REGMAP },
.base = WHAL_STM32F091_SPI1_BASE,

.cfg = &(whal_Stm32f0_Spi_Cfg) {
.pclk = 48000000,
Expand All @@ -132,7 +132,7 @@ whal_Spi g_whalSpi = {

/* I2C — I2C1 */
whal_I2c g_whalI2c = {
.regmap = { WHAL_STM32F091_I2C1_REGMAP },
.base = WHAL_STM32F091_I2C1_BASE,

.cfg = &(whal_Stm32f0_I2c_Cfg) {
.pclk = 48000000,
Expand All @@ -142,7 +142,7 @@ whal_I2c g_whalI2c = {

/* Flash — 256 KB */
whal_Flash g_whalFlash = {
.regmap = { WHAL_STM32F091_FLASH_REGMAP },
.base = WHAL_STM32F091_FLASH_BASE,
.driver = WHAL_STM32F091_FLASH_DRIVER,

.cfg = &(whal_Stm32f0_Flash_Cfg) {
Expand All @@ -154,7 +154,7 @@ whal_Flash g_whalFlash = {

#ifdef BOARD_WATCHDOG_IWDG
whal_Watchdog g_whalWatchdog = {
.regmap = { WHAL_STM32F091_IWDG_REGMAP },
.base = WHAL_STM32F091_IWDG_BASE,
.driver = WHAL_STM32F091_IWDG_DRIVER,

.cfg = &(whal_Stm32f0_Iwdg_Cfg) {
Expand Down
4 changes: 2 additions & 2 deletions boards/stm32f091rc_nucleo/board.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ GCC = $(GCC_PATH)arm-none-eabi-gcc
LD = $(GCC_PATH)arm-none-eabi-gcc
OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy

CFLAGS += -Wall -Werror $(INCLUDE) -g3 \
CFLAGS += -Wall -Werror $(INCLUDE) -g3 -Os -ffunction-sections -fdata-sections \
-ffreestanding -nostdlib -mcpu=cortex-m0 -mthumb \
-DPLATFORM_STM32F0 -MMD -MP \
-DWHAL_CFG_STM32F0_GPIO_DIRECT_API_MAPPING \
Expand All @@ -17,7 +17,7 @@ CFLAGS += -Wall -Werror $(INCLUDE) -g3 \
-DWHAL_CFG_STM32F0_I2C_DIRECT_API_MAPPING \
$(if $(filter iwdg,$(WATCHDOG)),-DBOARD_WATCHDOG_IWDG)
LDFLAGS = -mcpu=cortex-m0 -mthumb -ffreestanding -nostartfiles \
-Wl,--omagic -static
-Wl,--omagic -Wl,--gc-sections -static

LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld

Expand Down
18 changes: 9 additions & 9 deletions boards/stm32f302r8_nucleo/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ whal_Timeout g_whalTimeout = {

/* Clock — PLL at 48 MHz (HSI/2 * 12) */
whal_Clock g_whalClock = {
.regmap = { WHAL_STM32F302_RCC_REGMAP },
.base = WHAL_STM32F302_RCC_BASE,
};

static const whal_Stm32f3_Rcc_PeriphClk g_periphClks[] = {
Expand All @@ -47,7 +47,7 @@ static const whal_Stm32f3_Rcc_PeriphClk g_periphClks[] = {

/* GPIO */
whal_Gpio g_whalGpio = {
.regmap = { WHAL_STM32F302_GPIO_REGMAP },
.base = WHAL_STM32F302_GPIO_BASE,

.cfg = &(whal_Stm32f3_Gpio_Cfg) {
.pinCfg = (whal_Stm32f3_Gpio_PinCfg[PIN_COUNT]) {
Expand Down Expand Up @@ -103,7 +103,7 @@ whal_Gpio g_whalGpio = {

/* Timer — SysTick at 1 ms */
whal_Timer g_whalTimer = {
.regmap = { WHAL_CORTEX_M4_SYSTICK_REGMAP },
.base = WHAL_CORTEX_M4_SYSTICK_BASE,
.driver = WHAL_CORTEX_M4_SYSTICK_DRIVER,

.cfg = &(whal_SysTick_Cfg) {
Expand All @@ -115,7 +115,7 @@ whal_Timer g_whalTimer = {

/* UART — USART2 at 115200 baud */
whal_Uart g_whalUart = {
.regmap = { WHAL_STM32F302_USART2_REGMAP },
.base = WHAL_STM32F302_USART2_BASE,

.cfg = &(whal_Stm32f3_Uart_Cfg) {
.timeout = &g_whalTimeout,
Expand All @@ -125,7 +125,7 @@ whal_Uart g_whalUart = {

/* SPI — SPI3 */
whal_Spi g_whalSpi = {
.regmap = { WHAL_STM32F302_SPI3_REGMAP },
.base = WHAL_STM32F302_SPI3_BASE,

.cfg = &(whal_Stm32f3_Spi_Cfg) {
.pclk = 48000000,
Expand All @@ -135,7 +135,7 @@ whal_Spi g_whalSpi = {

/* I2C — I2C1 (HSI at 8 MHz per RCC_CFGR3.I2C1SW reset default) */
whal_I2c g_whalI2c = {
.regmap = { WHAL_STM32F302_I2C1_REGMAP },
.base = WHAL_STM32F302_I2C1_BASE,

.cfg = &(whal_Stm32f3_I2c_Cfg) {
.pclk = 8000000,
Expand All @@ -145,7 +145,7 @@ whal_I2c g_whalI2c = {

/* Flash — 64 KB */
whal_Flash g_whalFlash = {
.regmap = { WHAL_STM32F302_FLASH_REGMAP },
.base = WHAL_STM32F302_FLASH_BASE,
.driver = WHAL_STM32F302_FLASH_DRIVER,

.cfg = &(whal_Stm32f3_Flash_Cfg) {
Expand All @@ -157,7 +157,7 @@ whal_Flash g_whalFlash = {

#ifdef BOARD_WATCHDOG_IWDG
whal_Watchdog g_whalWatchdog = {
.regmap = { WHAL_STM32F302_IWDG_REGMAP },
.base = WHAL_STM32F302_IWDG_BASE,
.driver = WHAL_STM32F302_IWDG_DRIVER,

.cfg = &(whal_Stm32f3_Iwdg_Cfg) {
Expand All @@ -168,7 +168,7 @@ whal_Watchdog g_whalWatchdog = {
};
#elif defined(BOARD_WATCHDOG_WWDG)
whal_Watchdog g_whalWatchdog = {
.regmap = { WHAL_STM32F302_WWDG_REGMAP },
.base = WHAL_STM32F302_WWDG_BASE,
.driver = WHAL_STM32F302_WWDG_DRIVER,

.cfg = &(whal_Stm32f3_Wwdg_Cfg) {
Expand Down
4 changes: 2 additions & 2 deletions boards/stm32f302r8_nucleo/board.mk
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ GCC = $(GCC_PATH)arm-none-eabi-gcc
LD = $(GCC_PATH)arm-none-eabi-gcc
OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy

CFLAGS += -Wall -Werror $(INCLUDE) -g3 \
CFLAGS += -Wall -Werror $(INCLUDE) -g3 -Os -ffunction-sections -fdata-sections \
-ffreestanding -nostdlib \
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
-DPLATFORM_STM32F3 -MMD -MP \
Expand All @@ -19,7 +19,7 @@ CFLAGS += -Wall -Werror $(INCLUDE) -g3 \
$(if $(filter iwdg,$(WATCHDOG)),-DBOARD_WATCHDOG_IWDG) \
$(if $(filter wwdg,$(WATCHDOG)),-DBOARD_WATCHDOG_WWDG)
LDFLAGS = -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 \
-ffreestanding -nostartfiles -Wl,--omagic -static
-ffreestanding -nostartfiles -Wl,--omagic -Wl,--gc-sections -static

LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld

Expand Down
Loading
Loading