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 SlaveCounter;
|
||||||
extern volatile uint32_t oc_int_part;
|
extern volatile uint32_t oc_int_part;
|
||||||
extern volatile uint16_t oc_rem_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;
|
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) {
|
if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_UPDATE) == SET) {
|
||||||
__HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_UPDATE);
|
__HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_UPDATE);
|
||||||
SlaveCounter++;
|
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 SlaveCounter = 0;
|
||||||
volatile uint32_t oc_int_part = 0;
|
volatile uint32_t oc_int_part = 0;
|
||||||
volatile uint16_t oc_rem_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;
|
static int us_ticker_inited = 0;
|
||||||
|
|
||||||
|
@ -52,22 +50,32 @@ void us_ticker_init(void)
|
||||||
|
|
||||||
uint32_t us_ticker_read()
|
uint32_t us_ticker_read()
|
||||||
{
|
{
|
||||||
uint32_t counter;
|
|
||||||
|
|
||||||
TimMasterHandle.Instance = TIM_MST;
|
TimMasterHandle.Instance = TIM_MST;
|
||||||
|
|
||||||
if (!us_ticker_inited) us_ticker_init();
|
if (!us_ticker_inited) us_ticker_init();
|
||||||
|
|
||||||
#if defined(TARGET_STM32L0)
|
|
||||||
uint16_t cntH_old, cntH, cntL;
|
uint16_t cntH_old, cntH, cntL;
|
||||||
do {
|
do {
|
||||||
|
#if defined(TARGET_STM32L0)
|
||||||
// For some reason on L0xx series we need to read and clear the
|
// For some reason on L0xx series we need to read and clear the
|
||||||
// overflow flag which give extra time to propelry handle possible
|
// overflow flag which give extra time to propelry handle possible
|
||||||
// hiccup after ~60s
|
// hiccup after ~60s
|
||||||
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1OF) == SET) {
|
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1OF) == SET) {
|
||||||
__HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1OF);
|
__HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1OF);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
cntH_old = SlaveCounter;
|
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) {
|
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) {
|
||||||
cntH_old += 1;
|
cntH_old += 1;
|
||||||
}
|
}
|
||||||
|
@ -79,16 +87,6 @@ uint32_t us_ticker_read()
|
||||||
} while(cntH_old != cntH);
|
} while(cntH_old != cntH);
|
||||||
// Glue the upper and lower part together to get a 32 bit timer
|
// Glue the upper and lower part together to get a 32 bit timer
|
||||||
return (uint32_t)(cntH << 16 | cntL);
|
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)
|
void us_ticker_set_interrupt(timestamp_t timestamp)
|
||||||
|
|
Loading…
Reference in New Issue