From 840df6ccd7b80a53ce5c3736ea9ff8d10985acbc Mon Sep 17 00:00:00 2001 From: Bartosz Szczepanski Date: Mon, 16 May 2016 13:33:03 +0200 Subject: [PATCH] [NUCLEO_L053R8] Fix issue #816 NUCLEO_L053R8 is using a 16 bit timer as a internal ticker but the mBed ticker needs a 32 bit timer, so the upper upart of that timer is being calculated in software. Continous HIGH/LOW voltage levels were observerd for 65ms due to timer overflow, so to narrow down the issue, it was decided to switch to 16 bit values and glue them to get a 32 bit timer. Change-Id: I54a06d5aa0f8ddabd8abc194470845a2509e0c55 --- .../TARGET_NUCLEO_L053R8/hal_tick.c | 2 +- .../hal/TARGET_STM/TARGET_STM32L0/us_ticker.c | 53 ++++++++++++------- 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32L0/TARGET_NUCLEO_L053R8/hal_tick.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32L0/TARGET_NUCLEO_L053R8/hal_tick.c index 9e42da7a4e..b7c958fd97 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32L0/TARGET_NUCLEO_L053R8/hal_tick.c +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32L0/TARGET_NUCLEO_L053R8/hal_tick.c @@ -40,7 +40,7 @@ uint32_t PreviousVal = 0; void us_ticker_irq_handler(void); void set_compare(uint16_t count); -extern volatile uint32_t SlaveCounter; +extern volatile uint16_t SlaveCounter; extern volatile uint32_t oc_int_part; extern volatile uint16_t oc_rem_part; diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_STM32L0/us_ticker.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_STM32L0/us_ticker.c index cbaebe3489..564f6079f0 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_STM32L0/us_ticker.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_STM32L0/us_ticker.c @@ -26,6 +26,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include +#include #include "us_ticker_api.h" #include "PeripheralNames.h" @@ -34,8 +35,9 @@ static TIM_HandleTypeDef TimMasterHandle; static int us_ticker_inited = 0; +static bool us_ticker_stabilized = false; -volatile uint32_t SlaveCounter = 0; +volatile uint16_t SlaveCounter = 0; volatile uint32_t oc_int_part = 0; volatile uint16_t oc_rem_part = 0; @@ -58,24 +60,39 @@ void us_ticker_init(void) uint32_t us_ticker_read() { - uint32_t counter, counter2; + volatile uint16_t cntH_old, cntH, cntL; + if (!us_ticker_inited) us_ticker_init(); - // 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 += TIM_MST->CNT; - while (1) { - counter2 = (uint32_t)(SlaveCounter << 16); - counter2 += TIM_MST->CNT; - if (counter2 > counter) { - break; - } - counter = counter2; - } - return counter2; + + // There's a situation where the first tick still may overflow and to avoid + // it we need to check if our ticker has stabilized and due to that we need + // to return only the lower part of your 32 bit software timer. + if (us_ticker_stabilized) { + do { + // 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); + } + cntH_old = SlaveCounter; + if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) { + cntH_old += 1; + } + cntL = TIM_MST->CNT; + + cntH = SlaveCounter; + if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_UPDATE) == SET) { + cntH += 1; + } + } while(cntH_old != cntH); + } else { + us_ticker_stabilized = true; + return (uint32_t) TIM_MST->CNT; + } + + // Glue the upper and lower part together to get a 32 bit timer + return (uint32_t)(cntH << 16 | cntL); } void us_ticker_set_interrupt(timestamp_t timestamp)