mirror of https://github.com/ARMmbed/mbed-os.git
STM32: 16 bits ticker, fixes in set function and handler
This commit simplifies ticker interrupt set function and handler. There were issues around the 16 bits timer wrap-around timing as we were aligning interrupts with wrap-around limits (0xFFFF) and then reading TIM_MST->CNT again in timer_update_irq_handler which could lead to crossing case with the wrap-around (TIM_FLAG_UPDATE) case. Now we're using the 16 lower bits of the timestamp as the reference from using in set_compare and never changing it. There is also no need to set comparator again in timer_update_irq_handler. This is more robust and also more efficient.pull/4424/head
parent
b9b5f0b929
commit
35c68859c0
|
@ -24,20 +24,19 @@ extern TIM_HandleTypeDef TimMasterHandle;
|
|||
|
||||
extern volatile uint32_t SlaveCounter;
|
||||
extern volatile uint32_t oc_int_part;
|
||||
extern volatile uint16_t oc_rem_part;
|
||||
|
||||
volatile uint32_t PreviousVal = 0;
|
||||
|
||||
void us_ticker_irq_handler(void);
|
||||
void set_compare(uint16_t count);
|
||||
|
||||
|
||||
#if defined(TARGET_STM32F0)
|
||||
void timer_update_irq_handler(void) {
|
||||
#else
|
||||
void timer_irq_handler(void)
|
||||
{
|
||||
#endif
|
||||
uint16_t cnt_val = TIM_MST->CNT;
|
||||
TimMasterHandle.Instance = TIM_MST;
|
||||
|
||||
// Clear Update interrupt flag
|
||||
|
@ -53,7 +52,6 @@ void timer_irq_handler(void)
|
|||
// Used for mbed timeout (channel 1) and HAL tick (channel 2)
|
||||
void timer_oc_irq_handler(void)
|
||||
{
|
||||
uint16_t cnt_val = TIM_MST->CNT;
|
||||
TimMasterHandle.Instance = TIM_MST;
|
||||
#endif
|
||||
|
||||
|
@ -61,23 +59,18 @@ void timer_oc_irq_handler(void)
|
|||
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET) {
|
||||
if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_CC1) == SET) {
|
||||
__HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC1);
|
||||
if (oc_rem_part > 0) {
|
||||
set_compare(oc_rem_part); // Finish the remaining time left
|
||||
oc_rem_part = 0;
|
||||
} else {
|
||||
|
||||
if (oc_int_part > 0) {
|
||||
set_compare(0xFFFF);
|
||||
oc_rem_part = cnt_val; // To finish the counter loop the next time
|
||||
oc_int_part--;
|
||||
} else {
|
||||
us_ticker_irq_handler();
|
||||
us_ticker_irq_handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Channel 2 for HAL tick
|
||||
if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC2) == SET) {
|
||||
|
||||
if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_CC2) == SET) {
|
||||
__HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC2);
|
||||
uint32_t val = __HAL_TIM_GET_COUNTER(&TimMasterHandle);
|
||||
|
@ -114,11 +107,16 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
|||
TimMasterHandle.Init.Prescaler = (uint32_t)(SystemCoreClock / 1000000) - 1; // 1 us tick
|
||||
TimMasterHandle.Init.ClockDivision = 0;
|
||||
TimMasterHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
#ifdef TARGET_STM32F0
|
||||
#if !defined(TARGET_STM32L0)
|
||||
TimMasterHandle.Init.RepetitionCounter = 0;
|
||||
#endif
|
||||
#ifdef TIM_AUTORELOAD_PRELOAD_DISABLE
|
||||
TimMasterHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
#endif
|
||||
HAL_TIM_Base_Init(&TimMasterHandle);
|
||||
|
||||
//LL_TIM_EnableUpdateEvent(TimMasterHandle.Instance);
|
||||
|
||||
// Configure output compare channel 1 for mbed timeout (enabled later when used)
|
||||
HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_1);
|
||||
|
||||
|
@ -127,6 +125,8 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
|||
PreviousVal = __HAL_TIM_GET_COUNTER(&TimMasterHandle);
|
||||
__HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_2, PreviousVal + HAL_TICK_DELAY);
|
||||
|
||||
|
||||
|
||||
// Configure interrupts
|
||||
// Update interrupt used for 32-bit counter
|
||||
// Output compare channel 1 interrupt for mbed timeout
|
||||
|
|
|
@ -25,7 +25,6 @@ TIM_HandleTypeDef TimMasterHandle;
|
|||
|
||||
volatile uint32_t SlaveCounter = 0;
|
||||
volatile uint32_t oc_int_part = 0;
|
||||
volatile uint16_t oc_rem_part = 0;
|
||||
|
||||
static int us_ticker_inited = 0;
|
||||
|
||||
|
@ -91,22 +90,25 @@ uint32_t us_ticker_read()
|
|||
|
||||
void us_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
int delta = (int)((uint32_t)timestamp - us_ticker_read());
|
||||
|
||||
uint16_t cval = TIM_MST->CNT;
|
||||
int current_time = us_ticker_read();
|
||||
int delta = (int)(timestamp - current_time);
|
||||
|
||||
if (delta <= 0) { // This event was in the past
|
||||
us_ticker_irq_handler();
|
||||
/* Force the event to be handled in next interrupt context
|
||||
* This prevents calling interrupt handlers in loops as
|
||||
* us_ticker_set_interrupt might called again from the
|
||||
* application handler
|
||||
*/
|
||||
oc_int_part = 0;
|
||||
TimMasterHandle.Instance = TIM_MST;
|
||||
HAL_TIM_GenerateEvent(&TimMasterHandle, TIM_EVENTSOURCE_CC1);
|
||||
} else {
|
||||
/* set the comparator at the timestamp lower 16 bits
|
||||
* and count the number of wrap-around loops to do with
|
||||
* the upper 16 bits
|
||||
*/
|
||||
oc_int_part = (uint32_t)(delta >> 16);
|
||||
oc_rem_part = (uint16_t)(delta & 0xFFFF);
|
||||
if (oc_rem_part <= (0xFFFF - cval)) {
|
||||
set_compare(cval + oc_rem_part);
|
||||
oc_rem_part = 0;
|
||||
} else {
|
||||
set_compare(0xFFFF);
|
||||
oc_rem_part = oc_rem_part - (0xFFFF - cval);
|
||||
}
|
||||
set_compare(timestamp & 0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue