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 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 */