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 <erwan.gouriou@linaro.org>
This commit is contained in:
Erwan Gouriou 2021-01-27 11:07:03 +01:00 committed by Anas Nashif
commit 1c9041c3aa

View file

@ -59,10 +59,10 @@ LOG_MODULE_REGISTER(wdt_wwdg_stm32);
*/ */
#define ABS_DIFF_UINT(a, b) ((a) > (b) ? (a) - (b) : (b) - (a)) #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__) \ #define IS_WWDG_TIMEOUT(__TIMEOUT_GOLDEN__, __TIMEOUT__) \
(ABS_DIFF_UINT(__TIMEOUT_GOLDEN__, __TIMEOUT__) < \ (__TIMEOUT__ - __TIMEOUT_GOLDEN__) < \
WWDG_TIMEOUT_ERROR_MARGIN) WWDG_TIMEOUT_ERROR_MARGIN(__TIMEOUT_GOLDEN__)
static void wwdg_stm32_irq_config(const struct device *dev); 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); uint32_t clock_freq = wwdg_stm32_get_pclk(dev);
uint8_t divider = 0U; uint8_t divider = 0U;
uint8_t shift = 3U; uint8_t shift = 0U;
/* Convert timeout to seconds. */ /* Convert timeout to seconds. */
float timeout_s = (float)timeout / USEC_PER_SEC; float timeout_s = (float)timeout / USEC_PER_SEC;
@ -125,18 +125,19 @@ static void wwdg_stm32_convert_timeout(const struct device *dev,
*prescaler = 0; *prescaler = 0;
*counter = 0; *counter = 0;
for (divider = 8; divider >= 1; divider >>= 1) { for (divider = 0; divider <= 3; divider++) {
wwdg_freq = ((float)clock_freq) / WWDG_INTERNAL_DIVIDER / divider; wwdg_freq = ((float)clock_freq) / WWDG_INTERNAL_DIVIDER / (1 << divider);
/* +1 to ceil the result, which may lose from truncation */ /* +1 to ceil the result, which may lose from truncation */
*counter = (uint32_t)(timeout_s * wwdg_freq + 1) - 1; *counter = (uint32_t)(timeout_s * wwdg_freq + 1) - 1;
*counter |= WWDG_RESET_LIMIT; *counter += WWDG_RESET_LIMIT;
*prescaler = shift << 7; *prescaler = shift << 7;
if (*counter <= WWDG_COUNTER_MAX) { if (*counter <= WWDG_COUNTER_MAX) {
break; 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); wwdg_stm32_convert_timeout(dev, timeout, &prescaler, &counter);
calculated_timeout = wwdg_stm32_get_timeout(dev, 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) && if (!(IS_WWDG_PRESCALER(prescaler) && IS_WWDG_COUNTER(counter) &&
IS_WWDG_TIMEOUT(timeout, calculated_timeout))) { IS_WWDG_TIMEOUT(timeout, calculated_timeout))) {
/* One of the parameters provided is invalid */ /* One of the parameters provided is invalid */