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

Reply via email to