From eac6fefe0780b89a80c75a42858b4919cb60e216 Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Sun, 31 May 2026 13:29:03 -0400 Subject: [PATCH] [stm32wb0] Add support for the stm32wb0. Add stm32wb0 nucleo board --- .github/workflows/boards.yml | 2 +- boards/README.md | 1 + boards/stm32wb05kz_nucleo/board.c | 278 +++++++++++++++++++++++++ boards/stm32wb05kz_nucleo/board.h | 199 ++++++++++++++++++ boards/stm32wb05kz_nucleo/board.mk | 73 +++++++ boards/stm32wb05kz_nucleo/ivt.c | 168 +++++++++++++++ boards/stm32wb05kz_nucleo/linker.ld | 144 +++++++++++++ src/crypto/stm32wb0_pka.c | 7 + src/dma/stm32wb0_dma.c | 7 + src/flash/stm32wb0_flash.c | 312 ++++++++++++++++++++++++++++ src/gpio/stm32wb0_gpio.c | 163 +++++++++++++++ src/i2c/stm32wb0_i2c.c | 7 + src/rng/stm32wb0_rng.c | 120 +++++++++++ src/spi/stm32wb0_spi.c | 7 + src/uart/stm32wb0_uart.c | 7 + src/watchdog/stm32wb0_iwdg.c | 4 + wolfHAL/clock/stm32wb0_rcc.h | 311 +++++++++++++++++++++++++++ wolfHAL/crypto/stm32wb0_pka.h | 68 ++++++ wolfHAL/dma/stm32wb0_dma.h | 72 +++++++ wolfHAL/dma/stm32wb_dma.h | 6 +- wolfHAL/flash/stm32wb0_flash.h | 179 ++++++++++++++++ wolfHAL/gpio/stm32wb0_gpio.h | 132 ++++++++++++ wolfHAL/i2c/stm32wb0_i2c.h | 54 +++++ wolfHAL/i2c/stm32wb_i2c.h | 3 +- wolfHAL/platform/st/stm32wb05kz.h | 204 ++++++++++++++++++ wolfHAL/rng/stm32wb0_rng.h | 102 +++++++++ wolfHAL/spi/stm32wb0_spi.h | 55 +++++ wolfHAL/spi/stm32wb_spi.h | 6 +- wolfHAL/uart/stm32wb0_uart.h | 59 ++++++ wolfHAL/uart/stm32wb_uart.h | 6 +- wolfHAL/watchdog/stm32wb0_iwdg.h | 65 ++++++ 31 files changed, 2813 insertions(+), 8 deletions(-) create mode 100644 boards/stm32wb05kz_nucleo/board.c create mode 100644 boards/stm32wb05kz_nucleo/board.h create mode 100644 boards/stm32wb05kz_nucleo/board.mk create mode 100644 boards/stm32wb05kz_nucleo/ivt.c create mode 100644 boards/stm32wb05kz_nucleo/linker.ld create mode 100644 src/crypto/stm32wb0_pka.c create mode 100644 src/dma/stm32wb0_dma.c create mode 100644 src/flash/stm32wb0_flash.c create mode 100644 src/gpio/stm32wb0_gpio.c create mode 100644 src/i2c/stm32wb0_i2c.c create mode 100644 src/rng/stm32wb0_rng.c create mode 100644 src/spi/stm32wb0_spi.c create mode 100644 src/uart/stm32wb0_uart.c create mode 100644 src/watchdog/stm32wb0_iwdg.c create mode 100644 wolfHAL/clock/stm32wb0_rcc.h create mode 100644 wolfHAL/crypto/stm32wb0_pka.h create mode 100644 wolfHAL/dma/stm32wb0_dma.h create mode 100644 wolfHAL/flash/stm32wb0_flash.h create mode 100644 wolfHAL/gpio/stm32wb0_gpio.h create mode 100644 wolfHAL/i2c/stm32wb0_i2c.h create mode 100644 wolfHAL/platform/st/stm32wb05kz.h create mode 100644 wolfHAL/rng/stm32wb0_rng.h create mode 100644 wolfHAL/spi/stm32wb0_spi.h create mode 100644 wolfHAL/uart/stm32wb0_uart.h create mode 100644 wolfHAL/watchdog/stm32wb0_iwdg.h diff --git a/.github/workflows/boards.yml b/.github/workflows/boards.yml index b36ee8e..5c2c163 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, pic32cz_curiosity_ultra, stm32h563zi_nucleo, stm32f411_blackpill, stm32c031_nucleo, stm32f091rc_nucleo, stm32f302r8_nucleo, stm32l152re_nucleo, stm32n657a0_nucleo, stm32u5a5zj_nucleo] + 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] extra_cflags: ["", "-DWHAL_CFG_NO_TIMEOUT"] include: - board: stm32wb55xx_nucleo diff --git a/boards/README.md b/boards/README.md index b1ce88b..1d39631 100644 --- a/boards/README.md +++ b/boards/README.md @@ -20,6 +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-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.c b/boards/stm32wb05kz_nucleo/board.c new file mode 100644 index 0000000..f96806f --- /dev/null +++ b/boards/stm32wb05kz_nucleo/board.c @@ -0,0 +1,278 @@ +/* board.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 + */ + +/* Board configuration for the NUCLEO-WB05KZ dev board (UM3343 / MB1801+MB2032). */ + +#include +#include +#include "board.h" +#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. */ +#define BOARD_SYSCLK_HZ 64000000 + +/* SysTick timing */ +volatile uint32_t g_tick = 0; + +void SysTick_Handler(void) +{ + g_tick++; +} + +uint32_t Board_GetTick(void) +{ + return g_tick; +} + +whal_Timeout g_whalTimeout = { + .timeoutTicks = 1000, /* 1 s timeout */ + .GetTick = Board_GetTick, +}; + +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}, +#ifdef BOARD_WATCHDOG_IWDG + {WHAL_STM32WB05_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. */ +whal_Uart g_whalUart = { + .base = WHAL_STM32WB05_USART1_BASE, + /* .driver: direct API mapping */ + .cfg = &(whal_Stm32wb0_Uart_Cfg) { + .timeout = &g_whalTimeout, + .brr = WHAL_STM32WB0_UART_BRR(16000000, 115200), + }, +}; + +/* SPI3 */ +whal_Spi g_whalSpi = { + .base = WHAL_STM32WB05_SPI3_BASE, + /* .driver: direct API mapping */ + .cfg = &(whal_Stm32wb0_Spi_Cfg) { + .pclk = BOARD_SYSCLK_HZ, + .timeout = &g_whalTimeout, + }, +}; + +/* I2C1 */ +whal_I2c g_whalI2c = { + .base = WHAL_STM32WB05_I2C1_BASE, + /* .driver: direct API mapping */ + .cfg = &(whal_Stm32wb0_I2c_Cfg) { + .pclk = BOARD_SYSCLK_HZ, + .timeout = &g_whalTimeout, + }, +}; + +/* 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, + .cfg = &(whal_Stm32wb0_Pka_Cfg) { + .timeout = &g_whalTimeout, + }, +}; + +#ifdef BOARD_WATCHDOG_IWDG +whal_Watchdog g_whalWatchdog = { + .base = WHAL_STM32WB05_IWDG_BASE, + /* .driver: direct API mapping */ + .cfg = &(whal_Stm32wb0_Iwdg_Cfg) { + .prescaler = WHAL_STM32WB0_IWDG_PR_32, + .reload = 100, + .timeout = &g_whalTimeout, + }, +}; +#endif + +void Board_WaitMs(size_t ms) +{ + uint32_t startCount = g_tick; + while ((g_tick - startCount) < ms) + ; +} + +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. */ + 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(); + 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(); + if (err) + return err; + err = whal_Stm32wb0_Rcc_EnableHsiPll(); + 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); + if (err) + return err; + +#ifdef BOARD_WATCHDOG_IWDG + /* The IWDG is clocked from LSI (~32 kHz). */ + err = whal_Stm32wb0_Rcc_EnableLsi(); + if (err) + return err; +#endif + + /* Enable peripheral clocks */ + for (size_t i = 0; i < PERIPH_CLK_COUNT; i++) { + err = whal_Stm32wb0_Rcc_EnablePeriphClk(&g_periphClks[i]); + if (err) + return err; + } + + err = whal_Gpio_Init(BOARD_GPIO_DEV); + if (err) + return err; + + err = whal_Uart_Init(BOARD_UART_DEV); + if (err) + return err; + + err = whal_Spi_Init(BOARD_SPI_DEV); + if (err) + return err; + + err = whal_I2c_Init(BOARD_I2C_DEV); + if (err) + return err; + + err = whal_Flash_Init(BOARD_FLASH_DEV); + if (err) + return err; + + err = whal_Timer_Init(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Timer_Start(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Rng_Init(BOARD_RNG_DEV); + if (err) + return err; + + err = whal_Crypto_Init(BOARD_PKA_DEV); + if (err) + return err; + + + return WHAL_SUCCESS; +} + +whal_Error Board_Deinit(void) +{ + whal_Error err; + + err = whal_Timer_Stop(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Timer_Deinit(WHAL_INTERNAL_DEV); + if (err) + return err; + + err = whal_Crypto_Deinit(BOARD_PKA_DEV); + if (err) + return err; + + err = whal_Rng_Deinit(BOARD_RNG_DEV); + if (err) + return err; + + err = whal_Flash_Deinit(BOARD_FLASH_DEV); + if (err) + return err; + + err = whal_I2c_Deinit(BOARD_I2C_DEV); + if (err) + return err; + + err = whal_Spi_Deinit(BOARD_SPI_DEV); + if (err) + return err; + + err = whal_Uart_Deinit(BOARD_UART_DEV); + if (err) + return err; + + err = whal_Gpio_Deinit(BOARD_GPIO_DEV); + if (err) + return err; + + /* Disable peripheral clocks */ + for (size_t i = PERIPH_CLK_COUNT; i-- > 0; ) { + err = whal_Stm32wb0_Rcc_DisablePeriphClk(&g_periphClks[i]); + if (err) + return err; + } + +#ifdef BOARD_WATCHDOG_IWDG + err = whal_Stm32wb0_Rcc_DisableLsi(); + 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); + if (err) + return err; + + err = whal_Stm32wb0_Flash_Ext_SetLatency(BOARD_FLASH_DEV, + WHAL_STM32WB0_FLASH_LATENCY_0); + if (err) + return err; + + return WHAL_SUCCESS; +} diff --git a/boards/stm32wb05kz_nucleo/board.h b/boards/stm32wb05kz_nucleo/board.h new file mode 100644 index 0000000..ced28d9 --- /dev/null +++ b/boards/stm32wb05kz_nucleo/board.h @@ -0,0 +1,199 @@ +/* board.h + * + * 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 + */ + +#ifndef BOARD_H +#define BOARD_H + +#include +#include +#include +#include + +extern whal_Uart g_whalUart; +extern whal_Spi g_whalSpi; +extern whal_I2c g_whalI2c; +#ifdef BOARD_WATCHDOG_IWDG +extern whal_Watchdog g_whalWatchdog; +#endif +extern whal_Crypto g_whalPka; + +extern whal_Timeout g_whalTimeout; +extern volatile uint32_t g_tick; + +enum { + LED_PIN, + BUTTON_PIN, + UART_TX_PIN, + UART_RX_PIN, + SPI_SCK_PIN, + SPI_MISO_PIN, + SPI_MOSI_PIN, + SPI_CS_PIN, + I2C_SCL_PIN, + I2C_SDA_PIN, + PIN_COUNT, +}; + +#define BOARD_LED_PIN 0 + +/* Flash array on WB05KZ: 192 KB at 0x10040000, 2 KB pages = 96 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_SECTOR_SZ 0x800 +#define BOARD_FLASH_TEST_ADDR (BOARD_FLASH_START_ADDR + BOARD_FLASH_SIZE - BOARD_FLASH_SECTOR_SZ) + +/* --- Single-instance device initializers --- + * Each driver TU defines its singleton from these macros after #include + * "board.h". Names are WB0-prefixed; the alias header bridges them to the + * WB-prefixed names that the leaf drivers consume. + */ + +/* GPIO dev initializer — singleton defined in stm32wb0_gpio.c. */ +#define WHAL_CFG_STM32WB0_GPIO_DEV { \ + .base = WHAL_STM32WB05_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 */ \ + [LED_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_B, 1, WHAL_STM32WB0_GPIO_MODE_OUT, \ + WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB0_GPIO_SPEED_LOW, \ + WHAL_STM32WB0_GPIO_PULL_NONE, 0), \ + /* B1 user button on PA0, input, pull-up */ \ + [BUTTON_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_A, 0, WHAL_STM32WB0_GPIO_MODE_IN, \ + WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB0_GPIO_SPEED_LOW, \ + WHAL_STM32WB0_GPIO_PULL_UP, 0), \ + /* USART TX on PA1 AF2 (NUCLEO VCP TX) */ \ + [UART_TX_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_A, 1, WHAL_STM32WB0_GPIO_MODE_ALTFN, \ + WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB0_GPIO_SPEED_FAST, \ + WHAL_STM32WB0_GPIO_PULL_UP, 2), \ + /* USART RX on PB0 AF0 (NUCLEO VCP RX) */ \ + [UART_RX_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_B, 0, WHAL_STM32WB0_GPIO_MODE_ALTFN, \ + WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB0_GPIO_SPEED_FAST, \ + WHAL_STM32WB0_GPIO_PULL_UP, 0), \ + /* SPI3 SCK on PB3 AF4 */ \ + [SPI_SCK_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_B, 3, WHAL_STM32WB0_GPIO_MODE_ALTFN, \ + WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB0_GPIO_SPEED_FAST, \ + WHAL_STM32WB0_GPIO_PULL_NONE, 4), \ + /* SPI3 MISO on PA8 AF3 */ \ + [SPI_MISO_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_A, 8, WHAL_STM32WB0_GPIO_MODE_ALTFN, \ + WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB0_GPIO_SPEED_FAST, \ + WHAL_STM32WB0_GPIO_PULL_NONE, 3), \ + /* SPI3 MOSI on PA11 AF3 */ \ + [SPI_MOSI_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_A, 11, WHAL_STM32WB0_GPIO_MODE_ALTFN, \ + WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB0_GPIO_SPEED_FAST, \ + WHAL_STM32WB0_GPIO_PULL_NONE, 3), \ + /* SPI3 CS on PA9 as plain GPIO output (avoid SPI3_NSS AF) */ \ + [SPI_CS_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_A, 9, WHAL_STM32WB0_GPIO_MODE_OUT, \ + WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WB0_GPIO_SPEED_FAST, \ + WHAL_STM32WB0_GPIO_PULL_UP, 0), \ + /* I2C1 SCL on PB6 AF0, open-drain */ \ + [I2C_SCL_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_B, 6, WHAL_STM32WB0_GPIO_MODE_ALTFN, \ + WHAL_STM32WB0_GPIO_OUTTYPE_OPENDRAIN, WHAL_STM32WB0_GPIO_SPEED_FAST, \ + WHAL_STM32WB0_GPIO_PULL_UP, 0), \ + /* I2C1 SDA on PB7 AF0, open-drain */ \ + [I2C_SDA_PIN] = WHAL_STM32WB0_GPIO_PIN( \ + WHAL_STM32WB0_GPIO_PORT_B, 7, WHAL_STM32WB0_GPIO_MODE_ALTFN, \ + WHAL_STM32WB0_GPIO_OUTTYPE_OPENDRAIN, WHAL_STM32WB0_GPIO_SPEED_FAST, \ + WHAL_STM32WB0_GPIO_PULL_UP, 0), \ + }, \ + .pinCount = PIN_COUNT, \ + }, \ +} + +/* 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, \ + .cfg = (void *)&(const whal_Stm32wb0_Flash_Cfg){ \ + .startAddr = WHAL_STM32WB05_FLASH_ARRAY_BASE, \ + .size = WHAL_STM32WB05_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, \ + /* .driver: direct API mapping */ \ + .cfg = (void *)&(const whal_Stm32wb0_Rng_Cfg){ \ + .timeout = &g_whalTimeout, \ + }, \ +} + +/* 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, \ + /* .driver: direct API mapping */ \ + .cfg = (void *)&(const whal_Stm32wb0_Iwdg_Cfg){ \ + .prescaler = WHAL_STM32WB0_IWDG_PR_32, \ + .reload = 100, \ + .timeout = &g_whalTimeout, \ + }, \ +} + +/* 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, \ + .cfg = (void *)&(const whal_Stm32wb0_Pka_Cfg){ \ + .timeout = &g_whalTimeout, \ + }, \ +} + +/* SysTick dev initializer — singleton defined in systick.c. */ +#define WHAL_CFG_SYSTICK_DEV { \ + .base = WHAL_CORTEX_M0PLUS_SYSTICK_BASE, \ + /* .driver: direct API mapping */ \ + .cfg = (void *)&(const whal_SysTick_Cfg){ \ + .cyclesPerTick = 64000000 / 1000, \ + .clkSrc = WHAL_SYSTICK_CLKSRC_SYSCLK, \ + .tickInt = WHAL_SYSTICK_TICKINT_ENABLED, \ + }, \ +} + +/* BOARD_*_DEV: how this board reaches each peripheral. */ +#define BOARD_GPIO_DEV WHAL_INTERNAL_DEV +#define BOARD_UART_DEV (&g_whalUart) +#define BOARD_SPI_DEV (&g_whalSpi) +#define BOARD_I2C_DEV (&g_whalI2c) +#define BOARD_FLASH_DEV ((whal_Flash *)&whal_Stm32wb0_Flash_Dev) +#define BOARD_RNG_DEV WHAL_INTERNAL_DEV +#ifdef BOARD_WATCHDOG_IWDG +#define BOARD_WATCHDOG_DEV (&g_whalWatchdog) +#endif +#define BOARD_PKA_DEV (&g_whalPka) + +whal_Error Board_Init(void); +whal_Error Board_Deinit(void); +void Board_WaitMs(size_t ms); + +#endif /* BOARD_H */ diff --git a/boards/stm32wb05kz_nucleo/board.mk b/boards/stm32wb05kz_nucleo/board.mk new file mode 100644 index 0000000..0597e52 --- /dev/null +++ b/boards/stm32wb05kz_nucleo/board.mk @@ -0,0 +1,73 @@ +# board.mk +# +# 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 +# + +_BOARD_DIR := $(patsubst %/,%,$(dir $(lastword $(MAKEFILE_LIST)))) + +PLATFORM = stm32wb0 +TESTS ?= gpio flash timer rng uart spi i2c + +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 -Os -ffunction-sections -fdata-sections \ + -ffreestanding -nostdlib -mcpu=cortex-m0plus -mthumb \ + -DPLATFORM_STM32WB0 -MMD -MP \ + -DWHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB0_RNG_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB0_UART_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB0_SPI_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB0_I2C_DIRECT_API_MAPPING \ + -DWHAL_CFG_STM32WB0_PKA_DIRECT_API_MAPPING \ + $(if $(filter iwdg,$(WATCHDOG)),\ + -DBOARD_WATCHDOG_IWDG \ + -DWHAL_CFG_STM32WB0_IWDG_DIRECT_API_MAPPING) \ + -DWHAL_CFG_SYSTICK_TIMER_DIRECT_API_MAPPING +LDFLAGS = -mcpu=cortex-m0plus -mthumb -ffreestanding -nostartfiles \ + -Wl,--omagic -Wl,--gc-sections -static + +LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld + +INCLUDE += -I$(_BOARD_DIR) -I$(WHAL_DIR)/boards/peripheral + +BOARD_SOURCE = $(_BOARD_DIR)/ivt.c +BOARD_SOURCE += $(_BOARD_DIR)/board.c +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/flash.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/sensor.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/block.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/crypto.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/stm32wb0_*.c) +BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c) + +# Peripheral devices +include $(WHAL_DIR)/boards/peripheral/board.mk + +# Flash via openocd: make flash BOARD= IMAGE= +OPENOCD ?= /opt/openocd/bin/openocd +OPENOCD_INTERFACE ?= interface/stlink.cfg +OPENOCD_TARGET ?= target/stm32wb0x.cfg + +.PHONY: flash +flash: + @test -n "$(IMAGE)" || { echo "IMAGE= required" >&2; exit 1; } + $(OPENOCD) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) \ + -c "program $(IMAGE) verify reset exit" diff --git a/boards/stm32wb05kz_nucleo/ivt.c b/boards/stm32wb05kz_nucleo/ivt.c new file mode 100644 index 0000000..411ba11 --- /dev/null +++ b/boards/stm32wb05kz_nucleo/ivt.c @@ -0,0 +1,168 @@ +/* ivt.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 + +extern uint32_t _estack[]; +extern uint32_t _sidata[]; +extern uint32_t _sdata[]; +extern uint32_t _edata[]; +extern uint32_t _sbss[]; +extern uint32_t _ebss[]; + +extern void main(void); + +void __attribute__((naked, noreturn)) Default_Handler(void) +{ + while (1); +} + +void Reset_Handler(void) __attribute__((weak)); +void NMI_Handler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void HardFault_Handler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void SVC_Handler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +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) */ +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"))); +void I2C1_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void SPI3_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void USART_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void LPUART_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void TIM2_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void RTC_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void ADC_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void PKA_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPIOA_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void GPIOB_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void DMA_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void BLE_TXRX_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void RADIO_CTRL_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void MR_BLE_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void CPU_WKUP_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +void BLE_WKUP_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler"))); +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"))); + +#define RESERVED Default_Handler + +void *memcpy(void *dest, const void *src, size_t n) +{ + unsigned char *d = dest; + const unsigned char *s = src; + + for (size_t i = 0; i < n; i++) + d[i] = s[i]; + + return dest; +} + +void *memset(void *s, int c, size_t n) +{ + unsigned char *p = s; + unsigned char v = (unsigned char)c; + + for (size_t i = 0; i < n; i++) + p[i] = v; + + return s; +} + +void (* const interrupt_vector_table[])(void) __attribute__((section(".isr_vector"))) = { + (void (*)(void))_estack, + Reset_Handler, + NMI_Handler, + HardFault_Handler, + RESERVED, /* Reserved */ + RESERVED, /* Reserved */ + RESERVED, /* Reserved */ + RESERVED, /* Reserved */ + RESERVED, /* Reserved */ + RESERVED, /* Reserved */ + RESERVED, /* Reserved */ + SVC_Handler, + RESERVED, /* Reserved */ + RESERVED, /* Reserved */ + PendSV_Handler, + SysTick_Handler, + /* STM32WB05xZ peripheral interrupts (Table 6) */ + NVM_IRQHandler, /* 0 Flash controller */ + RCC_IRQHandler, /* 1 Reset and clock controller */ + BATTERY_IRQHandler, /* 2 PVD */ + I2C1_IRQHandler, /* 3 I2C1 */ + RESERVED, /* 4 Reserved */ + RESERVED, /* 5 Reserved */ + RESERVED, /* 6 Reserved */ + SPI3_IRQHandler, /* 7 SPI3 */ + USART_IRQHandler, /* 8 USART */ + LPUART_IRQHandler, /* 9 LPUART */ + TIM2_IRQHandler, /* 10 TIM2 */ + RTC_IRQHandler, /* 11 RTC */ + ADC_IRQHandler, /* 12 ADC (shared with reserved slot in TRM) */ + PKA_IRQHandler, /* 13 PKA */ + RESERVED, /* 14 Reserved */ + GPIOA_IRQHandler, /* 15 GPIOA */ + GPIOB_IRQHandler, /* 16 GPIOB */ + DMA_IRQHandler, /* 17 DMA */ + BLE_TXRX_IRQHandler, /* 18 BLE end-of-transfer */ + RESERVED, /* 19 Reserved */ + RESERVED, /* 20 Reserved */ + RADIO_CTRL_IRQHandler, /* 21 Radio control slow-clock measurement */ + MR_BLE_IRQHandler, /* 22 RRM and radio FSM */ + CPU_WKUP_IRQHandler, /* 23 CPU wakeup */ + BLE_WKUP_IRQHandler, /* 24 BLE wakeup */ + BLE_SEQ_IRQHandler, /* 25 BLE RX/TX sequence */ + TIM16_IRQHandler, /* 26 TIM16 */ + TIM17_IRQHandler, /* 27 TIM17 */ + RESERVED, /* 28 Reserved */ + RESERVED, /* 29 Reserved */ + RESERVED, /* 30 Reserved */ + RESERVED, /* 31 Reserved */ +}; + +void __attribute__((naked)) Reset_Handler(void) +{ + __asm__("ldr r0, =_estack\n\t" + "mov sp, r0"); + + /* Copy data section from flash to RAM */ + uint32_t data_section_size = _edata - _sdata; + memcpy(_sdata, _sidata, data_section_size * 4); + + /* Zero out bss */ + uint32_t bss_section_size = _ebss - _sbss; + memset(_sbss, 0, bss_section_size * 4); + + /* Set Interrupt Vector Table Offset (Cortex-M0+ VTOR at 0xE000ED08). */ + uint32_t *vtor = (uint32_t *)0xE000ED08; + *vtor = (uint32_t)interrupt_vector_table; + + /* WB0 bootROM hands control to user code with PRIMASK set. Clear it + * so SysTick and other exceptions can be delivered. */ + __asm__ volatile ("cpsie i" ::: "memory"); + + main(); +} diff --git a/boards/stm32wb05kz_nucleo/linker.ld b/boards/stm32wb05kz_nucleo/linker.ld new file mode 100644 index 0000000..f14d1c8 --- /dev/null +++ b/boards/stm32wb05kz_nucleo/linker.ld @@ -0,0 +1,144 @@ +/* linker.ld + * + * 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 + */ + +/* Entry Point */ +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) + * + * 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. + */ +_estack = 0x20006000; /* end of SRAM1 = SRAM0 base + 24 KB */ +_Min_Stack_Size = 0x500; /* required amount of stack */ + +MEMORY +{ +FLASH (rx) : ORIGIN = 0x10040000, LENGTH = 192K +RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 24K +} + +SECTIONS +{ + /* The startup code goes first into FLASH */ + .isr_vector : + { + . = ALIGN(4); + KEEP(*(.isr_vector)) /* Startup code */ + . = ALIGN(4); + } >FLASH + + /* The program code and other data goes into FLASH */ + .text : + { + . = ALIGN(4); + *(.text) + *(.text*) + *(.glue_7) + *(.glue_7t) + *(.eh_frame) + + KEEP (*(.init)) + KEEP (*(.fini)) + + . = ALIGN(4); + _etext = .; + } >FLASH + + .rodata : + { + . = ALIGN(4); + *(.rodata) + *(.rodata*) + . = ALIGN(4); + } >FLASH + + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH + .ARM : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >FLASH + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array*)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array*)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array*)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH + + _sidata = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _sdata = .; + *(.data) + *(.data*) + + . = ALIGN(4); + _edata = .; + } >RAM AT> FLASH + + . = ALIGN(4); + .bss : + { + _sbss = .; + __bss_start__ = _sbss; + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; + __bss_end__ = _ebss; + } >RAM + + ._user_heap_stack : + { + . = ALIGN(8); + PROVIDE ( end = . ); + PROVIDE ( _end = . ); + . = . + _Min_Stack_Size; + . = ALIGN(8); + } >RAM +} diff --git a/src/crypto/stm32wb0_pka.c b/src/crypto/stm32wb0_pka.c new file mode 100644 index 0000000..47d009f --- /dev/null +++ b/src/crypto/stm32wb0_pka.c @@ -0,0 +1,7 @@ +#ifdef WHAL_CFG_STM32WB0_PKA_DIRECT_API_MAPPING +#define WHAL_CFG_STM32WB_PKA_DIRECT_API_MAPPING +#endif +#ifdef WHAL_CFG_STM32WB0_PKA_INIT_DIRECT_API_MAPPING +#define WHAL_CFG_STM32WB_PKA_INIT_DIRECT_API_MAPPING +#endif +#include "stm32wb_pka.c" diff --git a/src/dma/stm32wb0_dma.c b/src/dma/stm32wb0_dma.c new file mode 100644 index 0000000..971f312 --- /dev/null +++ b/src/dma/stm32wb0_dma.c @@ -0,0 +1,7 @@ +#ifdef WHAL_CFG_STM32WB0_DMA_DIRECT_API_MAPPING +#define WHAL_CFG_STM32WB_DMA_DIRECT_API_MAPPING +#endif +#ifdef WHAL_CFG_STM32WB0_DMA_SINGLE_INSTANCE +#define WHAL_CFG_STM32WB_DMA_SINGLE_INSTANCE +#endif +#include "stm32wb_dma.c" diff --git a/src/flash/stm32wb0_flash.c b/src/flash/stm32wb0_flash.c new file mode 100644 index 0000000..cbffde5 --- /dev/null +++ b/src/flash/stm32wb0_flash.c @@ -0,0 +1,312 @@ +/* stm32wb0_flash.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 "board.h" /* provides WHAL_CFG_STM32WB0_FLASH_DEV initializer */ +#include +#include +#include +#include +#include +#include + +const whal_Flash whal_Stm32wb0_Flash_Dev = WHAL_CFG_STM32WB0_FLASH_DEV; + +/* + * STM32WB0 Flash controller register layout (RM0529 section 9.4). + * + * The controller is command-driven: write an opcode to COMMAND, watch + * IRQSTAT for CMDSTART then CMDDONE, then clear those flags by writing + * 1 to the corresponding bit. ADDRESS is encoded in flash-internal word + * coordinates (page+row+word), not bytes. + */ + +#define FLASH_COMMAND_REG 0x00 +#define FLASH_COMMAND_ERASE 0x11 +#define FLASH_COMMAND_MASSERASE 0x22 +#define FLASH_COMMAND_WRITE 0x33 +#define FLASH_COMMAND_MASSREAD 0x55 +#define FLASH_COMMAND_SLEEP 0xAA +#define FLASH_COMMAND_WAKEUP 0xBB +#define FLASH_COMMAND_BURSTWRITE 0xCC +#define FLASH_COMMAND_OTPWRITE 0xEE +#define FLASH_COMMAND_KEYWRITE 0xFF + +#define FLASH_CONFIG_REG 0x04 +#define FLASH_CONFIG_WAIT_STATES_Pos 4 +#define FLASH_CONFIG_WAIT_STATES_Msk (WHAL_BITMASK(2) << FLASH_CONFIG_WAIT_STATES_Pos) + +#define FLASH_IRQSTAT_REG 0x08 +#define FLASH_IRQRAW_REG 0x10 +#define FLASH_IRQ_CMDDONE_Pos 0 +#define FLASH_IRQ_CMDDONE_Msk (1UL << FLASH_IRQ_CMDDONE_Pos) +#define FLASH_IRQ_CMDSTART_Pos 1 +#define FLASH_IRQ_CMDSTART_Msk (1UL << FLASH_IRQ_CMDSTART_Pos) +#define FLASH_IRQ_CMDERR_Pos 2 +#define FLASH_IRQ_CMDERR_Msk (1UL << FLASH_IRQ_CMDERR_Pos) +#define FLASH_IRQ_ILLCMD_Pos 3 +#define FLASH_IRQ_ILLCMD_Msk (1UL << FLASH_IRQ_ILLCMD_Pos) +#define FLASH_IRQ_READOK_Pos 4 +#define FLASH_IRQ_READOK_Msk (1UL << FLASH_IRQ_READOK_Pos) +#define FLASH_IRQ_ALL_ERR_Msk (FLASH_IRQ_CMDERR_Msk | FLASH_IRQ_ILLCMD_Msk) + +#define FLASH_ADDRESS_REG 0x18 +#define FLASH_DATA0_REG 0x40 +#define FLASH_DATA1_REG 0x44 +#define FLASH_DATA2_REG 0x48 +#define FLASH_DATA3_REG 0x4C + +/* WB0 page size: 2 KB. ADDRESS encodes word index; one word = 4 bytes. */ +#define FLASH_PAGE_SIZE 0x800u +#define FLASH_WORD_SIZE 4u + +#ifdef WHAL_CFG_STM32WB0_FLASH_DIRECT_API_MAPPING +#define whal_Stm32wb0_Flash_Init whal_Flash_Init +#define whal_Stm32wb0_Flash_Deinit whal_Flash_Deinit +#define whal_Stm32wb0_Flash_Lock whal_Flash_Lock +#define whal_Stm32wb0_Flash_Unlock whal_Flash_Unlock +#define whal_Stm32wb0_Flash_Read whal_Flash_Read +#define whal_Stm32wb0_Flash_Write whal_Flash_Write +#define whal_Stm32wb0_Flash_Erase whal_Flash_Erase +#endif /* WHAL_CFG_STM32WB0_FLASH_DIRECT_API_MAPPING */ + +/* + * Run a single Flash controller command: poll CMDSTART, clear it, poll + * CMDDONE, clear it, then sweep CMDERR/ILLCMD into an error code. All + * polling loops are bounded by the configured whal_Timeout. + */ +static whal_Error whal_Stm32wb0_Flash_RunCommand(size_t base, uint32_t cmd, + whal_Timeout *timeout) +{ + whal_Error err; + size_t irq; + + /* Clear any stale start/done/error flags before launching. */ + whal_Reg_Write(base, FLASH_IRQSTAT_REG, + FLASH_IRQ_CMDSTART_Msk | FLASH_IRQ_CMDDONE_Msk | + FLASH_IRQ_ALL_ERR_Msk); + + whal_Reg_Write(base, FLASH_COMMAND_REG, cmd); + + /* Wait for CMDSTART (controller has accepted the opcode). */ + WHAL_TIMEOUT_START(timeout); + while (1) { + if (WHAL_TIMEOUT_EXPIRED(timeout)) + return WHAL_ETIMEOUT; + irq = whal_Reg_Read(base, FLASH_IRQRAW_REG); + if (irq & FLASH_IRQ_ALL_ERR_Msk) { + whal_Reg_Write(base, FLASH_IRQSTAT_REG, FLASH_IRQ_ALL_ERR_Msk); + return WHAL_EHARDWARE; + } + if (irq & FLASH_IRQ_CMDSTART_Msk) + break; + } + whal_Reg_Write(base, FLASH_IRQSTAT_REG, FLASH_IRQ_CMDSTART_Msk); + + /* Wait for CMDDONE. */ + WHAL_TIMEOUT_START(timeout); + while (1) { + if (WHAL_TIMEOUT_EXPIRED(timeout)) + return WHAL_ETIMEOUT; + irq = whal_Reg_Read(base, FLASH_IRQRAW_REG); + if (irq & FLASH_IRQ_ALL_ERR_Msk) { + whal_Reg_Write(base, FLASH_IRQSTAT_REG, FLASH_IRQ_ALL_ERR_Msk); + err = WHAL_EHARDWARE; + /* Still clear CMDDONE if present so we don't leave it set. */ + whal_Reg_Write(base, FLASH_IRQSTAT_REG, FLASH_IRQ_CMDDONE_Msk); + return err; + } + if (irq & FLASH_IRQ_CMDDONE_Msk) + break; + } + whal_Reg_Write(base, FLASH_IRQSTAT_REG, FLASH_IRQ_CMDDONE_Msk); + + return WHAL_SUCCESS; +} + +/* + * Convert a byte address inside the main flash array into the + * controller's word-index format (page<<9 | row<<6 | word). + * + * The hardware uses ADDRESS[15:0] = XADR[9:0] & YADR[5:0]: + * XADR[9:3] = page address + * XADR[2:0] = row address (8 rows per page) + * YADR[5:0] = word address (64 words per row) + * Combined, the field is (byteOffset >> 2) where byteOffset is the + * offset from cfg->startAddr. The shift drops the 2-bit byte index + * since the controller addresses 32-bit words. + */ +static uint32_t whal_Stm32wb0_Flash_AddrToHw(const whal_Stm32wb0_Flash_Cfg *cfg, + size_t addr) +{ + return (uint32_t)((addr - cfg->startAddr) >> 2); +} + +whal_Error whal_Stm32wb0_Flash_Init(whal_Flash *flashDev) +{ + (void)flashDev; + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wb0_Flash_Deinit(whal_Flash *flashDev) +{ + (void)flashDev; + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wb0_Flash_Lock(whal_Flash *flashDev, size_t addr, + size_t len) +{ + (void)flashDev; + (void)addr; + (void)len; + /* The WB0 flash controller has no software lock register — all + * writes are gated only by the per-page PAGEPROT bits. */ + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wb0_Flash_Unlock(whal_Flash *flashDev, size_t addr, + size_t len) +{ + (void)flashDev; + (void)addr; + (void)len; + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wb0_Flash_Read(whal_Flash *flashDev, size_t addr, + void *data, size_t dataSz) +{ + const whal_Stm32wb0_Flash_Cfg *cfg = + (const whal_Stm32wb0_Flash_Cfg *)whal_Stm32wb0_Flash_Dev.cfg; + uint8_t *dataBuf = (uint8_t *)data; + (void)flashDev; + + if (!data) + return WHAL_EINVAL; + if (dataSz == 0) + return WHAL_SUCCESS; + if (addr < cfg->startAddr || addr + dataSz > cfg->startAddr + cfg->size) + return WHAL_EINVAL; + + /* Flash is memory-mapped; a simple byte copy is fine. */ + uint8_t *src = (uint8_t *)addr; + for (size_t i = 0; i < dataSz; ++i) + dataBuf[i] = src[i]; + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wb0_Flash_Write(whal_Flash *flashDev, size_t addr, + const void *data, size_t dataSz) +{ + const whal_Stm32wb0_Flash_Cfg *cfg = + (const whal_Stm32wb0_Flash_Cfg *)whal_Stm32wb0_Flash_Dev.cfg; + size_t base = whal_Stm32wb0_Flash_Dev.base; + const uint8_t *dataBuf = (const uint8_t *)data; + whal_Error err; + (void)flashDev; + + if (!data) + return WHAL_EINVAL; + if (dataSz == 0) + return WHAL_SUCCESS; + if (addr < cfg->startAddr || addr + dataSz > cfg->startAddr + cfg->size) + return WHAL_EINVAL; + /* The WRITE command programs one 32-bit word at a time; address and + * size must be word-aligned. */ + if ((addr & 0x3u) || (dataSz & 0x3u)) + return WHAL_EINVAL; + + for (size_t i = 0; i < dataSz; i += FLASH_WORD_SIZE) { + uint32_t word; + /* Copy bytewise to avoid relying on dataBuf alignment. */ + word = ((uint32_t)dataBuf[i + 0]) | + ((uint32_t)dataBuf[i + 1] << 8) | + ((uint32_t)dataBuf[i + 2] << 16) | + ((uint32_t)dataBuf[i + 3] << 24); + + whal_Reg_Write(base, FLASH_ADDRESS_REG, + whal_Stm32wb0_Flash_AddrToHw(cfg, addr + i)); + whal_Reg_Write(base, FLASH_DATA0_REG, word); + + err = whal_Stm32wb0_Flash_RunCommand(base, FLASH_COMMAND_WRITE, + cfg->timeout); + if (err) + return err; + } + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wb0_Flash_Erase(whal_Flash *flashDev, size_t addr, + size_t dataSz) +{ + const whal_Stm32wb0_Flash_Cfg *cfg = + (const whal_Stm32wb0_Flash_Cfg *)whal_Stm32wb0_Flash_Dev.cfg; + size_t base = whal_Stm32wb0_Flash_Dev.base; + whal_Error err; + (void)flashDev; + + if (dataSz == 0) + return WHAL_SUCCESS; + if (addr < cfg->startAddr || addr + dataSz > cfg->startAddr + cfg->size) + return WHAL_EINVAL; + + /* Round to the page that contains addr, then erase all pages that + * intersect [addr, addr+dataSz). */ + size_t firstPage = (addr - cfg->startAddr) / FLASH_PAGE_SIZE; + size_t lastPage = (addr - cfg->startAddr + dataSz - 1) / FLASH_PAGE_SIZE; + + for (size_t p = firstPage; p <= lastPage; ++p) { + /* For ERASE, ADDRESS[15:9] = page number, lower bits zero. */ + uint32_t hwAddr = (uint32_t)(p * FLASH_PAGE_SIZE / FLASH_WORD_SIZE); + whal_Reg_Write(base, FLASH_ADDRESS_REG, hwAddr); + + err = whal_Stm32wb0_Flash_RunCommand(base, FLASH_COMMAND_ERASE, + cfg->timeout); + if (err) + return err; + } + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wb0_Flash_Ext_SetLatency(whal_Flash *flashDev, + enum whal_Stm32wb0_Flash_Latency latency) +{ + size_t base = whal_Stm32wb0_Flash_Dev.base; + (void)flashDev; + + whal_Reg_Update(base, FLASH_CONFIG_REG, FLASH_CONFIG_WAIT_STATES_Msk, + whal_SetBits(FLASH_CONFIG_WAIT_STATES_Msk, + FLASH_CONFIG_WAIT_STATES_Pos, latency)); + return WHAL_SUCCESS; +} + +#ifndef WHAL_CFG_STM32WB0_FLASH_DIRECT_API_MAPPING +const whal_FlashDriver whal_Stm32wb0_Flash_Driver = { + .Init = whal_Stm32wb0_Flash_Init, + .Deinit = whal_Stm32wb0_Flash_Deinit, + .Lock = whal_Stm32wb0_Flash_Lock, + .Unlock = whal_Stm32wb0_Flash_Unlock, + .Read = whal_Stm32wb0_Flash_Read, + .Write = whal_Stm32wb0_Flash_Write, + .Erase = whal_Stm32wb0_Flash_Erase, +}; +#endif /* !WHAL_CFG_STM32WB0_FLASH_DIRECT_API_MAPPING */ diff --git a/src/gpio/stm32wb0_gpio.c b/src/gpio/stm32wb0_gpio.c new file mode 100644 index 0000000..4720d5f --- /dev/null +++ b/src/gpio/stm32wb0_gpio.c @@ -0,0 +1,163 @@ +/* stm32wb0_gpio.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 "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_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); + } + + 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) + return WHAL_EINVAL; + + pinCfg = cfg->pinCfg[idx]; + port = WHAL_STM32WB0_GPIO_GET_PORT(pinCfg); + pin = WHAL_STM32WB0_GPIO_GET_PIN(pinCfg); + + if (pin > 15) + return WHAL_EINVAL; + + portBase = whal_Stm32wb0_Gpio_Dev.base + (port * GPIO_PORT_STRIDE); + mask = 1UL << pin; + + if (set) { + whal_Reg_Update(portBase, GPIO_ODR_REG, mask, + whal_SetBits(mask, pin, *value)); + } 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 */ diff --git a/src/i2c/stm32wb0_i2c.c b/src/i2c/stm32wb0_i2c.c new file mode 100644 index 0000000..9607209 --- /dev/null +++ b/src/i2c/stm32wb0_i2c.c @@ -0,0 +1,7 @@ +#ifdef WHAL_CFG_STM32WB0_I2C_DIRECT_API_MAPPING +#define WHAL_CFG_STM32WB_I2C_DIRECT_API_MAPPING +#endif +#ifdef WHAL_CFG_STM32WB0_I2C_SINGLE_INSTANCE +#define WHAL_CFG_STM32WB_I2C_SINGLE_INSTANCE +#endif +#include "stm32wb_i2c.c" diff --git a/src/rng/stm32wb0_rng.c b/src/rng/stm32wb0_rng.c new file mode 100644 index 0000000..1865b7f --- /dev/null +++ b/src/rng/stm32wb0_rng.c @@ -0,0 +1,120 @@ +/* stm32wb0_rng.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 "board.h" /* provides WHAL_CFG_STM32WB0_RNG_DEV initializer */ +#include +#include +#include +#include +#include + +const whal_Rng whal_Stm32wb0_Rng_Dev = WHAL_CFG_STM32WB0_RNG_DEV; + +/* + * STM32WB0 RNG register layout (RM0529 section 14.2). All accesses must + * be 32-bit wide — narrower accesses raise an AHB error and hard fault. + */ + +/* Control register */ +#define RNG_CR_REG 0x00 +#define RNG_CR_RNG_DIS_Pos 2 +#define RNG_CR_RNG_DIS_Msk (1UL << RNG_CR_RNG_DIS_Pos) +#define RNG_CR_TST_CLK_Pos 3 +#define RNG_CR_TST_CLK_Msk (1UL << RNG_CR_TST_CLK_Pos) + +/* Status register */ +#define RNG_SR_REG 0x04 +#define RNG_SR_RNGRDY_Pos 0 +#define RNG_SR_RNGRDY_Msk (1UL << RNG_SR_RNGRDY_Pos) +#define RNG_SR_REVCLK_Pos 1 +#define RNG_SR_REVCLK_Msk (1UL << RNG_SR_REVCLK_Pos) +#define RNG_SR_FAULT_Pos 2 +#define RNG_SR_FAULT_Msk (1UL << RNG_SR_FAULT_Pos) + +/* Value register — 16-bit random sample in bits [15:0]. */ +#define RNG_VAL_REG 0x08 +#define RNG_VAL_Msk 0xFFFFu + +#ifdef WHAL_CFG_STM32WB0_RNG_DIRECT_API_MAPPING +#define whal_Stm32wb0_Rng_Init whal_Rng_Init +#define whal_Stm32wb0_Rng_Deinit whal_Rng_Deinit +#define whal_Stm32wb0_Rng_Generate whal_Rng_Generate +#endif /* WHAL_CFG_STM32WB0_RNG_DIRECT_API_MAPPING */ + +whal_Error whal_Stm32wb0_Rng_Init(whal_Rng *rngDev) +{ + size_t base = whal_Stm32wb0_Rng_Dev.base; + (void)rngDev; + + /* Full CR write: clears RNG_DIS to enable the oscillators and wipes + * any stale state the bootROM may have left in reserved bits. + * Matches ST's HAL/LL pattern. The TST_CLK / REVCLK probe is the + * optional clock-error detection feature, not a required init step. */ + whal_Reg_Write(base, RNG_CR_REG, 0); + + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wb0_Rng_Deinit(whal_Rng *rngDev) +{ + size_t base = whal_Stm32wb0_Rng_Dev.base; + (void)rngDev; + + /* Disable: set RNG_DIS to power down the internal free-running + * oscillators. */ + whal_Reg_Update(base, RNG_CR_REG, RNG_CR_RNG_DIS_Msk, + whal_SetBits(RNG_CR_RNG_DIS_Msk, RNG_CR_RNG_DIS_Pos, 1)); + return WHAL_SUCCESS; +} + +whal_Error whal_Stm32wb0_Rng_Generate(whal_Rng *rngDev, void *rngData, + size_t rngDataSz) +{ + uint8_t *rngBuf = (uint8_t *)rngData; + size_t base = whal_Stm32wb0_Rng_Dev.base; + size_t offset = 0; + (void)rngDev; + + if (!rngData) + return WHAL_EINVAL; + + while (offset < rngDataSz) { + + /* 32-bit-only read, low half is the random value. */ + uint32_t word = whal_Reg_Read(base, RNG_VAL_REG); + uint16_t rnd = (uint16_t)(word & RNG_VAL_Msk); + + for (size_t i = 0; i < 2 && offset < rngDataSz; i++, offset++) { + rngBuf[offset] = (uint8_t)(rnd >> (i * 8)); + } + } + + return WHAL_SUCCESS; +} + +#ifndef WHAL_CFG_STM32WB0_RNG_DIRECT_API_MAPPING +const whal_RngDriver whal_Stm32wb0_Rng_Driver = { + .Init = whal_Stm32wb0_Rng_Init, + .Deinit = whal_Stm32wb0_Rng_Deinit, + .Generate = whal_Stm32wb0_Rng_Generate, +}; +#endif /* !WHAL_CFG_STM32WB0_RNG_DIRECT_API_MAPPING */ diff --git a/src/spi/stm32wb0_spi.c b/src/spi/stm32wb0_spi.c new file mode 100644 index 0000000..131c7cb --- /dev/null +++ b/src/spi/stm32wb0_spi.c @@ -0,0 +1,7 @@ +#ifdef WHAL_CFG_STM32WB0_SPI_DIRECT_API_MAPPING +#define WHAL_CFG_STM32WB_SPI_DIRECT_API_MAPPING +#endif +#ifdef WHAL_CFG_STM32WB0_SPI_SINGLE_INSTANCE +#define WHAL_CFG_STM32WB_SPI_SINGLE_INSTANCE +#endif +#include "stm32wb_spi.c" diff --git a/src/uart/stm32wb0_uart.c b/src/uart/stm32wb0_uart.c new file mode 100644 index 0000000..12767e7 --- /dev/null +++ b/src/uart/stm32wb0_uart.c @@ -0,0 +1,7 @@ +#ifdef WHAL_CFG_STM32WB0_UART_DIRECT_API_MAPPING +#define WHAL_CFG_STM32WB_UART_DIRECT_API_MAPPING +#endif +#ifdef WHAL_CFG_STM32WB0_UART_SINGLE_INSTANCE +#define WHAL_CFG_STM32WB_UART_SINGLE_INSTANCE +#endif +#include "stm32wb_uart.c" diff --git a/src/watchdog/stm32wb0_iwdg.c b/src/watchdog/stm32wb0_iwdg.c new file mode 100644 index 0000000..fe8cf38 --- /dev/null +++ b/src/watchdog/stm32wb0_iwdg.c @@ -0,0 +1,4 @@ +#ifdef WHAL_CFG_STM32WB0_IWDG_DIRECT_API_MAPPING +#define WHAL_CFG_STM32WB_IWDG_DIRECT_API_MAPPING +#endif +#include "stm32wb_iwdg.c" diff --git a/wolfHAL/clock/stm32wb0_rcc.h b/wolfHAL/clock/stm32wb0_rcc.h new file mode 100644 index 0000000..8b81153 --- /dev/null +++ b/wolfHAL/clock/stm32wb0_rcc.h @@ -0,0 +1,311 @@ +/* stm32wb0_rcc.h + * + * 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 + */ + +#ifndef WHAL_STM32WB0_RCC_H +#define WHAL_STM32WB0_RCC_H + +#include +#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. + */ + +#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 + +/** + * @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). + */ +typedef enum { + WHAL_STM32WB0_RCC_SYSCLK_64MHZ = 0, + WHAL_STM32WB0_RCC_SYSCLK_32MHZ = 1, + WHAL_STM32WB0_RCC_SYSCLK_16MHZ = 2, + WHAL_STM32WB0_RCC_SYSCLK_8MHZ = 3, + WHAL_STM32WB0_RCC_SYSCLK_4MHZ = 4, + WHAL_STM32WB0_RCC_SYSCLK_2MHZ = 5, + WHAL_STM32WB0_RCC_SYSCLK_1MHZ = 6, +} whal_Stm32wb0_Rcc_SysClkDiv; + +/** + * @brief Fast clock source selection (RCC_CFGR.HSESEL). + */ +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; + +/** + * @brief Peripheral clock descriptor (RCC *ENR enable bit). + */ +typedef struct { + size_t regOffset; + size_t enableMask; + size_t enablePos; +} whal_Stm32wb0_Rcc_PeriphClk; + +/** + * @brief Enable the internal HSI64M oscillator (always on at reset on + * WB0; this just polls the ready bit defensively). + * + * @retval WHAL_SUCCESS Always. + */ +static inline whal_Error whal_Stm32wb0_Rcc_EnableHsi(void) +{ + size_t rdy; + + 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 Enable the LSI oscillator and wait for it to be ready. + * + * @retval WHAL_SUCCESS Always. + */ +static inline whal_Error whal_Stm32wb0_Rcc_EnableLsi(void) +{ + 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); + return WHAL_SUCCESS; +} + +/** + * @brief Disable the LSI oscillator. + * + * @retval WHAL_SUCCESS Always. + */ +static inline whal_Error whal_Stm32wb0_Rcc_DisableLsi(void) +{ + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, WHAL_STM32WB0_RCC_CR_REG, + WHAL_STM32WB0_RCC_CR_LSION_Msk, 0); + return WHAL_SUCCESS; +} + +/** + * @brief Enable the external HSE oscillator (32 MHz XO) and wait for it + * to be ready. + * + * @retval WHAL_SUCCESS Always. + */ +static inline whal_Error whal_Stm32wb0_Rcc_EnableHse(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); + return WHAL_SUCCESS; +} + +/** + * @brief Enable the RC64MPLL block that locks the internal 64 MHz RC onto + * the HSE reference. HSE must be enabled first. + * + * @retval WHAL_SUCCESS Always. + */ +static inline whal_Error whal_Stm32wb0_Rcc_EnableHsiPll(void) +{ + size_t rdy; + + 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; +} + +/** + * @brief Select the fast clock tree source (RC64MPLL vs direct HSE). + * + * 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. + * + * @retval WHAL_SUCCESS Always. + */ +static inline whal_Error whal_Stm32wb0_Rcc_SetFastClkSrc( + whal_Stm32wb0_Rcc_FastClkSrc src) +{ + 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); + return WHAL_SUCCESS; +} + +/** + * @brief Set the system clock divider (CLKSYSDIV) and wait for the + * frequency switch to apply. + * + * The hardware reports the active frequency in CLKSYSDIV_STATUS and may + * take up to ~128 system clock cycles to settle. + * + * @param div System clock divider selection. + * + * @retval WHAL_SUCCESS Always. + */ +static inline whal_Error whal_Stm32wb0_Rcc_SetSysClock( + whal_Stm32wb0_Rcc_SysClkDiv div) +{ + size_t status; + + 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_SUCCESS; +} + +/** + * @brief Set the enable bit for a peripheral clock gate. + * + * @param clk Peripheral clock descriptor (RCC *ENR register + bit). + * + * @retval WHAL_SUCCESS Always. + */ +static inline whal_Error whal_Stm32wb0_Rcc_EnablePeriphClk( + const whal_Stm32wb0_Rcc_PeriphClk *clk) +{ + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, clk->regOffset, clk->enableMask, + whal_SetBits(clk->enableMask, clk->enablePos, 1)); + return WHAL_SUCCESS; +} + +/** + * @brief Clear the enable bit for a peripheral clock gate. + * + * @param clk Peripheral clock descriptor (RCC *ENR register + bit). + * + * @retval WHAL_SUCCESS Always. + */ +static inline whal_Error whal_Stm32wb0_Rcc_DisablePeriphClk( + const whal_Stm32wb0_Rcc_PeriphClk *clk) +{ + whal_Reg_Update(WHAL_STM32WB0_RCC_BASE, clk->regOffset, clk->enableMask, + whal_SetBits(clk->enableMask, clk->enablePos, 0)); + return WHAL_SUCCESS; +} + +#endif /* WHAL_STM32WB0_RCC_H */ diff --git a/wolfHAL/crypto/stm32wb0_pka.h b/wolfHAL/crypto/stm32wb0_pka.h new file mode 100644 index 0000000..c5918a2 --- /dev/null +++ b/wolfHAL/crypto/stm32wb0_pka.h @@ -0,0 +1,68 @@ +/* stm32wb0_pka.h + * + * 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 + */ + +#ifndef WHAL_STM32WB0_PKA_H +#define WHAL_STM32WB0_PKA_H + +/** + * @file stm32wb0_pka.h + * @brief STM32WB0 public-key accelerator driver (alias for STM32WB PKA). + * + * The STM32WB0 PKA peripheral is register-compatible with the STM32WB + * PKA: + * - PKA_CR/SR/CLRFR at offsets 0x00/0x04/0x08 with matching bit + * positions (EN=0, START=1, MODE[13:8], PROCENDIE/F=17, + * RAMERRIE/F=19, ADDRERRIE/F=20). + * - Identical opcode list and operating modes (RM0529 sections + * 13.4.1–13.4.18). + * - Identical PKA RAM layout (PKA_RAM at +0x400). Modular + * exponentiation operand offsets at 0x400/0x404/0x594/0xA44/0xBD0/ + * 0xD5C are verified against RM0529 Table 38. + * This header re-exports the STM32WB PKA driver symbols under + * STM32WB0-specific names. + */ + +#include + +typedef whal_Stm32wb_Pka_Cfg whal_Stm32wb0_Pka_Cfg; + +#define whal_Stm32wb0_Pka_Dev whal_Stm32wb_Pka_Dev + +#ifndef WHAL_CFG_STM32WB0_PKA_INIT_DIRECT_API_MAPPING +#define whal_Stm32wb0_Pka_Init whal_Stm32wb_Pka_Init +#define whal_Stm32wb0_Pka_Deinit whal_Stm32wb_Pka_Deinit +#define whal_Stm32wb0_Pka_CryptoDriver whal_Stm32wb_Pka_CryptoDriver +#endif /* !WHAL_CFG_STM32WB0_PKA_INIT_DIRECT_API_MAPPING */ + +#ifndef WHAL_CFG_STM32WB0_PKA_DIRECT_API_MAPPING +#define whal_Stm32wb0_Pka_ModExp whal_Stm32wb_Pka_ModExp +#define whal_Stm32wb0_Pka_ModInv whal_Stm32wb_Pka_ModInv +#define whal_Stm32wb0_Pka_ModReduce whal_Stm32wb_Pka_ModReduce +#define whal_Stm32wb0_Pka_IntMul whal_Stm32wb_Pka_IntMul +#define whal_Stm32wb0_Pka_IntSub whal_Stm32wb_Pka_IntSub +#define whal_Stm32wb0_Pka_RsaCrtExp whal_Stm32wb_Pka_RsaCrtExp +#endif /* !WHAL_CFG_STM32WB0_PKA_DIRECT_API_MAPPING */ + +/* Config initializer macro alias. The WB0 board.h supplies the body under + * the WB0-prefixed name; the WB driver source consumes the WB name. */ +#define WHAL_CFG_STM32WB_PKA_DEV WHAL_CFG_STM32WB0_PKA_DEV + +#endif /* WHAL_STM32WB0_PKA_H */ diff --git a/wolfHAL/dma/stm32wb0_dma.h b/wolfHAL/dma/stm32wb0_dma.h new file mode 100644 index 0000000..9549df4 --- /dev/null +++ b/wolfHAL/dma/stm32wb0_dma.h @@ -0,0 +1,72 @@ +/* stm32wb0_dma.h + * + * 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 + */ + +#ifndef WHAL_STM32WB0_DMA_H +#define WHAL_STM32WB0_DMA_H + +/** + * @file stm32wb0_dma.h + * @brief STM32WB0 DMA driver (alias for STM32WB DMA). + * + * The STM32WB0 DMA controller is register-compatible with the STM32WB + * DMA (DMA_ISR/IFCR at 0x00/0x04, per-channel CCR/CNDTR/CPAR/CMAR at + * 0x08 + 0x14*(ch-1)), paired with the same DMAMUX layout. The WB0 + * has a single controller with 8 channels (vs WB's DMA1+DMA2 split). + * Boards configure cfg->numChannels = 8. + */ + +#include + +typedef whal_Stm32wb_Dma_Dir whal_Stm32wb0_Dma_Dir; +typedef whal_Stm32wb_Dma_Width whal_Stm32wb0_Dma_Width; +typedef whal_Stm32wb_Dma_Inc whal_Stm32wb0_Dma_Inc; +typedef whal_Stm32wb_Dma_ChCfg whal_Stm32wb0_Dma_ChCfg; +typedef whal_Stm32wb_Dma_Cfg whal_Stm32wb0_Dma_Cfg; +typedef whal_Stm32wb_Dma_Callback whal_Stm32wb0_Dma_Callback; + +#define whal_Stm32wb0_Dma_Dev whal_Stm32wb_Dma_Dev + +#ifndef WHAL_CFG_STM32WB0_DMA_DIRECT_API_MAPPING +#define whal_Stm32wb0_Dma_Driver whal_Stm32wb_Dma_Driver +#define whal_Stm32wb0_Dma_Init whal_Stm32wb_Dma_Init +#define whal_Stm32wb0_Dma_Deinit whal_Stm32wb_Dma_Deinit +#define whal_Stm32wb0_Dma_Configure whal_Stm32wb_Dma_Configure +#define whal_Stm32wb0_Dma_Start whal_Stm32wb_Dma_Start +#define whal_Stm32wb0_Dma_Stop whal_Stm32wb_Dma_Stop +#endif /* !WHAL_CFG_STM32WB0_DMA_DIRECT_API_MAPPING */ + +#define whal_Stm32wb0_Dma_IRQHandler whal_Stm32wb_Dma_IRQHandler + +/* Enum-value aliases. */ +#define WHAL_STM32WB0_DMA_DIR_PERIPH_TO_MEM WHAL_STM32WB_DMA_DIR_PERIPH_TO_MEM +#define WHAL_STM32WB0_DMA_DIR_MEM_TO_PERIPH WHAL_STM32WB_DMA_DIR_MEM_TO_PERIPH +#define WHAL_STM32WB0_DMA_DIR_MEM_TO_MEM WHAL_STM32WB_DMA_DIR_MEM_TO_MEM +#define WHAL_STM32WB0_DMA_WIDTH_8BIT WHAL_STM32WB_DMA_WIDTH_8BIT +#define WHAL_STM32WB0_DMA_WIDTH_16BIT WHAL_STM32WB_DMA_WIDTH_16BIT +#define WHAL_STM32WB0_DMA_WIDTH_32BIT WHAL_STM32WB_DMA_WIDTH_32BIT +#define WHAL_STM32WB0_DMA_INC_DISABLE WHAL_STM32WB_DMA_INC_DISABLE +#define WHAL_STM32WB0_DMA_INC_ENABLE WHAL_STM32WB_DMA_INC_ENABLE + +/* Config initializer macro alias. The WB0 board.h supplies the body under + * the WB0-prefixed name; the WB driver source consumes the WB name. */ +#define WHAL_CFG_STM32WB_DMA_DEV WHAL_CFG_STM32WB0_DMA_DEV + +#endif /* WHAL_STM32WB0_DMA_H */ diff --git a/wolfHAL/dma/stm32wb_dma.h b/wolfHAL/dma/stm32wb_dma.h index ed77dea..5496428 100644 --- a/wolfHAL/dma/stm32wb_dma.h +++ b/wolfHAL/dma/stm32wb_dma.h @@ -101,11 +101,13 @@ typedef struct { * @brief Single-instance device struct. Defined in the driver TU * from the WHAL_CFG_STM32WB_DMA_DEV initializer in board.h. */ -#ifdef WHAL_CFG_STM32WB_DMA_SINGLE_INSTANCE +#if defined(WHAL_CFG_STM32WB_DMA_SINGLE_INSTANCE) || \ + defined(WHAL_CFG_STM32WB0_DMA_SINGLE_INSTANCE) extern const whal_Dma whal_Stm32wb_Dma_Dev; #endif -#ifndef WHAL_CFG_STM32WB_DMA_DIRECT_API_MAPPING +#if !defined(WHAL_CFG_STM32WB_DMA_DIRECT_API_MAPPING) && \ + !defined(WHAL_CFG_STM32WB0_DMA_DIRECT_API_MAPPING) /* * @brief Driver instance for STM32WB DMA. */ diff --git a/wolfHAL/flash/stm32wb0_flash.h b/wolfHAL/flash/stm32wb0_flash.h new file mode 100644 index 0000000..3160c88 --- /dev/null +++ b/wolfHAL/flash/stm32wb0_flash.h @@ -0,0 +1,179 @@ +/* stm32wb0_flash.h + * + * 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 + */ + +#ifndef WHAL_STM32WB0_FLASH_H +#define WHAL_STM32WB0_FLASH_H + +#include +#include + +/** + * @file stm32wb0_flash.h + * @brief STM32WB0 flash driver configuration and helpers. + * + * The STM32WB0 flash controller uses a command-based interface that + * differs significantly from the rest of the STM32 line: + * - 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 = + * 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). + * - One specific address can be programmed at most twice between + * erases — the controller enforces this by only allowing 1->0 + * transitions. + */ + +/** + * @brief Flash device configuration. + */ +typedef struct whal_Stm32wb0_Flash_Cfg { + size_t startAddr; /* Flash base address (0x10040000 on WB0). */ + size_t size; /* Flash size in bytes (depends on device). */ + whal_Timeout *timeout; +} 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). + */ +typedef enum whal_Stm32wb0_Flash_Latency { + WHAL_STM32WB0_FLASH_LATENCY_0, + WHAL_STM32WB0_FLASH_LATENCY_1, +} whal_Stm32wb0_Flash_Latency; + +#ifndef WHAL_CFG_STM32WB0_FLASH_DIRECT_API_MAPPING +/** + * @brief Driver instance for STM32WB0 flash. + */ +extern const whal_FlashDriver whal_Stm32wb0_Flash_Driver; + +/** + * @brief Platform-owned flash device singleton. Defined in the driver TU + * from the WHAL_CFG_STM32WB0_FLASH_DEV initializer in board.h. + */ +extern const whal_Flash whal_Stm32wb0_Flash_Dev; + +/** + * @brief Initialize the STM32WB0 flash controller. + * + * No unlock sequence is required for write/erase on WB0 — the controller + * accepts opcodes directly. Init is a no-op kept for API consistency. + * + * @param flashDev Flash device instance. + * + * @retval WHAL_SUCCESS Always. + */ +whal_Error whal_Stm32wb0_Flash_Init(whal_Flash *flashDev); + +/** + * @brief Deinitialize the STM32WB0 flash controller. + * + * @param flashDev Flash device instance. + * + * @retval WHAL_SUCCESS Always. + */ +whal_Error whal_Stm32wb0_Flash_Deinit(whal_Flash *flashDev); + +/** + * @brief No-op lock (WB0 controller has no software lock register). + * + * @retval WHAL_SUCCESS Always. + */ +whal_Error whal_Stm32wb0_Flash_Lock(whal_Flash *flashDev, size_t addr, + size_t len); + +/** + * @brief No-op unlock (WB0 controller has no KEYR unlock sequence). + * + * @retval WHAL_SUCCESS Always. + */ +whal_Error whal_Stm32wb0_Flash_Unlock(whal_Flash *flashDev, size_t addr, + size_t len); + +/** + * @brief Read data from flash into a buffer (memory-mapped read). + * + * @param flashDev Flash device instance. + * @param addr Byte address in flash. + * @param data Destination buffer. + * @param dataSz Number of bytes to read. + * + * @retval WHAL_SUCCESS Read completed. + * @retval WHAL_EINVAL Null buffer or out-of-range range. + */ +whal_Error whal_Stm32wb0_Flash_Read(whal_Flash *flashDev, size_t addr, + void *data, size_t dataSz); + +/** + * @brief Program flash one 32-bit word at a time via the WRITE command. + * + * Address and size must be 4-byte aligned. The controller enforces a + * 1->0-only programming rule — overwriting requires an Erase first. + * + * @param flashDev Flash device instance. + * @param addr Byte address in flash. + * @param data Buffer to program. + * @param dataSz Number of bytes to program. + * + * @retval WHAL_SUCCESS Write completed. + * @retval WHAL_EINVAL Misaligned, null, or out-of-range arguments. + * @retval WHAL_ETIMEOUT Command did not complete before timeout. + * @retval WHAL_EHARDWARE Controller reported CMDERR or ILLCMD. + */ +whal_Error whal_Stm32wb0_Flash_Write(whal_Flash *flashDev, size_t addr, + const void *data, size_t dataSz); + +/** + * @brief Erase one or more 2 KB pages covering the requested range. + * + * @param flashDev Flash device instance. + * @param addr Byte address inside the first page to erase. + * @param dataSz Number of bytes to erase (rounded up to page size). + * + * @retval WHAL_SUCCESS Erase completed. + * @retval WHAL_EINVAL Out-of-range range. + * @retval WHAL_ETIMEOUT Command did not complete before timeout. + * @retval WHAL_EHARDWARE Controller reported CMDERR or ILLCMD. + */ +whal_Error whal_Stm32wb0_Flash_Erase(whal_Flash *flashDev, size_t addr, + size_t dataSz); +#endif /* !WHAL_CFG_STM32WB0_FLASH_DIRECT_API_MAPPING */ + +/** + * @brief Update flash latency wait states. + * + * @param flashDev Flash device instance. + * @param latency Latency setting to apply. + * + * @retval WHAL_SUCCESS Always. + */ +whal_Error whal_Stm32wb0_Flash_Ext_SetLatency(whal_Flash *flashDev, + enum whal_Stm32wb0_Flash_Latency latency); + +#endif /* WHAL_STM32WB0_FLASH_H */ diff --git a/wolfHAL/gpio/stm32wb0_gpio.h b/wolfHAL/gpio/stm32wb0_gpio.h new file mode 100644 index 0000000..253bbc5 --- /dev/null +++ b/wolfHAL/gpio/stm32wb0_gpio.h @@ -0,0 +1,132 @@ +/* stm32wb0_gpio.h + * + * 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 + */ + +#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. + * + * 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). + * + * 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 + */ +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_STM32WB0_GPIO_PORT_A 0 +#define WHAL_STM32WB0_GPIO_PORT_B 1 + +#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 + +#define WHAL_STM32WB0_GPIO_OUTTYPE_PUSHPULL 0 +#define WHAL_STM32WB0_GPIO_OUTTYPE_OPENDRAIN 1 + +#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 + +#define WHAL_STM32WB0_GPIO_PULL_NONE 0 +#define WHAL_STM32WB0_GPIO_PULL_UP 1 +#define WHAL_STM32WB0_GPIO_PULL_DOWN 2 + +/** + * @brief Pack a pin configuration into a uint32_t. + */ +#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_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 device configuration. + */ +typedef struct { + const whal_Stm32wb0_Gpio_PinCfg *pinCfg; + size_t pinCount; +} whal_Stm32wb0_Gpio_Cfg; + +/** + * @brief Platform-owned GPIO device singleton. Defined in the driver TU + * from the WHAL_CFG_STM32WB0_GPIO_DEV initializer in board.h. + */ +extern const whal_Gpio whal_Stm32wb0_Gpio_Dev; + +#ifndef WHAL_CFG_STM32WB0_GPIO_DIRECT_API_MAPPING +extern const whal_GpioDriver whal_Stm32wb0_Gpio_Driver; + +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 */ + +#endif /* WHAL_STM32WB0_GPIO_H */ diff --git a/wolfHAL/i2c/stm32wb0_i2c.h b/wolfHAL/i2c/stm32wb0_i2c.h new file mode 100644 index 0000000..debece5 --- /dev/null +++ b/wolfHAL/i2c/stm32wb0_i2c.h @@ -0,0 +1,54 @@ +/* stm32wb0_i2c.h + * + * 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 + */ + +#ifndef WHAL_STM32WB0_I2C_H +#define WHAL_STM32WB0_I2C_H + +/** + * @file stm32wb0_i2c.h + * @brief STM32WB0 I2C driver (alias for STM32WB I2C). + * + * The STM32WB0 I2C peripheral is register-compatible with the wider + * STM32 V2 I2C (CR1, CR2, TIMINGR, ISR, ICR, RXDR, TXDR layout per + * RM0529 section 21.6). This header re-exports the STM32WB I2C driver + * types and symbols under STM32WB0-specific names. + */ + +#include + +typedef whal_Stm32wb_I2c_Cfg whal_Stm32wb0_I2c_Cfg; + +#define whal_Stm32wb0_I2c_Dev whal_Stm32wb_I2c_Dev + +#ifndef WHAL_CFG_STM32WB0_I2C_DIRECT_API_MAPPING +#define whal_Stm32wb0_I2c_Driver whal_Stm32wb_I2c_Driver +#define whal_Stm32wb0_I2c_Init whal_Stm32wb_I2c_Init +#define whal_Stm32wb0_I2c_Deinit whal_Stm32wb_I2c_Deinit +#define whal_Stm32wb0_I2c_StartCom whal_Stm32wb_I2c_StartCom +#define whal_Stm32wb0_I2c_EndCom whal_Stm32wb_I2c_EndCom +#define whal_Stm32wb0_I2c_Transfer whal_Stm32wb_I2c_Transfer +#endif /* !WHAL_CFG_STM32WB0_I2C_DIRECT_API_MAPPING */ + +/* Config initializer macro alias. The WB0 board.h supplies the body under + * the WB0-prefixed name; the WB driver source consumes the WB name. */ +#define WHAL_CFG_STM32WB_I2C_DEV WHAL_CFG_STM32WB0_I2C_DEV + +#endif /* WHAL_STM32WB0_I2C_H */ diff --git a/wolfHAL/i2c/stm32wb_i2c.h b/wolfHAL/i2c/stm32wb_i2c.h index f12f5e3..5b1d784 100644 --- a/wolfHAL/i2c/stm32wb_i2c.h +++ b/wolfHAL/i2c/stm32wb_i2c.h @@ -55,7 +55,8 @@ typedef struct whal_Stm32wb_I2c_Cfg { #if defined(WHAL_CFG_STM32WB_I2C_SINGLE_INSTANCE) || \ defined(WHAL_CFG_STM32F0_I2C_SINGLE_INSTANCE) || \ defined(WHAL_CFG_STM32F3_I2C_SINGLE_INSTANCE) || \ - defined(WHAL_CFG_STM32N6_I2C_SINGLE_INSTANCE) + defined(WHAL_CFG_STM32N6_I2C_SINGLE_INSTANCE) || \ + defined(WHAL_CFG_STM32WB0_I2C_SINGLE_INSTANCE) extern const whal_I2c whal_Stm32wb_I2c_Dev; #endif diff --git a/wolfHAL/platform/st/stm32wb05kz.h b/wolfHAL/platform/st/stm32wb05kz.h new file mode 100644 index 0000000..21cbe6a --- /dev/null +++ b/wolfHAL/platform/st/stm32wb05kz.h @@ -0,0 +1,204 @@ +/* stm32wb05kz.h + * + * 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 + */ + +#ifndef WHAL_STM32WB05KZ_H +#define WHAL_STM32WB05KZ_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @file stm32wb05kz.h + * @brief Convenience initializers for STM32WB05KZ device instances. + * + * Base addresses from RM0529 Table 3 (STM32WB05xZ memory map and + * peripheral register boundary addresses). + * + * GPIOA 0x48000000 (1 KB) + * GPIOB 0x48100000 (1 KB) — port stride is 1 MB, not 0x400 + * CRC 0x48200000 + * PKA slave 0x48300000 (PKA RAM at +0x400) + * RCC 0x48400000 + * PWRC 0x48500000 + * RNG 0x48600000 + * DMA slave 0x48700000 (8 channels) + * DMAMUX 0x48800000 + * SYSCFG 0x40000000 + * FLASH_CTRL 0x40001000 + * TIM2 0x40002000 + * IWDG 0x40003000 + * RTC 0x40004000 + * TIM16 0x40005000 + * TIM17 0x40006000 + * I2C1 0x41000000 + * USART 0x41004000 + * LPUART 0x41005000 + * ADC 0x41006000 + * SPI3 0x41007000 + * + * Main flash array is memory-mapped at 0x10040000 (192 KB on WB05KZ). + */ + +/* --- 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 + +/* --- 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 + +/* --- Peripheral clock gate descriptors --- + * RCC base 0x48400000; offsets are register-from-base. + * AHBENR 0x50 — GPIO, DMA, CRC, PKA, RNG + * APB0ENR 0x54 — TIM2/16/17, RTC, IWDG, SYSCFG + * APB1ENR 0x58 — USART, LPUART, SPI3, I2C1, ADC + * APB2ENR 0x60 — MR_BLE radio + */ + +/* RCC_AHBENR (offset 0x50) */ +#define WHAL_STM32WB05_DMA1_CLOCK \ + .regOffset = 0x50, \ + .enableMask = (1UL << 0), \ + .enablePos = 0 + +#define WHAL_STM32WB05_GPIOA_CLOCK \ + .regOffset = 0x50, \ + .enableMask = (1UL << 2), \ + .enablePos = 2 + +#define WHAL_STM32WB05_GPIOB_CLOCK \ + .regOffset = 0x50, \ + .enableMask = (1UL << 3), \ + .enablePos = 3 + +#define WHAL_STM32WB05_CRC_CLOCK \ + .regOffset = 0x50, \ + .enableMask = (1UL << 12), \ + .enablePos = 12 + +#define WHAL_STM32WB05_PKA_CLOCK \ + .regOffset = 0x50, \ + .enableMask = (1UL << 16), \ + .enablePos = 16 + +#define WHAL_STM32WB05_RNG_CLOCK \ + .regOffset = 0x50, \ + .enableMask = (1UL << 18), \ + .enablePos = 18 + +/* RCC_APB0ENR (offset 0x54) */ +#define WHAL_STM32WB05_TIM2_CLOCK \ + .regOffset = 0x54, \ + .enableMask = (1UL << 0), \ + .enablePos = 0 + +#define WHAL_STM32WB05_TIM16_CLOCK \ + .regOffset = 0x54, \ + .enableMask = (1UL << 1), \ + .enablePos = 1 + +#define WHAL_STM32WB05_TIM17_CLOCK \ + .regOffset = 0x54, \ + .enableMask = (1UL << 2), \ + .enablePos = 2 + +#define WHAL_STM32WB05_SYSCFG_CLOCK \ + .regOffset = 0x54, \ + .enableMask = (1UL << 8), \ + .enablePos = 8 + +#define WHAL_STM32WB05_RTC_CLOCK \ + .regOffset = 0x54, \ + .enableMask = (1UL << 12), \ + .enablePos = 12 + +#define WHAL_STM32WB05_IWDG_CLOCK \ + .regOffset = 0x54, \ + .enableMask = (1UL << 14), \ + .enablePos = 14 + +/* RCC_APB1ENR (offset 0x58) */ +#define WHAL_STM32WB05_ADCDIG_CLOCK \ + .regOffset = 0x58, \ + .enableMask = (1UL << 4), \ + .enablePos = 4 + +#define WHAL_STM32WB05_ADCANA_CLOCK \ + .regOffset = 0x58, \ + .enableMask = (1UL << 5), \ + .enablePos = 5 + +#define WHAL_STM32WB05_LPUART1_CLOCK \ + .regOffset = 0x58, \ + .enableMask = (1UL << 8), \ + .enablePos = 8 + +#define WHAL_STM32WB05_USART1_CLOCK \ + .regOffset = 0x58, \ + .enableMask = (1UL << 10), \ + .enablePos = 10 + +#define WHAL_STM32WB05_SPI3_CLOCK \ + .regOffset = 0x58, \ + .enableMask = (1UL << 14), \ + .enablePos = 14 + +#define WHAL_STM32WB05_I2C1_CLOCK \ + .regOffset = 0x58, \ + .enableMask = (1UL << 21), \ + .enablePos = 21 + +#endif /* WHAL_STM32WB05KZ_H */ diff --git a/wolfHAL/rng/stm32wb0_rng.h b/wolfHAL/rng/stm32wb0_rng.h new file mode 100644 index 0000000..d27b43a --- /dev/null +++ b/wolfHAL/rng/stm32wb0_rng.h @@ -0,0 +1,102 @@ +/* stm32wb0_rng.h + * + * 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 + */ + +#ifndef WHAL_STM32WB0_RNG_H +#define WHAL_STM32WB0_RNG_H + +#include +#include +#include + +/** + * @file stm32wb0_rng.h + * @brief STM32WB0 RNG driver configuration. + * + * The STM32WB0 RNG is a Bluetooth-LE-oriented true random number generator + * that differs from the standard STM32 RNG IP: + * - RNG_VAL is a 16-bit register (not 32-bit DR), delivered every 20 + * RNGCLK cycles. Reads stall the AHB bus until a value is available. + * - Only 32-bit accesses are allowed on the RNG registers; an 8-bit or + * 16-bit access generates an AHB fault. + * - RNG_CR has RNG_DIS at bit 2 (active-low disable; cleared at reset) + * and TST_CLK at bit 3. + * - RNG_SR exposes RNGRDY (bit 0), REVCLK (bit 1), and FAULT (bit 2). + * - No CONDRST, no CED, no clock source selection — RNGCLK is a fixed + * 16 MHz internal feed enabled through RCC_AHBENR.RNGEN. + */ + +/** + * @brief RNG device configuration. + */ +typedef struct whal_Stm32wb0_Rng_Cfg { + whal_Timeout *timeout; +} whal_Stm32wb0_Rng_Cfg; + +/** + * @brief Platform-owned RNG device singleton. Defined in the driver TU + * from the WHAL_CFG_STM32WB0_RNG_DEV initializer in board.h. + */ +extern const whal_Rng whal_Stm32wb0_Rng_Dev; + +#ifndef WHAL_CFG_STM32WB0_RNG_DIRECT_API_MAPPING +/** + * @brief Driver instance for STM32WB0 RNG peripheral. + */ +extern const whal_RngDriver whal_Stm32wb0_Rng_Driver; + +/** + * @brief Initialize the STM32WB0 RNG peripheral. + * + * Enables the RNG analog block (clears RNG_DIS). + * + * @param rngDev RNG device instance. + * + * @retval WHAL_SUCCESS Initialization completed. + */ +whal_Error whal_Stm32wb0_Rng_Init(whal_Rng *rngDev); +/** + * @brief Deinitialize the STM32WB0 RNG peripheral. + * + * Disables the RNG by setting RNG_DIS to put the internal free-running + * oscillators into power-down. + * + * @param rngDev RNG device instance. + * + * @retval WHAL_SUCCESS Deinit completed. + */ +whal_Error whal_Stm32wb0_Rng_Deinit(whal_Rng *rngDev); +/** + * @brief Generate random data. + * + * Reads 16-bit RNG_VAL values until rngDataSz bytes have been delivered. + * + * @param rngDev RNG device instance. + * @param rngData Destination buffer. + * @param rngDataSz Number of random bytes to generate. + * + * @retval WHAL_SUCCESS Buffer filled with random data. + * @retval WHAL_EINVAL Null destination buffer. + */ +whal_Error whal_Stm32wb0_Rng_Generate(whal_Rng *rngDev, void *rngData, + size_t rngDataSz); +#endif /* !WHAL_CFG_STM32WB0_RNG_DIRECT_API_MAPPING */ + +#endif /* WHAL_STM32WB0_RNG_H */ diff --git a/wolfHAL/spi/stm32wb0_spi.h b/wolfHAL/spi/stm32wb0_spi.h new file mode 100644 index 0000000..c0c2d89 --- /dev/null +++ b/wolfHAL/spi/stm32wb0_spi.h @@ -0,0 +1,55 @@ +/* stm32wb0_spi.h + * + * 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 + */ + +#ifndef WHAL_STM32WB0_SPI_H +#define WHAL_STM32WB0_SPI_H + +/** + * @file stm32wb0_spi.h + * @brief STM32WB0 SPI driver (alias for STM32WB SPI). + * + * The STM32WB0 SPI3 peripheral is register-compatible with the STM32WB + * SPI (V1 SPI: CR1 layout with CPHA=0, CPOL=1, MSTR=2, BR[2:0]=3..5, + * SPE=6, SSI=8, SSM=9; CR2 with DS=8..11, FRXTH=12; SR with RXNE=0, + * TXE=1, BSY=7; DR at 0x0C). This header re-exports the STM32WB SPI + * driver types and symbols under STM32WB0-specific names. + */ + +#include + +typedef whal_Stm32wb_Spi_Cfg whal_Stm32wb0_Spi_Cfg; + +#define whal_Stm32wb0_Spi_Dev whal_Stm32wb_Spi_Dev + +#ifndef WHAL_CFG_STM32WB0_SPI_DIRECT_API_MAPPING +#define whal_Stm32wb0_Spi_Driver whal_Stm32wb_Spi_Driver +#define whal_Stm32wb0_Spi_Init whal_Stm32wb_Spi_Init +#define whal_Stm32wb0_Spi_Deinit whal_Stm32wb_Spi_Deinit +#define whal_Stm32wb0_Spi_StartCom whal_Stm32wb_Spi_StartCom +#define whal_Stm32wb0_Spi_EndCom whal_Stm32wb_Spi_EndCom +#define whal_Stm32wb0_Spi_SendRecv whal_Stm32wb_Spi_SendRecv +#endif /* !WHAL_CFG_STM32WB0_SPI_DIRECT_API_MAPPING */ + +/* Config initializer macro alias. The WB0 board.h supplies the body under + * the WB0-prefixed name; the WB driver source consumes the WB name. */ +#define WHAL_CFG_STM32WB_SPI_DEV WHAL_CFG_STM32WB0_SPI_DEV + +#endif /* WHAL_STM32WB0_SPI_H */ diff --git a/wolfHAL/spi/stm32wb_spi.h b/wolfHAL/spi/stm32wb_spi.h index 34d1c9b..bfee6a5 100644 --- a/wolfHAL/spi/stm32wb_spi.h +++ b/wolfHAL/spi/stm32wb_spi.h @@ -55,12 +55,14 @@ typedef struct whal_Stm32wb_Spi_Cfg { #if defined(WHAL_CFG_STM32WB_SPI_SINGLE_INSTANCE) || \ defined(WHAL_CFG_STM32C0_SPI_SINGLE_INSTANCE) || \ defined(WHAL_CFG_STM32F0_SPI_SINGLE_INSTANCE) || \ - defined(WHAL_CFG_STM32F3_SPI_SINGLE_INSTANCE) + defined(WHAL_CFG_STM32F3_SPI_SINGLE_INSTANCE) || \ + defined(WHAL_CFG_STM32WB0_SPI_SINGLE_INSTANCE) extern const whal_Spi whal_Stm32wb_Spi_Dev; #endif #if !defined(WHAL_CFG_STM32WB_SPI_DIRECT_API_MAPPING) && \ - !defined(WHAL_CFG_STM32C0_SPI_DIRECT_API_MAPPING) + !defined(WHAL_CFG_STM32C0_SPI_DIRECT_API_MAPPING) && \ + !defined(WHAL_CFG_STM32WB0_SPI_DIRECT_API_MAPPING) /* * @brief Driver instance for STM32 SPI peripheral. */ diff --git a/wolfHAL/uart/stm32wb0_uart.h b/wolfHAL/uart/stm32wb0_uart.h new file mode 100644 index 0000000..10ad7e0 --- /dev/null +++ b/wolfHAL/uart/stm32wb0_uart.h @@ -0,0 +1,59 @@ +/* stm32wb0_uart.h + * + * 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 + */ + +#ifndef WHAL_STM32WB0_UART_H +#define WHAL_STM32WB0_UART_H + +/** + * @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. + */ + +#include + +typedef whal_Stm32wb_Uart_Cfg whal_Stm32wb0_Uart_Cfg; + +#define whal_Stm32wb0_Uart_Dev whal_Stm32wb_Uart_Dev + +#ifndef WHAL_CFG_STM32WB0_UART_DIRECT_API_MAPPING +#define whal_Stm32wb0_Uart_Driver whal_Stm32wb_Uart_Driver +#define whal_Stm32wb0_Uart_Init whal_Stm32wb_Uart_Init +#define whal_Stm32wb0_Uart_Deinit whal_Stm32wb_Uart_Deinit +#define whal_Stm32wb0_Uart_Send whal_Stm32wb_Uart_Send +#define whal_Stm32wb0_Uart_Recv whal_Stm32wb_Uart_Recv +#endif /* !WHAL_CFG_STM32WB0_UART_DIRECT_API_MAPPING */ + +/** + * @brief Baud rate register helpers (re-exported from STM32WB). + */ +#define WHAL_STM32WB0_UART_BRR WHAL_STM32WB_UART_BRR +#define WHAL_STM32WB0_LPUART_BRR WHAL_STM32WB_LPUART_BRR + +/* Config initializer macro alias. The WB0 board.h supplies the body under + * the WB0-prefixed name; the WB driver source consumes the WB name. */ +#define WHAL_CFG_STM32WB_UART_DEV WHAL_CFG_STM32WB0_UART_DEV + +#endif /* WHAL_STM32WB0_UART_H */ diff --git a/wolfHAL/uart/stm32wb_uart.h b/wolfHAL/uart/stm32wb_uart.h index 5365c53..a6ced2c 100644 --- a/wolfHAL/uart/stm32wb_uart.h +++ b/wolfHAL/uart/stm32wb_uart.h @@ -59,7 +59,8 @@ typedef struct whal_Stm32wb_Uart_Cfg { defined(WHAL_CFG_STM32H5_UART_SINGLE_INSTANCE) || \ defined(WHAL_CFG_STM32C0_UART_SINGLE_INSTANCE) || \ defined(WHAL_CFG_STM32N6_UART_SINGLE_INSTANCE) || \ - defined(WHAL_CFG_STM32WBA_UART_SINGLE_INSTANCE) + defined(WHAL_CFG_STM32WBA_UART_SINGLE_INSTANCE) || \ + defined(WHAL_CFG_STM32WB0_UART_SINGLE_INSTANCE) extern const whal_Uart whal_Stm32wb_Uart_Dev; #endif @@ -68,7 +69,8 @@ extern const whal_Uart whal_Stm32wb_Uart_Dev; !defined(WHAL_CFG_STM32H5_UART_DIRECT_API_MAPPING) && \ !defined(WHAL_CFG_STM32C0_UART_DIRECT_API_MAPPING) && \ !defined(WHAL_CFG_STM32N6_UART_DIRECT_API_MAPPING) && \ - !defined(WHAL_CFG_STM32WBA_UART_DIRECT_API_MAPPING) + !defined(WHAL_CFG_STM32WBA_UART_DIRECT_API_MAPPING) && \ + !defined(WHAL_CFG_STM32WB0_UART_DIRECT_API_MAPPING) /* * @brief Polled UART driver. Implements Init, Deinit, Send, Recv. */ diff --git a/wolfHAL/watchdog/stm32wb0_iwdg.h b/wolfHAL/watchdog/stm32wb0_iwdg.h new file mode 100644 index 0000000..a49379d --- /dev/null +++ b/wolfHAL/watchdog/stm32wb0_iwdg.h @@ -0,0 +1,65 @@ +/* stm32wb0_iwdg.h + * + * 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 + */ + +#ifndef WHAL_STM32WB0_IWDG_H +#define WHAL_STM32WB0_IWDG_H + +/** + * @file stm32wb0_iwdg.h + * @brief STM32WB0 IWDG driver (alias for STM32WB IWDG). + * + * The STM32WB0 IWDG is register-compatible with the wider STM32 IWDG: + * key register (IWDG_KR) at 0x00 with the 0xCCCC/0xAAAA/0x5555 key + * sequence, prescaler at 0x04, reload at 0x08, status at 0x0C with + * PVU/RVU/WVU update flags. The window register (IWDG_WINR) exists + * on WB0 but the WB driver does not configure it; the WVU status bit + * is therefore left out of the update poll. + */ + +#include + +typedef whal_Stm32wb_Iwdg_Cfg whal_Stm32wb0_Iwdg_Cfg; + +#define whal_Stm32wb0_Iwdg_Dev whal_Stm32wb_Iwdg_Dev + +#ifndef WHAL_CFG_STM32WB0_IWDG_DIRECT_API_MAPPING +#define whal_Stm32wb0_Iwdg_Driver whal_Stm32wb_Iwdg_Driver +#define whal_Stm32wb0_Iwdg_Init whal_Stm32wb_Iwdg_Init +#define whal_Stm32wb0_Iwdg_Deinit whal_Stm32wb_Iwdg_Deinit +#define whal_Stm32wb0_Iwdg_Refresh whal_Stm32wb_Iwdg_Refresh +#endif /* !WHAL_CFG_STM32WB0_IWDG_DIRECT_API_MAPPING */ + +/** + * @brief Prescaler values (re-exported from STM32WB). + */ +#define WHAL_STM32WB0_IWDG_PR_4 WHAL_STM32WB_IWDG_PR_4 +#define WHAL_STM32WB0_IWDG_PR_8 WHAL_STM32WB_IWDG_PR_8 +#define WHAL_STM32WB0_IWDG_PR_16 WHAL_STM32WB_IWDG_PR_16 +#define WHAL_STM32WB0_IWDG_PR_32 WHAL_STM32WB_IWDG_PR_32 +#define WHAL_STM32WB0_IWDG_PR_64 WHAL_STM32WB_IWDG_PR_64 +#define WHAL_STM32WB0_IWDG_PR_128 WHAL_STM32WB_IWDG_PR_128 +#define WHAL_STM32WB0_IWDG_PR_256 WHAL_STM32WB_IWDG_PR_256 + +/* Config initializer macro alias. The WB0 board.h supplies the body under + * the WB0-prefixed name; the WB driver source consumes the WB name. */ +#define WHAL_CFG_STM32WB_IWDG_DEV WHAL_CFG_STM32WB0_IWDG_DEV + +#endif /* WHAL_STM32WB0_IWDG_H */