diff --git a/drivers/watchdog/wdt_iwdg_stm32.c b/drivers/watchdog/wdt_iwdg_stm32.c index 50b59476b7e..df3d42d83a7 100644 --- a/drivers/watchdog/wdt_iwdg_stm32.c +++ b/drivers/watchdog/wdt_iwdg_stm32.c @@ -84,7 +84,9 @@ static void iwdg_stm32_convert_timeout(uint32_t timeout, static int iwdg_stm32_setup(const struct device *dev, uint8_t options) { + struct iwdg_stm32_data *data = IWDG_STM32_DATA(dev); IWDG_TypeDef *iwdg = IWDG_STM32_STRUCT(dev); + uint32_t tickstart; /* Deactivate running when debugger is attached. */ if (options & WDT_OPT_PAUSE_HALTED_BY_DBG) { @@ -106,8 +108,24 @@ static int iwdg_stm32_setup(const struct device *dev, uint8_t options) return -ENOTSUP; } - /* Enable the IWDG now (timeout has been installed previoulsy) */ - LL_IWDG_Enable(iwdg); /* No need to Reload counter */ + /* Enable the IWDG now and write IWDG registers at the same time */ + LL_IWDG_Enable(iwdg); + LL_IWDG_EnableWriteAccess(iwdg); + /* Write the prescaler and reload counter to the IWDG registers*/ + LL_IWDG_SetPrescaler(iwdg, data->prescaler); + LL_IWDG_SetReloadCounter(iwdg, data->reload); + + tickstart = k_uptime_get_32(); + + /* Wait for the update operation completed */ + while (LL_IWDG_IsReady(iwdg) == 0) { + if ((k_uptime_get_32() - tickstart) > IWDG_SR_UPDATE_TIMEOUT) { + return -ENODEV; + } + } + + /* Reload counter just before leaving */ + LL_IWDG_ReloadCounter(iwdg); return 0; } @@ -123,16 +141,16 @@ static int iwdg_stm32_disable(const struct device *dev) static int iwdg_stm32_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *config) { - IWDG_TypeDef *iwdg = IWDG_STM32_STRUCT(dev); + struct iwdg_stm32_data *data = IWDG_STM32_DATA(dev); uint32_t timeout = config->window.max * USEC_PER_MSEC; uint32_t prescaler = 0U; uint32_t reload = 0U; - uint32_t tickstart; if (config->callback != NULL) { return -ENOTSUP; } + /* Calculating parameters to be applied later, on setup */ iwdg_stm32_convert_timeout(timeout, &prescaler, &reload); if (!(IS_IWDG_TIMEOUT(timeout) && IS_IWDG_PRESCALER(prescaler) && @@ -141,19 +159,11 @@ static int iwdg_stm32_install_timeout(const struct device *dev, return -EINVAL; } - tickstart = k_uptime_get_32(); - - /* Do not enable the wdg during install but during wdt_setup() */ - LL_IWDG_EnableWriteAccess(iwdg); - LL_IWDG_SetPrescaler(iwdg, prescaler); - - /* Wait for the update operation completed */ - while (LL_IWDG_IsActiveFlag_PVU(iwdg) == 0) { - if ((k_uptime_get_32() - tickstart) > IWDG_SR_UPDATE_TIMEOUT) { - return -ENODEV; - } - } + /* Store the calculated values to write in the iwdg registers */ + data->prescaler = prescaler; + data->reload = reload; + /* Do not enable and update the iwdg here but during wdt_setup() */ return 0; } diff --git a/drivers/watchdog/wdt_iwdg_stm32.h b/drivers/watchdog/wdt_iwdg_stm32.h index 64e91cfa63c..d953f61b99d 100644 --- a/drivers/watchdog/wdt_iwdg_stm32.h +++ b/drivers/watchdog/wdt_iwdg_stm32.h @@ -24,6 +24,8 @@ struct iwdg_stm32_data { /* IWDG peripheral instance. */ IWDG_TypeDef *Instance; + uint32_t prescaler; + uint32_t reload; }; #define IWDG_STM32_DATA(dev) \