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
2 changes: 1 addition & 1 deletion .github/workflows/boards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
board: [stm32wb55xx_nucleo, stm32wba55cg_nucleo, stm32wb05kz_nucleo, pic32cz_curiosity_ultra, stm32h563zi_nucleo, stm32f411_blackpill, stm32c031_nucleo, stm32f091rc_nucleo, stm32f302r8_nucleo, stm32l152re_nucleo, stm32n657a0_nucleo, stm32u5a5zj_nucleo]
board: [stm32wb55xx_nucleo, stm32wba55cg_nucleo, stm32wb09ke_nucleo, pic32cz_curiosity_ultra, stm32h563zi_nucleo, stm32f411_blackpill, stm32c031_nucleo, stm32f091rc_nucleo, stm32f302r8_nucleo, stm32l152re_nucleo, stm32n657a0_nucleo, stm32u5a5zj_nucleo]
extra_cflags: ["", "-DWHAL_CFG_NO_TIMEOUT"]
include:
- board: stm32wb55xx_nucleo
Expand Down
2 changes: 1 addition & 1 deletion boards/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ build configuration.
| ST NUCLEO-F302R8 | STM32F3 | Cortex-M4 | `stm32f302r8_nucleo/` |
| WeAct BlackPill STM32F411 | STM32F4 | Cortex-M4 | `stm32f411_blackpill/` |
| ST NUCLEO-H563ZI | STM32H5 | Cortex-M33 | `stm32h563zi_nucleo/` |
| ST NUCLEO-WB05KZ | STM32WB0 | Cortex-M0+ | `stm32wb05kz_nucleo/` |
| ST NUCLEO-WB09KE | STM32WB0 | Cortex-M0+ | `stm32wb09ke_nucleo/` |
| ST NUCLEO-WB55RG | STM32WB | Cortex-M4 | `stm32wb55xx_nucleo/` |
| ST NUCLEO-L152RE | STM32L1 | Cortex-M3 | `stm32l152re_nucleo/` |
| ST NUCLEO-N657X0-Q | STM32N6 | Cortex-M55 | `stm32n657a0_nucleo/` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,15 @@ BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/systick.c)
# Peripheral devices
include $(WHAL_DIR)/boards/peripheral/board.mk

# Flash via openocd: make flash BOARD=<board> IMAGE=<path/to/image>
# Flash via openocd: make flash BOARD=<board> IMAGE=<path/to/image.bin>
# bluenrg-x.cfg is only used to connect; flash.tcl programs the flash
# controller directly.
OPENOCD ?= /opt/openocd/bin/openocd
OPENOCD_INTERFACE ?= interface/stlink.cfg
OPENOCD_TARGET ?= target/stm32wb0x.cfg
OPENOCD_INTERFACE ?= interface/stlink-dap.cfg
OPENOCD_TARGET ?= target/bluenrg-x.cfg

.PHONY: flash
flash:
@test -n "$(IMAGE)" || { echo "IMAGE=<path/to/image> required" >&2; exit 1; }
@test -n "$(IMAGE)" || { echo "IMAGE=<path/to/image.bin> required" >&2; exit 1; }
$(OPENOCD) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) \
-c "program $(IMAGE) verify reset exit"
-c "set IMAGE $(abspath $(IMAGE))" -f $(_BOARD_DIR)/flash.tcl
129 changes: 129 additions & 0 deletions boards/stm32wb09ke_nucleo/flash.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# flash.tcl
#
# Copyright (C) 2026 wolfSSL Inc.
#
# This file is part of wolfHAL.
#
# wolfHAL is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# wolfHAL is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
#

# Program a raw .bin into STM32WB09 main flash by driving the flash
# controller registers directly (RM0505 section 9.3), bypassing the
# OpenOCD bluenrg-x flash driver.
#
# Usage:
# openocd -f interface/stlink-dap.cfg -f target/bluenrg-x.cfg \
# -c "set IMAGE <path/to/image.bin>" -f flash.tcl
#
# The image is staged through SRAM in 32 KB chunks: each chunk is loaded
# with load_image into a 0xFF-filled RAM window, its pages are erased, and
# its non-blank words are programmed and read back for verification.

