Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: STM32L452_Nucleo_ticker
Fork of mbed-dev by
Diff: targets/TARGET_STM/us_ticker_16b.c
- 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);
}
