Skip to content

Commit d0639fe

Browse files
mathieuchopstmkartben
authored andcommitted
drivers: watchdog: iwdg_stm32: add support for STM32WB0
Add support for the STM32WB0 series to the existing STM32 driver for Independent Watchdog peripheral. NOTE: this commit only includes basic support for the watchdog. STM32WB0 specificities such as the different possible clock sources, LSI frequency measurement or window support are left for future implementation. Signed-off-by: Mathieu Choplain <[email protected]>
1 parent f4ee5fa commit d0639fe

File tree

1 file changed

+44
-3
lines changed

1 file changed

+44
-3
lines changed

drivers/watchdog/wdt_iwdg_stm32.c

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
#define DT_DRV_COMPAT st_stm32_watchdog
1111

1212
#include <zephyr/drivers/watchdog.h>
13+
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
1314
#include <zephyr/kernel.h>
1415
#include <zephyr/sys_clock.h>
1516
#include <soc.h>
1617
#include <stm32_ll_bus.h>
18+
#include <stm32_ll_rcc.h>
1719
#include <stm32_ll_iwdg.h>
1820
#include <stm32_ll_system.h>
1921
#include <errno.h>
@@ -90,14 +92,16 @@ static int iwdg_stm32_setup(const struct device *dev, uint8_t options)
9092

9193
/* Deactivate running when debugger is attached. */
9294
if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) {
93-
#if defined(CONFIG_SOC_SERIES_STM32F0X)
95+
#if defined(CONFIG_SOC_SERIES_STM32WB0X)
96+
/* STM32WB0 watchdog does not support halt by debugger */
97+
return -ENOTSUP;
98+
#elif defined(CONFIG_SOC_SERIES_STM32F0X)
9499
LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_DBGMCU);
95100
#elif defined(CONFIG_SOC_SERIES_STM32C0X) || defined(CONFIG_SOC_SERIES_STM32G0X)
96101
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_DBGMCU);
97102
#elif defined(CONFIG_SOC_SERIES_STM32L0X)
98103
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_DBGMCU);
99-
#endif
100-
#if defined(CONFIG_SOC_SERIES_STM32H7X)
104+
#elif defined(CONFIG_SOC_SERIES_STM32H7X)
101105
LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_IWDG1_STOP);
102106
#elif defined(CONFIG_SOC_SERIES_STM32H7RSX)
103107
LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_IWDG_STOP);
@@ -192,6 +196,43 @@ static DEVICE_API(wdt, iwdg_stm32_api) = {
192196

193197
static int iwdg_stm32_init(const struct device *dev)
194198
{
199+
/* Enable watchdog clock if needed */
200+
#if DT_INST_NODE_HAS_PROP(0, clocks)
201+
const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE);
202+
const struct stm32_pclken clk_cfg = STM32_CLOCK_INFO(0, DT_DRV_INST(0));
203+
int err = clock_control_on(clk, (clock_control_subsys_t)&clk_cfg);
204+
205+
if (err < 0) {
206+
return err;
207+
}
208+
#if defined(CONFIG_SOC_SERIES_STM32WB0X)
209+
/**
210+
* On STM32WB0, application must wait two slow clock cycles
211+
* before accessing the IWDG IP after turning on the WDGEN
212+
* bit in RCC registers. However, there is no register that
213+
* can be polled for this event.
214+
* To work around this limitation, force the IWDG to go
215+
* through a reset cycle, which also takes two slow clock
216+
* cycles, but can polled on (bit WDGRSTF of RCC_CIFR).
217+
*/
218+
219+
/* Clear bit beforehand to avoid early exit of polling loop */
220+
LL_RCC_ClearFlag_WDGRSTREL();
221+
222+
/* Place IWDG under reset, then release the reset */
223+
LL_APB0_GRP1_ForceReset(LL_APB0_GRP1_PERIPH_WDG);
224+
LL_APB0_GRP1_ReleaseReset(LL_APB0_GRP1_PERIPH_WDG);
225+
while (!LL_RCC_IsActiveFlag_WDGRSTREL()) {
226+
/* Wait for IWDG reset release event,
227+
* which takes two slow clock cycles
228+
*/
229+
}
230+
231+
/* Clear WDRSTF bit after polling completes */
232+
LL_RCC_ClearFlag_WDGRSTREL();
233+
#endif /* defined(CONFIG_SOC_SERIES_STM32WB0X) */
234+
#endif /* DT_INST_NODE_HAS_PROP(0, clocks) */
235+
195236
#ifndef CONFIG_WDT_DISABLE_AT_BOOT
196237
struct wdt_timeout_cfg config = {
197238
.window.max = CONFIG_IWDG_STM32_INITIAL_TIMEOUT

0 commit comments

Comments
 (0)