diff --git a/.github/workflows/boards.yml b/.github/workflows/boards.yml index 5c2c163..43a0e63 100644 --- a/.github/workflows/boards.yml +++ b/.github/workflows/boards.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - board: [stm32wb55xx_nucleo, stm32wba55cg_nucleo, stm32wb05kz_nucleo, pic32cz_curiosity_ultra, stm32h563zi_nucleo, stm32f411_blackpill, stm32c031_nucleo, stm32f091rc_nucleo, stm32f302r8_nucleo, stm32l152re_nucleo, stm32n657a0_nucleo, stm32u5a5zj_nucleo] + board: [stm32wb55xx_nucleo, stm32wba55cg_nucleo, stm32wb09ke_nucleo, pic32cz_curiosity_ultra, stm32h563zi_nucleo, stm32f411_blackpill, stm32c031_nucleo, stm32f091rc_nucleo, stm32f302r8_nucleo, stm32l152re_nucleo, stm32n657a0_nucleo, stm32u5a5zj_nucleo] extra_cflags: ["", "-DWHAL_CFG_NO_TIMEOUT"] include: - board: stm32wb55xx_nucleo diff --git a/boards/README.md b/boards/README.md index 8c7f324..b639917 100644 --- a/boards/README.md +++ b/boards/README.md @@ -20,7 +20,7 @@ build configuration. | ST NUCLEO-F302R8 | STM32F3 | Cortex-M4 | `stm32f302r8_nucleo/` | | WeAct BlackPill STM32F411 | STM32F4 | Cortex-M4 | `stm32f411_blackpill/` | | ST NUCLEO-H563ZI | STM32H5 | Cortex-M33 | `stm32h563zi_nucleo/` | -| ST NUCLEO-WB05KZ | STM32WB0 | Cortex-M0+ | `stm32wb05kz_nucleo/` | +| ST NUCLEO-WB09KE | STM32WB0 | Cortex-M0+ | `stm32wb09ke_nucleo/` | | ST NUCLEO-WB55RG | STM32WB | Cortex-M4 | `stm32wb55xx_nucleo/` | | ST NUCLEO-L152RE | STM32L1 | Cortex-M3 | `stm32l152re_nucleo/` | | ST NUCLEO-N657X0-Q | STM32N6 | Cortex-M55 | `stm32n657a0_nucleo/` | diff --git a/boards/stm32wb05kz_nucleo/board.mk b/boards/stm32wb09ke_nucleo/board.mk similarity index 88% rename from boards/stm32wb05kz_nucleo/board.mk rename to boards/stm32wb09ke_nucleo/board.mk index 0a54348..28d8dee 100644 --- a/boards/stm32wb05kz_nucleo/board.mk +++ b/boards/stm32wb09ke_nucleo/board.mk @@ -61,13 +61,15 @@ BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c) # Peripheral devices include $(WHAL_DIR)/boards/peripheral/board.mk -# Flash via openocd: make flash BOARD= IMAGE= +# Flash via openocd: make flash BOARD= IMAGE= +# bluenrg-x.cfg is only used to connect; flash.tcl programs the flash +# controller directly. OPENOCD ?= /opt/openocd/bin/openocd -OPENOCD_INTERFACE ?= interface/stlink.cfg -OPENOCD_TARGET ?= target/stm32wb0x.cfg +OPENOCD_INTERFACE ?= interface/stlink-dap.cfg +OPENOCD_TARGET ?= target/bluenrg-x.cfg .PHONY: flash flash: - @test -n "$(IMAGE)" || { echo "IMAGE= required" >&2; exit 1; } + @test -n "$(IMAGE)" || { echo "IMAGE= required" >&2; exit 1; } $(OPENOCD) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) \ - -c "program $(IMAGE) verify reset exit" + -c "set IMAGE $(abspath $(IMAGE))" -f $(_BOARD_DIR)/flash.tcl diff --git a/boards/stm32wb09ke_nucleo/flash.tcl b/boards/stm32wb09ke_nucleo/flash.tcl new file mode 100644 index 0000000..1ad24a4 --- /dev/null +++ b/boards/stm32wb09ke_nucleo/flash.tcl @@ -0,0 +1,129 @@ +# flash.tcl +# +# Copyright (C) 2026 wolfSSL Inc. +# +# This file is part of wolfHAL. +# +# wolfHAL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# wolfHAL is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA +# + +# Program a raw .bin into STM32WB09 main flash by driving the flash +# controller registers directly (RM0505 section 9.3), bypassing the +# OpenOCD bluenrg-x flash driver. +# +# Usage: +# openocd -f interface/stlink-dap.cfg -f target/bluenrg-x.cfg \ +# -c "set IMAGE " -f flash.tcl +# +# The image is staged through SRAM in 32 KB chunks: each chunk is loaded +# with load_image into a 0xFF-filled RAM window, its pages are erased, and +# its non-blank words are programmed and read back for verification. + +set FC 0x40001000 +set COMMAND [expr {$FC + 0x00}] +set IRQSTAT [expr {$FC + 0x08}] +set IRQRAW [expr {$FC + 0x10}] +set ADDRESS [expr {$FC + 0x18}] +set PAGEPROT0 [expr {$FC + 0x34}] +set PAGEPROT1 [expr {$FC + 0x38}] +set DATA0 [expr {$FC + 0x40}] + +set FLASH_BASE 0x10040000 +set FLASH_SIZE 0x80000 +set PAGE_SIZE 0x800 +set RAM_WIN 0x20008000 +set CHUNK 0x8000 + +proc rd {a} { return [lindex [read_memory $a 32 1] 0] } +proc wr {a v} { write_memory $a 32 [list $v] } + +# Issue one controller command and wait for CMDSTART then CMDDONE. +proc run_cmd {cmd what} { + global IRQSTAT IRQRAW COMMAND + wr $IRQSTAT 0xF + wr $COMMAND $cmd + foreach {bit name} {2 CMDSTART 1 CMDDONE} { + set ok 0 + for {set i 0} {$i < 2000} {incr i} { + set irq [rd $IRQRAW] + if {$irq & 0xC} { + wr $IRQSTAT 0xF + error [format "%s: flash error IRQRAW=0x%08x" $what $irq] + } + if {$irq & $bit} { set ok 1; break } + } + if {!$ok} { + error [format "%s: timeout waiting for %s IRQRAW=0x%08x" \ + $what $name [rd $IRQRAW]] + } + wr $IRQSTAT $bit + } +} + +if {![info exists IMAGE]} { error "set IMAGE first" } +if {[file extension $IMAGE] ne ".bin"} { error "IMAGE must be a raw .bin" } +set size [file size $IMAGE] +if {$size == 0 || $size > $FLASH_SIZE} { + error [format "image size %d out of range" $size] +} + +init +reset halt +halt + +wr $PAGEPROT0 0 +wr $PAGEPROT1 0 + +for {set off 0} {$off < $size} {incr off $CHUNK} { + set len [expr {$size - $off}] + if {$len > $CHUNK} { set len $CHUNK } + set nwords [expr {($len + 3) / 4}] + set npages [expr {($len + $PAGE_SIZE - 1) / $PAGE_SIZE}] + + mww $RAM_WIN 0xFFFFFFFF [expr {$CHUNK / 4}] + load_image $IMAGE [expr {$RAM_WIN - $off}] bin $RAM_WIN $CHUNK + set words [read_memory $RAM_WIN 32 $nwords] + + set firstPage [expr {$off / $PAGE_SIZE}] + for {set p $firstPage} {$p < $firstPage + $npages} {incr p} { + wr $ADDRESS [expr {$p * $PAGE_SIZE / 4}] + run_cmd 0x11 "erase page $p" + } + + set base [expr {$off / 4}] + for {set i 0} {$i < $nwords} {incr i} { + set w [lindex $words $i] + if {$w != 0xFFFFFFFF} { + wr $ADDRESS [expr {$base + $i}] + wr $DATA0 $w + run_cmd 0x33 [format "write word %d" [expr {$base + $i}]] + } + } + + set rb [read_memory [expr {$FLASH_BASE + $off}] 32 $nwords] + for {set i 0} {$i < $nwords} {incr i} { + if {[lindex $rb $i] != [lindex $words $i]} { + error [format "verify failed @0x%08x: got 0x%08x want 0x%08x" \ + [expr {$FLASH_BASE + $off + $i * 4}] \ + [lindex $rb $i] [lindex $words $i]] + } + } + echo [format "programmed 0x%08x-0x%08x" [expr {$FLASH_BASE + $off}] \ + [expr {$FLASH_BASE + $off + $len - 1}]] +} + +echo "verify ok" +reset run +shutdown diff --git a/boards/stm32wb05kz_nucleo/ivt.c b/boards/stm32wb09ke_nucleo/ivt.c similarity index 96% rename from boards/stm32wb05kz_nucleo/ivt.c rename to boards/stm32wb09ke_nucleo/ivt.c index 411ba11..89f7f51 100644 --- a/boards/stm32wb05kz_nucleo/ivt.c +++ b/boards/stm32wb09ke_nucleo/ivt.c @@ -43,7 +43,7 @@ void SVC_Handler(void) __attribute__((weak, noreturn, alias("Default_Hand void PendSV_Handler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); void SysTick_Handler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); -/* STM32WB05xZ peripheral interrupts (RM0529 Table 6) */ +/* STM32WB09xE peripheral interrupts (RM0505 Table 6) */ void NVM_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); void RCC_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); void BATTERY_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); @@ -66,6 +66,7 @@ void BLE_WKUP_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Ha void BLE_SEQ_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); void TIM16_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); void TIM17_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void TRNG_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); #define RESERVED Default_Handler @@ -108,7 +109,7 @@ void (* const interrupt_vector_table[])(void) __attribute__((section(".isr_vecto RESERVED, /* Reserved */ PendSV_Handler, SysTick_Handler, - /* STM32WB05xZ peripheral interrupts (Table 6) */ + /* STM32WB09xE peripheral interrupts (Table 6) */ NVM_IRQHandler, /* 0 Flash controller */ RCC_IRQHandler, /* 1 Reset and clock controller */ BATTERY_IRQHandler, /* 2 PVD */ @@ -137,7 +138,7 @@ void (* const interrupt_vector_table[])(void) __attribute__((section(".isr_vecto BLE_SEQ_IRQHandler, /* 25 BLE RX/TX sequence */ TIM16_IRQHandler, /* 26 TIM16 */ TIM17_IRQHandler, /* 27 TIM17 */ - RESERVED, /* 28 Reserved */ + TRNG_IRQHandler, /* 28 TRNG */ RESERVED, /* 29 Reserved */ RESERVED, /* 30 Reserved */ RESERVED, /* 31 Reserved */ diff --git a/boards/stm32wb05kz_nucleo/linker.ld b/boards/stm32wb09ke_nucleo/linker.ld similarity index 78% rename from boards/stm32wb05kz_nucleo/linker.ld rename to boards/stm32wb09ke_nucleo/linker.ld index f14d1c8..6a2b63b 100644 --- a/boards/stm32wb05kz_nucleo/linker.ld +++ b/boards/stm32wb09ke_nucleo/linker.ld @@ -23,24 +23,24 @@ ENTRY(Reset_Handler) /* - * STM32WB05KZ memory layout (DS14591): - * Flash: 192 KB @ 0x10040000 (96 pages of 2 KB) - * SRAM0: 12 KB @ 0x20000000 (always retained in Deepstop) - * SRAM1: 12 KB @ 0x20003000 (retention is programmable) + * STM32WB09KE memory layout (RM0505 Table 3): + * Flash: 512 KB @ 0x10040000 (256 pages of 2 KB) + * SRAM0: 16 KB @ 0x20000000 (always retained in Deepstop) + * SRAM1: 16 KB @ 0x20004000 (retention is programmable) + * SRAM2: 16 KB @ 0x20008000 (retention is programmable) + * SRAM3: 16 KB @ 0x2000C000 (retention is programmable) * - * We treat the two SRAM banks as one contiguous 24 KB region — they are - * adjacent in the memory map and the linker can place the heap/stack at - * the top of SRAM1 without any special handling. The lowest part of - * SRAM0 (0x20000000–0x20000033) is reserved for boot-time use; the - * vector remap puts those words at 0x00000000 — see RM0529 Table 4. + * The four adjacent banks are treated as one 64 KB region. SRAM0 + * 0x20000000-0x20000017 is reserved for the boot ROM and low-power + * manager (RM0505 Table 4), so RAM starts just above it. */ -_estack = 0x20006000; /* end of SRAM1 = SRAM0 base + 24 KB */ +_estack = 0x20010000; /* end of SRAM3 */ _Min_Stack_Size = 0x500; /* required amount of stack */ MEMORY { -FLASH (rx) : ORIGIN = 0x10040000, LENGTH = 192K -RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 24K +FLASH (rx) : ORIGIN = 0x10040000, LENGTH = 512K +RAM (rwx) : ORIGIN = 0x20000018, LENGTH = 64K - 0x18 } SECTIONS diff --git a/boards/stm32wb05kz_nucleo/wolfHAL_board.c b/boards/stm32wb09ke_nucleo/wolfHAL_board.c similarity index 70% rename from boards/stm32wb05kz_nucleo/wolfHAL_board.c rename to boards/stm32wb09ke_nucleo/wolfHAL_board.c index 208902b..96ed1e1 100644 --- a/boards/stm32wb05kz_nucleo/wolfHAL_board.c +++ b/boards/stm32wb09ke_nucleo/wolfHAL_board.c @@ -19,12 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -/* Board configuration for the NUCLEO-WB05KZ dev board (UM3343 / MB1801+MB2032). */ +/* Board configuration for the NUCLEO-WB09KE dev board (UM3345 / MB1801+MB2032). */ #include #include #include "wolfHAL_board.h" -#include +#include /* Target SYSCLK 64 MHz from the HSI64M tree (PLL-locked onto the 32 MHz * HSE crystal). Flash needs 1 wait state above 32 MHz. */ @@ -49,34 +49,34 @@ whal_Timeout g_whalTimeout = { }; static const whal_Stm32wb0_Rcc_PeriphClk g_periphClks[] = { - {WHAL_STM32WB05_GPIOA_CLOCK}, - {WHAL_STM32WB05_GPIOB_CLOCK}, - {WHAL_STM32WB05_USART1_CLOCK}, - {WHAL_STM32WB05_SPI3_CLOCK}, - {WHAL_STM32WB05_I2C1_CLOCK}, - {WHAL_STM32WB05_PKA_CLOCK}, - {WHAL_STM32WB05_SYSCFG_CLOCK}, - {WHAL_STM32WB05_RNG_CLOCK}, + {WHAL_STM32WB09_GPIOA_CLOCK}, + {WHAL_STM32WB09_GPIOB_CLOCK}, + {WHAL_STM32WB09_USART1_CLOCK}, + {WHAL_STM32WB09_SPI3_CLOCK}, + {WHAL_STM32WB09_I2C1_CLOCK}, + {WHAL_STM32WB09_PKA_CLOCK}, + {WHAL_STM32WB09_SYSCFG_CLOCK}, + {WHAL_STM32WB09_RNG_CLOCK}, #ifdef BOARD_WATCHDOG_IWDG - {WHAL_STM32WB05_IWDG_CLOCK}, + {WHAL_STM32WB09_IWDG_CLOCK}, #endif }; #define PERIPH_CLK_COUNT (sizeof(g_periphClks) / sizeof(g_periphClks[0])) -/* UART (USART via VCP at 115200 baud). - * BRR uses APB1 clock = SYSCLK on WB0. */ +/* UART (USART via VCP at 115200 baud). BRR uses the fixed 16 MHz USART + * kernel clock. */ whal_Uart g_whalUart = { - .base = WHAL_STM32WB05_USART1_BASE, + .base = WHAL_STM32WB09_USART1_BASE, /* .driver: direct API mapping */ .cfg = &(whal_Stm32wb0_Uart_Cfg) { .timeout = &g_whalTimeout, - .brr = WHAL_STM32WB0_UART_BRR(16000000, 115200), + .brr = WHAL_STM32WB0_UART_BRR(WHAL_STM32WB0_UART_CLK_HZ, 115200), }, }; /* SPI3 */ whal_Spi g_whalSpi = { - .base = WHAL_STM32WB05_SPI3_BASE, + .base = WHAL_STM32WB09_SPI3_BASE, /* .driver: direct API mapping */ .cfg = &(whal_Stm32wb0_Spi_Cfg) { .pclk = BOARD_SYSCLK_HZ, @@ -86,7 +86,7 @@ whal_Spi g_whalSpi = { /* I2C1 */ whal_I2c g_whalI2c = { - .base = WHAL_STM32WB05_I2C1_BASE, + .base = WHAL_STM32WB09_I2C1_BASE, /* .driver: direct API mapping */ .cfg = &(whal_Stm32wb0_I2c_Cfg) { .pclk = BOARD_SYSCLK_HZ, @@ -96,8 +96,8 @@ whal_I2c g_whalI2c = { /* PKA (public-key accelerator) — vtable dispatcher for whal_Crypto_Init/Deinit. */ whal_Crypto g_whalPka = { - .base = WHAL_STM32WB05_PKA_BASE, - .driver = WHAL_STM32WB05_PKA_DRIVER, + .base = WHAL_STM32WB09_PKA_BASE, + .driver = WHAL_STM32WB09_PKA_DRIVER, .cfg = &(whal_Stm32wb0_Pka_Cfg) { .timeout = &g_whalTimeout, }, @@ -105,7 +105,7 @@ whal_Crypto g_whalPka = { #ifdef BOARD_WATCHDOG_IWDG whal_Watchdog g_whalWatchdog = { - .base = WHAL_STM32WB05_IWDG_BASE, + .base = WHAL_STM32WB09_IWDG_BASE, /* .driver: direct API mapping */ .cfg = &(whal_Stm32wb0_Iwdg_Cfg) { .prescaler = WHAL_STM32WB0_IWDG_PR_32, @@ -127,39 +127,42 @@ whal_Error Board_Init(void) whal_Error err; /* Bring up flash latency BEFORE raising SYSCLK above 32 MHz. - * RM0529 9.4.2: 1 wait state for sysclk == 64 MHz. */ + * RM0505 9.3.2: 1 wait state for sysclk == 64 MHz. */ err = whal_Stm32wb0_Flash_Ext_SetLatency(BOARD_FLASH_DEV, WHAL_STM32WB0_FLASH_LATENCY_1); if (err) return err; - /* HSI64M is on at reset; defensively poll its ready bit. */ - err = whal_Stm32wb0_Rcc_EnableHsi(); + /* RC64MPLL runs from reset as the free-running 64 MHz HSI. */ + err = whal_Stm32wb0_Rcc_EnableHsi(&g_whalTimeout); if (err) return err; - /* Enable the 32 MHz HSE crystal and lock the RC64MPLL onto it. - * The Nucleo board ships an X2 32 MHz crystal so HSE is the right - * PLL reference; running the PLL locked yields a clean 64 MHz tree. */ - err = whal_Stm32wb0_Rcc_EnableHse(); + /* Lock the RC64MPLL onto the 32 MHz HSE crystal for an accurate + * PLL64M, then run SYSCLK undivided at 64 MHz. */ + err = whal_Stm32wb0_Rcc_EnableOsc( + &(whal_Stm32wb0_Rcc_OscCfg){WHAL_STM32WB0_RCC_HSE_CFG}, + &g_whalTimeout); if (err) return err; - err = whal_Stm32wb0_Rcc_EnableHsiPll(); + err = whal_Stm32wb0_Rcc_EnablePll( + &(whal_Stm32wb0_Rcc_PllCfg){.lockDetNstop = 0}, &g_whalTimeout); if (err) return err; - - /* Source the fast clock tree from the PLL-locked RC64M, then divide - * by 1 to land at 64 MHz SYSCLK. */ - err = whal_Stm32wb0_Rcc_SetFastClkSrc(WHAL_STM32WB0_RCC_FASTCLK_RC64MPLL); - if (err) - return err; - err = whal_Stm32wb0_Rcc_SetSysClock(WHAL_STM32WB0_RCC_SYSCLK_64MHZ); + err = whal_Stm32wb0_Rcc_SetSysClock(WHAL_STM32WB0_RCC_SYSCLK_SRC_RC64MPLL, + WHAL_STM32WB0_RCC_SYSCLK_64MHZ, + &g_whalTimeout); if (err) return err; #ifdef BOARD_WATCHDOG_IWDG - /* The IWDG is clocked from LSI (~32 kHz). */ - err = whal_Stm32wb0_Rcc_EnableLsi(); + /* The IWDG is clocked from the slow clock tree, fed here by LSI. */ + err = whal_Stm32wb0_Rcc_EnableOsc( + &(whal_Stm32wb0_Rcc_OscCfg){WHAL_STM32WB0_RCC_LSI_CFG}, + &g_whalTimeout); + if (err) + return err; + err = whal_Stm32wb0_Rcc_SetSlowClock(WHAL_STM32WB0_RCC_SLOWCLK_SRC_LSI); if (err) return err; #endif @@ -259,13 +262,26 @@ whal_Error Board_Deinit(void) } #ifdef BOARD_WATCHDOG_IWDG - err = whal_Stm32wb0_Rcc_DisableLsi(); + err = whal_Stm32wb0_Rcc_SetSlowClock(WHAL_STM32WB0_RCC_SLOWCLK_SRC_NONE); + if (err) + return err; + err = whal_Stm32wb0_Rcc_DisableOsc( + &(whal_Stm32wb0_Rcc_OscCfg){WHAL_STM32WB0_RCC_LSI_CFG}); if (err) return err; #endif /* Drop back to the default 16 MHz sysclk before dropping flash latency. */ - err = whal_Stm32wb0_Rcc_SetSysClock(WHAL_STM32WB0_RCC_SYSCLK_16MHZ); + err = whal_Stm32wb0_Rcc_SetSysClock(WHAL_STM32WB0_RCC_SYSCLK_SRC_RC64MPLL, + WHAL_STM32WB0_RCC_SYSCLK_16MHZ, + &g_whalTimeout); + if (err) + return err; + err = whal_Stm32wb0_Rcc_DisablePll(); + if (err) + return err; + err = whal_Stm32wb0_Rcc_DisableOsc( + &(whal_Stm32wb0_Rcc_OscCfg){WHAL_STM32WB0_RCC_HSE_CFG}); if (err) return err; diff --git a/boards/stm32wb05kz_nucleo/wolfHAL_board.h b/boards/stm32wb09ke_nucleo/wolfHAL_board.h similarity index 92% rename from boards/stm32wb05kz_nucleo/wolfHAL_board.h rename to boards/stm32wb09ke_nucleo/wolfHAL_board.h index 246a977..bf3a8b7 100644 --- a/boards/stm32wb05kz_nucleo/wolfHAL_board.h +++ b/boards/stm32wb09ke_nucleo/wolfHAL_board.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include extern whal_Uart g_whalUart; extern whal_Spi g_whalSpi; @@ -54,10 +54,10 @@ enum { #define BOARD_LED_PIN 0 -/* Flash array on WB05KZ: 192 KB at 0x10040000, 2 KB pages = 96 pages. +/* Flash array on WB09KE: 512 KB at 0x10040000, 2 KB pages = 256 pages. * Reserve the last page for test scratch. */ -#define BOARD_FLASH_START_ADDR WHAL_STM32WB05_FLASH_ARRAY_BASE -#define BOARD_FLASH_SIZE WHAL_STM32WB05_FLASH_SIZE +#define BOARD_FLASH_START_ADDR WHAL_STM32WB09_FLASH_ARRAY_BASE +#define BOARD_FLASH_SIZE WHAL_STM32WB09_FLASH_SIZE #define BOARD_FLASH_SECTOR_SZ 0x800 #define BOARD_FLASH_TEST_ADDR (BOARD_FLASH_START_ADDR + BOARD_FLASH_SIZE - BOARD_FLASH_SECTOR_SZ) @@ -69,7 +69,7 @@ enum { /* GPIO dev initializer — singleton defined in stm32wb0_gpio.c. */ #define WHAL_CFG_STM32WB0_GPIO_DEV { \ - .base = WHAL_STM32WB05_GPIO_BASE, \ + .base = WHAL_STM32WB09_GPIO_BASE, \ .cfg = (void *)&(const whal_Stm32wb0_Gpio_Cfg){ \ .pinCfg = (const whal_Stm32wb0_Gpio_PinCfg[PIN_COUNT]){ \ /* LD1 (blue) on PB1, output, push-pull, low speed, no pull */ \ @@ -129,18 +129,18 @@ enum { /* Flash dev initializer — singleton defined in stm32wb0_flash.c. */ #define WHAL_CFG_STM32WB0_FLASH_DEV { \ - .driver = WHAL_STM32WB05_FLASH_DRIVER, \ - .base = WHAL_STM32WB05_FLASH_BASE, \ + .driver = WHAL_STM32WB09_FLASH_DRIVER, \ + .base = WHAL_STM32WB09_FLASH_BASE, \ .cfg = (void *)&(const whal_Stm32wb0_Flash_Cfg){ \ - .startAddr = WHAL_STM32WB05_FLASH_ARRAY_BASE, \ - .size = WHAL_STM32WB05_FLASH_SIZE, \ + .startAddr = WHAL_STM32WB09_FLASH_ARRAY_BASE, \ + .size = WHAL_STM32WB09_FLASH_SIZE, \ .timeout = &g_whalTimeout, \ }, \ } /* RNG dev initializer — singleton defined in stm32wb0_rng.c. */ #define WHAL_CFG_STM32WB0_RNG_DEV { \ - .base = WHAL_STM32WB05_RNG_BASE, \ + .base = WHAL_STM32WB09_RNG_BASE, \ /* .driver: direct API mapping */ \ .cfg = (void *)&(const whal_Stm32wb0_Rng_Cfg){ \ .timeout = &g_whalTimeout, \ @@ -150,7 +150,7 @@ enum { /* IWDG dev initializer — singleton defined in stm32wb_iwdg.c * (stm32wb0 alias points at the stm32wb leaf). */ #define WHAL_CFG_STM32WB0_IWDG_DEV { \ - .base = WHAL_STM32WB05_IWDG_BASE, \ + .base = WHAL_STM32WB09_IWDG_BASE, \ /* .driver: direct API mapping */ \ .cfg = (void *)&(const whal_Stm32wb0_Iwdg_Cfg){ \ .prescaler = WHAL_STM32WB0_IWDG_PR_32, \ @@ -162,8 +162,8 @@ enum { /* PKA dev initializer — singleton defined in stm32wb_pka.c * (stm32wb0 alias points at the stm32wb leaf). */ #define WHAL_CFG_STM32WB0_PKA_DEV { \ - .base = WHAL_STM32WB05_PKA_BASE, \ - .driver = WHAL_STM32WB05_PKA_DRIVER, \ + .base = WHAL_STM32WB09_PKA_BASE, \ + .driver = WHAL_STM32WB09_PKA_DRIVER, \ .cfg = (void *)&(const whal_Stm32wb0_Pka_Cfg){ \ .timeout = &g_whalTimeout, \ }, \ diff --git a/src/flash/stm32wb0_flash.c b/src/flash/stm32wb0_flash.c index 04b2818..8fa0012 100644 --- a/src/flash/stm32wb0_flash.c +++ b/src/flash/stm32wb0_flash.c @@ -31,7 +31,7 @@ const whal_Flash whal_Stm32wb0_Flash_Dev = WHAL_CFG_STM32WB0_FLASH_DEV; /* - * STM32WB0 Flash controller register layout (RM0529 section 9.4). + * STM32WB0 Flash controller register layout (RM0505 section 9.3). * * The controller is command-driven: write an opcode to COMMAND, watch * IRQSTAT for CMDSTART then CMDDONE, then clear those flags by writing @@ -70,13 +70,17 @@ const whal_Flash whal_Stm32wb0_Flash_Dev = WHAL_CFG_STM32WB0_FLASH_DEV; #define FLASH_ADDRESS_REG 0x18 -/* PAGEPROTx: two write-protect segments per register (RM0529 9.4.9) */ +/* PAGEPROTx: two write-protect segments per register (RM0505 9.3.9) */ #define FLASH_PAGEPROT0_REG 0x34 #define FLASH_PAGEPROT1_REG 0x38 #define FLASH_PAGEPROT_SEG0_SIZE_Pos 0 -#define FLASH_PAGEPROT_SEG0_SIZE_Msk (0x7FUL << FLASH_PAGEPROT_SEG0_SIZE_Pos) +#define FLASH_PAGEPROT_SEG0_SIZE_Msk (0xFFUL << FLASH_PAGEPROT_SEG0_SIZE_Pos) #define FLASH_PAGEPROT_SEG0_OFFSET_Pos 8 -#define FLASH_PAGEPROT_SEG0_OFFSET_Msk (0x7FUL << FLASH_PAGEPROT_SEG0_OFFSET_Pos) +#define FLASH_PAGEPROT_SEG0_OFFSET_Msk (0xFFUL << FLASH_PAGEPROT_SEG0_OFFSET_Pos) +#define FLASH_PAGEPROT_SEG1_SIZE_Pos 16 +#define FLASH_PAGEPROT_SEG1_SIZE_Msk (0xFFUL << FLASH_PAGEPROT_SEG1_SIZE_Pos) +#define FLASH_PAGEPROT_SEG1_OFFSET_Pos 24 +#define FLASH_PAGEPROT_SEG1_OFFSET_Msk (0xFFUL << FLASH_PAGEPROT_SEG1_OFFSET_Pos) #define FLASH_DATA0_REG 0x40 #define FLASH_DATA1_REG 0x44 #define FLASH_DATA2_REG 0x48 @@ -188,12 +192,17 @@ whal_Error whal_Stm32wb0_Flash_Lock(whal_Flash *flashDev, size_t addr, (void)addr; (void)len; - /* A segment from page 0 with the largest SIZE ends at the last page */ + /* Pages 0-127 and 128 onward; a segment running past the end is + * clamped to the last page */ whal_Reg_Write(base, FLASH_PAGEPROT0_REG, whal_SetBits(FLASH_PAGEPROT_SEG0_OFFSET_Msk, FLASH_PAGEPROT_SEG0_OFFSET_Pos, 0) | whal_SetBits(FLASH_PAGEPROT_SEG0_SIZE_Msk, - FLASH_PAGEPROT_SEG0_SIZE_Pos, 0x7F)); + FLASH_PAGEPROT_SEG0_SIZE_Pos, 0x80) | + whal_SetBits(FLASH_PAGEPROT_SEG1_OFFSET_Msk, + FLASH_PAGEPROT_SEG1_OFFSET_Pos, 0x80) | + whal_SetBits(FLASH_PAGEPROT_SEG1_SIZE_Msk, + FLASH_PAGEPROT_SEG1_SIZE_Pos, 0x80)); return WHAL_SUCCESS; } diff --git a/src/gpio/stm32wb0_gpio.c b/src/gpio/stm32wb0_gpio.c index bfd71a7..6c4e897 100644 --- a/src/gpio/stm32wb0_gpio.c +++ b/src/gpio/stm32wb0_gpio.c @@ -19,144 +19,9 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#include -#include "wolfHAL_board.h" /* provides WHAL_CFG_STM32WB0_GPIO_DEV initializer */ -#include -#include -#include -#include -#include - -const whal_Gpio whal_Stm32wb0_Gpio_Dev = WHAL_CFG_STM32WB0_GPIO_DEV; - -/* - * STM32WB0 GPIO register layout — per-port block uses standard STM32 - * offsets, but ports are 0x100000 (1 MB) apart rather than the usual - * 0x400. Only ports A (0x48000000) and B (0x48100000) exist. - */ -#define GPIO_PORT_STRIDE 0x100000u - -#define GPIO_MODE_REG 0x00 /* MODER: 2 bits/pin */ -#define GPIO_OUTTYPE_REG 0x04 /* OTYPER: 1 bit/pin */ -#define GPIO_SPEED_REG 0x08 /* OSPEEDR: 2 bits/pin */ -#define GPIO_PULL_REG 0x0C /* PUPDR: 2 bits/pin */ -#define GPIO_IDR_REG 0x10 -#define GPIO_ODR_REG 0x14 -#define GPIO_BSRR_REG 0x18 /* BSRR: 0..15 set, 16..31 reset */ -#define GPIO_BSRR_BR_Pos 16 -#define GPIO_ALTFNL_REG 0x20 /* AFRL: 4 bits/pin for pins 0..7 */ -#define GPIO_ALTFNH_REG 0x24 /* AFRH: 4 bits/pin for pins 8..15 */ - #ifdef WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING -#define whal_Stm32wb0_Gpio_Init whal_Gpio_Init -#define whal_Stm32wb0_Gpio_Deinit whal_Gpio_Deinit -#define whal_Stm32wb0_Gpio_Get whal_Gpio_Get -#define whal_Stm32wb0_Gpio_Set whal_Gpio_Set -#endif /* WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING */ - -static inline whal_Error whal_Stm32wb0_Gpio_InitPin(whal_Stm32wb0_Gpio_PinCfg cfg) -{ - uint8_t pin = WHAL_STM32WB0_GPIO_GET_PIN(cfg); - size_t portBase; - uint8_t pos2; - size_t mask2, mask1; - - if (pin > 15) - return WHAL_EINVAL; - - portBase = whal_Stm32wb0_Gpio_Dev.base + - (WHAL_STM32WB0_GPIO_GET_PORT(cfg) * GPIO_PORT_STRIDE); - pos2 = pin << 1; - mask2 = WHAL_BITMASK(2) << pos2; - mask1 = 1UL << pin; - - whal_Reg_Update(portBase, GPIO_MODE_REG, mask2, - WHAL_STM32WB0_GPIO_GET_MODE(cfg) << pos2); - whal_Reg_Update(portBase, GPIO_SPEED_REG, mask2, - WHAL_STM32WB0_GPIO_GET_SPEED(cfg) << pos2); - whal_Reg_Update(portBase, GPIO_PULL_REG, mask2, - WHAL_STM32WB0_GPIO_GET_PULL(cfg) << pos2); - whal_Reg_Update(portBase, GPIO_OUTTYPE_REG, mask1, - WHAL_STM32WB0_GPIO_GET_OUTTYPE(cfg) << pin); - - if (WHAL_STM32WB0_GPIO_GET_MODE(cfg) == WHAL_STM32WB0_GPIO_MODE_ALTFN) { - uint8_t afPos = (pin & 7) << 2; - - whal_Reg_Update(portBase, - (pin < 8) ? GPIO_ALTFNL_REG : GPIO_ALTFNH_REG, - WHAL_BITMASK(4) << afPos, - WHAL_STM32WB0_GPIO_GET_ALTFN(cfg) << afPos); - } +#define WHAL_CFG_STM32WB_GPIO_DIRECT_API_MAPPING +#endif - return WHAL_SUCCESS; -} - -whal_Error whal_Stm32wb0_Gpio_Init(whal_Gpio *gpioDev) -{ - const whal_Stm32wb0_Gpio_Cfg *cfg = - (const whal_Stm32wb0_Gpio_Cfg *)whal_Stm32wb0_Gpio_Dev.cfg; - const whal_Stm32wb0_Gpio_PinCfg *pinCfg = cfg->pinCfg; - whal_Error err; - (void)gpioDev; - - for (size_t i = 0; i < cfg->pinCount; ++i) { - err = whal_Stm32wb0_Gpio_InitPin(pinCfg[i]); - if (err) - return err; - } - return WHAL_SUCCESS; -} - -whal_Error whal_Stm32wb0_Gpio_Deinit(whal_Gpio *gpioDev) -{ - (void)gpioDev; - return WHAL_SUCCESS; -} - -static whal_Error whal_Stm32wb0_Gpio_SetOrGet(whal_Gpio *gpioDev, size_t idx, - size_t *value, uint8_t set) -{ - const whal_Stm32wb0_Gpio_Cfg *cfg = - (const whal_Stm32wb0_Gpio_Cfg *)whal_Stm32wb0_Gpio_Dev.cfg; - whal_Stm32wb0_Gpio_PinCfg pinCfg; - uint8_t port, pin; - size_t portBase, mask; - (void)gpioDev; - - if (!value || idx >= cfg->pinCount) - return WHAL_EINVAL; - - pinCfg = cfg->pinCfg[idx]; - port = WHAL_STM32WB0_GPIO_GET_PORT(pinCfg); - pin = WHAL_STM32WB0_GPIO_GET_PIN(pinCfg); - - portBase = whal_Stm32wb0_Gpio_Dev.base + (port * GPIO_PORT_STRIDE); - mask = 1UL << pin; - - if (set) { - whal_Reg_Write(portBase, GPIO_BSRR_REG, - *value ? mask : (mask << GPIO_BSRR_BR_Pos)); - } else { - whal_Reg_Get(portBase, GPIO_IDR_REG, mask, pin, value); - } - return WHAL_SUCCESS; -} - -whal_Error whal_Stm32wb0_Gpio_Get(whal_Gpio *gpioDev, size_t pin, size_t *value) -{ - return whal_Stm32wb0_Gpio_SetOrGet(gpioDev, pin, value, 0); -} - -whal_Error whal_Stm32wb0_Gpio_Set(whal_Gpio *gpioDev, size_t pin, size_t value) -{ - return whal_Stm32wb0_Gpio_SetOrGet(gpioDev, pin, &value, 1); -} - -#ifndef WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING -const whal_GpioDriver whal_Stm32wb0_Gpio_Driver = { - .Init = whal_Stm32wb0_Gpio_Init, - .Deinit = whal_Stm32wb0_Gpio_Deinit, - .Get = whal_Stm32wb0_Gpio_Get, - .Set = whal_Stm32wb0_Gpio_Set, -}; -#endif /* !WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING */ +#include +#include "stm32wb_gpio.c" diff --git a/src/gpio/stm32wb_gpio.c b/src/gpio/stm32wb_gpio.c index 9bd105a..c334d29 100644 --- a/src/gpio/stm32wb_gpio.c +++ b/src/gpio/stm32wb_gpio.c @@ -32,13 +32,10 @@ const whal_Gpio whal_Stm32wb_Gpio_Dev = WHAL_CFG_STM32WB_GPIO_DEV; /* * STM32WB GPIO Register Definitions * - * Each GPIO port has a 0x400 byte register block. Register offsets - * are relative to the port base address. + * Register offsets are relative to the port base address. Ports are + * WHAL_STM32WB_GPIO_PORT_SIZE bytes apart. */ -/* Size of each GPIO port register block */ -#define GPIO_PORT_SIZE 0x400 - /* Mode register - 2 bits per pin, selects input/output/altfn/analog */ #define GPIO_MODE_REG 0x00 /* Output type register - 1 bit per pin, push-pull or open-drain */ @@ -80,7 +77,7 @@ static inline whal_Error whal_Stm32wb_Gpio_InitPin(whal_Stm32wb_Gpio_PinCfg cfg) return WHAL_EINVAL; portBase = whal_Stm32wb_Gpio_Dev.base + - (WHAL_STM32WB_GPIO_GET_PORT(cfg) * GPIO_PORT_SIZE); + (WHAL_STM32WB_GPIO_GET_PORT(cfg) * WHAL_STM32WB_GPIO_PORT_SIZE); pos2 = pin << 1; mask2 = WHAL_BITMASK(2) << pos2; mask1 = 1UL << pin; @@ -158,7 +155,7 @@ static whal_Error whal_Stm32wb_Gpio_SetOrGet(whal_Gpio *gpioDev, size_t idx, port = WHAL_STM32WB_GPIO_GET_PORT(pinCfg); pin = WHAL_STM32WB_GPIO_GET_PIN(pinCfg); - portBase = whal_Stm32wb_Gpio_Dev.base + (port * GPIO_PORT_SIZE); + portBase = whal_Stm32wb_Gpio_Dev.base + (port * WHAL_STM32WB_GPIO_PORT_SIZE); mask = 1UL << pin; if (set) { diff --git a/tests/clock/test_stm32wb0_clock.c b/tests/clock/test_stm32wb0_clock.c new file mode 100644 index 0000000..986ea50 --- /dev/null +++ b/tests/clock/test_stm32wb0_clock.c @@ -0,0 +1,99 @@ +/* test_stm32wb0_clock.c + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfHAL. + * + * wolfHAL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfHAL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include +#include +#include "wolfHAL_board.h" +#include "test.h" + +static void Test_Clock_EnableDisable(void) +{ + whal_Stm32wb0_Rcc_PeriphClk testClk = { WHAL_STM32WB09_CRC_CLOCK }; + size_t origVal = 0; + size_t val = 0; + + whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, testClk.regOffset, testClk.enableMask, + testClk.enablePos, &origVal); + + WHAL_ASSERT_EQ(whal_Stm32wb0_Rcc_EnablePeriphClk(&testClk), WHAL_SUCCESS); + whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, testClk.regOffset, testClk.enableMask, + testClk.enablePos, &val); + WHAL_ASSERT_EQ(val, 1); + + WHAL_ASSERT_EQ(whal_Stm32wb0_Rcc_DisablePeriphClk(&testClk), WHAL_SUCCESS); + whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, testClk.regOffset, testClk.enableMask, + testClk.enablePos, &val); + WHAL_ASSERT_EQ(val, 0); + + if (origVal) + whal_Stm32wb0_Rcc_EnablePeriphClk(&testClk); +} + +/* Board_Init leaves SYSCLK at 64 MHz on the PLL-locked RC64MPLL tree. */ +static void Test_Clock_Pll64mActive(void) +{ + size_t val = 0; + + whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, + WHAL_STM32WB0_RCC_CR_HSERDY_Msk, + WHAL_STM32WB0_RCC_CR_HSERDY_Pos, &val); + WHAL_ASSERT_EQ(val, 1); + + whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, + WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Msk, + WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Pos, &val); + WHAL_ASSERT_EQ(val, 1); + + whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Msk, + WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Pos, &val); + WHAL_ASSERT_EQ(val, WHAL_STM32WB0_RCC_SYSCLK_SRC_RC64MPLL); + + whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Msk, + WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Pos, &val); + WHAL_ASSERT_EQ(val, WHAL_STM32WB0_RCC_SYSCLK_64MHZ); +} + +static void Test_Clock_RejectHse64Mhz(void) +{ + WHAL_ASSERT_EQ(whal_Stm32wb0_Rcc_SetSysClock( + WHAL_STM32WB0_RCC_SYSCLK_SRC_HSE, + WHAL_STM32WB0_RCC_SYSCLK_64MHZ, &g_whalTimeout), + WHAL_EINVAL); +} + +static void Test_Clock_PllBadLockDet(void) +{ + WHAL_ASSERT_EQ(whal_Stm32wb0_Rcc_EnablePll( + &(whal_Stm32wb0_Rcc_PllCfg){.lockDetNstop = 8}, + &g_whalTimeout), + WHAL_EINVAL); +} + +void whal_Test_Clock_Platform(void) +{ + WHAL_TEST(Test_Clock_EnableDisable); + WHAL_TEST(Test_Clock_Pll64mActive); + WHAL_TEST(Test_Clock_RejectHse64Mhz); + WHAL_TEST(Test_Clock_PllBadLockDet); +} diff --git a/tests/flash/test_stm32wb0_flash.c b/tests/flash/test_stm32wb0_flash.c index 40020b0..b60aa8e 100644 --- a/tests/flash/test_stm32wb0_flash.c +++ b/tests/flash/test_stm32wb0_flash.c @@ -24,7 +24,7 @@ #include "wolfHAL_board.h" #include "test.h" -/* RM0529 does not say whether a command on a PAGEPROT-protected page raises +/* RM0505 does not say whether a command on a PAGEPROT-protected page raises * CMDERR or is ignored, so the test checks the flash contents rather than the * return code. */ diff --git a/tests/gpio/test_stm32wb0_gpio.c b/tests/gpio/test_stm32wb0_gpio.c index fb850c6..499a13c 100644 --- a/tests/gpio/test_stm32wb0_gpio.c +++ b/tests/gpio/test_stm32wb0_gpio.c @@ -19,91 +19,5 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#include #include -#include -#include "wolfHAL_board.h" -#include "test.h" - -/* STM32WB0 ports are 0x100000 apart; the per-port offsets match other STM32 - * families. */ -#define GPIOx_MODE_REG 0x00 -#define GPIOx_OTYPER_REG 0x04 -#define GPIOx_OSPEEDR_REG 0x08 -#define GPIOx_PUPDR_REG 0x0C -#define GPIOx_ODR_REG 0x14 -#define GPIOx_AFRL_REG 0x20 -#define GPIOx_AFRH_REG 0x24 -#define GPIOx_STRIDE 0x100000 - -static const whal_Stm32wb0_Gpio_Cfg *GpioCfg(void) -{ - return (const whal_Stm32wb0_Gpio_Cfg *)whal_Stm32wb0_Gpio_Dev.cfg; -} - -static size_t PortBase(whal_Stm32wb0_Gpio_PinCfg p) -{ - return whal_Stm32wb0_Gpio_Dev.base + - WHAL_STM32WB0_GPIO_GET_PORT(p) * GPIOx_STRIDE; -} - -/* Every pin in the board table reads back with its configured mode, output - * type, speed, pull and, for alternate-function pins, AF number. */ -static void Test_Gpio_PinTableRegisters(void) -{ - const whal_Stm32wb0_Gpio_Cfg *cfg = GpioCfg(); - - for (size_t i = 0; i < cfg->pinCount; i++) { - whal_Stm32wb0_Gpio_PinCfg p = cfg->pinCfg[i]; - size_t base = PortBase(p); - size_t pin = WHAL_STM32WB0_GPIO_GET_PIN(p); - size_t pos2 = pin << 1; - size_t val = 0; - - whal_Reg_Get(base, GPIOx_MODE_REG, WHAL_BITMASK(2) << pos2, pos2, - &val); - WHAL_ASSERT_EQ(val, WHAL_STM32WB0_GPIO_GET_MODE(p)); - - whal_Reg_Get(base, GPIOx_OTYPER_REG, 1UL << pin, pin, &val); - WHAL_ASSERT_EQ(val, WHAL_STM32WB0_GPIO_GET_OUTTYPE(p)); - - whal_Reg_Get(base, GPIOx_OSPEEDR_REG, WHAL_BITMASK(2) << pos2, pos2, - &val); - WHAL_ASSERT_EQ(val, WHAL_STM32WB0_GPIO_GET_SPEED(p)); - - whal_Reg_Get(base, GPIOx_PUPDR_REG, WHAL_BITMASK(2) << pos2, pos2, - &val); - WHAL_ASSERT_EQ(val, WHAL_STM32WB0_GPIO_GET_PULL(p)); - - if (WHAL_STM32WB0_GPIO_GET_MODE(p) == WHAL_STM32WB0_GPIO_MODE_ALTFN) { - size_t afPos = (pin & 7) << 2; - - whal_Reg_Get(base, (pin < 8) ? GPIOx_AFRL_REG : GPIOx_AFRH_REG, - WHAL_BITMASK(4) << afPos, afPos, &val); - WHAL_ASSERT_EQ(val, WHAL_STM32WB0_GPIO_GET_ALTFN(p)); - } - } -} - -static void Test_Gpio_SetLedReg(void) -{ - whal_Stm32wb0_Gpio_PinCfg led = GpioCfg()->pinCfg[BOARD_LED_PIN]; - size_t pin = WHAL_STM32WB0_GPIO_GET_PIN(led); - size_t val = 0; - - WHAL_ASSERT_EQ(whal_Gpio_Set(BOARD_GPIO_DEV, BOARD_LED_PIN, 1), - WHAL_SUCCESS); - whal_Reg_Get(PortBase(led), GPIOx_ODR_REG, 1UL << pin, pin, &val); - WHAL_ASSERT_EQ(val, 1); - - WHAL_ASSERT_EQ(whal_Gpio_Set(BOARD_GPIO_DEV, BOARD_LED_PIN, 0), - WHAL_SUCCESS); - whal_Reg_Get(PortBase(led), GPIOx_ODR_REG, 1UL << pin, pin, &val); - WHAL_ASSERT_EQ(val, 0); -} - -void whal_Test_Gpio_Platform(void) -{ - WHAL_TEST(Test_Gpio_PinTableRegisters); - WHAL_TEST(Test_Gpio_SetLedReg); -} +#include "test_stm32wb_gpio.c" diff --git a/tests/gpio/test_stm32wb_gpio.c b/tests/gpio/test_stm32wb_gpio.c index aa5c2bc..7bfa39c 100644 --- a/tests/gpio/test_stm32wb_gpio.c +++ b/tests/gpio/test_stm32wb_gpio.c @@ -27,8 +27,8 @@ /* * GPIO register offsets. Port and pin are derived from the LED entry in - * whal_Stm32wb_Gpio_Dev.cfg->pinCfg[BOARD_LED_PIN]. Port stride is 0x400 on all - * supported STM32 families. + * whal_Stm32wb_Gpio_Dev.cfg->pinCfg[BOARD_LED_PIN]. Ports are + * WHAL_STM32WB_GPIO_PORT_SIZE apart. */ #define GPIOx_MODE_REG 0x00 #define GPIOx_OTYPER_REG 0x04 @@ -37,13 +37,12 @@ #define GPIOx_ODR_REG 0x14 #define GPIOx_AFRL_REG 0x20 #define GPIOx_AFRH_REG 0x24 -#define GPIOx_STRIDE 0x400 static inline size_t Board_LedPortBase(void) { const whal_Stm32wb_Gpio_Cfg *cfg = (const whal_Stm32wb_Gpio_Cfg *)whal_Stm32wb_Gpio_Dev.cfg; whal_Stm32wb_Gpio_PinCfg led = cfg->pinCfg[BOARD_LED_PIN]; - return whal_Stm32wb_Gpio_Dev.base + WHAL_STM32WB_GPIO_GET_PORT(led) * GPIOx_STRIDE; + return whal_Stm32wb_Gpio_Dev.base + WHAL_STM32WB_GPIO_GET_PORT(led) * WHAL_STM32WB_GPIO_PORT_SIZE; } static inline size_t Board_LedPinNum(void) @@ -105,7 +104,7 @@ static void Test_Gpio_PinTableRegisters(void) for (size_t i = 0; i < cfg->pinCount; i++) { whal_Stm32wb_Gpio_PinCfg p = cfg->pinCfg[i]; size_t base = whal_Stm32wb_Gpio_Dev.base + - WHAL_STM32WB_GPIO_GET_PORT(p) * GPIOx_STRIDE; + WHAL_STM32WB_GPIO_GET_PORT(p) * WHAL_STM32WB_GPIO_PORT_SIZE; size_t pin = WHAL_STM32WB_GPIO_GET_PIN(p); size_t pos2 = pin << 1; size_t val = 0; diff --git a/wolfHAL/clock/stm32wb0_rcc.h b/wolfHAL/clock/stm32wb0_rcc.h index 8b81153..107928e 100644 --- a/wolfHAL/clock/stm32wb0_rcc.h +++ b/wolfHAL/clock/stm32wb0_rcc.h @@ -27,80 +27,85 @@ #include #include #include +#include /** * @file stm32wb0_rcc.h * @brief STM32WB0 RCC (Reset and Clock Control) driver. * * Boards bring up the clock tree imperatively from Board_Init by calling - * the helpers below. The STM32WB0 has a Bluetooth-LE-oriented RCC that - * differs significantly from the wider STM32 line: - * - Two high-speed sources: HSI64M (internal 64 MHz RC, optionally - * PLL-locked onto HSE — represented by HSIPLLON+HSIPLLRDY) and a - * direct HSE path (32 MHz crystal). - * - System clock frequency is selected through CLKSYSDIV[2:0] in - * RCC_CFGR rather than a PLL output divider. Frequencies of 64 / 32 - * / 16 / 8 / 4 / 2 / 1 MHz are derived from the fast clock tree. - * - HSESEL chooses between the RC64MPLL tree and the direct HSE tree. - * - Peripheral clock gates live in AHBENR (0x50), APB0ENR (0x54), - * APB1ENR (0x58), and APB2ENR (0x60). - * - * The RCC peripheral lives at a fixed address (0x48400000) — clock is a - * board-level driver with no device struct, no generic API, no vtable. + * the helpers below in order. The RCC peripheral lives at a fixed address; + * clock is a board-level driver with no device struct, no generic API and + * no vtable. + * + * The fast clock tree has two sources selected by RCC_CFGR.HSESEL: + * - RC64MPLL: the 64 MHz block that runs either as a free-running RC + * (HSI) or as a PLL locked onto the 32 MHz HSE crystal (PLL64M). + * - HSE: the 32 MHz crystal directly, capping SYSCLK at 32 MHz. + * SYSCLK is the fast clock divided by RCC_CFGR.CLKSYSDIV (64 MHz down to + * 1 MHz). USART, I2C, LPUART, TRNG and the flash controller also run from a + * fixed 16 MHz kernel clock that does not follow CLKSYSDIV. + * + * The slow clock tree (RTC, IWDG, LPUART in Deepstop, radio timer) is fed + * by RCC_CFGR.CLKSLOWSEL from LSE, LSI, or the 16 MHz clock divided by 512. */ -#define WHAL_STM32WB0_RCC_BASE 0x48400000 - -/* Clock source control register */ -#define WHAL_STM32WB0_RCC_CR_REG 0x000 -#define WHAL_STM32WB0_RCC_CR_LSION_Pos 2 -#define WHAL_STM32WB0_RCC_CR_LSION_Msk (1UL << WHAL_STM32WB0_RCC_CR_LSION_Pos) -#define WHAL_STM32WB0_RCC_CR_LSIRDY_Pos 3 -#define WHAL_STM32WB0_RCC_CR_LSIRDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_LSIRDY_Pos) -#define WHAL_STM32WB0_RCC_CR_LSEON_Pos 4 -#define WHAL_STM32WB0_RCC_CR_LSEON_Msk (1UL << WHAL_STM32WB0_RCC_CR_LSEON_Pos) -#define WHAL_STM32WB0_RCC_CR_LSERDY_Pos 5 -#define WHAL_STM32WB0_RCC_CR_LSERDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_LSERDY_Pos) -#define WHAL_STM32WB0_RCC_CR_HSIRDY_Pos 10 -#define WHAL_STM32WB0_RCC_CR_HSIRDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSIRDY_Pos) -#define WHAL_STM32WB0_RCC_CR_HSEPLLBUFON_Pos 12 -#define WHAL_STM32WB0_RCC_CR_HSEPLLBUFON_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSEPLLBUFON_Pos) -#define WHAL_STM32WB0_RCC_CR_HSIPLLON_Pos 13 -#define WHAL_STM32WB0_RCC_CR_HSIPLLON_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSIPLLON_Pos) -#define WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Pos 14 -#define WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Pos) -#define WHAL_STM32WB0_RCC_CR_HSEON_Pos 16 -#define WHAL_STM32WB0_RCC_CR_HSEON_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSEON_Pos) -#define WHAL_STM32WB0_RCC_CR_HSERDY_Pos 17 -#define WHAL_STM32WB0_RCC_CR_HSERDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSERDY_Pos) - -/* Clock configuration register */ -#define WHAL_STM32WB0_RCC_CFGR_REG 0x008 -#define WHAL_STM32WB0_RCC_CFGR_HSESEL_Pos 1 -#define WHAL_STM32WB0_RCC_CFGR_HSESEL_Msk (1UL << WHAL_STM32WB0_RCC_CFGR_HSESEL_Pos) -#define WHAL_STM32WB0_RCC_CFGR_STOPHSI_Pos 2 -#define WHAL_STM32WB0_RCC_CFGR_STOPHSI_Msk (1UL << WHAL_STM32WB0_RCC_CFGR_STOPHSI_Pos) -#define WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Pos 3 -#define WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Msk (1UL << WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Pos) -#define WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Pos 5 -#define WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Msk (WHAL_BITMASK(3) << WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Pos) -#define WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Pos 8 -#define WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Msk (WHAL_BITMASK(3) << WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Pos) - -/* AHB0 macro cells clock enable register */ -#define WHAL_STM32WB0_RCC_AHBENR_REG 0x050 -/* APB0 macro cell clock enable register */ -#define WHAL_STM32WB0_RCC_APB0ENR_REG 0x054 -/* APB1 macro cells clock enable register */ -#define WHAL_STM32WB0_RCC_APB1ENR_REG 0x058 -/* APB2 macro cells clock enable register */ -#define WHAL_STM32WB0_RCC_APB2ENR_REG 0x060 +#define WHAL_STM32WB0_RCC_BASE 0x48400000 + +#define WHAL_STM32WB0_RCC_CR_REG 0x000 +#define WHAL_STM32WB0_RCC_CR_LSION_Pos 2 +#define WHAL_STM32WB0_RCC_CR_LSION_Msk (1UL << WHAL_STM32WB0_RCC_CR_LSION_Pos) +#define WHAL_STM32WB0_RCC_CR_LSIRDY_Pos 3 +#define WHAL_STM32WB0_RCC_CR_LSIRDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_LSIRDY_Pos) +#define WHAL_STM32WB0_RCC_CR_LSEON_Pos 4 +#define WHAL_STM32WB0_RCC_CR_LSEON_Msk (1UL << WHAL_STM32WB0_RCC_CR_LSEON_Pos) +#define WHAL_STM32WB0_RCC_CR_LSERDY_Pos 5 +#define WHAL_STM32WB0_RCC_CR_LSERDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_LSERDY_Pos) +#define WHAL_STM32WB0_RCC_CR_LSEBYP_Pos 6 +#define WHAL_STM32WB0_RCC_CR_LSEBYP_Msk (1UL << WHAL_STM32WB0_RCC_CR_LSEBYP_Pos) +#define WHAL_STM32WB0_RCC_CR_LOCKDET_NSTOP_Pos 7 +#define WHAL_STM32WB0_RCC_CR_LOCKDET_NSTOP_Msk (WHAL_BITMASK(3) << WHAL_STM32WB0_RCC_CR_LOCKDET_NSTOP_Pos) +#define WHAL_STM32WB0_RCC_CR_HSIRDY_Pos 10 +#define WHAL_STM32WB0_RCC_CR_HSIRDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSIRDY_Pos) +#define WHAL_STM32WB0_RCC_CR_HSEPLLBUFON_Pos 12 +#define WHAL_STM32WB0_RCC_CR_HSEPLLBUFON_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSEPLLBUFON_Pos) +#define WHAL_STM32WB0_RCC_CR_HSIPLLON_Pos 13 +#define WHAL_STM32WB0_RCC_CR_HSIPLLON_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSIPLLON_Pos) +#define WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Pos 14 +#define WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Pos) +#define WHAL_STM32WB0_RCC_CR_HSEON_Pos 16 +#define WHAL_STM32WB0_RCC_CR_HSEON_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSEON_Pos) +#define WHAL_STM32WB0_RCC_CR_HSERDY_Pos 17 +#define WHAL_STM32WB0_RCC_CR_HSERDY_Msk (1UL << WHAL_STM32WB0_RCC_CR_HSERDY_Pos) + +#define WHAL_STM32WB0_RCC_CFGR_REG 0x008 +#define WHAL_STM32WB0_RCC_CFGR_HSESEL_Pos 1 +#define WHAL_STM32WB0_RCC_CFGR_HSESEL_Msk (1UL << WHAL_STM32WB0_RCC_CFGR_HSESEL_Pos) +#define WHAL_STM32WB0_RCC_CFGR_STOPHSI_Pos 2 +#define WHAL_STM32WB0_RCC_CFGR_STOPHSI_Msk (1UL << WHAL_STM32WB0_RCC_CFGR_STOPHSI_Pos) +#define WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Pos 3 +#define WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Msk (1UL << WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Pos) +#define WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Pos 5 +#define WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Msk (WHAL_BITMASK(3) << WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Pos) +#define WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Pos 8 +#define WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Msk (WHAL_BITMASK(3) << WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Pos) +#define WHAL_STM32WB0_RCC_CFGR_LPUCLKSEL_Pos 13 +#define WHAL_STM32WB0_RCC_CFGR_LPUCLKSEL_Msk (1UL << WHAL_STM32WB0_RCC_CFGR_LPUCLKSEL_Pos) +#define WHAL_STM32WB0_RCC_CFGR_CLKSLOWSEL_Pos 15 +#define WHAL_STM32WB0_RCC_CFGR_CLKSLOWSEL_Msk (WHAL_BITMASK(2) << WHAL_STM32WB0_RCC_CFGR_CLKSLOWSEL_Pos) + +/** + * @brief Fast clock tree source (RCC_CFGR.HSESEL). + */ +typedef enum { + WHAL_STM32WB0_RCC_SYSCLK_SRC_RC64MPLL = 0, /* HSI, or PLL64M once locked */ + WHAL_STM32WB0_RCC_SYSCLK_SRC_HSE = 1, /* 32 MHz crystal, max 32 MHz */ +} whal_Stm32wb0_Rcc_SysClockSrc; /** * @brief System clock frequency selection (RCC_CFGR.CLKSYSDIV). * - * The fast clock tree (HSI64M or HSE) is divided by 2^N to produce the - * system clock. 64 MHz is only available when HSESEL=0 (HSI64M tree). + * 64 MHz is only reachable from the RC64MPLL source. */ typedef enum { WHAL_STM32WB0_RCC_SYSCLK_64MHZ = 0, @@ -110,15 +115,25 @@ typedef enum { WHAL_STM32WB0_RCC_SYSCLK_4MHZ = 4, WHAL_STM32WB0_RCC_SYSCLK_2MHZ = 5, WHAL_STM32WB0_RCC_SYSCLK_1MHZ = 6, -} whal_Stm32wb0_Rcc_SysClkDiv; +} whal_Stm32wb0_Rcc_SysClockDiv; + +/** + * @brief Slow clock tree source (RCC_CFGR.CLKSLOWSEL). + */ +typedef enum { + WHAL_STM32WB0_RCC_SLOWCLK_SRC_NONE = 0, + WHAL_STM32WB0_RCC_SLOWCLK_SRC_LSE = 1, + WHAL_STM32WB0_RCC_SLOWCLK_SRC_LSI = 2, + WHAL_STM32WB0_RCC_SLOWCLK_SRC_16MHZ_DIV512 = 3, +} whal_Stm32wb0_Rcc_SlowClockSrc; /** - * @brief Fast clock source selection (RCC_CFGR.HSESEL). + * @brief LPUART kernel clock source (RCC_CFGR.LPUCLKSEL). */ typedef enum { - WHAL_STM32WB0_RCC_FASTCLK_RC64MPLL = 0, /* HSI64M (RC) or PLL-locked onto HSE */ - WHAL_STM32WB0_RCC_FASTCLK_HSE = 1, /* Direct HSE (max 32 MHz sysclk) */ -} whal_Stm32wb0_Rcc_FastClkSrc; + WHAL_STM32WB0_RCC_LPUARTCLK_SRC_16MHZ = 0, + WHAL_STM32WB0_RCC_LPUARTCLK_SRC_LSE = 1, +} whal_Stm32wb0_Rcc_LpuartClockSrc; /** * @brief Peripheral clock descriptor (RCC *ENR enable bit). @@ -130,151 +145,271 @@ typedef struct { } whal_Stm32wb0_Rcc_PeriphClk; /** - * @brief Enable the internal HSI64M oscillator (always on at reset on - * WB0; this just polls the ready bit defensively). + * @brief Cfg for EnableOsc/DisableOsc: on bit + ready bit. + */ +typedef struct { + size_t onReg; + size_t onMsk; + size_t rdyReg; + size_t rdyMsk; + size_t rdyPos; +} whal_Stm32wb0_Rcc_OscCfg; + +#define WHAL_STM32WB0_RCC_HSE_CFG \ + .onReg = 0x000, .onMsk = (1UL << 16), \ + .rdyReg = 0x000, .rdyMsk = (1UL << 17), .rdyPos = 17 +#define WHAL_STM32WB0_RCC_LSI_CFG \ + .onReg = 0x000, .onMsk = (1UL << 2), \ + .rdyReg = 0x000, .rdyMsk = (1UL << 3), .rdyPos = 3 +#define WHAL_STM32WB0_RCC_LSE_CFG \ + .onReg = 0x000, .onMsk = (1UL << 4), \ + .rdyReg = 0x000, .rdyMsk = (1UL << 5), .rdyPos = 5 +/* External 32 kHz clock injected on OSC32_IN; mutually exclusive with LSE. */ +#define WHAL_STM32WB0_RCC_LSE_BYPASS_CFG \ + .onReg = 0x000, .onMsk = (1UL << 6), \ + .rdyReg = 0x000, .rdyMsk = (1UL << 5), .rdyPos = 5 + +/** + * @brief RC64MPLL lock configuration. * - * @retval WHAL_SUCCESS Always. + * The PLL has a fixed 32 MHz HSE reference and a fixed 64 MHz output; the + * only tunable is the lock detector window, (lockDetNstop + 1) * 64 cycles, + * that the analog lock signal must stay stable for before HSIPLLRDY sets. */ -static inline whal_Error whal_Stm32wb0_Rcc_EnableHsi(void) -{ - size_t rdy; +typedef struct { + uint8_t lockDetNstop; /* 0..7 */ +} whal_Stm32wb0_Rcc_PllCfg; - do { - whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, - WHAL_STM32WB0_RCC_CR_HSIRDY_Msk, - WHAL_STM32WB0_RCC_CR_HSIRDY_Pos, &rdy); - } while (!rdy); - return WHAL_SUCCESS; +/** + * @brief Turn on an oscillator and wait for its ready bit. + * + * @param cfg Oscillator on/ready bit descriptor (e.g. WHAL_STM32WB0_RCC_HSE_CFG). + * @param timeout Timeout instance (NULL for unbounded wait). + * + * @retval WHAL_SUCCESS Oscillator is ready. + * @retval WHAL_ETIMEOUT Ready bit did not set within the timeout. + */ +static inline whal_Error whal_Stm32wb0_Rcc_EnableOsc( + const whal_Stm32wb0_Rcc_OscCfg *cfg, whal_Timeout *timeout) +{ + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, cfg->onReg, cfg->onMsk, cfg->onMsk); + return whal_Reg_ReadPoll(WHAL_STM32WB0_RCC_BASE, cfg->rdyReg, cfg->rdyMsk, + cfg->rdyMsk, timeout); } /** - * @brief Enable the LSI oscillator and wait for it to be ready. + * @brief Turn off an oscillator. + * + * @param cfg Oscillator on/ready bit descriptor. * * @retval WHAL_SUCCESS Always. */ -static inline whal_Error whal_Stm32wb0_Rcc_EnableLsi(void) +static inline whal_Error whal_Stm32wb0_Rcc_DisableOsc( + const whal_Stm32wb0_Rcc_OscCfg *cfg) { - size_t rdy; - - whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, - WHAL_STM32WB0_RCC_CR_LSION_Msk, - WHAL_STM32WB0_RCC_CR_LSION_Msk); - do { - whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, - WHAL_STM32WB0_RCC_CR_LSIRDY_Msk, - WHAL_STM32WB0_RCC_CR_LSIRDY_Pos, &rdy); - } while (!rdy); + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, cfg->onReg, cfg->onMsk, 0); return WHAL_SUCCESS; } /** - * @brief Disable the LSI oscillator. + * @brief Release the RC64MPLL stop request and wait for the 64 MHz RC. * - * @retval WHAL_SUCCESS Always. + * The RC64MPLL block runs out of reset; this clears RCC_CFGR.STOPHSI and + * polls RCC_CR.HSIRDY. + * + * @param timeout Timeout instance (NULL for unbounded wait). + * + * @retval WHAL_SUCCESS HSI is ready. + * @retval WHAL_ETIMEOUT HSIRDY did not set within the timeout. */ -static inline whal_Error whal_Stm32wb0_Rcc_DisableLsi(void) +static inline whal_Error whal_Stm32wb0_Rcc_EnableHsi(whal_Timeout *timeout) { - whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, - WHAL_STM32WB0_RCC_CR_LSION_Msk, 0); - return WHAL_SUCCESS; + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_STOPHSI_Msk, 0); + return whal_Reg_ReadPoll(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, + WHAL_STM32WB0_RCC_CR_HSIRDY_Msk, + WHAL_STM32WB0_RCC_CR_HSIRDY_Msk, timeout); } /** - * @brief Enable the external HSE oscillator (32 MHz XO) and wait for it - * to be ready. + * @brief Request the RC64MPLL block to stop (RCC_CFGR.STOPHSI). + * + * Only takes effect while the fast clock tree runs from HSE. Hardware + * restarts the block if SYSCLK is set to 64 MHz or HSE is lost. * * @retval WHAL_SUCCESS Always. */ -static inline whal_Error whal_Stm32wb0_Rcc_EnableHse(void) +static inline whal_Error whal_Stm32wb0_Rcc_DisableHsi(void) { - size_t rdy; - - whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, - WHAL_STM32WB0_RCC_CR_HSEON_Msk, - WHAL_STM32WB0_RCC_CR_HSEON_Msk); - do { - whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, - WHAL_STM32WB0_RCC_CR_HSERDY_Msk, - WHAL_STM32WB0_RCC_CR_HSERDY_Pos, &rdy); - } while (!rdy); + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_STOPHSI_Msk, + WHAL_STM32WB0_RCC_CFGR_STOPHSI_Msk); return WHAL_SUCCESS; } /** - * @brief Enable the RC64MPLL block that locks the internal 64 MHz RC onto - * the HSE reference. HSE must be enabled first. + * @brief Lock the RC64MPLL onto HSE and wait for PLL64M. * - * @retval WHAL_SUCCESS Always. + * Programs LOCKDET_NSTOP, sets HSIPLLON and polls HSIPLLRDY. Once locked + * the RC64MPLL source of the fast clock tree is the accurate PLL64M. HSE + * must already be running. + * + * @param cfg PLL configuration. + * @param timeout Timeout instance (NULL for unbounded wait). + * + * @retval WHAL_SUCCESS PLL is locked. + * @retval WHAL_EINVAL lockDetNstop is out of range. + * @retval WHAL_ENOTREADY HSE is not running. + * @retval WHAL_ETIMEOUT HSIPLLRDY did not set within the timeout. */ -static inline whal_Error whal_Stm32wb0_Rcc_EnableHsiPll(void) +static inline whal_Error whal_Stm32wb0_Rcc_EnablePll( + const whal_Stm32wb0_Rcc_PllCfg *cfg, whal_Timeout *timeout) { - size_t rdy; + if (cfg->lockDetNstop > 7) + return WHAL_EINVAL; + + if (!(whal_Reg_Read(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG) & + WHAL_STM32WB0_RCC_CR_HSERDY_Msk)) + return WHAL_ENOTREADY; + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, + WHAL_STM32WB0_RCC_CR_LOCKDET_NSTOP_Msk, + whal_SetBits(WHAL_STM32WB0_RCC_CR_LOCKDET_NSTOP_Msk, + WHAL_STM32WB0_RCC_CR_LOCKDET_NSTOP_Pos, + cfg->lockDetNstop)); whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, WHAL_STM32WB0_RCC_CR_HSIPLLON_Msk, WHAL_STM32WB0_RCC_CR_HSIPLLON_Msk); - do { - whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, - WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Msk, - WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Pos, &rdy); - } while (!rdy); - return WHAL_SUCCESS; + return whal_Reg_ReadPoll(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, + WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Msk, + WHAL_STM32WB0_RCC_CR_HSIPLLRDY_Msk, timeout); } /** - * @brief Select the fast clock tree source (RC64MPLL vs direct HSE). + * @brief Release the PLL lock (clears RCC_CR.HSIPLLON). * - * Writes RCC_CFGR.HSESEL and polls HSESEL_STATUS until the switch - * completes. Use WHAL_STM32WB0_RCC_FASTCLK_HSE when running directly off - * the 32 MHz crystal without the PLL; WHAL_STM32WB0_RCC_FASTCLK_RC64MPLL - * for the internal 64 MHz tree (with or without PLL lock). - * - * @param src Fast clock source selection. + * The RC64MPLL source falls back to the free-running HSI. * * @retval WHAL_SUCCESS Always. */ -static inline whal_Error whal_Stm32wb0_Rcc_SetFastClkSrc( - whal_Stm32wb0_Rcc_FastClkSrc src) +static inline whal_Error whal_Stm32wb0_Rcc_DisablePll(void) { - size_t status; - - whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, - WHAL_STM32WB0_RCC_CFGR_HSESEL_Msk, - whal_SetBits(WHAL_STM32WB0_RCC_CFGR_HSESEL_Msk, - WHAL_STM32WB0_RCC_CFGR_HSESEL_Pos, src)); - do { - whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, - WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Msk, - WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Pos, &status); - } while (status != (size_t)src); + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, + WHAL_STM32WB0_RCC_CR_HSIPLLON_Msk, 0); return WHAL_SUCCESS; } /** - * @brief Set the system clock divider (CLKSYSDIV) and wait for the - * frequency switch to apply. + * @brief Select the fast clock source and SYSCLK frequency. * - * The hardware reports the active frequency in CLKSYSDIV_STATUS and may - * take up to ~128 system clock cycles to settle. + * Switching to HSE lowers CLKSYSDIV before setting HSESEL; switching to + * RC64MPLL sets HSESEL first and then applies CLKSYSDIV, so SYSCLK never + * requests 64 MHz from the HSE path. Each step polls its status field. * - * @param div System clock divider selection. + * Uses the direct RCC_CFGR path, which is not safe while MR_BLE is clocked. * - * @retval WHAL_SUCCESS Always. + * @param src Fast clock tree source. + * @param div SYSCLK frequency selection. + * @param timeout Timeout instance (NULL for unbounded wait). + * + * @retval WHAL_SUCCESS Clock switched. + * @retval WHAL_EINVAL 64 MHz requested from HSE, or invalid div. + * @retval WHAL_ETIMEOUT A status field did not update within the timeout. */ static inline whal_Error whal_Stm32wb0_Rcc_SetSysClock( - whal_Stm32wb0_Rcc_SysClkDiv div) + whal_Stm32wb0_Rcc_SysClockSrc src, whal_Stm32wb0_Rcc_SysClockDiv div, + whal_Timeout *timeout) { - size_t status; + whal_Error err; + size_t hseSel = (src == WHAL_STM32WB0_RCC_SYSCLK_SRC_HSE); + + if (div > WHAL_STM32WB0_RCC_SYSCLK_1MHZ) + return WHAL_EINVAL; + if (hseSel && div == WHAL_STM32WB0_RCC_SYSCLK_64MHZ) + return WHAL_EINVAL; + + if (hseSel) { + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Msk, + whal_SetBits(WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Msk, + WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Pos, div)); + err = whal_Reg_ReadPoll(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Msk, + whal_SetBits(WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Msk, + WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Pos, + div), + timeout); + if (err) + return err; + } + + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_HSESEL_Msk, + whal_SetBits(WHAL_STM32WB0_RCC_CFGR_HSESEL_Msk, + WHAL_STM32WB0_RCC_CFGR_HSESEL_Pos, hseSel)); + err = whal_Reg_ReadPoll(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Msk, + whal_SetBits(WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Msk, + WHAL_STM32WB0_RCC_CFGR_HSESEL_STATUS_Pos, + hseSel), + timeout); + if (err || hseSel) + return err; whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Msk, whal_SetBits(WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Msk, WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_Pos, div)); - do { - whal_Reg_Get(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, - WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Msk, - WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Pos, &status); - } while (status != (size_t)div); + return whal_Reg_ReadPoll(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Msk, + whal_SetBits(WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Msk, + WHAL_STM32WB0_RCC_CFGR_CLKSYSDIV_STATUS_Pos, + div), + timeout); +} + +/** + * @brief Select the slow clock tree source (RCC_CFGR.CLKSLOWSEL). + * + * The selected oscillator must already be running. The hardware has no + * glitch-free switch on this mux. + * + * @param src Slow clock source. + * + * @retval WHAL_SUCCESS Source selected. + * @retval WHAL_EINVAL Invalid source. + */ +static inline whal_Error whal_Stm32wb0_Rcc_SetSlowClock( + whal_Stm32wb0_Rcc_SlowClockSrc src) +{ + if (src > WHAL_STM32WB0_RCC_SLOWCLK_SRC_16MHZ_DIV512) + return WHAL_EINVAL; + + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_CLKSLOWSEL_Msk, + whal_SetBits(WHAL_STM32WB0_RCC_CFGR_CLKSLOWSEL_Msk, + WHAL_STM32WB0_RCC_CFGR_CLKSLOWSEL_Pos, src)); + return WHAL_SUCCESS; +} + +/** + * @brief Select the LPUART kernel clock (RCC_CFGR.LPUCLKSEL). + * + * @param src LPUART clock source. + * + * @retval WHAL_SUCCESS Source selected. + * @retval WHAL_EINVAL Invalid source. + */ +static inline whal_Error whal_Stm32wb0_Rcc_SetLpuartClock( + whal_Stm32wb0_Rcc_LpuartClockSrc src) +{ + if (src > WHAL_STM32WB0_RCC_LPUARTCLK_SRC_LSE) + return WHAL_EINVAL; + + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CFGR_REG, + WHAL_STM32WB0_RCC_CFGR_LPUCLKSEL_Msk, + whal_SetBits(WHAL_STM32WB0_RCC_CFGR_LPUCLKSEL_Msk, + WHAL_STM32WB0_RCC_CFGR_LPUCLKSEL_Pos, src)); return WHAL_SUCCESS; } diff --git a/wolfHAL/flash/stm32wb0_flash.h b/wolfHAL/flash/stm32wb0_flash.h index b634cbc..94a19ae 100644 --- a/wolfHAL/flash/stm32wb0_flash.h +++ b/wolfHAL/flash/stm32wb0_flash.h @@ -34,15 +34,15 @@ * - Operations are launched by writing a single-byte opcode to * COMMAND (ERASE=0x11, MASSERASE=0x22, WRITE=0x33, BURSTWRITE=0xCC, * KEYWRITE=0xFF). There is no KEYR unlock sequence. - * - The 14-bit ADDRESS register encodes XADR[9:0]+YADR[5:0] (page + - * row + word) — not a byte address. Page = ADDRESS[15:9], word = + * - The 17-bit ADDRESS register encodes XADDR[10:0]+YADDR[5:0] (page + + * row + word), not a byte address. Page = ADDRESS[16:9], word = * ADDRESS[5:0] (1 word = 4 bytes). * - DATA0-3 carry up to 4 words for BURSTWRITE; single WRITE only * uses DATA0. * - Operation status is tracked through IRQSTAT (CMDSTART / CMDDONE * write-1-to-clear flags). Errors land in CMDERR / ILLCMD. - * - Main flash spans 0x10040000 onward in 2 KB pages (96 pages on - * WB05KZ). + * - Main flash spans 0x10040000 onward in 2 KB pages (256 pages on + * WB09KE). * - One specific address can be programmed at most twice between * erases — the controller enforces this by only allowing 1->0 * transitions. @@ -60,7 +60,7 @@ typedef struct whal_Stm32wb0_Flash_Cfg { /** * @brief Flash access latency selection (CONFIG.WAIT_STATES). * - * 0 WS for system clock <= 32 MHz; 1 WS for 64 MHz (RM0529 9.4.2). + * 0 WS for system clock <= 32 MHz; 1 WS for 64 MHz (RM0505 9.3.2). */ typedef enum whal_Stm32wb0_Flash_Latency { WHAL_STM32WB0_FLASH_LATENCY_0, @@ -101,7 +101,7 @@ whal_Error whal_Stm32wb0_Flash_Init(whal_Flash *flashDev); whal_Error whal_Stm32wb0_Flash_Deinit(whal_Flash *flashDev); /** - * @brief Write-protect the whole flash with a PAGEPROT segment. + * @brief Write-protect the whole flash with two PAGEPROT segments. * * Ignores @p addr and @p len. * diff --git a/wolfHAL/gpio/stm32wb0_gpio.h b/wolfHAL/gpio/stm32wb0_gpio.h index 95c1746..74b9098 100644 --- a/wolfHAL/gpio/stm32wb0_gpio.h +++ b/wolfHAL/gpio/stm32wb0_gpio.h @@ -22,111 +22,80 @@ #ifndef WHAL_STM32WB0_GPIO_H #define WHAL_STM32WB0_GPIO_H -#include -#include -#include - /** * @file stm32wb0_gpio.h - * @brief STM32WB0 GPIO driver. - * - * The STM32WB0 GPIO peripheral has the same per-port register layout as - * the rest of the STM32 family (MODER/OTYPER/OSPEEDR/PUPDR/IDR/ODR/ - * BSRR/AFRL/AFRH at offsets 0x00..0x24, 2-bit-per-pin encoding) but a - * very different inter-port address spacing: GPIOA at 0x48000000, - * GPIOB at 0x48100000 (1 MB apart, not the usual 0x400). Only ports - * A and B exist. + * @brief STM32WB0 GPIO driver (alias for STM32WB GPIO). * - * Because the wider STM32WB GPIO driver indexes ports off - * base + (port * 0x400), it cannot be aliased for WB0. This is a - * dedicated driver that uses the same pin packing and field encodings - * but the WB0-specific port spacing. - */ - -/** - * @brief Packed per-pin GPIO configuration (uint32_t). + * The STM32WB0 GPIO port registers (MODER/OTYPER/OSPEEDR/PUPDR/IDR/ODR/ + * BSRR/AFRL/AFRH) are register-compatible with the STM32WB GPIO. Ports A + * (0x48000000) and B (0x48100000) are 1 MB apart instead of 0x400, which + * the STM32WB driver picks up through WHAL_STM32WB_GPIO_PORT_SIZE. * - * Bit layout matches the wider STM32 driver to keep the pinCfg helpers - * uniform across platforms: - * [3:0] port — 0 (port A) or 1 (port B) - * [7:4] pin — Pin number 0..15 - * [9:8] mode — Pin mode (00 in, 01 out, 10 altfn, 11 analog) - * [10] outType — Output type (0 push-pull, 1 open-drain) - * [12:11] speed — Output speed - * [14:13] pull — Pull resistor - * [18:15] altFn — Alternate function 0..7 on WB0 + * While PWRC_CR1.APC is set (reset default), pull-ups and pull-downs come + * from PWRC_PUCRx/PDCRx and the GPIOx_PUPDR value written by this driver + * has no effect on the pins. */ -typedef uint32_t whal_Stm32wb0_Gpio_PinCfg; -#define WHAL_STM32WB0_GPIO_PORT_Pos 0 -#define WHAL_STM32WB0_GPIO_PIN_Pos 4 -#define WHAL_STM32WB0_GPIO_MODE_Pos 8 -#define WHAL_STM32WB0_GPIO_OUTTYPE_Pos 10 -#define WHAL_STM32WB0_GPIO_SPEED_Pos 11 -#define WHAL_STM32WB0_GPIO_PULL_Pos 13 -#define WHAL_STM32WB0_GPIO_ALTFN_Pos 15 +#define WHAL_STM32WB_GPIO_PORT_SIZE 0x100000 -#define WHAL_STM32WB0_GPIO_PORT_A 0 -#define WHAL_STM32WB0_GPIO_PORT_B 1 +#include -#define WHAL_STM32WB0_GPIO_MODE_IN 0 -#define WHAL_STM32WB0_GPIO_MODE_OUT 1 -#define WHAL_STM32WB0_GPIO_MODE_ALTFN 2 -#define WHAL_STM32WB0_GPIO_MODE_ANALOG 3 +typedef whal_Stm32wb_Gpio_Cfg whal_Stm32wb0_Gpio_Cfg; +typedef whal_Stm32wb_Gpio_PinCfg whal_Stm32wb0_Gpio_PinCfg; -#define WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL 0 -#define WHAL_STM32WB0_GPIO_OUTTYPE_OPENDRAIN 1 +#define whal_Stm32wb0_Gpio_Dev whal_Stm32wb_Gpio_Dev -#define WHAL_STM32WB0_GPIO_SPEED_LOW 0 -#define WHAL_STM32WB0_GPIO_SPEED_MEDIUM 1 -#define WHAL_STM32WB0_GPIO_SPEED_FAST 2 -#define WHAL_STM32WB0_GPIO_SPEED_HIGH 3 +#ifndef WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING +#define whal_Stm32wb0_Gpio_Driver whal_Stm32wb_Gpio_Driver +#define whal_Stm32wb0_Gpio_Init whal_Stm32wb_Gpio_Init +#define whal_Stm32wb0_Gpio_Deinit whal_Stm32wb_Gpio_Deinit +#define whal_Stm32wb0_Gpio_Get whal_Stm32wb_Gpio_Get +#define whal_Stm32wb0_Gpio_Set whal_Stm32wb_Gpio_Set +#endif /* !WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING */ -#define WHAL_STM32WB0_GPIO_PULL_NONE 0 -#define WHAL_STM32WB0_GPIO_PULL_UP 1 -#define WHAL_STM32WB0_GPIO_PULL_DOWN 2 +/** + * @brief GPIO mode selection (re-exported from STM32WB). + */ +#define WHAL_STM32WB0_GPIO_MODE_IN WHAL_STM32WB_GPIO_MODE_IN +#define WHAL_STM32WB0_GPIO_MODE_OUT WHAL_STM32WB_GPIO_MODE_OUT +#define WHAL_STM32WB0_GPIO_MODE_ALTFN WHAL_STM32WB_GPIO_MODE_ALTFN +#define WHAL_STM32WB0_GPIO_MODE_ANALOG WHAL_STM32WB_GPIO_MODE_ANALOG /** - * @brief Pack a pin configuration into a uint32_t. + * @brief GPIO output type (re-exported from STM32WB). */ -#define WHAL_STM32WB0_GPIO_PIN(port, pin, mode, outType, speed, pull, altFn) \ - ((((uint32_t)(port) & 0xFu) << WHAL_STM32WB0_GPIO_PORT_Pos) | \ - (((uint32_t)(pin) & 0xFu) << WHAL_STM32WB0_GPIO_PIN_Pos) | \ - (((uint32_t)(mode) & 0x3u) << WHAL_STM32WB0_GPIO_MODE_Pos) | \ - (((uint32_t)(outType) & 0x1u) << WHAL_STM32WB0_GPIO_OUTTYPE_Pos) | \ - (((uint32_t)(speed) & 0x3u) << WHAL_STM32WB0_GPIO_SPEED_Pos) | \ - (((uint32_t)(pull) & 0x3u) << WHAL_STM32WB0_GPIO_PULL_Pos) | \ - (((uint32_t)(altFn) & 0xFu) << WHAL_STM32WB0_GPIO_ALTFN_Pos)) +#define WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL WHAL_STM32WB_GPIO_OUTTYPE_PUSHPULL +#define WHAL_STM32WB0_GPIO_OUTTYPE_OPENDRAIN WHAL_STM32WB_GPIO_OUTTYPE_OPENDRAIN -#define WHAL_STM32WB0_GPIO_GET_PORT(cfg) (((cfg) >> WHAL_STM32WB0_GPIO_PORT_Pos) & 0xF) -#define WHAL_STM32WB0_GPIO_GET_PIN(cfg) (((cfg) >> WHAL_STM32WB0_GPIO_PIN_Pos) & 0xF) -#define WHAL_STM32WB0_GPIO_GET_MODE(cfg) (((cfg) >> WHAL_STM32WB0_GPIO_MODE_Pos) & 0x3) -#define WHAL_STM32WB0_GPIO_GET_OUTTYPE(cfg) (((cfg) >> WHAL_STM32WB0_GPIO_OUTTYPE_Pos) & 0x1) -#define WHAL_STM32WB0_GPIO_GET_SPEED(cfg) (((cfg) >> WHAL_STM32WB0_GPIO_SPEED_Pos) & 0x3) -#define WHAL_STM32WB0_GPIO_GET_PULL(cfg) (((cfg) >> WHAL_STM32WB0_GPIO_PULL_Pos) & 0x3) -#define WHAL_STM32WB0_GPIO_GET_ALTFN(cfg) (((cfg) >> WHAL_STM32WB0_GPIO_ALTFN_Pos) & 0xF) +/** + * @brief GPIO speed selection (re-exported from STM32WB). + */ +#define WHAL_STM32WB0_GPIO_SPEED_LOW WHAL_STM32WB_GPIO_SPEED_LOW +#define WHAL_STM32WB0_GPIO_SPEED_MEDIUM WHAL_STM32WB_GPIO_SPEED_MEDIUM +#define WHAL_STM32WB0_GPIO_SPEED_FAST WHAL_STM32WB_GPIO_SPEED_FAST +#define WHAL_STM32WB0_GPIO_SPEED_HIGH WHAL_STM32WB_GPIO_SPEED_HIGH /** - * @brief GPIO device configuration. + * @brief GPIO pull-up/pull-down selection (re-exported from STM32WB). */ -typedef struct { - const whal_Stm32wb0_Gpio_PinCfg *pinCfg; - size_t pinCount; -} whal_Stm32wb0_Gpio_Cfg; +#define WHAL_STM32WB0_GPIO_PULL_NONE WHAL_STM32WB_GPIO_PULL_NONE +#define WHAL_STM32WB0_GPIO_PULL_UP WHAL_STM32WB_GPIO_PULL_UP +#define WHAL_STM32WB0_GPIO_PULL_DOWN WHAL_STM32WB_GPIO_PULL_DOWN /** - * @brief Platform-owned GPIO device singleton. Defined in the driver TU - * from the WHAL_CFG_STM32WB0_GPIO_DEV initializer in wolfHAL_board.h. + * @brief GPIO port selection (re-exported from STM32WB). */ -extern const whal_Gpio whal_Stm32wb0_Gpio_Dev; +#define WHAL_STM32WB0_GPIO_PORT_A WHAL_STM32WB_GPIO_PORT_A +#define WHAL_STM32WB0_GPIO_PORT_B WHAL_STM32WB_GPIO_PORT_B -#ifndef WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING -extern const whal_GpioDriver whal_Stm32wb0_Gpio_Driver; +/** + * @brief Pack a GPIO pin configuration into a single word (re-exported from + * STM32WB). + */ +#define WHAL_STM32WB0_GPIO_PIN WHAL_STM32WB_GPIO_PIN -whal_Error whal_Stm32wb0_Gpio_Init(whal_Gpio *gpioDev); -whal_Error whal_Stm32wb0_Gpio_Deinit(whal_Gpio *gpioDev); -whal_Error whal_Stm32wb0_Gpio_Get(whal_Gpio *gpioDev, size_t pin, size_t *value); -whal_Error whal_Stm32wb0_Gpio_Set(whal_Gpio *gpioDev, size_t pin, size_t value); -#endif /* !WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING */ +/* Config initializer macro alias. The WB0 wolfHAL_board.h supplies the body + * under the WB0-prefixed name; the WB driver source consumes the WB name. */ +#define WHAL_CFG_STM32WB_GPIO_DEV WHAL_CFG_STM32WB0_GPIO_DEV #endif /* WHAL_STM32WB0_GPIO_H */ diff --git a/wolfHAL/gpio/stm32wb_gpio.h b/wolfHAL/gpio/stm32wb_gpio.h index 77c1d1d..37f81f9 100644 --- a/wolfHAL/gpio/stm32wb_gpio.h +++ b/wolfHAL/gpio/stm32wb_gpio.h @@ -38,9 +38,17 @@ * - Internal pull-up and pull-down resistors * - Alternate function mapping for peripheral connections (UART, SPI, etc.) * - * Each port occupies 0x400 bytes in the memory map starting from GPIOA base. + * Ports are WHAL_STM32WB_GPIO_PORT_SIZE bytes apart starting from GPIOA base. */ +/* + * @brief Address stride between consecutive GPIO ports. Platforms with a + * different port spacing define this before including this header. + */ +#ifndef WHAL_STM32WB_GPIO_PORT_SIZE +#define WHAL_STM32WB_GPIO_PORT_SIZE 0x400 +#endif + /* * @brief Packed per-pin GPIO configuration (uint32_t). * @@ -138,7 +146,8 @@ extern const whal_Gpio whal_Stm32wb_Gpio_Dev; !defined(WHAL_CFG_STM32F4_GPIO_DIRECT_API_MAPPING) && \ !defined(WHAL_CFG_STM32H5_GPIO_DIRECT_API_MAPPING) && \ !defined(WHAL_CFG_STM32C0_GPIO_DIRECT_API_MAPPING) && \ - !defined(WHAL_CFG_STM32F0_GPIO_DIRECT_API_MAPPING) + !defined(WHAL_CFG_STM32F0_GPIO_DIRECT_API_MAPPING) && \ + !defined(WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING) /* * @brief Driver instance for STM32 GPIO. */ diff --git a/wolfHAL/platform/st/stm32wb05kz.h b/wolfHAL/platform/st/stm32wb09ke.h similarity index 65% rename from wolfHAL/platform/st/stm32wb05kz.h rename to wolfHAL/platform/st/stm32wb09ke.h index 21cbe6a..aeec538 100644 --- a/wolfHAL/platform/st/stm32wb05kz.h +++ b/wolfHAL/platform/st/stm32wb09ke.h @@ -1,4 +1,4 @@ -/* stm32wb05kz.h +/* stm32wb09ke.h * * Copyright (C) 2026 wolfSSL Inc. * @@ -19,8 +19,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifndef WHAL_STM32WB05KZ_H -#define WHAL_STM32WB05KZ_H +#ifndef WHAL_STM32WB09KE_H +#define WHAL_STM32WB09KE_H #include @@ -36,14 +36,14 @@ #include /** - * @file stm32wb05kz.h - * @brief Convenience initializers for STM32WB05KZ device instances. + * @file stm32wb09ke.h + * @brief Convenience initializers for STM32WB09KE device instances. * - * Base addresses from RM0529 Table 3 (STM32WB05xZ memory map and + * Base addresses from RM0505 Table 3 (STM32WB09xE memory map and * peripheral register boundary addresses). * * GPIOA 0x48000000 (1 KB) - * GPIOB 0x48100000 (1 KB) — port stride is 1 MB, not 0x400 + * GPIOB 0x48100000 (1 KB), port stride is 1 MB, not 0x400 * CRC 0x48200000 * PKA slave 0x48300000 (PKA RAM at +0x400) * RCC 0x48400000 @@ -64,41 +64,41 @@ * ADC 0x41006000 * SPI3 0x41007000 * - * Main flash array is memory-mapped at 0x10040000 (192 KB on WB05KZ). + * Main flash array is memory-mapped at 0x10040000 (512 KB on WB09KE). */ /* --- Base addresses --- */ -#define WHAL_STM32WB05_GPIO_BASE 0x48000000 -#define WHAL_STM32WB05_CRC_BASE 0x48200000 -#define WHAL_STM32WB05_PKA_BASE 0x48300000 -#define WHAL_STM32WB05_PWR_BASE 0x48500000 -#define WHAL_STM32WB05_RNG_BASE 0x48600000 -#define WHAL_STM32WB05_DMA1_BASE 0x48700000 -#define WHAL_STM32WB05_DMAMUX1_BASE 0x48800000 - -#define WHAL_STM32WB05_SYSCFG_BASE 0x40000000 -#define WHAL_STM32WB05_FLASH_BASE 0x40001000 -#define WHAL_STM32WB05_FLASH_ARRAY_BASE 0x10040000 -#define WHAL_STM32WB05_FLASH_SIZE 0x00030000 /* 192 KB on WB05KZ */ -#define WHAL_STM32WB05_TIM2_BASE 0x40002000 -#define WHAL_STM32WB05_IWDG_BASE 0x40003000 -#define WHAL_STM32WB05_RTC_BASE 0x40004000 -#define WHAL_STM32WB05_TIM16_BASE 0x40005000 -#define WHAL_STM32WB05_TIM17_BASE 0x40006000 - -#define WHAL_STM32WB05_I2C1_BASE 0x41000000 -#define WHAL_STM32WB05_USART1_BASE 0x41004000 -#define WHAL_STM32WB05_LPUART1_BASE 0x41005000 -#define WHAL_STM32WB05_SPI3_BASE 0x41007000 +#define WHAL_STM32WB09_GPIO_BASE 0x48000000 +#define WHAL_STM32WB09_CRC_BASE 0x48200000 +#define WHAL_STM32WB09_PKA_BASE 0x48300000 +#define WHAL_STM32WB09_PWR_BASE 0x48500000 +#define WHAL_STM32WB09_RNG_BASE 0x48600000 +#define WHAL_STM32WB09_DMA1_BASE 0x48700000 +#define WHAL_STM32WB09_DMAMUX1_BASE 0x48800000 + +#define WHAL_STM32WB09_SYSCFG_BASE 0x40000000 +#define WHAL_STM32WB09_FLASH_BASE 0x40001000 +#define WHAL_STM32WB09_FLASH_ARRAY_BASE 0x10040000 +#define WHAL_STM32WB09_FLASH_SIZE 0x00080000 /* 512 KB on WB09KE */ +#define WHAL_STM32WB09_TIM2_BASE 0x40002000 +#define WHAL_STM32WB09_IWDG_BASE 0x40003000 +#define WHAL_STM32WB09_RTC_BASE 0x40004000 +#define WHAL_STM32WB09_TIM16_BASE 0x40005000 +#define WHAL_STM32WB09_TIM17_BASE 0x40006000 + +#define WHAL_STM32WB09_I2C1_BASE 0x41000000 +#define WHAL_STM32WB09_USART1_BASE 0x41004000 +#define WHAL_STM32WB09_LPUART1_BASE 0x41005000 +#define WHAL_STM32WB09_SPI3_BASE 0x41007000 /* --- Vtable-pointer macros --- * Only required for drivers whose _DRIVER symbol callers may reference. * Flash uses vtable dispatch (lets boards coexist with SPI NOR). PKA uses * the crypto peripheral-level vtable. */ -#define WHAL_STM32WB05_FLASH_DRIVER &whal_Stm32wb0_Flash_Driver -#define WHAL_STM32WB05_PKA_DRIVER &whal_Stm32wb0_Pka_CryptoDriver +#define WHAL_STM32WB09_FLASH_DRIVER &whal_Stm32wb0_Flash_Driver +#define WHAL_STM32WB09_PKA_DRIVER &whal_Stm32wb0_Pka_CryptoDriver /* --- Peripheral clock gate descriptors --- * RCC base 0x48400000; offsets are register-from-base. @@ -109,96 +109,96 @@ */ /* RCC_AHBENR (offset 0x50) */ -#define WHAL_STM32WB05_DMA1_CLOCK \ +#define WHAL_STM32WB09_DMA1_CLOCK \ .regOffset = 0x50, \ .enableMask = (1UL << 0), \ .enablePos = 0 -#define WHAL_STM32WB05_GPIOA_CLOCK \ +#define WHAL_STM32WB09_GPIOA_CLOCK \ .regOffset = 0x50, \ .enableMask = (1UL << 2), \ .enablePos = 2 -#define WHAL_STM32WB05_GPIOB_CLOCK \ +#define WHAL_STM32WB09_GPIOB_CLOCK \ .regOffset = 0x50, \ .enableMask = (1UL << 3), \ .enablePos = 3 -#define WHAL_STM32WB05_CRC_CLOCK \ +#define WHAL_STM32WB09_CRC_CLOCK \ .regOffset = 0x50, \ .enableMask = (1UL << 12), \ .enablePos = 12 -#define WHAL_STM32WB05_PKA_CLOCK \ +#define WHAL_STM32WB09_PKA_CLOCK \ .regOffset = 0x50, \ .enableMask = (1UL << 16), \ .enablePos = 16 -#define WHAL_STM32WB05_RNG_CLOCK \ +#define WHAL_STM32WB09_RNG_CLOCK \ .regOffset = 0x50, \ .enableMask = (1UL << 18), \ .enablePos = 18 /* RCC_APB0ENR (offset 0x54) */ -#define WHAL_STM32WB05_TIM2_CLOCK \ +#define WHAL_STM32WB09_TIM2_CLOCK \ .regOffset = 0x54, \ .enableMask = (1UL << 0), \ .enablePos = 0 -#define WHAL_STM32WB05_TIM16_CLOCK \ +#define WHAL_STM32WB09_TIM16_CLOCK \ .regOffset = 0x54, \ .enableMask = (1UL << 1), \ .enablePos = 1 -#define WHAL_STM32WB05_TIM17_CLOCK \ +#define WHAL_STM32WB09_TIM17_CLOCK \ .regOffset = 0x54, \ .enableMask = (1UL << 2), \ .enablePos = 2 -#define WHAL_STM32WB05_SYSCFG_CLOCK \ +#define WHAL_STM32WB09_SYSCFG_CLOCK \ .regOffset = 0x54, \ .enableMask = (1UL << 8), \ .enablePos = 8 -#define WHAL_STM32WB05_RTC_CLOCK \ +#define WHAL_STM32WB09_RTC_CLOCK \ .regOffset = 0x54, \ .enableMask = (1UL << 12), \ .enablePos = 12 -#define WHAL_STM32WB05_IWDG_CLOCK \ +#define WHAL_STM32WB09_IWDG_CLOCK \ .regOffset = 0x54, \ .enableMask = (1UL << 14), \ .enablePos = 14 /* RCC_APB1ENR (offset 0x58) */ -#define WHAL_STM32WB05_ADCDIG_CLOCK \ +#define WHAL_STM32WB09_ADCDIG_CLOCK \ .regOffset = 0x58, \ .enableMask = (1UL << 4), \ .enablePos = 4 -#define WHAL_STM32WB05_ADCANA_CLOCK \ +#define WHAL_STM32WB09_ADCANA_CLOCK \ .regOffset = 0x58, \ .enableMask = (1UL << 5), \ .enablePos = 5 -#define WHAL_STM32WB05_LPUART1_CLOCK \ +#define WHAL_STM32WB09_LPUART1_CLOCK \ .regOffset = 0x58, \ .enableMask = (1UL << 8), \ .enablePos = 8 -#define WHAL_STM32WB05_USART1_CLOCK \ +#define WHAL_STM32WB09_USART1_CLOCK \ .regOffset = 0x58, \ .enableMask = (1UL << 10), \ .enablePos = 10 -#define WHAL_STM32WB05_SPI3_CLOCK \ +#define WHAL_STM32WB09_SPI3_CLOCK \ .regOffset = 0x58, \ .enableMask = (1UL << 14), \ .enablePos = 14 -#define WHAL_STM32WB05_I2C1_CLOCK \ +#define WHAL_STM32WB09_I2C1_CLOCK \ .regOffset = 0x58, \ .enableMask = (1UL << 21), \ .enablePos = 21 -#endif /* WHAL_STM32WB05KZ_H */ +#endif /* WHAL_STM32WB09KE_H */ diff --git a/wolfHAL/uart/stm32wb0_uart.h b/wolfHAL/uart/stm32wb0_uart.h index 13282a6..6f72ca6 100644 --- a/wolfHAL/uart/stm32wb0_uart.h +++ b/wolfHAL/uart/stm32wb0_uart.h @@ -26,10 +26,13 @@ * @file stm32wb0_uart.h * @brief STM32WB0 UART driver (alias for STM32WB UART). * - * The STM32WB0 USART peripheral is register-compatible with the STM32WB - * USART (FIFO USART variant: CR1.FIFOEN at bit 29, BRR at 0x0C, ISR at - * 0x1C, RDR at 0x24, TDR at 0x28). This header re-exports the STM32WB - * UART driver types and symbols under STM32WB0-specific names. + * The STM32WB0 USART is register-compatible with the STM32WB FIFO USART + * (CR1.FIFOEN at bit 29, BRR at 0x0C, ISR at 0x1C, ICR at 0x20, RDR at 0x24, + * TDR at 0x28). This header re-exports the STM32WB UART driver types and + * symbols under STM32WB0-specific names. + * + * The USART baud rate generator runs from a fixed 16 MHz kernel clock that + * does not follow SYSCLK, so BRR is computed from WHAL_STM32WB0_UART_CLK_HZ. */ #include @@ -46,6 +49,11 @@ typedef whal_Stm32wb_Uart_Cfg whal_Stm32wb0_Uart_Cfg; #define whal_Stm32wb0_Uart_Recv whal_Stm32wb_Uart_Recv #endif /* !WHAL_CFG_STM32WB0_UART_DIRECT_API_MAPPING */ +/** + * @brief USART kernel clock frequency. + */ +#define WHAL_STM32WB0_UART_CLK_HZ 16000000 + /** * @brief Baud rate register helpers (re-exported from STM32WB). */