mirror of https://github.com/ARMmbed/mbed-os.git
[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: I54a06d5aa0f8ddabd8abc194470845a2509e0c55pull/1743/head
parent
1d1f7ab133
commit
840df6ccd7
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue