diff --git a/targets/TARGET_STM/TARGET_STM32F1/TARGET_BLUEPILL_F103C8/device/hal_tick.c b/targets/TARGET_STM/TARGET_STM32F1/TARGET_BLUEPILL_F103C8/device/hal_tick.c index 7e9a884268..d9a2a94362 100644 --- a/targets/TARGET_STM/TARGET_STM32F1/TARGET_BLUEPILL_F103C8/device/hal_tick.c +++ b/targets/TARGET_STM/TARGET_STM32F1/TARGET_BLUEPILL_F103C8/device/hal_tick.c @@ -43,10 +43,9 @@ void set_compare(uint16_t count); extern volatile uint32_t SlaveCounter; extern volatile uint32_t oc_int_part; extern volatile uint16_t oc_rem_part; -extern volatile uint16_t cnt_val; void timer_irq_handler(void) { - cnt_val = TIM_MST->CNT; + uint16_t cval = TIM_MST->CNT; TimMasterHandle.Instance = TIM_MST; @@ -68,7 +67,7 @@ void timer_irq_handler(void) { } else { if (oc_int_part > 0) { set_compare(0xFFFF); - oc_rem_part = cnt_val; // To finish the counter loop the next time + oc_rem_part = cval; // To finish the counter loop the next time oc_int_part--; } else { us_ticker_irq_handler(); diff --git a/targets/TARGET_STM/TARGET_STM32F1/TARGET_NUCLEO_F103RB/device/hal_tick.c b/targets/TARGET_STM/TARGET_STM32F1/TARGET_NUCLEO_F103RB/device/hal_tick.c index 5200b6ee90..0d76d72fe7 100644 --- a/targets/TARGET_STM/TARGET_STM32F1/TARGET_NUCLEO_F103RB/device/hal_tick.c +++ b/targets/TARGET_STM/TARGET_STM32F1/TARGET_NUCLEO_F103RB/device/hal_tick.c @@ -43,10 +43,9 @@ void set_compare(uint16_t count); extern volatile uint32_t SlaveCounter; extern volatile uint32_t oc_int_part; extern volatile uint16_t oc_rem_part; -extern volatile uint16_t cnt_val; void timer_irq_handler(void) { - cnt_val = TIM_MST->CNT; + uint16_t cval = TIM_MST->CNT; TimMasterHandle.Instance = TIM_MST; @@ -68,7 +67,7 @@ void timer_irq_handler(void) { } else { if (oc_int_part > 0) { set_compare(0xFFFF); - oc_rem_part = cnt_val; // To finish the counter loop the next time + oc_rem_part = cval; // To finish the counter loop the next time oc_int_part--; } else { us_ticker_irq_handler(); diff --git a/targets/TARGET_STM/TARGET_STM32F1/us_ticker.c b/targets/TARGET_STM/TARGET_STM32F1/us_ticker.c index 1511a387e0..19a971b479 100644 --- a/targets/TARGET_STM/TARGET_STM32F1/us_ticker.c +++ b/targets/TARGET_STM/TARGET_STM32F1/us_ticker.c @@ -38,7 +38,6 @@ static int us_ticker_inited = 0; volatile uint32_t SlaveCounter = 0; volatile uint32_t oc_int_part = 0; volatile uint16_t oc_rem_part = 0; -volatile uint16_t cnt_val = 0; void set_compare(uint16_t count) { @@ -59,15 +58,24 @@ void us_ticker_init(void) uint32_t us_ticker_read() { - uint32_t counter; + uint32_t counter, counter2; if (!us_ticker_inited) us_ticker_init(); - - //Current value of TIM_MST->CNT is stored in cnt_val and is - //updated in interrupt context + // A situation might appear when Master overflows right after Slave is read and before the + // new (overflowed) value of Master is read. Which would make the code below consider the + // previous (incorrect) value of Slave and the new value of Master, which would return a + // value in the past. Avoid this by computing consecutive values of the timer until they + // are properly ordered. counter = (uint32_t)(SlaveCounter << 16); - counter += cnt_val; - - return counter; + counter += TIM_MST->CNT; + while (1) { + counter2 = (uint32_t)(SlaveCounter << 16); + counter2 += TIM_MST->CNT; + if (counter2 > counter) { + break; + } + counter = counter2; + } + return counter2; } void us_ticker_set_interrupt(timestamp_t timestamp)