Skip to content
Open
Show file tree
Hide file tree
Changes from all 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