Skip to content

Commit d08de01

Browse files
committed
[watchdog, stm32wb, tests] Implement watchdog abstraction. Implement IWDG/WWDG drivers for STM32WB. Implement generic watchdog test
1 parent 3779228 commit d08de01

22 files changed

Lines changed: 833 additions & 68 deletions

File tree

.github/workflows/boards.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: Board Builds
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
boards:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
board: [stm32wb55xx_nucleo, pic32cz_curiosity_ultra, stm32h563zi_nucleo, stm32f411_blackpill, stm32c031_nucleo]
15+
extra_cflags: ["", "-DWHAL_CFG_NO_TIMEOUT"]
16+
include:
17+
- board: stm32wb55xx_nucleo
18+
extra_cflags: "-DBOARD_DMA"
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Install ARM toolchain
23+
run: sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi
24+
25+
- name: Build blinky
26+
working-directory: examples/blinky
27+
run: CFLAGS="${{ matrix.extra_cflags }}" make BOARD=${{ matrix.board }}
28+
29+
- name: Build tests
30+
working-directory: tests
31+
run: CFLAGS="${{ matrix.extra_cflags }}" make BOARD=${{ matrix.board }}

.github/workflows/ci.yml

Lines changed: 0 additions & 67 deletions
This file was deleted.

.github/workflows/core-tests.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Core Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
core-tests:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
extra_cflags: ["", "-DWHAL_CFG_NO_TIMEOUT"]
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Build and run core tests
19+
working-directory: tests/core
20+
run: CFLAGS="${{ matrix.extra_cflags }}" make run
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Peripheral Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
peripheral-tests:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
include:
15+
- board: stm32wb55xx_nucleo
16+
peripherals: bmi270
17+
tests: bmi270
18+
- board: stm32wb55xx_nucleo
19+
peripherals: spi_nor_w25q64
20+
tests: flash
21+
- board: stm32wb55xx_nucleo
22+
peripherals: sdhc_spi_sdcard32gb
23+
tests: block
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- name: Install ARM toolchain
28+
run: sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi
29+
30+
- name: Build tests
31+
working-directory: tests
32+
run: make BOARD=${{ matrix.board }} PERIPHERALS="${{ matrix.peripherals }}" TESTS="${{ matrix.tests }}"
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Watchdog Tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
watchdog-tests:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
include:
15+
- board: stm32wb55xx_nucleo
16+
watchdog: iwdg
17+
- board: stm32wb55xx_nucleo
18+
watchdog: wwdg
19+
steps:
20+
- uses: actions/checkout@v4
21+
22+
- name: Install ARM toolchain
23+
run: sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi
24+
25+
- name: Build tests
26+
working-directory: tests
27+
run: make BOARD=${{ matrix.board }} TESTS=watchdog WATCHDOG=${{ matrix.watchdog }}

boards/stm32wb55xx_nucleo/Makefile.inc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ OBJCOPY = $(GCC_PATH)arm-none-eabi-objcopy
1010
CFLAGS += -Wall -Werror $(INCLUDE) -g3 \
1111
-ffreestanding -nostdlib -mcpu=cortex-m4 \
1212
-DPLATFORM_STM32WB -MMD -MP \
13-
$(if $(DMA),-DBOARD_DMA)
13+
$(if $(DMA),-DBOARD_DMA) \
14+
$(if $(filter iwdg,$(WATCHDOG)),-DBOARD_WATCHDOG_IWDG) \
15+
$(if $(filter wwdg,$(WATCHDOG)),-DBOARD_WATCHDOG_WWDG)
1416
LDFLAGS = --omagic -static
1517

