1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-15 12:25:20 +03:00

Fix micros using COUNTFLAG

Current micros() may return past time when called from ISR or elevated BASEPRI context. This is because a call to the SysTick interrupt handler sysTick_Hanlder(), which is responsible for 1ms rollover is blocked in these contexts.

This PR introduces microsISR() that is guranteed to return correct time in these contexts. Legacy micros() was also modified to call microISR() in these contexts.

The microISR() uses SysTick's COUNTFLAG to detect a pending rollover and use it to compensate the return value on its own. Actual rollover to sysTickUptime variable is still handled in the sysTick_Hanlder().
This commit is contained in:
jflyper 2016-09-26 23:42:35 +09:00
parent a21694b065
commit 59e78fcd8e
2 changed files with 44 additions and 1 deletions

View file

@ -24,6 +24,7 @@
#include "light_led.h"
#include "sound_beeper.h"
#include "nvic.h"
#include "common/atomic.h"
#include "system.h"
@ -61,15 +62,56 @@ void cycleCounterInit(void)
}
// SysTick
static volatile int sysTickPending = 0;
void SysTick_Handler(void)
{
sysTickUptime++;
ATOMIC_BLOCK(NVIC_PRIO_MAX) {
sysTickUptime++;
sysTickPending = 0;
(void)(SysTick->CTRL);
}
}
// Return system uptime in microseconds (rollover in 70minutes)
uint32_t microsISR(void)
{
register uint32_t ms, cycle_cnt;
ATOMIC_BLOCK(NVIC_PRIO_MAX) {
cycle_cnt = SysTick->VAL;
if (SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) {
// Update pending.
// Remember it for multiple calls within the same rollover period
// (Will be cleared when serviced).
// Note that multiple rollovers are not considered.
sysTickPending = 1;
// Read VAL again to ensure the value is read after the rollover.
cycle_cnt = SysTick->VAL;
}
ms = sysTickUptime;
}
return ((ms + sysTickPending) * 1000) + (usTicks * 1000 - cycle_cnt) / usTicks;
}
uint32_t micros(void)
{
register uint32_t ms, cycle_cnt;
// Call microsISR() in interrupt and elevated (non-zero) BASEPRI context
if ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) || (__get_BASEPRI())) {
return microsISR();
}
do {
ms = sysTickUptime;
cycle_cnt = SysTick->VAL;

View file

@ -22,6 +22,7 @@ void delayMicroseconds(uint32_t us);
void delay(uint32_t ms);
uint32_t micros(void);
uint32_t microsISR(void);
uint32_t millis(void);
typedef enum {