feat: better microsecond timer (#4112)

This commit is contained in:
Raphael Coeffic
2023-09-26 18:30:55 +02:00
committed by GitHub
parent 6f40ea44ad
commit 6abd4263a4
22 changed files with 135 additions and 195 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ extern safetych_t safetyCh[MAX_OUTPUT_CHANNELS];
extern uint8_t trimsCheckTimer;
extern uint8_t trimsDisplayTimer;
extern uint8_t trimsDisplayMask;
extern uint16_t maxMixerDuration;
extern uint32_t maxMixerDuration;
extern uint8_t requiredSpeakerVolume;
extern uint8_t requiredBacklightBright;
+9
View File
@@ -20,6 +20,7 @@
*/
#include "opentx.h"
#include "haptic.h"
hapticQueue::hapticQueue()
{
@@ -107,3 +108,11 @@ void hapticQueue::event(uint8_t e)
}
hapticQueue haptic;
// from timers_driver.cpp
void per5ms()
{
DEBUG_TIMER_START(debugTimerHaptic);
HAPTIC_HEARTBEAT();
DEBUG_TIMER_STOP(debugTimerHaptic);
}
+6 -1
View File
@@ -63,7 +63,7 @@ Clipboard clipboard;
GlobalData globalData;
uint16_t maxMixerDuration; // step = 0.01ms
uint32_t maxMixerDuration; // microseconds
uint8_t heartbeat;
#if defined(OVERRIDE_CHANNEL_FUNCTION)
@@ -138,6 +138,9 @@ void checkValidMCU(void)
void per10ms()
{
DEBUG_TIMER_START(debugTimerPer10ms);
DEBUG_TIMER_SAMPLE(debugTimerPer10msPeriod);
g_tmr10ms++;
#if defined(GUI)
@@ -203,6 +206,8 @@ void per10ms()
outputTelemetryBuffer.per10ms();
heartbeat |= HEART_TIMER_10MS;
DEBUG_TIMER_STOP(debugTimerPer10ms);
}
FlightModeData *flightModeAddress(uint8_t idx)
-1
View File
@@ -445,7 +445,6 @@ void doMixerPeriodicUpdates();
void checkTrims();
extern uint8_t currentBacklightBright;
void perMain();
void per10ms();
getvalue_t getValue(mixsrc_t i, bool* valid = nullptr);
+4 -4
View File
@@ -23,7 +23,7 @@
#include "sbus.h"
#include "timers_driver.h"
#define SBUS_FRAME_GAP_DELAY 1000 // 500uS
#define SBUS_FRAME_GAP_DELAY_US 500
#define SBUS_START_BYTE 0x0F
#define SBUS_END_BYTE 0x00
@@ -99,7 +99,7 @@ void processSbusInput()
// TODO: place this outside of the function
static uint8_t SbusIndex = 0;
static uint16_t SbusTimer;
static uint32_t SbusTimer;
static uint8_t SbusFrame[SBUS_FRAME_SIZE];
uint32_t active = 0;
@@ -117,13 +117,13 @@ void processSbusInput()
// Data has been received
if (active) {
SbusTimer = getTmr2MHz();
SbusTimer = timersGetUsTick();
return;
}
// Check if end-of-frame is detected
if (SbusIndex) {
if ((uint16_t)(getTmr2MHz() - SbusTimer) > SBUS_FRAME_GAP_DELAY) {
if ((uint32_t)(timersGetUsTick() - SbusTimer) > SBUS_FRAME_GAP_DELAY_US) {
processSbusFrame(SbusFrame, trainerInput, SbusIndex);
SbusIndex = 0;
}
@@ -30,6 +30,7 @@ set(BOOTLOADER_SRC
../usbd_usr.cpp
../usbd_storage_msd.cpp
../delays_driver.cpp
../timers_driver.cpp
../usbd_desc.c
../usb_bsp.c
../usb_driver.cpp
@@ -38,6 +39,7 @@ set(BOOTLOADER_SRC
../stm32_serial_driver.cpp
../stm32_usart_driver.cpp
../stm32_gpio_driver.cpp
../stm32_timer.cpp
../stm32_dma.cpp
init.c
boot.cpp
@@ -34,6 +34,7 @@
// #include "keys.h"
#include "debug.h"
#include "timers_driver.h"
#include "watchdog_driver.h"
#include "hal/rotary_encoder.h"
@@ -97,7 +98,7 @@ uint32_t unlocked = 0;
volatile uint32_t timer10MsCount;
void interrupt10ms()
void per10ms()
{
timer10MsCount++;
tenms |= 1u; // 10 mS has passed
@@ -122,48 +123,6 @@ extern "C" uint32_t HAL_GetTick(void)
return timer10MsCount * 10;
}
#if !defined(SIMU)
static volatile uint32_t _us_overflow_cnt;
void initTimers()
{
timer10MsCount = 0;
INTERRUPT_xMS_TIMER->ARR = 9999; // 10mS in uS
INTERRUPT_xMS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS
INTERRUPT_xMS_TIMER->CR1 = TIM_CR1_CEN;
INTERRUPT_xMS_TIMER->DIER = TIM_DIER_UIE;
NVIC_EnableIRQ(INTERRUPT_xMS_IRQn);
_us_overflow_cnt = 0;
TIMER_2MHz_TIMER->ARR = 65535;
TIMER_2MHz_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5 uS, 2 MHz
TIMER_2MHz_TIMER->CR1 = TIM_CR1_CEN;
TIMER_2MHz_TIMER->DIER = TIM_DIER_UIE;
NVIC_EnableIRQ(TIMER_2MHz_IRQn);
while(timer10MsCount < 10);
}
uint32_t timersGetUsTick()
{
uint32_t us;
us = TIMER_2MHz_TIMER->CNT >> 1;
us += _us_overflow_cnt << 15;
return us;
}
extern "C" void INTERRUPT_xMS_IRQHandler()
{
INTERRUPT_xMS_TIMER->SR &= ~TIM_SR_UIF;
interrupt10ms();
}
extern "C" void TIMER_2MHz_IRQHandler()
{
TIMER_2MHz_TIMER->SR &= ~TIM_SR_UIF;
_us_overflow_cnt += 1;
}
#endif
uint32_t isValidBufferStart(const uint8_t * buffer)
{
@@ -254,9 +213,7 @@ void bootloaderInitApp()
ENABLE);
RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph | LCD_RCC_APB1Periph |
BACKLIGHT_RCC_APB1Periph |
INTERRUPT_xMS_RCC_APB1Periph |
TIMER_2MHz_RCC_APB1Periph,
BACKLIGHT_RCC_APB1Periph,
ENABLE);
RCC_APB2PeriphClockCmd(
@@ -322,7 +279,7 @@ void bootloaderInitApp()
eepromInit();
#endif
initTimers();
timersInit();
// SD card detect pin
sdInit();
@@ -36,7 +36,6 @@ volatile HeartbeatCapture heartbeatCapture;
static void trigger_intmodule_heartbeat()
{
heartbeatCapture.timestamp = getTmr2MHz();
#if defined(DEBUG_LATENCY)
heartbeatCapture.count++;
#endif
@@ -22,7 +22,6 @@
#pragma once
struct HeartbeatCapture {
uint32_t timestamp;
uint8_t valid;
#if defined(DEBUG_LATENCY)
uint32_t count;
@@ -21,6 +21,7 @@
#include "mixer_scheduler.h"
#include "stm32_hal_ll.h"
#include "stm32_timer.h"
#include "FreeRTOSConfig.h"
#include "hal.h"
@@ -28,6 +29,8 @@
// Start scheduler with default period
void mixerSchedulerStart()
{
stm32_timer_enable_clock(MIXER_SCHEDULER_TIMER);
MIXER_SCHEDULER_TIMER->CR1 &= ~TIM_CR1_CEN;
MIXER_SCHEDULER_TIMER->PSC = MIXER_SCHEDULER_TIMER_FREQ / 1000000 - 1; // 1uS (1Mhz)
MIXER_SCHEDULER_TIMER->CCER = 0;
@@ -35,6 +35,10 @@ void stm32_timer_enable_clock(TIM_TypeDef *TIMx)
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM5);
} else if (TIMx == TIM8) {
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM8);
} else if (TIMx == TIM12) {
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM12);
} else if (TIMx == TIM14) {
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM14);
}
}
@@ -52,5 +56,9 @@ void stm32_timer_disable_clock(TIM_TypeDef *TIMx)
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM5);
} else if (TIMx == TIM8) {
LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_TIM8);
} else if (TIMx == TIM12) {
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM12);
} else if (TIMx == TIM14) {
LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM14);
}
}
@@ -19,109 +19,95 @@
* GNU General Public License for more details.
*/
#include "opentx.h"
#include "timers_driver.h"
#include "stm32_timer.h"
#include "stm32_hal_ll.h"
#include "hal.h"
#include "watchdog_driver.h"
static volatile uint32_t msTickCount; // Used to get 1 kHz counter
static volatile uint32_t _us_overflow_cnt;
static volatile uint32_t _ms_ticks;
// Start TIMER at 2000000Hz
void init2MhzTimer()
static void _init_1ms_timer()
{
_us_overflow_cnt = 0;
TIMER_2MHz_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5 uS, 2 MHz
TIMER_2MHz_TIMER->ARR = 65535;
TIMER_2MHz_TIMER->CR2 = 0;
TIMER_2MHz_TIMER->CR1 = TIM_CR1_CEN;
TIMER_2MHz_TIMER->DIER = TIM_DIER_UIE;
stm32_timer_enable_clock(MS_TIMER);
NVIC_EnableIRQ(TIMER_2MHz_IRQn);
NVIC_SetPriority(TIMER_2MHz_IRQn, 4);
_ms_ticks = 0;
MS_TIMER->ARR = 999; // 1mS in uS
MS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS
MS_TIMER->CCER = 0;
MS_TIMER->CCMR1 = 0;
MS_TIMER->EGR = 0;
MS_TIMER->CR1 = TIM_CR1_CEN | TIM_CR1_URS;
MS_TIMER->DIER = TIM_DIER_UIE;
NVIC_EnableIRQ(MS_TIMER_IRQn);
NVIC_SetPriority(MS_TIMER_IRQn, 4);
}
// Start TIMER at 1000Hz
void init1msTimer()
void timersInit()
{
msTickCount = 0;
INTERRUPT_xMS_TIMER->ARR = 999; // 1mS in uS
INTERRUPT_xMS_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 1000000 - 1; // 1uS
INTERRUPT_xMS_TIMER->CCER = 0;
INTERRUPT_xMS_TIMER->CCMR1 = 0;
INTERRUPT_xMS_TIMER->EGR = 0;
INTERRUPT_xMS_TIMER->CR1 = TIM_CR1_CEN | TIM_CR1_URS;
INTERRUPT_xMS_TIMER->DIER = TIM_DIER_UIE;
NVIC_EnableIRQ(INTERRUPT_xMS_IRQn);
NVIC_SetPriority(INTERRUPT_xMS_IRQn, 4);
}
void stop1msTimer()
{
INTERRUPT_xMS_TIMER->CR1 = 0; // stop timer
NVIC_DisableIRQ(INTERRUPT_xMS_IRQn);
_init_1ms_timer();
}
uint32_t timersGetMsTick()
{
return msTickCount;
return _ms_ticks;
}
uint32_t timersGetUsTick()
{
uint32_t ms;
uint32_t us;
us = TIMER_2MHz_TIMER->CNT >> 1;
us += _us_overflow_cnt << 15;
return us;
do {
ms = _ms_ticks;
us = MS_TIMER->CNT;
asm volatile("nop");
asm volatile("nop");
} while (ms != _ms_ticks);
return ms * 1000 + us;
}
static uint32_t watchdogTimeout = 0;
static volatile uint32_t watchdogTimeout = 0;
void watchdogSuspend(uint32_t timeout)
{
watchdogTimeout = timeout;
}
static void interrupt1ms()
#define __weak __attribute__((weak))
__weak void per10ms() {}
__weak void per5ms() {}
static inline void _interrupt_1ms()
{
static uint8_t pre_scale = 0;
++pre_scale;
++msTickCount;
++_ms_ticks;
// 5ms loop
if(pre_scale == 5 || pre_scale == 10) {
#if defined(HAPTIC)
DEBUG_TIMER_START(debugTimerHaptic);
HAPTIC_HEARTBEAT();
DEBUG_TIMER_STOP(debugTimerHaptic);
#endif
per5ms();
}
// 10ms loop
if (pre_scale == 10) {
pre_scale = 0;
if (watchdogTimeout) {
watchdogTimeout -= 1;
WDG_RESET(); // Retrigger hardware watchdog
}
DEBUG_TIMER_START(debugTimerPer10ms);
DEBUG_TIMER_SAMPLE(debugTimerPer10msPeriod);
per10ms();
DEBUG_TIMER_STOP(debugTimerPer10ms);
}
}
extern "C" void INTERRUPT_xMS_IRQHandler()
extern "C" void MS_TIMER_IRQHandler()
{
INTERRUPT_xMS_TIMER->SR &= ~TIM_SR_UIF;
interrupt1ms();
DEBUG_INTERRUPT(INT_5MS);
}
extern "C" void TIMER_2MHz_IRQHandler()
{
TIMER_2MHz_TIMER->SR &= ~TIM_SR_UIF;
_us_overflow_cnt += 1;
MS_TIMER->SR &= ~TIM_SR_UIF;
_interrupt_1ms();
}
@@ -21,33 +21,18 @@
#pragma once
#if defined(SIMU)
uint16_t getTmr2MHz();
#define watchdogSuspend(timeout)
#else // SIMU
#include "hal.h"
void init2MhzTimer();
void init1msTimer();
void stop1msTimer();
#define getTmr2MHz() TIMER_2MHz_TIMER->CNT
void watchdogSuspend(uint32_t timeout);
#endif
#include "opentx_types.h"
extern "C" volatile tmr10ms_t g_tmr10ms;
static inline tmr10ms_t get_tmr10ms() { return g_tmr10ms; }
static inline tmr10ms_t get_tmr10ms()
{
return g_tmr10ms;
}
void watchdogSuspend(uint32_t timeout);
void timersInit();
uint32_t timersGetMsTick();
uint32_t timersGetUsTick();
// declared "weak", to be implemented by application
void per5ms();
void per10ms();
+1 -5
View File
@@ -106,12 +106,9 @@ void boardInit()
ENABLE);
RCC_APB1PeriphClockCmd(ROTARY_ENCODER_RCC_APB1Periph |
INTERRUPT_xMS_RCC_APB1Periph |
TIMER_2MHz_RCC_APB1Periph |
AUDIO_RCC_APB1Periph |
TELEMETRY_RCC_APB1Periph |
AUDIO_RCC_APB1Periph |
MIXER_SCHEDULER_TIMER_RCC_APB1Periph |
BACKLIGHT_RCC_APB1Periph,
ENABLE);
@@ -172,8 +169,7 @@ void boardInit()
if (!adcInit(&_adc_driver))
TRACE("adcInit failed");
init2MhzTimer();
init1msTimer();
timersInit();
usbInit();
hapticInit();
+4 -13
View File
@@ -987,21 +987,12 @@
#define TRAINER_MODULE_CPPM_TIMER_IRQHandler TIM4_IRQHandler
#define TRAINER_MODULE_CPPM_GPIO_AF LL_GPIO_AF_2
// Xms Interrupt
#define INTERRUPT_xMS_RCC_APB1Periph RCC_APB1Periph_TIM14
#define INTERRUPT_xMS_TIMER TIM14
#define INTERRUPT_xMS_IRQn TIM8_TRG_COM_TIM14_IRQn
#define INTERRUPT_xMS_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler
// 2MHz Timer
#define TIMER_2MHz_RCC_APB1Periph RCC_APB1Periph_TIM7
#define TIMER_2MHz_TIMER TIM7
#define TIMER_2MHz_IRQn TIM7_IRQn
#define TIMER_2MHz_IRQHandler TIM7_IRQHandler
// Millisecond timer
#define MS_TIMER TIM14
#define MS_TIMER_IRQn TIM8_TRG_COM_TIM14_IRQn
#define MS_TIMER_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler
// Mixer scheduler timer
#define MIXER_SCHEDULER_TIMER_RCC_APB1Periph RCC_APB1Periph_TIM13
#define MIXER_SCHEDULER_TIMER TIM13
#define MIXER_SCHEDULER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#define MIXER_SCHEDULER_TIMER_IRQn TIM8_UP_TIM13_IRQn
+3 -9
View File
@@ -126,14 +126,9 @@ void delay_self(int count)
)
#define RCC_AHB3PeriphMinimum (SDRAM_RCC_AHB3Periph)
#define RCC_APB1PeriphMinimum (INTERRUPT_xMS_RCC_APB1Periph |\
TIMER_2MHz_RCC_APB1Periph |\
BACKLIGHT_RCC_APB1Periph \
)
#define RCC_APB1PeriphMinimum (BACKLIGHT_RCC_APB1Periph)
#define RCC_APB1PeriphOther (TELEMETRY_RCC_APB1Periph |\
MIXER_SCHEDULER_TIMER_RCC_APB1Periph \
)
#define RCC_APB1PeriphOther (TELEMETRY_RCC_APB1Periph)
#define RCC_APB2PeriphMinimum (LCD_RCC_APB2Periph)
#define RCC_APB2PeriphOther (HAPTIC_RCC_APB2Periph |\
@@ -228,8 +223,7 @@ void boardInit()
init_trainer();
battery_charge_init();
flysky_gimbal_init();
init2MhzTimer();
init1msTimer();
timersInit();
TouchInit();
usbInit();
+4 -12
View File
@@ -541,20 +541,12 @@
#define BT_CMD_MODE_GPIO GPIOH
#define BT_CMD_MODE_GPIO_PIN GPIO_Pin_6 // PH.6
// Xms Interrupt
#define INTERRUPT_xMS_RCC_APB1Periph RCC_APB1Periph_TIM14
#define INTERRUPT_xMS_TIMER TIM14
#define INTERRUPT_xMS_IRQn TIM8_TRG_COM_TIM14_IRQn
#define INTERRUPT_xMS_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler
// 2MHz Timer
#define TIMER_2MHz_RCC_APB1Periph RCC_APB1Periph_TIM7
#define TIMER_2MHz_TIMER TIM7
#define TIMER_2MHz_IRQn TIM7_IRQn
#define TIMER_2MHz_IRQHandler TIM7_IRQHandler
// Millisecond timer
#define MS_TIMER TIM14
#define MS_TIMER_IRQn TIM8_TRG_COM_TIM14_IRQn
#define MS_TIMER_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler
// Mixer scheduler timer
#define MIXER_SCHEDULER_TIMER_RCC_APB1Periph RCC_APB1Periph_TIM12
#define MIXER_SCHEDULER_TIMER TIM12
#define MIXER_SCHEDULER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#define MIXER_SCHEDULER_TIMER_IRQn TIM8_BRK_TIM12_IRQn
+1
View File
@@ -18,6 +18,7 @@ set(SIMU_DRIVERS
backlight_driver.cpp
gyro_driver.cpp
bt_driver.cpp
timers_driver.cpp
)
set(HW_DESC_JSON ${FLAVOUR}.json)
+26
View File
@@ -0,0 +1,26 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "timers_driver.h"
void watchdogSuspend(unsigned int) {}
uint32_t timersGetUsTick() { return 0; }
+1 -5
View File
@@ -107,10 +107,7 @@ void boardInit()
AUDIO_RCC_APB1Periph |
BACKLIGHT_RCC_APB1Periph |
HAPTIC_RCC_APB1Periph |
INTERRUPT_xMS_RCC_APB1Periph |
TIMER_2MHz_RCC_APB1Periph |
TELEMETRY_RCC_APB1Periph |
MIXER_SCHEDULER_TIMER_RCC_APB1Periph |
BT_RCC_APB1Periph,
ENABLE);
@@ -224,8 +221,7 @@ void boardInit()
lcdInit(); // delaysInit() must be called before
audioInit();
init2MhzTimer();
init1msTimer();
timersInit();
usbInit();
#if defined(DEBUG)
+4 -12
View File
@@ -2800,20 +2800,12 @@
#define BT_RCC_APB2Periph 0
#endif
// Xms Interrupt
#define INTERRUPT_xMS_RCC_APB1Periph RCC_APB1Periph_TIM14
#define INTERRUPT_xMS_TIMER TIM14
#define INTERRUPT_xMS_IRQn TIM8_TRG_COM_TIM14_IRQn
#define INTERRUPT_xMS_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler
// 2MHz Timer
#define TIMER_2MHz_RCC_APB1Periph RCC_APB1Periph_TIM7
#define TIMER_2MHz_TIMER TIM7
#define TIMER_2MHz_IRQn TIM7_IRQn
#define TIMER_2MHz_IRQHandler TIM7_IRQHandler
// Millisecond timer
#define MS_TIMER TIM14
#define MS_TIMER_IRQn TIM8_TRG_COM_TIM14_IRQn
#define MS_TIMER_IRQHandler TIM8_TRG_COM_TIM14_IRQHandler
// Mixer scheduler timer
#define MIXER_SCHEDULER_TIMER_RCC_APB1Periph RCC_APB1Periph_TIM12
#define MIXER_SCHEDULER_TIMER TIM12
#define MIXER_SCHEDULER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#define MIXER_SCHEDULER_TIMER_IRQn TIM8_BRK_TIM12_IRQn
+2 -2
View File
@@ -187,7 +187,7 @@ TASK_FUNCTION(mixerTask)
if (_mixer_running) {
uint16_t t0 = getTmr2MHz();
uint32_t t0 = timersGetUsTick();
DEBUG_TIMER_START(debugTimerMixer);
mixerTaskLock();
@@ -213,7 +213,7 @@ TASK_FUNCTION(mixerTask)
// so let's do it here.
WDG_RESET();
t0 = getTmr2MHz() - t0;
t0 = timersGetUsTick() - t0;
if (t0 > maxMixerDuration)
maxMixerDuration = t0;
}