mirror of https://github.com/ARMmbed/mbed-os.git
STM32 16bits ticker: rework us_ticker_read()
Move to a single more reliable implementation of us_ticker_read() There were historically 2 versions of us_ticker_read() implementation. The one removed here was not reliable because us_ticker_read() can be called in interrupt context which means that TIM_MST->CNT would have wrapped around while SlaveCounter is not yet updated. So there is a need to check the TIM_FLAG_UPDATE inside this function, which was not done in the implementation that is removed here.pull/4424/head
parent
40042f0b00
commit
b9b5f0b929
|
@ -25,8 +25,6 @@ extern TIM_HandleTypeDef TimMasterHandle;
|
|||
extern volatile uint32_t SlaveCounter;
|
||||
extern volatile uint32_t oc_int_part;
|
||||
extern volatile uint16_t oc_rem_part;
|
||||
extern volatile uint8_t tim_it_update;
|
||||
extern volatile uint32_t tim_it_counter;
|
||||
|
||||
volatile uint32_t PreviousVal = 0;
|
||||
|
||||
|
@ -47,8 +45,6 @@ void timer_irq_handler(void)
|
|||
if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_UPDATE) == SET) {
|
||||
__HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_UPDATE);
|
||||
SlaveCounter++;
|
||||
tim_it_counter = cnt_val + (uint32_t)(SlaveCounter << 16);
|
||||
tim_it_update = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@ TIM_HandleTypeDef TimMasterHandle;
|
|||
volatile uint32_t SlaveCounter = 0;
|
||||
volatile uint32_t oc_int_part = 0;
|
||||
volatile uint16_t oc_rem_part = 0;
|
||||
volatile uint8_t tim_it_update; // TIM_IT_UPDATE event flag set in timer_irq_handler()
|
||||
volatile uint32_t tim_it_counter = 0; // Time stamp to be updated by timer_irq_handler()
|
||||
|
||||
static int us_ticker_inited = 0;
|
||||
|
||||
|
@ -52,22 +50,32 @@ void us_ticker_init(void)
|
|||
|
||||
uint32_t us_ticker_read()
|
||||
{
|
||||
uint32_t counter;
|
||||
|
||||
TimMasterHandle.Instance = TIM_MST;
|
||||
|
||||
if (!us_ticker_inited) us_ticker_init();
|
||||
|
||||
#if defined(TARGET_STM32L0)
|
||||
uint16_t cntH_old, cntH, cntL;
|
||||
do {
|
||||
#if defined(TARGET_STM32L0)
|
||||
// For some reason on L0xx series we need to read and clear the
|
||||
// overflow flag which give extra time to propelry handle possible
|
||||
// hiccup after ~60s
|
||||
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1OF) == SET) {
|
||||
__HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1OF);
|
||||
}
|
||||
#endif
|
||||
cntH_old = SlaveCounter;
|
||||
/* SlaveCounter needs to be checked before AND after we read the
|
||||
* current counter TIM_MST->CNT, in case it wraps around.
|
||||
* there are 2 possible cases of wrap around
|
||||
* 1) in case this function is interrupted by timer_irq_handler and
|
||||
* the SlaveCounter is updated. In that case we will loop again.
|
||||
* 2) in case this function is called from context interrupt during
|
||||
* wrap-around condtion. That would prevent/delay the timer_irq_handler
|
||||
* to be called so we need to locally check the FLAG_UPDATE and
|
||||
* update the cntH accordingly. The SlaveCounter variable itself will
|
||||
* be updated in the interrupt handler just after ...
|
||||
*/
|
||||
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) {
|
||||
cntH_old += 1;
|
||||
}
|
||||
|
@ -79,16 +87,6 @@ uint32_t us_ticker_read()
|
|||
} while(cntH_old != cntH);
|
||||
// Glue the upper and lower part together to get a 32 bit timer
|
||||
return (uint32_t)(cntH << 16 | cntL);
|
||||
#else
|
||||
tim_it_update = 0; // Clear TIM_IT_UPDATE event flag
|
||||
counter = TIM_MST->CNT + (uint32_t)(SlaveCounter << 16); // Calculate new time stamp
|
||||
if (tim_it_update == 1) {
|
||||
return tim_it_counter; // In case of TIM_IT_UPDATE return the time stamp that was calculated in timer_irq_handler()
|
||||
}
|
||||
else {
|
||||
return counter; // Otherwise return the time stamp calculated here
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void us_ticker_set_interrupt(timestamp_t timestamp)
|
||||
|
|
Loading…
Reference in New Issue