set FC 0x40001000
set COMMAND [expr {$FC + 0x00}]
set IRQSTAT [expr {$FC + 0x08}]
set IRQRAW [expr {$FC + 0x10}]
set ADDRESS [expr {$FC + 0x18}]
set PAGEPROT0 [expr {$FC + 0x34}]
set PAGEPROT1 [expr {$FC + 0x38}]
set DATA0 [expr {$FC + 0x40}]

set FLASH_BASE 0x10040000
set FLASH_SIZE 0x80000
set PAGE_SIZE 0x800
set RAM_WIN 0x20008000
set CHUNK 0x8000

proc rd {a} { return [lindex [read_memory $a 32 1] 0] }
proc wr {a v} { write_memory $a 32 [list $v] }

# Issue one controller command and wait for CMDSTART then CMDDONE.
proc run_cmd {cmd what} {
global IRQSTAT IRQRAW COMMAND
wr $IRQSTAT 0xF
wr $COMMAND $cmd
foreach {bit name} {2 CMDSTART 1 CMDDONE} {
set ok 0
for {set i 0} {$i < 2000} {incr i} {
set irq [rd $IRQRAW]
if {$irq & 0xC} {
wr $IRQSTAT 0xF
error [format "%s: flash error IRQRAW=0x%08x" $what $irq]
}
if {$irq & $bit} { set ok 1; break }
}
if {!$ok} {
error [format "%s: timeout waiting for %s IRQRAW=0x%08x" \
$what $name [rd $IRQRAW]]
}
wr $IRQSTAT $bit
}
}

if {![info exists IMAGE]} { error "set IMAGE <path/to/image.bin> first" }
if {[file extension $IMAGE] ne ".bin"} { error "IMAGE must be a raw .bin" }
set size [file size $IMAGE]
if {$size == 0 || $size > $FLASH_SIZE} {
error [format "image size %d out of range" $size]
}

init
reset halt
halt

wr $PAGEPROT0 0
wr $PAGEPROT1 0

for {set off 0} {$off < $size} {incr off $CHUNK} {
set len [expr {$size - $off}]
if {$len > $CHUNK} { set len $CHUNK }
set nwords [expr {($len + 3) / 4}]
set npages [expr {($len + $PAGE_SIZE - 1) / $PAGE_SIZE}]

mww $RAM_WIN 0xFFFFFFFF [expr {$CHUNK / 4}]
load_image $IMAGE [expr {$RAM_WIN - $off}] bin $RAM_WIN $CHUNK
set words [read_memory $RAM_WIN 32 $nwords]

set firstPage [expr {$off / $PAGE_SIZE}]
for {set p $firstPage} {$p < $firstPage + $npages} {incr p} {
wr $ADDRESS [expr {$p * $PAGE_SIZE / 4}]
run_cmd 0x11 "erase page $p"
}

set base [expr {$off / 4}]
for {set i 0} {$i < $nwords} {incr i} {
set w [lindex $words $i]
if {$w != 0xFFFFFFFF} {
wr $ADDRESS [expr {$base + $i}]
wr $DATA0 $w
run_cmd 0x33 [format "write word %d" [expr {$base + $i}]]
}
}

set rb [read_memory [expr {$FLASH_BASE + $off}] 32 $nwords]
for {set i 0} {$i < $nwords} {incr i} {
if {[lindex $rb $i] != [lindex $words $i]} {
error [format "verify failed @0x%08x: got 0x%08x want 0x%08x" \
[expr {$FLASH_BASE + $off + $i * 4}] \
[lindex $rb $i] [lindex $words $i]]
}
}
echo [format "programmed 0x%08x-0x%08x" [expr {$FLASH_BASE + $off}] \
[expr {$FLASH_BASE + $off + $len - 1}]]
}

