From 1c9041c3aa5cc642b6ae6baa4c67f9755fa35e70 Mon Sep 17 00:00:00 2001 From: Erwan Gouriou Date: Wed, 27 Jan 2021 11:07:03 +0100 Subject: [PATCH] drivers/watchdog: window-watchdog stm32: Fix timeout computing Fix the timeout computation to provide more accurate timeouts versus requested timeout. Additionally, the error margin is reworked in order to: - be relative to the application requested timeout (10% tolerance) - exclude timeouts inferior to application request Signed-off-by: Erwan Gouriou --- drivers/watchdog/wdt_wwdg_stm32.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/watchdog/wdt_wwdg_stm32.c b/drivers/watchdog/wdt_wwdg_stm32.c index 68eb696e160..b813de201f7 100644 --- a/drivers/watchdog/wdt_wwdg_stm32.c +++ b/drivers/watchdog/wdt_wwdg_stm32.c @@ -59,10 +59,10 @@ LOG_MODULE_REGISTER(wdt_wwdg_stm32); */ #define ABS_DIFF_UINT(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) -#define WWDG_TIMEOUT_ERROR_MARGIN (100 * USEC_PER_MSEC) +#define WWDG_TIMEOUT_ERROR_MARGIN(__TIMEOUT__) (__TIMEOUT__ / 10) #define IS_WWDG_TIMEOUT(__TIMEOUT_GOLDEN__, __TIMEOUT__) \ - (ABS_DIFF_UINT(__TIMEOUT_GOLDEN__, __TIMEOUT__) < \ - WWDG_TIMEOUT_ERROR_MARGIN) + (__TIMEOUT__ - __TIMEOUT_GOLDEN__) < \ + WWDG_TIMEOUT_ERROR_MARGIN(__TIMEOUT_GOLDEN__) static void wwdg_stm32_irq_config(const struct device *dev); @@ -116,7 +116,7 @@ static void wwdg_stm32_convert_timeout(const struct device *dev, { uint32_t clock_freq = wwdg_stm32_get_pclk(dev); uint8_t divider = 0U; - uint8_t shift = 3U; + uint8_t shift = 0U; /* Convert timeout to seconds. */ float timeout_s = (float)timeout / USEC_PER_SEC; @@ -125,18 +125,19 @@ static void wwdg_stm32_convert_timeout(const struct device *dev, *prescaler = 0; *counter = 0; - for (divider = 8; divider >= 1; divider >>= 1) { - wwdg_freq = ((float)clock_freq) / WWDG_INTERNAL_DIVIDER / divider; + for (divider = 0; divider <= 3; divider++) { + wwdg_freq = ((float)clock_freq) / WWDG_INTERNAL_DIVIDER / (1 << divider); /* +1 to ceil the result, which may lose from truncation */ *counter = (uint32_t)(timeout_s * wwdg_freq + 1) - 1; - *counter |= WWDG_RESET_LIMIT; + *counter += WWDG_RESET_LIMIT; *prescaler = shift << 7; if (*counter <= WWDG_COUNTER_MAX) { break; } - shift--; + shift++; + *counter = WWDG_COUNTER_MAX; } } @@ -190,8 +191,11 @@ static int wwdg_stm32_install_timeout(const struct device *dev, } wwdg_stm32_convert_timeout(dev, timeout, &prescaler, &counter); - calculated_timeout = wwdg_stm32_get_timeout(dev, prescaler, counter); + + LOG_DBG("Desired WDT: %d us", timeout); + LOG_DBG("Set WDT: %d us", calculated_timeout); + if (!(IS_WWDG_PRESCALER(prescaler) && IS_WWDG_COUNTER(counter) && IS_WWDG_TIMEOUT(timeout, calculated_timeout))) { /* One of the parameters provided is invalid */