From c4827937bac4d4806f51f653512fcd401b544172 Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Fri, 12 Jun 2026 11:52:47 -0400 Subject: [PATCH] Implement port for STM32WBA. Bump wolfHAL lib to latest --- .github/workflows/test-configs.yml | 6 ++ arch.mk | 6 ++ config/examples/stm32wba.config | 19 ++++ hal/boards/stm32wba55cg_nucleo/board.c | 133 ++++++++++++++++++++++++ hal/boards/stm32wba55cg_nucleo/board.h | 117 +++++++++++++++++++++ hal/boards/stm32wba55cg_nucleo/board.mk | 42 ++++++++ hal/stm32wba.ld | 50 +++++++++ lib/wolfHAL | 2 +- 8 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 config/examples/stm32wba.config create mode 100644 hal/boards/stm32wba55cg_nucleo/board.c create mode 100644 hal/boards/stm32wba55cg_nucleo/board.h create mode 100644 hal/boards/stm32wba55cg_nucleo/board.mk create mode 100644 hal/stm32wba.ld diff --git a/.github/workflows/test-configs.yml b/.github/workflows/test-configs.yml index 862e79a641..42ab51890a 100644 --- a/.github/workflows/test-configs.yml +++ b/.github/workflows/test-configs.yml @@ -674,6 +674,12 @@ jobs: config-file: ./config/examples/stm32wb.config make-args: WOLFHAL=1 BOARD=stm32wb_nucleo + stm32wba_wolfhal_test: + uses: ./.github/workflows/test-build.yml + with: + arch: arm + config-file: ./config/examples/stm32wba.config + # TODO: ti-tms570lc435.config requires F021 Flash API (Windows installer only) # ti_tms570lc435_test: # uses: ./.github/workflows/test-build-ti-hercules.yml diff --git a/arch.mk b/arch.mk index e9dd8af33f..6306e3bf71 100644 --- a/arch.mk +++ b/arch.mk @@ -243,6 +243,12 @@ ifeq ($(ARCH),ARM) endif endif + ifeq ($(TARGET),stm32wba) + CORTEX_M33=1 + ARCH_FLASH_OFFSET=0x08000000 + SPI_TARGET=stm32 + endif + ifeq ($(TARGET),stm32l5) CORTEX_M33=1 CFLAGS+=-Ihal diff --git a/config/examples/stm32wba.config b/config/examples/stm32wba.config new file mode 100644 index 0000000000..eabb9cee97 --- /dev/null +++ b/config/examples/stm32wba.config @@ -0,0 +1,19 @@ +# STM32WBA55CG Nucleo, wolfBoot on the wolfHAL backend. +# +# Flash: 1 MB at 0x08000000, 8 KB pages, 128-bit (16-byte) aligned writes. +# Non-secure / flat mode (the wolfHAL stm32wba flash driver uses the NS +# flash registers). Bootloader occupies the first 64 KB; two 128 KB +# partitions plus an 8 KB swap follow. +TARGET=stm32wba +BOARD=stm32wba55cg_nucleo +WOLFHAL=1 +ARCH=ARM +SIGN=ECC256 +HASH=SHA256 +NO_MPU=1 +WOLFBOOT_SECTOR_SIZE=0x2000 +WOLFBOOT_PARTITION_SIZE=0x20000 +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x08010000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x08030000 +WOLFBOOT_PARTITION_SWAP_ADDRESS=0x08050000 +NVM_FLASH_WRITEONCE=1 diff --git a/hal/boards/stm32wba55cg_nucleo/board.c b/hal/boards/stm32wba55cg_nucleo/board.c new file mode 100644 index 0000000000..b87db21ec5 --- /dev/null +++ b/hal/boards/stm32wba55cg_nucleo/board.c @@ -0,0 +1,133 @@ +/* board.c + * + * STM32WBA55CG Nucleo board configuration using upstream wolfHAL drivers. + * Flash/Gpio/Uart singletons are instantiated by the driver .c files from + * the WHAL_CFG_* initializer macros in board.h; board.c uses the + * BOARD_*_DEV handles for the rest. RCC is header-inlined and hardcodes + * its base — no dev pointer needed. + * + * Clock target: HSE32 -> PLL1 (M=1, N=25, R=3) -> SYSCLK = 100 MHz, which + * requires PWR voltage scaling Range 1 and 3 flash wait states (RM0493). + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot 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. + * + * wolfBoot 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 "hal.h" +#include "board.h" + +/* Flash clock gate — enabled before raising the wait-state count. */ +static const whal_Stm32wba_Rcc_PeriphClk g_flashClock = {WHAL_STM32WBA55_FLASH_CLOCK}; + +#ifdef DEBUG_UART +/* GPIO ports A (LED PA9, USART1 RX PA8) and B (USART1 TX PB12) plus USART1. */ +static const whal_Stm32wba_Rcc_PeriphClk g_periphClks[] = { + {WHAL_STM32WBA55_GPIOA_CLOCK}, + {WHAL_STM32WBA55_GPIOB_CLOCK}, + {WHAL_STM32WBA55_USART1_CLOCK}, +}; +#define PERIPH_CLK_COUNT (sizeof(g_periphClks) / sizeof(g_periphClks[0])) +#endif + +/* + * Switch PWR voltage scaling to Range 1 (required for >16 MHz operation). + * After reset the device is in Range 2 (max 16 MHz). Must switch to Range 1 + * before configuring PLL or increasing SYSCLK. + * + * PWR base: 0x46020800, PWR_VOSR offset 0x00C + * bit 16 VOS: 0=Range2, 1=Range1 + * bit 15 VOSRDY: read-only, 1 when stable + */ +#define PWR_BASE 0x46020800 +#define PWR_VOSR_REG 0x00C +#define PWR_VOSR_VOS_Msk (1UL << 16) +#define PWR_VOSR_VOSRDY_Msk (1UL << 15) + +static void set_vos_range1(void) +{ + whal_Reg_Update(PWR_BASE, PWR_VOSR_REG, PWR_VOSR_VOS_Msk, PWR_VOSR_VOS_Msk); + while (!(whal_Reg_Read(PWR_BASE, PWR_VOSR_REG) & PWR_VOSR_VOSRDY_Msk)) + ; +} + +/* HSE32 -> PLL1 (M=1, N=25, R=3 -> 100 MHz) -> SYSCLK */ +static void pll_clock_on(void) +{ + /* Enable PWR clock so the PWR registers are accessible, then move to + * voltage Range 1 (Range 2 after reset caps SYSCLK at 16 MHz). */ + static const whal_Stm32wba_Rcc_PeriphClk pwrClock = {WHAL_STM32WBA55_PWR_CLOCK}; + whal_Stm32wba_Rcc_EnablePeriphClk(&pwrClock); + set_vos_range1(); + + /* Enable flash clock and set latency before increasing clock speed. + * 100 MHz @ 3.3V needs 3 wait states (RM0493 Table 69). */ + whal_Stm32wba_Rcc_EnablePeriphClk(&g_flashClock); + whal_Stm32wba_Flash_Ext_SetLatency(BOARD_FLASH_DEV, 3); + + /* AHB5 max 32 MHz: prescale 100 MHz / 4 = 25 MHz (0b101 = div 4). */ + whal_Stm32wba_Rcc_SetHpre5(5); + + whal_Stm32wba_Rcc_EnableOsc( + &(whal_Stm32wba_Rcc_OscCfg){WHAL_STM32WBA_RCC_HSE32_CFG}); + whal_Stm32wba_Rcc_EnablePll1(&(whal_Stm32wba_Rcc_Pll1Cfg){ + .clkSrc = WHAL_STM32WBA_RCC_PLL1SRC_HSE32, + .rge = WHAL_STM32WBA_RCC_PLL1RGE_8_16, + .m = 1, .n = 25, .r = 3, .q = 0, .p = 0, + }); + whal_Stm32wba_Rcc_SetSysClock(WHAL_STM32WBA_RCC_SYSCLK_SRC_PLL1); +} + +static void pll_clock_off(void) +{ + whal_Stm32wba_Rcc_SetSysClock(WHAL_STM32WBA_RCC_SYSCLK_SRC_HSI16); + whal_Stm32wba_Rcc_DisablePll1(); + whal_Stm32wba_Rcc_DisableOsc( + &(whal_Stm32wba_Rcc_OscCfg){WHAL_STM32WBA_RCC_HSE32_CFG}); + whal_Stm32wba_Flash_Ext_SetLatency(BOARD_FLASH_DEV, 1); +} + +void hal_init(void) +{ + pll_clock_on(); + whal_Flash_Init(BOARD_FLASH_DEV); + +#ifdef DEBUG_UART + for (size_t i = 0; i < PERIPH_CLK_COUNT; i++) { + whal_Stm32wba_Rcc_EnablePeriphClk(&g_periphClks[i]); + } + + whal_Gpio_Init(BOARD_GPIO_DEV); + whal_Uart_Init(BOARD_UART_DEV); +#endif +} + +void hal_prepare_boot(void) +{ +#ifdef DEBUG_UART + whal_Uart_Deinit(BOARD_UART_DEV); + whal_Gpio_Deinit(BOARD_GPIO_DEV); + + for (size_t i = PERIPH_CLK_COUNT; i-- > 0; ) { + whal_Stm32wba_Rcc_DisablePeriphClk(&g_periphClks[i]); + } +#endif + + whal_Flash_Deinit(BOARD_FLASH_DEV); + pll_clock_off(); +} diff --git a/hal/boards/stm32wba55cg_nucleo/board.h b/hal/boards/stm32wba55cg_nucleo/board.h new file mode 100644 index 0000000000..fc4ea8eb1a --- /dev/null +++ b/hal/boards/stm32wba55cg_nucleo/board.h @@ -0,0 +1,117 @@ +/* board.h + * + * STM32WBA55CG Nucleo wolfHAL board header. Provides the WHAL_CFG_*_DEV + * initializer macros that the upstream chip drivers use to instantiate the + * device singletons (in their own .c file), plus the BOARD_X_DEV handles + * that the wolfBoot adapter (hal/wolfhal.c) and board.c pass into the + * wolfHAL API. + * + * The STM32WBA GPIO/UART peripherals are register-compatible with the + * STM32WB; the upstream stm32wba_{gpio,uart}.c TUs simply include the + * stm32wb implementation. The alias headers bridge the names: the GPIO + * alias maps WHAL_CFG_STM32WB_GPIO_DEV onto the WBA-named macro below, + * while the UART driver consumes WHAL_CFG_STM32WB_UART_DEV directly (the + * UART alias header bridges only the singleton symbol). Flash is a native + * STM32WBA driver and uses the WBA-named macro. + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot 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. + * + * wolfBoot 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 WOLFHAL_BOARD_H +#define WOLFHAL_BOARD_H + +#include +#include +#include +#include +#include +#include + +/* GPIO pin indices used by the runtime-addressable pinCfg table. */ +enum { + BOARD_LED_PIN, + BOARD_UART_TX_PIN, + BOARD_UART_RX_PIN, + BOARD_PIN_COUNT, +}; + +/* Singletons owned by the upstream driver .c files. Declared here so a + * handle could take their address in the future; the SINGLE_INSTANCE / + * DIRECT_API_MAPPING drivers read their static singleton directly and + * ignore the passed dev pointer. (whal_Stm32wba_{Gpio,Uart}_Dev are + * macro-aliased onto the whal_Stm32wb_* symbols by the alias headers.) */ +extern const whal_Flash whal_Stm32wba_Flash_Dev; +extern const whal_Gpio whal_Stm32wba_Gpio_Dev; +extern const whal_Uart whal_Stm32wba_Uart_Dev; + +/* Device handles passed into the wolfHAL API. The direct-mapped / + * single-instance drivers ignore the dev pointer and read from their + * static singleton, so the INTERNAL_DEV sentinel is sufficient. */ +#define BOARD_GPIO_DEV WHAL_INTERNAL_DEV +#define BOARD_UART_DEV WHAL_INTERNAL_DEV +#define BOARD_FLASH_DEV WHAL_INTERNAL_DEV + +/* Flash singleton initializer — instantiated by stm32wba_flash.c. + * STM32WBA55: 1 MB flash at 0x08000000, 8 KB pages, 128-bit writes. */ +#define WHAL_CFG_STM32WBA_FLASH_DEV { \ + .base = WHAL_STM32WBA55_FLASH_BASE, \ + .cfg = (void *)&(const whal_Stm32wba_Flash_Cfg){ \ + .startAddr = 0x08000000, \ + .size = 0x100000, \ + }, \ +} + +/* GPIO singleton initializer — consumed by the stm32wb gpio driver via + * the WHAL_CFG_STM32WB_GPIO_DEV alias in stm32wba_gpio.h. */ +#define WHAL_CFG_STM32WBA_GPIO_DEV { \ + .base = WHAL_STM32WBA55_GPIO_BASE, \ + .cfg = (void *)&(const whal_Stm32wba_Gpio_Cfg){ \ + .pinCfg = (const whal_Stm32wba_Gpio_PinCfg[BOARD_PIN_COUNT]){ \ + /* LED: PA9 (LD2, green), output push-pull, low speed, pull-up */ \ + [BOARD_LED_PIN] = WHAL_STM32WBA_GPIO_PIN( \ + WHAL_STM32WBA_GPIO_PORT_A, 9, WHAL_STM32WBA_GPIO_MODE_OUT, \ + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_LOW, \ + WHAL_STM32WBA_GPIO_PULL_UP, 0), \ + /* USART1 TX: PB12, AF7 */ \ + [BOARD_UART_TX_PIN] = WHAL_STM32WBA_GPIO_PIN( \ + WHAL_STM32WBA_GPIO_PORT_B, 12, WHAL_STM32WBA_GPIO_MODE_ALTFN, \ + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_FAST, \ + WHAL_STM32WBA_GPIO_PULL_UP, 7), \ + /* USART1 RX: PA8, AF7 */ \ + [BOARD_UART_RX_PIN] = WHAL_STM32WBA_GPIO_PIN( \ + WHAL_STM32WBA_GPIO_PORT_A, 8, WHAL_STM32WBA_GPIO_MODE_ALTFN, \ + WHAL_STM32WBA_GPIO_OUTTYPE_PUSHPULL, WHAL_STM32WBA_GPIO_SPEED_FAST, \ + WHAL_STM32WBA_GPIO_PULL_UP, 7), \ + }, \ + .pinCount = BOARD_PIN_COUNT, \ + }, \ +} + +/* UART singleton initializer — instantiated by stm32wb_uart.c (included by + * stm32wba_uart.c) when WHAL_CFG_STM32WB_UART_SINGLE_INSTANCE is defined. + * The UART alias header does not bridge the CFG macro, so the WB name is + * used directly here. USART1 is clocked from SYSCLK (PLL1 = 100 MHz). */ +#define WHAL_CFG_STM32WB_UART_DEV { \ + .base = WHAL_STM32WBA55_USART1_BASE, \ + .cfg = (void *)&(const whal_Stm32wba_Uart_Cfg){ \ + .brr = WHAL_STM32WBA_UART_BRR(100000000, 115200), \ + }, \ +} + +#endif /* WOLFHAL_BOARD_H */ diff --git a/hal/boards/stm32wba55cg_nucleo/board.mk b/hal/boards/stm32wba55cg_nucleo/board.mk new file mode 100644 index 0000000000..b4a935145f --- /dev/null +++ b/hal/boards/stm32wba55cg_nucleo/board.mk @@ -0,0 +1,42 @@ +ARCH_FLASH_OFFSET=0x08000000 +LSCRIPT_IN=hal/stm32wba.ld + +CFLAGS+=-DWHAL_CFG_NO_TIMEOUT + +# Upstream wolfHAL drivers from lib/wolfHAL/src/. wolfBoot's hal_flash_* +# contract is satisfied by hal/wolfhal.c (added automatically because +# WOLFHAL=1) calling whal_Flash_*. +# +# Direct API mapping binds each driver's functions straight to the +# top-level whal_* symbols (no vtable dispatch source compiled). + +# Flash is a native STM32WBA driver — it checks the WBA-prefixed flag. +CFLAGS+=-DWHAL_CFG_STM32WBA_FLASH_DIRECT_API_MAPPING + +# GPIO/UART reuse the STM32WB implementation (the stm32wba_*.c TUs include +# stm32wb_*.c). The UART wrapper forwards its WBA flags to the WB names, so +# it takes the WBA-prefixed flags. The GPIO wrapper does NOT forward, so the +# underlying stm32wb_gpio.c must be given the WB-prefixed flag directly. +CFLAGS+=-DWHAL_CFG_STM32WB_GPIO_DIRECT_API_MAPPING +CFLAGS+=-DWHAL_CFG_STM32WBA_UART_DIRECT_API_MAPPING +# UART is single-instance — reads its singleton from board.h instead of the +# passed dev pointer. +CFLAGS+=-DWHAL_CFG_STM32WBA_UART_SINGLE_INSTANCE + +WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/reg.o +WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/flash/stm32wba_flash.o +ifeq ($(DEBUG_UART),1) + WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/gpio/stm32wba_gpio.o + WOLFHAL_OBJS+=$(WOLFHAL_ROOT)/src/uart/stm32wba_uart.o +endif + +OBJS+=$(WOLFHAL_OBJS) +APP_OBJS+=$(WOLFHAL_OBJS) + +# With RAM_CODE=1, place the flash driver in RAM so erase/program runs while +# the same flash bank is being modified. +ifeq ($(RAM_CODE),1) + WOLFHAL_FLASH_EXCLUDE_TEXT=*(EXCLUDE_FILE(*stm32wba_flash.o) .text*) + WOLFHAL_FLASH_EXCLUDE_RODATA=*(EXCLUDE_FILE(*stm32wba_flash.o) .rodata*) + WOLFHAL_FLASH_RAM_SECTIONS=*stm32wba_flash.o(.text* .rodata*) +endif diff --git a/hal/stm32wba.ld b/hal/stm32wba.ld new file mode 100644 index 0000000000..407657b44b --- /dev/null +++ b/hal/stm32wba.ld @@ -0,0 +1,50 @@ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = @BOOTLOADER_PARTITION_SIZE@ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000 +} + +SECTIONS +{ + .text : + { + _start_text = .; + KEEP(*(.isr_vector)) + @WOLFHAL_FLASH_EXCLUDE_TEXT@ + @WOLFHAL_FLASH_EXCLUDE_RODATA@ + . = ALIGN(4); + _end_text = .; + } > FLASH + .edidx : + { + . = ALIGN(4); + *(.ARM.exidx*) + } > FLASH + + _stored_data = .; + .data : AT (_stored_data) + { + _start_data = .; + KEEP(*(.data*)) + . = ALIGN(4); + KEEP(*(.ramcode)) + @WOLFHAL_FLASH_RAM_SECTIONS@ + . = ALIGN(4); + _end_data = .; + } > RAM + + .bss (NOLOAD) : + { + _start_bss = .; + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + _end_bss = .; + __bss_end__ = .; + _end = .; + } > RAM + . = ALIGN(4); +} + +END_STACK = ORIGIN(RAM) + LENGTH(RAM); diff --git a/lib/wolfHAL b/lib/wolfHAL index 2bc2938b0b..0e9fa47f1c 160000 --- a/lib/wolfHAL +++ b/lib/wolfHAL @@ -1 +1 @@ -Subproject commit 2bc2938b0bbcc977177153a7f38393710702bf70 +Subproject commit 0e9fa47f1cb281ab3c2c92d9f1e383be3f8341f4