echo "verify ok"
reset run
shutdown
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void SVC_Handler(void) __attribute__((weak, noreturn, alias("Default_Hand
void PendSV_Handler(void) __attribute__((weak, noreturn, alias("Default_Handler")));
void SysTick_Handler(void) __attribute__((weak, noreturn, alias("Default_Handler")));

/* STM32WB05xZ peripheral interrupts (RM0529 Table 6) */
/* STM32WB09xE peripheral interrupts (RM0505 Table 6) */
void NVM_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler")));
void RCC_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler")));
void BATTERY_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler")));
Expand All @@ -66,6 +66,7 @@ void BLE_WKUP_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Ha
void BLE_SEQ_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler")));
void TIM16_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler")));
void TIM17_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler")));
void TRNG_IRQHandler(void) __attribute__((weak, noreturn, alias("Default_Handler")));

#define RESERVED Default_Handler

Expand Down Expand Up @@ -108,7 +109,7 @@ void (* const interrupt_vector_table[])(void) __attribute__((section(".isr_vecto
RESERVED, /* Reserved */
PendSV_Handler,
SysTick_Handler,
/* STM32WB05xZ peripheral interrupts (Table 6) */
/* STM32WB09xE peripheral interrupts (Table 6) */
NVM_IRQHandler, /* 0 Flash controller */
RCC_IRQHandler, /* 1 Reset and clock controller */
BATTERY_IRQHandler, /* 2 PVD */
Expand Down Expand Up @@ -137,7 +138,7 @@ void (* const interrupt_vector_table[])(void) __attribute__((section(".isr_vecto
BLE_SEQ_IRQHandler, /* 25 BLE RX/TX sequence */
TIM16_IRQHandler, /* 26 TIM16 */
TIM17_IRQHandler, /* 27 TIM17 */
RESERVED, /* 28 Reserved */
TRNG_IRQHandler, /* 28 TRNG */
RESERVED, /* 29 Reserved */
RESERVED, /* 30 Reserved */
RESERVED, /* 31 Reserved */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,24 @@
ENTRY(Reset_Handler)

/*
* STM32WB05KZ memory layout (DS14591):
* Flash: 192 KB @ 0x10040000 (96 pages of 2 KB)
* SRAM0: 12 KB @ 0x20000000 (always retained in Deepstop)
* SRAM1: 12 KB @ 0x20003000 (retention is programmable)
* STM32WB09KE memory layout (RM0505 Table 3):
* Flash: 512 KB @ 0x10040000 (256 pages of 2 KB)
* SRAM0: 16 KB @ 0x20000000 (always retained in Deepstop)
* SRAM1: 16 KB @ 0x20004000 (retention is programmable)
* SRAM2: 16 KB @ 0x20008000 (retention is programmable)
* SRAM3: 16 KB @ 0x2000C000 (retention is programmable)
*
* We treat the two SRAM banks as one contiguous 24 KB region — they are
* adjacent in the memory map and the linker can place the heap/stack at
* the top of SRAM1 without any special handling. The lowest part of
* SRAM0 (0x20000000–0x20000033) is reserved for boot-time use; the
* vector remap puts those words at 0x00000000 — see RM0529 Table 4.
* The four adjacent banks are treated as one 64 KB region. SRAM0
* 0x20000000-0x20000017 is reserved for the boot ROM and low-power
* manager (RM0505 Table 4), so RAM starts just above it.
*/
_estack = 0x20006000; /* end of SRAM1 = SRAM0 base + 24 KB */
_estack = 0x20010000; /* end of SRAM3 */
_Min_Stack_Size = 0x500; /* required amount of stack */

MEMORY
{
FLASH (rx) : ORIGIN = 0x10040000, LENGTH = 192K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 24K
FLASH (rx) : ORIGIN = 0x10040000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x20000018, LENGTH = 64K - 0x18
}

SECTIONS
Expand Down
Loading
Loading