From 74d44ed05778a2e941cfece80f365828ed4a52c7 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 19 Apr 2023 11:43:25 +0200 Subject: [PATCH] fix: Corrupt data using soft serial driver (#3329) * restore bit start detection IRQ for soft serial * restore bit start detection IRQ for softserial (target Taranis and Horus) * target Taranis: EXTI9_5 is a shared interrupt for Rotary Encoder and Heartbeat for X7, X7-ACCESS und TPRO radios. Changed IRQ priority accordingly * fix crashes where the heartbeat ISR running at interrupt priorities higher than 5 interferes with FreeRTOS calls made from within the heartbeat ISR. * changed mixer scheduler timer initialization to allow for software generated update events to avoid freeRTOS calls from now prio 0 heartbeat ISR. * resolved review feedback: using defines for IRQ prio settings * following review by @raphaelcoeffic: - new function void mixerSchedulerSoftTrigger() (to be called by heartbeat driver) - defines in hal.h for targets horus and taranis * following @raphaelcoeffics review - changed all but telemetry EXIT IRQ (soft serial) definition back to their original state and added define to override EXIT IRQ (soft serial) prio --- radio/src/mixer_scheduler.h | 10 +++++----- .../common/arm/stm32/heartbeat_driver.cpp | 3 +-- .../arm/stm32/mixer_scheduler_driver.cpp | 20 +++++++++---------- radio/src/targets/horus/hal.h | 6 +++++- radio/src/targets/taranis/hal.h | 6 +++++- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/radio/src/mixer_scheduler.h b/radio/src/mixer_scheduler.h index b79d7c7af..0f1c34fca 100644 --- a/radio/src/mixer_scheduler.h +++ b/radio/src/mixer_scheduler.h @@ -40,9 +40,6 @@ void mixerSchedulerStart(); // Stop the scheduler timer void mixerSchedulerStop(); -// Set the timer counter to 0 -void mixerSchedulerResetTimer(); - // Set the scheduling period for a given module void mixerSchedulerSetPeriod(uint8_t moduleIdx, uint16_t periodUs); @@ -55,6 +52,9 @@ void mixerSchedulerEnableTrigger(); // Disable the timer trigger void mixerSchedulerDisableTrigger(); +// Trigger mixer from heartbeat interrupt +void mixerSchedulerSoftTrigger(); + // Fetch the current scheduling period uint16_t getMixerSchedulerPeriod(); @@ -66,14 +66,14 @@ void mixerSchedulerISRTrigger(); #define mixerSchedulerInit() #define mixerSchedulerStart() #define mixerSchedulerStop() -#define mixerSchedulerResetTimer() #define mixerSchedulerSetPeriod(m,p) ((void)(p)) #define mixerSchedulerGetPeriod(m) ((uint16_t)MIXER_SCHEDULER_DEFAULT_PERIOD_US) -#define mixerSchedulerClearTrigger() #define mixerSchedulerEnableTrigger() #define mixerSchedulerDisableTrigger() +#define mixerSchedulerSoftTrigger() + #define getMixerSchedulerPeriod() (MIXER_SCHEDULER_DEFAULT_PERIOD_US) #define mixerSchedulerISRTrigger() diff --git a/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp b/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp index b059af8ba..58a054eba 100644 --- a/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp +++ b/radio/src/targets/common/arm/stm32/heartbeat_driver.cpp @@ -41,8 +41,7 @@ static void trigger_intmodule_heartbeat() heartbeatCapture.count++; #endif - mixerSchedulerResetTimer(); - mixerSchedulerISRTrigger(); + mixerSchedulerSoftTrigger(); } void init_intmodule_heartbeat() diff --git a/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp b/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp index dc6504e2a..258314032 100644 --- a/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp +++ b/radio/src/targets/common/arm/stm32/mixer_scheduler_driver.cpp @@ -30,13 +30,11 @@ void mixerSchedulerStart() { MIXER_SCHEDULER_TIMER->CR1 &= ~TIM_CR1_CEN; - - MIXER_SCHEDULER_TIMER->CR1 = TIM_CR1_URS; // do not generate interrupt on soft update MIXER_SCHEDULER_TIMER->PSC = MIXER_SCHEDULER_TIMER_FREQ / 1000000 - 1; // 1uS (1Mhz) MIXER_SCHEDULER_TIMER->CCER = 0; MIXER_SCHEDULER_TIMER->CCMR1 = 0; MIXER_SCHEDULER_TIMER->ARR = getMixerSchedulerPeriod() - 1; - MIXER_SCHEDULER_TIMER->EGR = TIM_EGR_UG; // reset timer + MIXER_SCHEDULER_TIMER->CNT = 0; // reset counter NVIC_EnableIRQ(MIXER_SCHEDULER_TIMER_IRQn); NVIC_SetPriority(MIXER_SCHEDULER_TIMER_IRQn, @@ -53,13 +51,6 @@ void mixerSchedulerStop() NVIC_DisableIRQ(MIXER_SCHEDULER_TIMER_IRQn); } -void mixerSchedulerResetTimer() -{ - mixerSchedulerDisableTrigger(); - MIXER_SCHEDULER_TIMER->CNT = 0; - mixerSchedulerEnableTrigger(); -} - void mixerSchedulerEnableTrigger() { MIXER_SCHEDULER_TIMER->DIER |= TIM_DIER_UIE; // enable interrupt @@ -70,6 +61,15 @@ void mixerSchedulerDisableTrigger() MIXER_SCHEDULER_TIMER->DIER &= ~TIM_DIER_UIE; // disable interrupt } +void mixerSchedulerSoftTrigger() { + // Generate a timer update event (TIM_EGR_UG) to reload the Prescaler and the repetition + // counter value immediately to avoid making FreeRTOS calls within this ISR: + // - fires MIXER_SCHEDULER_TIMER interrupt after returning from this ISR + // - MIXER_SCHEDULER_TIMER_IRQHandler(void) takes care of making FreeRTOS calls + // to ensure switching to highest priority task. + MIXER_SCHEDULER_TIMER->EGR = TIM_EGR_UG; +} + extern "C" void MIXER_SCHEDULER_TIMER_IRQHandler(void) { MIXER_SCHEDULER_TIMER->SR &= ~TIM_SR_UIF; // clear flag diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index ca33d7a5c..67cb0df44 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -28,6 +28,8 @@ #define TIMER_MULT_APB1 2 #define TIMER_MULT_APB2 2 +#define TELEMETRY_EXTI_PRIO 0 // required for soft serial + // Keys #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOJ) #if defined(PCBX12S) @@ -521,8 +523,10 @@ // TELEMETRY_EXTI IRQ #if !defined(USE_EXTI9_5_IRQ) #define USE_EXTI9_5_IRQ - #define EXTI9_5_IRQ_Priority 5 #endif +// overwrite priority +#undef EXTI9_5_IRQ_Priority +#define EXTI9_5_IRQ_Priority TELEMETRY_EXTI_PRIO #define TELEMETRY_TIMER TIM11 #define TELEMETRY_TIMER_IRQn TIM1_TRG_COM_TIM11_IRQn diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 788b0b6f0..03b045d40 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -35,6 +35,8 @@ #define TIMER_MULT_APB1 2 #define TIMER_MULT_APB2 2 +#define TELEMETRY_EXTI_PRIO 0 // required for soft serial + // Keys #if defined(PCBX9E) #define KEYS_GPIO_REG_MENU GPIOD->IDR @@ -1962,8 +1964,10 @@ // TELEMETRY_EXTI IRQ #if !defined(USE_EXTI9_5_IRQ) #define USE_EXTI9_5_IRQ - #define EXTI9_5_IRQ_Priority 5 #endif +// overwrite priority +#undef EXTI9_5_IRQ_Priority +#define EXTI9_5_IRQ_Priority TELEMETRY_EXTI_PRIO #define TELEMETRY_TIMER TIM11 #define TELEMETRY_TIMER_PRESCALER ()