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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/workflows/test-configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions arch.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 19 additions & 0 deletions config/examples/stm32wba.config
Original file line number Diff line number Diff line change
@@ -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
133 changes: 133 additions & 0 deletions hal/boards/stm32wba55cg_nucleo/board.c
Original file line number Diff line number Diff line change
@@ -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 <stddef.h>
#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();
}
117 changes: 117 additions & 0 deletions hal/boards/stm32wba55cg_nucleo/board.h
Original file line number Diff line number Diff line change
@@ -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 <wolfHAL/wolfHAL.h>
#include <wolfHAL/platform/st/stm32wba55cg.h>
#include <wolfHAL/clock/stm32wba_rcc.h>
#include <wolfHAL/flash/stm32wba_flash.h>
#include <wolfHAL/gpio/stm32wba_gpio.h>
#include <wolfHAL/uart/stm32wba_uart.h>

/* 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 */
42 changes: 42 additions & 0 deletions hal/boards/stm32wba55cg_nucleo/board.mk
Original file line number Diff line number Diff line change
@@ -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
50 changes: 50 additions & 0 deletions hal/stm32wba.ld
Original file line number Diff line number Diff line change
@@ -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);
2 changes: 1 addition & 1 deletion lib/wolfHAL
Submodule wolfHAL updated 164 files
Loading