1618
LINKER_SCRIPT ?= $(_BOARD_DIR)/linker.ld
@@ -29,6 +31,7 @@ BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/flash.c)
2931
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/spi.c)
3032
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/i2c.c)
3133
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/sensor.c)
34+
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/watchdog.c)
3235
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/rng.c)
3336
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/crypto.c)
3437
BOARD_SOURCE += $(wildcard $(WHAL_DIR)/src/*/block.c)

boards/stm32wb55xx_nucleo/board.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ static const whal_Stm32wbRcc_Clk g_clocks[] = {
5959
{WHAL_STM32WB55_RNG_CLOCK},
6060
{WHAL_STM32WB55_AES1_CLOCK},
6161
{WHAL_STM32WB55_I2C1_CLOCK},
62+
#ifdef BOARD_WATCHDOG_WWDG
63+
{WHAL_STM32WB55_WWDG_CLOCK},
64+
#endif
6265
};
6366
#define CLOCK_COUNT (sizeof(g_clocks) / sizeof(g_clocks[0]))
6467

@@ -244,6 +247,28 @@ whal_Crypto g_whalCrypto = {
244247
},
245248
};
246249

250+
#ifdef BOARD_WATCHDOG_IWDG
251+
whal_Watchdog g_whalWatchdog = {
252+
WHAL_STM32WB55_IWDG_DEVICE,
253+
254+
.cfg = &(whal_Stm32wbIwdg_Cfg) {
255+
.prescaler = WHAL_STM32WB_IWDG_PR_32,
256+
.reload = 100,
257+
.timeout = &g_whalTimeout,
258+
},
259+
};
260+
#elif defined(BOARD_WATCHDOG_WWDG)
261+
whal_Watchdog g_whalWatchdog = {
262+
WHAL_STM32WB55_WWDG_DEVICE,
263+
264+
.cfg = &(whal_Stm32wbWwdg_Cfg) {
265+
.prescaler = WHAL_STM32WB_WWDG_TB_128,
266+
.window = 0x7F,
267+
.counter = 0x7F,
268+
},
269+
};
270+
#endif
271+
247272
void Board_WaitMs(size_t ms)
248273
{
249274
uint32_t startCount = g_tick;
@@ -276,6 +301,14 @@ whal_Error Board_Init(void)
276301
return err;
277302
}
278303

304+
#ifdef BOARD_WATCHDOG_IWDG
305+
/* Enable LSI osc required by the IWDG */
306+
err = whal_Stm32wbRcc_Ext_EnableLsi(&g_whalClock, 1);
307+
if (err) {
308+
return err;
309+
}
310+
#endif
311+
279312
/* Enable clocks */
280313
for (size_t i = 0; i < CLOCK_COUNT; i++) {
281314
err = whal_Clock_Enable(&g_whalClock, &g_clocks[i]);
@@ -445,6 +478,13 @@ whal_Error Board_Deinit(void)
445478
return err;
446479
}
447480

481+
#ifdef BOARD_WATCHDOG_IWDG
482+
err = whal_Stm32wbRcc_Ext_EnableLsi(&g_whalClock, 0);
483+
if (err) {
484+
return err;
485+
}
486+
#endif
487+
448488
err = whal_Clock_Deinit(&g_whalClock);
449489
if (err) {
450490
return err;

boards/stm32wb55xx_nucleo/board.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extern whal_Rng g_whalRng;
1515
extern whal_Crypto g_whalCrypto;
1616
extern whal_I2c g_whalI2c;
1717
extern whal_Irq g_whalIrq;
18+
extern whal_Watchdog g_whalWatchdog;
1819

1920
extern whal_Timeout g_whalTimeout;
2021
extern volatile uint32_t g_tick;

docs/adding_a_board.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,18 @@ whal_Error Board_Init(void)
106106
107107
return WHAL_SUCCESS;
108108
}
109+
```
110+
111+
The watchdog is intentionally excluded from `Board_Init()` and `Board_Deinit()`.
112+
Once started, most watchdog peripherals cannot be stopped — if `Board_Init()`
113+
starts the watchdog, any delay before the application begins refreshing it will
114+
cause an unexpected reset. The application or test should call
115+
`whal_Watchdog_Init()` directly when it is ready to begin refreshing. The board
116+
still defines the `g_whalWatchdog` instance and enables any required clocks
117+
(e.g., WWDG APB clock, IWDG LSI oscillator) so the watchdog is ready to be
118+
started.
109119

120+
```c
110121
whal_Error Board_Deinit(void)
111122
{
112123
whal_Error err;

docs/writing_a_driver.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,50 @@ a transfer needs to be cancelled.
10531053

10541054
---
10551055

1056+
## Watchdog
1057+
1058+
Header: `wolfHAL/watchdog/watchdog.h`
1059+
1060+
The watchdog driver provides access to hardware watchdog timers that reset the
1061+
system if not periodically refreshed. On most hardware, the watchdog cannot be
1062+
stopped once started — only a system reset clears it.
1063+
1064+
### Init
1065+
1066+
Configure and start the watchdog. This typically involves:
1067+
1068+
- Setting the prescaler and reload/counter values from the configuration
1069+
- Enabling the watchdog peripheral
1070+
1071+
On some hardware (e.g., STM32 IWDG), the watchdog must be started before its
1072+
configuration registers can be written. The driver should handle this ordering
1073+
internally.
1074+
1075+
The board must enable any required clocks before calling Init. For example, the
1076+
STM32 WWDG requires an APB clock, while the IWDG requires the LSI oscillator.
1077+
1078+
The watchdog is NOT initialized in `Board_Init` — the test or application
1079+
controls when it starts, since once started it cannot be stopped.
1080+
1081+
### Deinit
1082+
1083+
Shut down the watchdog. On hardware where the watchdog cannot be stopped (e.g.,
1084+
STM32 IWDG), this function is a no-op.
1085+
1086+
### Refresh
1087+
1088+
Reload the watchdog counter to prevent a reset. Must be called periodically
1089+
within the configured timeout window. The exact mechanism is hardware-specific
1090+
(e.g., writing a reload key to IWDG_KR, or writing the counter value back to
1091+
WWDG_CR).
1092+
1093+
For window watchdogs, the refresh must occur within the valid window — refreshing
1094+
too early or too late triggers a reset. The driver does not enforce window timing;
1095+
it writes the reload value unconditionally and relies on the hardware to enforce
1096+
the window.
1097+
1098+
---
1099+
10561100
## EthPhy
10571101

10581102
Header: `wolfHAL/eth_phy/eth_phy.h`

0 commit comments

Comments
 (0)