mbed library sources. Supersedes mbed-src. Fixed broken STM32F1xx RTC on rtc_api.c

Dependents:   Nucleo_F103RB_RTC_battery_bkup_pwr_off_okay

Fork of mbed-dev by mbed official

Revision:
174:b96e65c34a4d
Parent:
167:e84263d55307
--- a/targets/TARGET_STM/us_ticker_16b.c	Fri Sep 15 14:59:18 2017 +0100
+++ b/targets/TARGET_STM/us_ticker_16b.c	Mon Oct 02 15:33:19 2017 +0100
@@ -26,22 +26,13 @@
 volatile uint32_t SlaveCounter = 0;
 volatile uint32_t oc_int_part = 0;
 
-static int us_ticker_inited = 0;
-
 void us_ticker_init(void)
 {
-    if (us_ticker_inited) return;
-    us_ticker_inited = 1;
-
-    TimMasterHandle.Instance = TIM_MST;
-
-    HAL_InitTick(0); // The passed value is not used
+    /* NOTE: assuming that HAL tick has already been initialized! */
 }
 
 uint32_t us_ticker_read()
 {
-    if (!us_ticker_inited) us_ticker_init();
-
     uint16_t cntH_old, cntH, cntL;
     do {
         cntH_old = SlaveCounter;
@@ -73,7 +64,7 @@
 {
     // NOTE: This function must be called with interrupts disabled to keep our
     //       timer interrupt setup atomic
-    TimMasterHandle.Instance = TIM_MST;
+
     // Set new output compare value
     __HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1, timestamp & 0xFFFF);
     // Ensure the compare event starts clear
@@ -81,120 +72,119 @@
     // Enable IT
     __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1);
 
-    int current_time = us_ticker_read();
-    int delta = (int)(timestamp - current_time);
-
-    if (delta <= 0) { // This event was in the past
-        /* Immediately set the compare event to cause the event to be handled in
-         * the next interrupt context.  This prevents calling interrupt handlers
-         * recursively as us_ticker_set_interrupt might be called again from the
-         * application handler
+    /* Set the number of timer wrap-around loops before the actual timestamp
+     * is reached.  If the calculated delta time is more than halfway to the
+     * next compare event, check to see if a compare event has already been
+     * set, and if so, add one to the wrap-around count.  This is done to
+     * ensure the correct wrap count is used in the corner cases where the
+     * 16 bit counter passes the compare value during the process of
+     * configuring this interrupt.
+     *
+     * Assumption: The time to execute this function is less than 32ms
+     *             (otherwise incorrect behaviour could result)
+     *
+     * Consider the following corner cases:
+     * 1) timestamp is 1 us in the future:
+     *      oc_int_part = 0 initially
+     *      oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000
+     *      Compare event should happen in 1 us and us_ticker_irq_handler()
+     *      called
+     * 2) timestamp is 0x8000 us in the future:
+     *      oc_int_part = 0 initially
+     *      oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000
+     *      There should be no possibility of the CC1 flag being set yet
+     *      (see assumption above).  When the compare event does occur in
+     *      32768 us, us_ticker_irq_handler() will be called
+     * 3) timestamp is 0x8001 us in the future:
+     *      oc_int_part = 0 initially
+     *      ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no
+     *      possibility of the CC1 flag being set yet (see assumption above),
+     *      so oc_int_part will be left at 0, and when the compare event
+     *      does occur in 32769 us, us_ticker_irq_handler() will be called
+     * 4) timestamp is 0x10000 us in the future:
+     *      oc_int_part = 0 initially
+     *      ((delta - 1) & 0xFFFF) >= 0x8000
+     *      There are two subcases:
+     *      a) The timer counter has not incremented past the compare
+     *          value while setting up the interrupt.  In this case, the
+     *          CC1 flag will not be set, so oc_int_part will be
+     *          left at 0, and when the compare event occurs in 65536 us,
+     *          us_ticker_irq_handler() will be called
+     *      b) The timer counter has JUST incremented past the compare
+     *          value.  In this case, the CC1 flag will be set, so
+     *          oc_int_part will be incremented to 1, and the interrupt will
+     *          occur immediately after this function returns, where
+     *          oc_int_part will decrement to 0 without calling
+     *          us_ticker_irq_handler().  Then about 65536 us later, the
+     *          compare event will occur again, and us_ticker_irq_handler()
+     *          will be called
+     * 5) timestamp is 0x10001 us in the future:
+     *      oc_int_part = 1 initially
+     *      oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000
+     *      CC1 flag will not be set (see assumption above).  In 1 us the
+     *      compare event will cause an interrupt, where oc_int_part will be
+     *      decremented to 0 without calling us_ticker_irq_handler().  Then
+     *      about 65536 us later, the compare event will occur again, and
+     *      us_ticker_irq_handler() will be called
+     * 6) timestamp is 0x18000 us in the future:
+     *      oc_int_part = 1 initially
+     *      oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000
+     *      There should be no possibility of the CC1 flag being set yet
+     *      (see assumption above).  When the compare event does occur in
+     *      32768 us, oc_int_part will be decremented to 0 without calling
+     *      us_ticker_irq_handler().  Then about 65536 us later, the
+     *      compare event will occur again, and us_ticker_irq_handler() will
+     *      be called
+     * 7) timestamp is 0x18001 us in the future:
+     *      oc_int_part = 1 initially
+     *      ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no
+     *      possibility of the CC1 flag being set yet (see assumption above),
+     *      so oc_int_part will be left at 1, and when the compare event
+     *      does occur in 32769 us, oc_int_part will be decremented to 0
+     *      without calling us_ticker_irq_handler().  Then about 65536 us
+     *      later, the compare event will occur again, and
+     *      us_ticker_irq_handler() will be called
+     *
+     * delta - 1 is used because the timer compare event happens on the
+     * counter incrementing to match the compare value, and it won't occur
+     * immediately when the compare value is set to the current counter
+     * value.
+     */
+    uint32_t current_time = us_ticker_read();
+    uint32_t delta = timestamp - current_time;
+    /* Note: The case of delta <= 0 is handled in MBED upper layer */
+    oc_int_part = (delta - 1) >> 16;
+    if ( ((delta - 1) & 0xFFFF) >= 0x8000 &&
+         __HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET ) {
+        ++oc_int_part;
+        /* NOTE: Instead of incrementing oc_int_part here, we could clear
+         *       the CC1 flag, but then you'd have to wait to ensure the
+         *       interrupt is knocked down before returning and reenabling
+         *       interrupts.  Since this is a rare case, it's not worth it
+         *       to try and optimize it, and it keeps the code simpler and
+         *       safer to just do this increment instead.
          */
-        oc_int_part = 0;
-        HAL_TIM_GenerateEvent(&TimMasterHandle, TIM_EVENTSOURCE_CC1);
-    } else {
-        /* Set the number of timer wrap-around loops before the actual timestamp
-         * is reached.  If the calculated delta time is more than halfway to the
-         * next compare event, check to see if a compare event has already been
-         * set, and if so, add one to the wrap-around count.  This is done to
-         * ensure the correct wrap count is used in the corner cases where the
-         * 16 bit counter passes the compare value during the process of
-         * configuring this interrupt.
-         *
-         * Assumption: The time to execute this function is less than 32ms
-         *             (otherwise incorrect behaviour could result)
-         *
-         * Consider the following corner cases:
-         * 1) timestamp is 1 us in the future:
-         *      oc_int_part = 0 initially
-         *      oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000
-         *      Compare event should happen in 1 us and us_ticker_irq_handler()
-         *      called
-         * 2) timestamp is 0x8000 us in the future:
-         *      oc_int_part = 0 initially
-         *      oc_int_part left at 0 because ((delta - 1) & 0xFFFF) < 0x8000
-         *      There should be no possibility of the CC1 flag being set yet
-         *      (see assumption above).  When the compare event does occur in
-         *      32768 us, us_ticker_irq_handler() will be called
-         * 3) timestamp is 0x8001 us in the future:
-         *      oc_int_part = 0 initially
-         *      ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no
-         *      possibility of the CC1 flag being set yet (see assumption above),
-         *      so oc_int_part will be left at 0, and when the compare event
-         *      does occur in 32769 us, us_ticker_irq_handler() will be called
-         * 4) timestamp is 0x10000 us in the future:
-         *      oc_int_part = 0 initially
-         *      ((delta - 1) & 0xFFFF) >= 0x8000
-         *      There are two subcases:
-         *      a) The timer counter has not incremented past the compare
-         *          value while setting up the interrupt.  In this case, the
-         *          CC1 flag will not be set, so oc_int_part will be
-         *          left at 0, and when the compare event occurs in 65536 us,
-         *          us_ticker_irq_handler() will be called
-         *      b) The timer counter has JUST incremented past the compare
-         *          value.  In this case, the CC1 flag will be set, so
-         *          oc_int_part will be incremented to 1, and the interrupt will
-         *          occur immediately after this function returns, where
-         *          oc_int_part will decrement to 0 without calling
-         *          us_ticker_irq_handler().  Then about 65536 us later, the
-         *          compare event will occur again, and us_ticker_irq_handler()
-         *          will be called
-         * 5) timestamp is 0x10001 us in the future:
-         *      oc_int_part = 1 initially
-         *      oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000
-         *      CC1 flag will not be set (see assumption above).  In 1 us the
-         *      compare event will cause an interrupt, where oc_int_part will be
-         *      decremented to 0 without calling us_ticker_irq_handler().  Then
-         *      about 65536 us later, the compare event will occur again, and
-         *      us_ticker_irq_handler() will be called
-         * 6) timestamp is 0x18000 us in the future:
-         *      oc_int_part = 1 initially
-         *      oc_int_part left at 1 because ((delta - 1) & 0xFFFF) < 0x8000
-         *      There should be no possibility of the CC1 flag being set yet
-         *      (see assumption above).  When the compare event does occur in
-         *      32768 us, oc_int_part will be decremented to 0 without calling
-         *      us_ticker_irq_handler().  Then about 65536 us later, the
-         *      compare event will occur again, and us_ticker_irq_handler() will
-         *      be called
-         * 7) timestamp is 0x18001 us in the future:
-         *      oc_int_part = 1 initially
-         *      ((delta - 1) & 0xFFFF) >= 0x8000 but there should be no
-         *      possibility of the CC1 flag being set yet (see assumption above),
-         *      so oc_int_part will be left at 1, and when the compare event
-         *      does occur in 32769 us, oc_int_part will be decremented to 0
-         *      without calling us_ticker_irq_handler().  Then about 65536 us
-         *      later, the compare event will occur again, and
-         *      us_ticker_irq_handler() will be called
-         *
-         * delta - 1 is used because the timer compare event happens on the
-         * counter incrementing to match the compare value, and it won't occur
-         * immediately when the compare value is set to the current counter
-         * value.
-         */
-        oc_int_part = ((uint32_t)delta - 1) >> 16;
-        if ( ((delta - 1) & 0xFFFF) >= 0x8000 &&
-             __HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET ) {
-            ++oc_int_part;
-            /* NOTE: Instead of incrementing oc_int_part here, we could clear
-             *       the CC1 flag, but then you'd have to wait to ensure the
-             *       interrupt is knocked down before returning and reenabling
-             *       interrupts.  Since this is a rare case, it's not worth it
-             *       to try and optimize it, and it keeps the code simpler and
-             *       safer to just do this increment instead.
-             */
-        }
     }
+
 }
 
+void us_ticker_fire_interrupt(void)
+{
+    /* When firing the event, the number of 16 bits counter wrap-ups (oc_int)
+     * must be re-initialized */
+    oc_int_part = 0;
+    HAL_TIM_GenerateEvent(&TimMasterHandle, TIM_EVENTSOURCE_CC1);
+}
+
+/* NOTE: must be called with interrupts disabled! */
 void us_ticker_disable_interrupt(void)
 {
-    TimMasterHandle.Instance = TIM_MST;
     __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1);
 }
 
+/* NOTE: must be called with interrupts disabled! */
 void us_ticker_clear_interrupt(void)
 {
-    TimMasterHandle.Instance = TIM_MST;
     __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1);
 }