diff --git a/radio/src/targets/common/arm/stm32/stm32_pulse_driver.cpp b/radio/src/targets/common/arm/stm32/stm32_pulse_driver.cpp index b1d16e216..1ecce348f 100644 --- a/radio/src/targets/common/arm/stm32/stm32_pulse_driver.cpp +++ b/radio/src/targets/common/arm/stm32/stm32_pulse_driver.cpp @@ -76,11 +76,14 @@ void stm32_pulse_config_output(const stm32_pulse_timer_t* tim, bool polarity, ocInit.OCMode = ocmode; ocInit.CompareValue = cmp_val; + uint32_t channel = tim->TIM_Channel; if (tim->TIM_Channel != LL_TIM_CHANNEL_CH1N) { ocInit.OCState = LL_TIM_OCSTATE_ENABLE; + ocInit.OCNState = LL_TIM_OCSTATE_DISABLE; } else { + ocInit.OCState = LL_TIM_OCSTATE_DISABLE; ocInit.OCNState = LL_TIM_OCSTATE_ENABLE; - polarity = !polarity; + channel = LL_TIM_CHANNEL_CH1; } uint32_t ll_polarity; @@ -96,8 +99,8 @@ void stm32_pulse_config_output(const stm32_pulse_timer_t* tim, bool polarity, ocInit.OCNPolarity = ll_polarity; } - LL_TIM_OC_Init(tim->TIMx, tim->TIM_Channel, &ocInit); - LL_TIM_OC_EnablePreload(tim->TIMx, tim->TIM_Channel); + LL_TIM_OC_Init(tim->TIMx, channel, &ocInit); + LL_TIM_OC_EnablePreload(tim->TIMx, channel); if (IS_TIM_BREAK_INSTANCE(tim->TIMx)) { LL_TIM_EnableAllOutputs(tim->TIMx); @@ -143,13 +146,22 @@ static void set_compare_reg(const stm32_pulse_timer_t* tim, uint32_t val) } } +static void set_oc_mode(const stm32_pulse_timer_t* tim, uint32_t ocmode) +{ + uint32_t channel = tim->TIM_Channel; + if (channel == LL_TIM_CHANNEL_CH1N) + channel = LL_TIM_CHANNEL_CH1; + + LL_TIM_OC_SetMode(tim->TIMx, channel, ocmode); +} + void stm32_pulse_start_dma_req(const stm32_pulse_timer_t* tim, const void* pulses, uint16_t length, uint32_t ocmode, uint32_t cmp_val) { // Re-configure timer output set_compare_reg(tim, cmp_val); - LL_TIM_OC_SetMode(tim->TIMx, tim->TIM_Channel, ocmode); + set_oc_mode(tim, ocmode); // re-init DMA stream LL_DMA_DeInit(tim->DMAx, tim->DMA_Stream); @@ -229,7 +241,7 @@ void stm32_pulse_dma_tc_isr(const stm32_pulse_timer_t* tim) LL_TIM_EnableIT_UPDATE(tim->TIMx); set_compare_reg(tim, 0); - LL_TIM_OC_SetMode(tim->TIMx, tim->TIM_Channel, LL_TIM_OCMODE_PWM1); + set_oc_mode(tim, LL_TIM_OCMODE_PWM1); } void stm32_pulse_tim_update_isr(const stm32_pulse_timer_t* tim) @@ -241,5 +253,5 @@ void stm32_pulse_tim_update_isr(const stm32_pulse_timer_t* tim) LL_TIM_DisableIT_UPDATE(tim->TIMx); // Halt pulses by forcing to inactive level - LL_TIM_OC_SetMode(tim->TIMx, tim->TIM_Channel, LL_TIM_OCMODE_FORCED_INACTIVE); + set_oc_mode(tim, LL_TIM_OCMODE_FORCED_INACTIVE); } diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index 410975d1b..4a4d94d2c 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -1450,17 +1450,17 @@ #define INTMODULE_TX_GPIO GPIOA #define INTMODULE_TX_GPIO_PIN GPIO_Pin_10 // PA.10 #define INTMODULE_TX_GPIO_PinSource GPIO_PinSource10 - #define INTMODULE_TIMER TIM1 - #define INTMODULE_TIMER_CC_IRQn TIM1_CC_IRQn - #define INTMODULE_TIMER_CC_IRQHandler TIM1_CC_IRQHandler #define INTMODULE_TX_GPIO_AF GPIO_AF_TIM1 - #define INTMODULE_DMA DMA2 - #define INTMODULE_DMA_CHANNEL DMA_Channel_6 - #define INTMODULE_DMA_STREAM DMA2_Stream5 - #define INTMODULE_DMA_STREAM_LL LL_DMA_STREAM_5 - #define INTMODULE_DMA_STREAM_IRQn DMA2_Stream5_IRQn - #define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream5_IRQHandler - #define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF5 + #define INTMODULE_TIMER TIM1 + #define INTMODULE_TIMER_Channel LL_TIM_CHANNEL_CH3 + #define INTMODULE_TIMER_IRQn TIM1_UP_TIM10_IRQn + #define INTMODULE_TIMER_IRQHandler TIM1_UP_TIM10_IRQHandler + #define INTMODULE_TIMER_DMA DMA2 + #define INTMODULE_TIMER_DMA_CHANNEL DMA_Channel_6 + #define INTMODULE_TIMER_DMA_STREAM_LL LL_DMA_STREAM_5 + #define INTMODULE_TIMER_DMA_STREAM DMA2_Stream5 + #define INTMODULE_TIMER_DMA_STREAM_IRQn DMA2_Stream5_IRQn + #define INTMODULE_TIMER_DMA_IRQHandler DMA2_Stream5_IRQHandler #define INTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) #elif (defined(RADIO_FAMILY_JUMPER_T12) && defined(HARDWARE_INTERNAL_MODULE)) || defined(RADIO_TX12) || defined(RADIO_T8) || defined(RADIO_TPRO) #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_DMA1) @@ -1492,16 +1492,17 @@ #define INTMODULE_TX_GPIO GPIOA #define INTMODULE_TX_GPIO_PIN GPIO_Pin_10 // PA.10 #define INTMODULE_TX_GPIO_PinSource GPIO_PinSource10 - #define INTMODULE_TIMER TIM1 - #define INTMODULE_TIMER_CC_IRQn TIM1_CC_IRQn - #define INTMODULE_TIMER_CC_IRQHandler TIM1_CC_IRQHandler #define INTMODULE_TX_GPIO_AF GPIO_AF_TIM1 - #define INTMODULE_DMA DMA2 - #define INTMODULE_DMA_CHANNEL DMA_Channel_6 - #define INTMODULE_DMA_STREAM DMA2_Stream5 - #define INTMODULE_DMA_STREAM_IRQn DMA2_Stream5_IRQn - #define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream5_IRQHandler - #define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF5 + #define INTMODULE_TIMER TIM1 + #define INTMODULE_TIMER_Channel LL_TIM_CHANNEL_CH3 + #define INTMODULE_TIMER_IRQn TIM1_UP_TIM10_IRQn + #define INTMODULE_TIMER_IRQHandler TIM1_UP_TIM10_IRQHandler + #define INTMODULE_TIMER_DMA DMA2 + #define INTMODULE_TIMER_DMA_CHANNEL DMA_Channel_6 + #define INTMODULE_TIMER_DMA_STREAM_LL LL_DMA_STREAM_5 + #define INTMODULE_TIMER_DMA_STREAM DMA2_Stream5 + #define INTMODULE_TIMER_DMA_STREAM_IRQn DMA2_Stream5_IRQn + #define INTMODULE_TIMER_DMA_IRQHandler DMA2_Stream5_IRQHandler #define INTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2) #endif diff --git a/radio/src/targets/taranis/intmodule_pulses_driver.cpp b/radio/src/targets/taranis/intmodule_pulses_driver.cpp index 4a5ee98f9..a6d5b1cc8 100644 --- a/radio/src/targets/taranis/intmodule_pulses_driver.cpp +++ b/radio/src/targets/taranis/intmodule_pulses_driver.cpp @@ -19,154 +19,71 @@ * GNU General Public License for more details. */ -#include "opentx.h" -#include "pulses/pulses.h" +#include "stm32_pulse_driver.h" + +#include "hal.h" +#include "timers_driver.h" + +static const stm32_pulse_timer_t intmoduleTimer = { + .GPIOx = INTMODULE_TX_GPIO, + .GPIO_Pin = INTMODULE_TX_GPIO_PIN, + .GPIO_Alternate = INTMODULE_TX_GPIO_AF, + .TIMx = INTMODULE_TIMER, + .TIM_Prescaler = __LL_TIM_CALC_PSC(INTMODULE_TIMER_FREQ, 2000000), + .TIM_Channel = INTMODULE_TIMER_Channel, + .TIM_IRQn = INTMODULE_TIMER_IRQn, + .DMAx = INTMODULE_TIMER_DMA, + .DMA_Stream = INTMODULE_TIMER_DMA_STREAM_LL, + .DMA_Channel = INTMODULE_TIMER_DMA_CHANNEL, + .DMA_IRQn = INTMODULE_TIMER_DMA_STREAM_IRQn, +}; + +// Make sure the timer channel is supported +static_assert(__STM32_PULSE_IS_TIMER_CHANNEL_SUPPORTED(INTMODULE_TIMER_Channel), + "Unsupported timer channel"); + +// Make sure the DMA channel is supported +static_assert(__STM32_PULSE_IS_DMA_STREAM_SUPPORTED(INTMODULE_TIMER_DMA_STREAM_LL), + "Unsupported DMA stream"); + +#if !defined(INTMODULE_TIMER_DMA_IRQHandler) +#error "Missing INTMODULE_TIMER_DMA_IRQHandler definition" +#endif + +extern "C" void INTMODULE_TIMER_DMA_IRQHandler() +{ + stm32_pulse_dma_tc_isr(&intmoduleTimer); +} + +#if !defined(INTMODULE_TIMER_IRQHandler) +#error "Missing INTMODULE_TIMER_IRQHandler definition" +#endif + +extern "C" void INTMODULE_TIMER_IRQHandler() +{ + stm32_pulse_tim_update_isr(&intmoduleTimer); +} void intmoduleStop() { INTERNAL_MODULE_OFF(); - - NVIC_DisableIRQ(INTMODULE_DMA_STREAM_IRQn); - NVIC_DisableIRQ(INTMODULE_TIMER_CC_IRQn); - - INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA - INTMODULE_TIMER->DIER &= ~(TIM_DIER_CC2IE | TIM_DIER_UDE); - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; + stm32_pulse_deinit(&intmoduleTimer); } -// #define HEARBEAT_OFFSET unsigned(6000 + g_model.flightModeData[0].gvars[0] * 100) -constexpr unsigned HEARBEAT_OFFSET = 6000; - #if defined(PXX1) void intmodulePxx1PulsesStart() { INTERNAL_MODULE_ON(); - - GPIO_PinAFConfig(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PinSource, INTMODULE_TX_GPIO_AF); - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure); - - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz) - - INTMODULE_TIMER->CCER = TIM_CCER_CC3E | TIM_CCER_CC3NE; - INTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs - INTMODULE_TIMER->CCR3 = 16; - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_0; // Force O/P high - INTMODULE_TIMER->EGR = 1; // Restart - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3PE; - INTMODULE_TIMER->ARR = 40000; - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - INTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update - INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; - - NVIC_EnableIRQ(INTMODULE_DMA_STREAM_IRQn); - NVIC_SetPriority(INTMODULE_DMA_STREAM_IRQn, 7); - NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn); - NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7); + stm32_pulse_config_output(&intmoduleTimer, false, LL_TIM_OCMODE_PWM1, 9 * 2); + stm32_pulse_init(&intmoduleTimer); } void intmoduleSendNextFramePxx1(const uint16_t* data, uint8_t size) { - if (INTMODULE_DMA_STREAM->CR & DMA_SxCR_EN) return; + if (!stm32_pulse_if_not_running_disable(&intmoduleTimer)) return; - // disable timer - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - - // INTMODULE_TIMER->CCR2 = last - 4000; // 2mS in advance - INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA - INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | - DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | - DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; - INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR); - INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(data); - INTMODULE_DMA_STREAM->NDTR = size; - INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA - - // re-init timer - INTMODULE_TIMER->EGR = 1; - INTMODULE_TIMER->CR1 |= TIM_CR1_CEN; + // Start DMA request and re-enable timer + stm32_pulse_start_dma_req(&intmoduleTimer, data, size, LL_TIM_OCMODE_PWM1, + 9 * 2); } #endif - -#if defined(INTERNAL_MODULE_PPM) -void intmodulePpmStart() -{ - INTERNAL_MODULE_ON(); - - GPIO_PinAFConfig(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PinSource, INTMODULE_TX_GPIO_AF); - - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; - GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure); - - INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN; - INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz - INTMODULE_TIMER->ARR = 45000; - INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1 - INTMODULE_TIMER->BDTR = TIM_BDTR_MOE; - INTMODULE_TIMER->EGR = 1; - INTMODULE_TIMER->DIER = TIM_DIER_UDE; - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - INTMODULE_TIMER->CCR2 = 40000; // The first frame will be sent in 20ms - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - INTMODULE_TIMER->CR1 = TIM_CR1_CEN; - - NVIC_EnableIRQ(INTMODULE_DMA_STREAM_IRQn); - NVIC_SetPriority(INTMODULE_DMA_STREAM_IRQn, 7); - NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn); - NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7); -} - -void intmoduleSendNextFramePPM(const uint8_t* data, uint8_t size) -{ - INTMODULE_TIMER->CCR3 = GET_MODULE_PPM_DELAY(INTERNAL_MODULE) * 2; - INTMODULE_TIMER->CCER = - TIM_CCER_CC3E | - (GET_MODULE_PPM_POLARITY(INTERNAL_MODULE) ? 0 : TIM_CCER_CC3P); - INTMODULE_TIMER->CCR2 = - *(intmodulePulsesData.ppm.ptr - 1) - 4000; // 2mS in advance - INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA - INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | - DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | - DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1; - INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR); - INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(data); - INTMODULE_DMA_STREAM->NDTR = size; - INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA -} -#endif // defined(INTERNAL_MODULE_PPM) - -extern "C" void INTMODULE_DMA_STREAM_IRQHandler() -{ - if (!DMA_GetITStatus(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC)) - return; - - DMA_ClearITPendingBit(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC); - - switch (moduleState[INTERNAL_MODULE].protocol) { - case PROTOCOL_CHANNELS_PPM: - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag - INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt - break; - } -} - -extern "C" void INTMODULE_TIMER_CC_IRQHandler() -{ - INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt - INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; - if (setupPulsesInternalModule()) { - intmoduleSendNextFrame(); - } -}