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
Laurent MEUNIER 2017-05-31 09:17:57 +02:00
parent 40042f0b00
commit b9b5f0b929
2 changed files with 13 additions and 19 deletions

View File

@ -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;
}
}

View File

@ -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)