From 4b16af6e2438db22e804aee57818be2b9d719dbd Mon Sep 17 00:00:00 2001 From: Filip Moc Date: Fri, 5 Oct 2018 23:30:41 +0000 Subject: [PATCH] stm32: iwdg: correct calculation for all ranges. The original calculations miscalculated ranges such as 512..639 or 1024..1151 or ... or 32768..32895 Reviewed-by: Karl Palsson --- lib/stm32/common/iwdg_common_all.c | 53 +++++++++++++++--------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/lib/stm32/common/iwdg_common_all.c b/lib/stm32/common/iwdg_common_all.c index f2b1c1d8..44b3b9b3 100644 --- a/lib/stm32/common/iwdg_common_all.c +++ b/lib/stm32/common/iwdg_common_all.c @@ -70,45 +70,44 @@ loading a previous value. @param[in] period uint32_t Period in milliseconds (< 32760) from a watchdog reset until a system reset is issued. */ - void iwdg_set_period_ms(uint32_t period) { - uint32_t count, prescale, reload, exponent; + const int PRESCALER_MAX = 6; + uint8_t prescale = 0; - /* Set the count to represent ticks of the 32kHz LSI clock */ - count = (period << 5); + /* Set the count to represent ticks of 8kHz clock (the 32kHz LSI clock + * divided by 4 = lowest prescaler setting) + */ + uint32_t count = period << 3; - /* Strip off the first 12 bits to get the prescale value required */ - prescale = (count >> 12); - if (prescale > 256) { - exponent = IWDG_PR_DIV256; reload = COUNT_MASK; - } else if (prescale > 128) { - exponent = IWDG_PR_DIV256; reload = (count >> 8); - } else if (prescale > 64) { - exponent = IWDG_PR_DIV128; reload = (count >> 7); - } else if (prescale > 32) { - exponent = IWDG_PR_DIV64; reload = (count >> 6); - } else if (prescale > 16) { - exponent = IWDG_PR_DIV32; reload = (count >> 5); - } else if (prescale > 8) { - exponent = IWDG_PR_DIV16; reload = (count >> 4); - } else if (prescale > 4) { - exponent = IWDG_PR_DIV8; reload = (count >> 3); - } else { - exponent = IWDG_PR_DIV4; reload = (count >> 2); - } - - /* Avoid the undefined situation of a zero count */ + /* Prevent underflow */ if (count == 0) { count = 1; } + /* Shift count while increasing prescaler as many times as needed to + * fit into IWDG_RLR + */ + while ((count - 1) >> COUNT_LENGTH) { + count >>= 1; + prescale++; + } + + /* IWDG_RLR actually holds count - 1 */ + count--; + + /* Clamp to max possible period */ + if (prescale > PRESCALER_MAX) { + count = COUNT_MASK; + prescale = PRESCALER_MAX; + } + while (iwdg_prescaler_busy()); IWDG_KR = IWDG_KR_UNLOCK; - IWDG_PR = exponent; + IWDG_PR = prescale; while (iwdg_reload_busy()); IWDG_KR = IWDG_KR_UNLOCK; - IWDG_RLR = (reload & COUNT_MASK); + IWDG_RLR = count & COUNT_MASK; } /*---------------------------------------------------------------------------*/