This fixes problems when values such as 512..639 or 1024..1151 or ... or 32768..32895 are passed to iwdg_set_period_ms.
Signed-off-by: Filip Moc <d...@moc6.cz> --- lib/stm32/common/iwdg_common_all.c | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/lib/stm32/common/iwdg_common_all.c b/lib/stm32/common/iwdg_common_all.c index f2b1c1d8..1e299893 100644 --- a/lib/stm32/common/iwdg_common_all.c +++ b/lib/stm32/common/iwdg_common_all.c @@ -42,6 +42,7 @@ relevant bit is not set, the IWDG timer must be enabled by software. #define LSI_FREQUENCY 32000 #define COUNT_LENGTH 12 #define COUNT_MASK ((1 << COUNT_LENGTH)-1) +#define PRESCALER_MAX 6 /*---------------------------------------------------------------------------*/ /** @brief IWDG Enable Watchdog Timer @@ -73,42 +74,41 @@ reset until a system reset is issued. void iwdg_set_period_ms(uint32_t period) { - uint32_t count, prescale, reload, exponent; - - /* Set the count to represent ticks of the 32kHz LSI clock */ - count = (period << 5); - - /* 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); - } + uint8_t prescale = 0; + + /* Set the count to represent ticks of 8kHz clock (the 32kHz LSI clock + * divided by 4 = lowest prescaler setting) + */ + uint32_t count = period << 3; - /* 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; } /*---------------------------------------------------------------------------*/ -- 2.11.0 _______________________________________________ libopencm3-devel mailing list libopencm3-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/libopencm3-devel