[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
pull/1743/head
Bartosz Szczepanski 2016-05-16 13:33:03 +02:00
parent 1d1f7ab133
commit 840df6ccd7
2 changed files with 36 additions and 19 deletions

View File

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

View File

@ -26,6 +26,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stddef.h>
#include <stdbool.h>
#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)