From 1bb27e70119c8b72c74e0c8516bb37de034e9d77 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Fri, 14 Jul 2023 06:54:32 +0200 Subject: [PATCH] fix: PWM gimbals initialisation and inversion (#3745) * fix: PWM gimbals initialisation and inversion * feat: add periph clock support in PWM stick driver --- radio/src/boards/generic_stm32/CMakeLists.txt | 2 + .../boards/generic_stm32/analog_inputs.cpp | 34 ++++ .../src/boards/generic_stm32/analog_inputs.h | 2 + .../targets/common/arm/stm32/CMakeLists.txt | 1 + .../common/arm/stm32/sticks_pwm_driver.cpp | 166 +++++++++--------- .../common/arm/stm32/sticks_pwm_driver.h | 26 ++- .../src/targets/common/arm/stm32/stm32_adc.h | 1 - .../common/arm/stm32/stm32_pulse_driver.cpp | 35 +--- .../targets/common/arm/stm32/stm32_timer.cpp | 56 ++++++ .../targets/common/arm/stm32/stm32_timer.h | 27 +++ radio/src/targets/horus/board.cpp | 6 +- radio/src/targets/horus/hal.h | 8 +- radio/src/targets/taranis/board.cpp | 12 +- radio/src/targets/taranis/hal.h | 27 +-- radio/util/hw_defs/hal_adc.py | 7 +- radio/util/hw_defs/stm32_adc_inputs.jinja | 1 - radio/util/hw_defs/stm32_pwm_inputs.jinja | 15 ++ 17 files changed, 282 insertions(+), 144 deletions(-) create mode 100644 radio/src/targets/common/arm/stm32/stm32_timer.cpp create mode 100644 radio/src/targets/common/arm/stm32/stm32_timer.h create mode 100644 radio/util/hw_defs/stm32_pwm_inputs.jinja diff --git a/radio/src/boards/generic_stm32/CMakeLists.txt b/radio/src/boards/generic_stm32/CMakeLists.txt index 3e765d010..c979a5450 100644 --- a/radio/src/boards/generic_stm32/CMakeLists.txt +++ b/radio/src/boards/generic_stm32/CMakeLists.txt @@ -3,6 +3,7 @@ AddHWGenTarget(${HW_DESC_JSON} stm32_keys stm32_keys.inc) AddHWGenTarget(${HW_DESC_JSON} stm32_switches stm32_switches.inc) AddHWGenTarget(${HW_DESC_JSON} stm32_adc_inputs stm32_adc_inputs.inc) +AddHWGenTarget(${HW_DESC_JSON} stm32_pwm_inputs stm32_pwm_inputs.inc) AddHWGenTarget(${HW_DESC_JSON} hal_adc_inputs hal_adc_inputs.inc) # Dependencies common to bootloader and firmware @@ -17,6 +18,7 @@ set(MINIMAL_BOARD_LIB_SRC set(BOARD_LIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/stm32_switches.inc ${CMAKE_CURRENT_BINARY_DIR}/stm32_adc_inputs.inc + ${CMAKE_CURRENT_BINARY_DIR}/stm32_pwm_inputs.inc ${CMAKE_CURRENT_BINARY_DIR}/hal_adc_inputs.inc boards/generic_stm32/module_ports.cpp diff --git a/radio/src/boards/generic_stm32/analog_inputs.cpp b/radio/src/boards/generic_stm32/analog_inputs.cpp index be19d78b1..19036a179 100644 --- a/radio/src/boards/generic_stm32/analog_inputs.cpp +++ b/radio/src/boards/generic_stm32/analog_inputs.cpp @@ -22,6 +22,7 @@ #include "analog_inputs.h" #include "stm32_adc.h" #include "stm32_spi_adc.h" +#include "sticks_pwm_driver.h" #include "hal.h" @@ -38,6 +39,7 @@ // generated files #include "stm32_adc_inputs.inc" +#include "stm32_pwm_inputs.inc" #include "hal_adc_inputs.inc" constexpr uint8_t n_ADC = DIM(_ADC_adc); @@ -83,3 +85,35 @@ const etx_hal_adc_driver_t _adc_driver = { adc_wait_completion }; +#if defined(PWM_STICKS) + +static const stick_pwm_timer_t _sticks_timer = { + PWM_GPIO, + PWM_GPIOA_PINS, + PWM_GPIO_AF, + PWM_TIMER, + PWM_IRQn, +}; + +#if !defined(PWM_IRQHandler) + #error "Missing PWM_IRQHandler" +#endif + +extern "C" void PWM_IRQHandler(void) +{ + sticks_pwm_isr(&_sticks_timer, _PWM_inputs, DIM(_PWM_inputs)); +} + +bool sticksPwmDetect() +{ + return sticks_pwm_detect(&_sticks_timer, _PWM_inputs, DIM(_PWM_inputs)); +} + +#else + +bool sticksPwmDetect() +{ + return false; +} + +#endif diff --git a/radio/src/boards/generic_stm32/analog_inputs.h b/radio/src/boards/generic_stm32/analog_inputs.h index c9e7b7b36..811f69dfa 100644 --- a/radio/src/boards/generic_stm32/analog_inputs.h +++ b/radio/src/boards/generic_stm32/analog_inputs.h @@ -22,3 +22,5 @@ #include "hal/adc_driver.h" extern const etx_hal_adc_driver_t _adc_driver; + +bool sticksPwmDetect(); diff --git a/radio/src/targets/common/arm/stm32/CMakeLists.txt b/radio/src/targets/common/arm/stm32/CMakeLists.txt index 68d505457..c0b99955d 100644 --- a/radio/src/targets/common/arm/stm32/CMakeLists.txt +++ b/radio/src/targets/common/arm/stm32/CMakeLists.txt @@ -43,6 +43,7 @@ set(FIRMWARE_TARGET_SRC ${FIRMWARE_TARGET_SRC} ../common/arm/stm32/module_timer_driver.cpp ../common/arm/stm32/stm32_switch_driver.cpp ../common/arm/stm32/stm32_adc.cpp + ../common/arm/stm32/stm32_timer.cpp ../common/arm/stm32/stm32_gpio_driver.cpp ../common/arm/stm32/mixer_scheduler_driver.cpp ) diff --git a/radio/src/targets/common/arm/stm32/sticks_pwm_driver.cpp b/radio/src/targets/common/arm/stm32/sticks_pwm_driver.cpp index eb7be03fa..87f955093 100644 --- a/radio/src/targets/common/arm/stm32/sticks_pwm_driver.cpp +++ b/radio/src/targets/common/arm/stm32/sticks_pwm_driver.cpp @@ -19,151 +19,157 @@ * GNU General Public License for more details. */ +#include "sticks_pwm_driver.h" +#include "stm32_gpio_driver.h" +#include "stm32_timer.h" #include "hal/adc_driver.h" #include "stm32_hal_ll.h" #include "delays_driver.h" -#include "hal.h" #include "dataconstants.h" -static volatile uint32_t pwm_interrupt_count; +static volatile uint32_t _pwm_interrupt_count; -static void sticksPwmInit() +static void sticks_pwm_init(const stick_pwm_timer_t* tim) { + stm32_gpio_enable_clock(tim->GPIOx); + LL_GPIO_InitTypeDef pinInit; - pinInit.Pin = PWM_GPIOA_PINS; + pinInit.Pin = tim->GPIO_Pin; + pinInit.Alternate = tim->GPIO_Alternate; pinInit.Mode = LL_GPIO_MODE_ALTERNATE; pinInit.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; pinInit.OutputType = LL_GPIO_OUTPUT_PUSHPULL; pinInit.Pull = LL_GPIO_PULL_UP; - LL_GPIO_Init(PWM_GPIO, &pinInit); + LL_GPIO_Init(tim->GPIOx, &pinInit); - PWM_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop timer - PWM_TIMER->PSC = 80; - PWM_TIMER->ARR = 0xffff; - PWM_TIMER->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0; - PWM_TIMER->CCMR2 = TIM_CCMR2_CC3S_0 | TIM_CCMR2_CC4S_0; - PWM_TIMER->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E; - PWM_TIMER->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE | TIM_DIER_CC4IE; - PWM_TIMER->CR1 = TIM_CR1_CEN; // Start timer + auto TIMx = tim->TIMx; - NVIC_EnableIRQ(PWM_IRQn); - NVIC_SetPriority(PWM_IRQn, 10); + stm32_timer_enable_clock(TIMx); + TIMx->CR1 &= ~TIM_CR1_CEN; // Stop timer + TIMx->PSC = 80; + TIMx->ARR = 0xffff; + TIMx->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0; + TIMx->CCMR2 = TIM_CCMR2_CC3S_0 | TIM_CCMR2_CC4S_0; + TIMx->CCER = TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E | TIM_CCER_CC4E; + TIMx->DIER |= TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE | TIM_DIER_CC4IE; + TIMx->CR1 = TIM_CR1_CEN; // Start timer + + NVIC_EnableIRQ(tim->TIM_IRQn); + NVIC_SetPriority(tim->TIM_IRQn, 10); } -static void sticksPwmDeInit() +static void sticks_pwm_deinit(const stick_pwm_timer_t* tim) { - NVIC_DisableIRQ(PWM_IRQn); - PWM_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop timer + NVIC_DisableIRQ(tim->TIM_IRQn); + + // Stop timer + auto TIMx = tim->TIMx; + TIMx->CR1 &= ~TIM_CR1_CEN; + stm32_timer_disable_clock(TIMx); LL_GPIO_InitTypeDef pinInit; LL_GPIO_StructInit(&pinInit); - pinInit.Pin = PWM_GPIOA_PINS; + pinInit.Pin = tim->GPIO_Pin; pinInit.Mode = LL_GPIO_MODE_INPUT; - LL_GPIO_Init(PWM_GPIO, &pinInit); + LL_GPIO_Init(tim->GPIOx, &pinInit); } -bool sticksPwmDetect() +bool sticks_pwm_detect(const stick_pwm_timer_t* timer, + const stick_pwm_input_t* inputs, + uint8_t n_inputs) { - pwm_interrupt_count = 0; - sticksPwmInit(); + if (!timer || !inputs || n_inputs == 0) + return false; + + _pwm_interrupt_count = 0; + sticks_pwm_init(timer); delay_ms(20); - if (pwm_interrupt_count < 32) { - sticksPwmDeInit(); + + if (_pwm_interrupt_count < 32) { + sticks_pwm_deinit(timer); return false; } + return true; } -static inline uint32_t TIM_GetCapture_Stick(uint8_t n) +static inline uint32_t tim_get_capture(TIM_TypeDef *TIMx, uint8_t channel) { - switch (n) { - case 0: - return PWM_TIMER->CCR1; - case 1: - return PWM_TIMER->CCR2; - case 2: - return PWM_TIMER->CCR3; - case 3: - return PWM_TIMER->CCR4; - default: - return 0; - } + auto* base_CCRx = &(TIMx->CCR1); + return READ_REG(*(base_CCRx + channel)); } -static inline void TIM_SetPolarityRising(uint8_t n) +static inline void tim_set_polarity_rising(TIM_TypeDef *TIMx, uint8_t channel) { - PWM_TIMER->CCER &= ~(TIM_CCER_CC1P << (n * 4)); + CLEAR_BIT(TIMx->CCER, TIM_CCER_CC1P << (channel * 4)); } -static inline void TIM_SetPolarityFalling(uint8_t n) +static inline void tim_set_polarity_falling(TIM_TypeDef *TIMx, uint8_t channel) { - PWM_TIMER->CCER |= (TIM_CCER_CC1P << (n * 4)); + SET_BIT(TIMx->CCER, TIM_CCER_CC1P << (channel * 4)); } -static inline void TIM_ClearITPendingBit(uint8_t n) +static inline uint32_t tim_is_active_flag_CCx(TIM_TypeDef *TIMx, uint8_t channel) { - PWM_TIMER->SR = ~(TIM_SR_CC1IF << n); + return READ_BIT(TIMx->SR, TIM_SR_CC1IF << channel); +} + +static inline void tim_clear_flag_CCx(TIM_TypeDef *TIMx, uint8_t channel) +{ + CLEAR_BIT(TIMx->SR, TIM_SR_CC1IF << channel); } static inline uint32_t diff_with_16bits_overflow(uint32_t a, uint32_t b) { - if (b > a) + if (b > a) { return b - a; - else - return b + 0xffff - a; + } + + return b + 0xffff - a; } -#if !defined(STICK_PWM_CHANNEL_0) - #define STICK_PWM_CHANNEL_0 0 -#endif - -#if !defined(STICK_PWM_CHANNEL_1) - #define STICK_PWM_CHANNEL_1 1 -#endif - -#if !defined(STICK_PWM_CHANNEL_2) - #define STICK_PWM_CHANNEL_2 2 -#endif - -#if !defined(STICK_PWM_CHANNEL_3) - #define STICK_PWM_CHANNEL_3 3 -#endif - -static const uint8_t _channel_map[] = { - STICK_PWM_CHANNEL_0, - STICK_PWM_CHANNEL_1, - STICK_PWM_CHANNEL_2, - STICK_PWM_CHANNEL_3, -}; - -extern "C" void PWM_IRQHandler(void) +void sticks_pwm_isr(const stick_pwm_timer_t* tim, + const stick_pwm_input_t* inputs, + uint8_t n_inputs) { static uint8_t timer_capture_states[MAX_STICKS]; static uint32_t timer_capture_rising_time[MAX_STICKS]; + auto TIMx = tim->TIMx; auto adcValues = getAnalogValues(); - for (uint8_t i=0; iSR & (TIM_SR_CC1IF << i)) { - uint32_t capture = TIM_GetCapture_Stick(i); + for (uint8_t i = 0; i < n_inputs; i++) { + + const auto& input = inputs[i]; + auto channel = input.channel; + + if (tim_is_active_flag_CCx(TIMx, channel)) { + + uint32_t capture = tim_get_capture(TIMx, channel); + tim_clear_flag_CCx(TIMx, channel); + // overflow may happen but we only use this to detect PWM / ADC on radio startup - pwm_interrupt_count++; + _pwm_interrupt_count++; + if (timer_capture_states[i] != 0) { uint32_t value = diff_with_16bits_overflow(timer_capture_rising_time[i], capture); - if (value < 10000) { - adcValues[_channel_map[i]] = (uint16_t) value; + + if (value <= ADC_MAX_VALUE) { + uint16_t v16 = (uint16_t)value; + adcValues[i] = input.inverted ? ADC_INVERT_VALUE(v16) : v16; } - TIM_SetPolarityRising(i); + + tim_set_polarity_rising(TIMx, channel); timer_capture_states[i] = 0; } else { timer_capture_rising_time[i] = capture; - TIM_SetPolarityFalling(i); + + tim_set_polarity_falling(TIMx, channel); timer_capture_states[i] = 0x80; } - TIM_ClearITPendingBit(i); } } } diff --git a/radio/src/targets/common/arm/stm32/sticks_pwm_driver.h b/radio/src/targets/common/arm/stm32/sticks_pwm_driver.h index 151992595..6a520500a 100644 --- a/radio/src/targets/common/arm/stm32/sticks_pwm_driver.h +++ b/radio/src/targets/common/arm/stm32/sticks_pwm_driver.h @@ -21,5 +21,29 @@ #pragma once +#include +#include "stm32_hal_ll.h" + +struct stick_pwm_input_t { + uint8_t channel; + uint8_t inverted; +}; + +struct stick_pwm_timer_t { + + GPIO_TypeDef* GPIOx; + uint32_t GPIO_Pin; + uint32_t GPIO_Alternate; + + TIM_TypeDef* TIMx; + IRQn_Type TIM_IRQn; +}; + // returns 'true' if PWM sticks have been detected -bool sticksPwmDetect(); +bool sticks_pwm_detect(const stick_pwm_timer_t* timer, + const stick_pwm_input_t* inputs, + uint8_t n_inputs); + +void sticks_pwm_isr(const stick_pwm_timer_t* tim, + const stick_pwm_input_t* inputs, + uint8_t n_inputs); diff --git a/radio/src/targets/common/arm/stm32/stm32_adc.h b/radio/src/targets/common/arm/stm32/stm32_adc.h index 1e53f708b..32a8886a8 100644 --- a/radio/src/targets/common/arm/stm32/stm32_adc.h +++ b/radio/src/targets/common/arm/stm32/stm32_adc.h @@ -26,7 +26,6 @@ struct stm32_adc_input_t { - const char* name; GPIO_TypeDef* GPIOx; uint32_t GPIO_Pin; uint32_t ADC_Channel; 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 eac8c6003..eefdf5349 100644 --- a/radio/src/targets/common/arm/stm32/stm32_pulse_driver.cpp +++ b/radio/src/targets/common/arm/stm32/stm32_pulse_driver.cpp @@ -20,6 +20,7 @@ */ #include "stm32_pulse_driver.h" +#include "stm32_timer.h" #include "stm32_dma.h" #include "definitions.h" @@ -34,21 +35,6 @@ // - DMA IRQ prio configurable (now 7) // - Timer IRQ prio configurable (now 7) -static void enable_tim_clock(TIM_TypeDef* TIMx) -{ - if (TIMx == TIM1) { - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1); - } else if (TIMx == TIM2) { - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); - } else if (TIMx == TIM3) { - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3); - } else if (TIMx == TIM4) { - LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4); - } else if (TIMx == TIM8) { - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM8); - } -} - void stm32_pulse_init(const stm32_pulse_timer_t* tim, uint32_t freq) { if (tim->DMA_TC_CallbackPtr) { @@ -72,7 +58,7 @@ void stm32_pulse_init(const stm32_pulse_timer_t* tim, uint32_t freq) timInit.Prescaler = __LL_TIM_CALC_PSC(tim->TIM_Freq, freq); timInit.Autoreload = STM32_DEFAULT_TIMER_AUTORELOAD; - enable_tim_clock(tim->TIMx); + stm32_timer_enable_clock(tim->TIMx); LL_TIM_Init(tim->TIMx, &timInit); if (tim->DMAx) { @@ -86,21 +72,6 @@ void stm32_pulse_init(const stm32_pulse_timer_t* tim, uint32_t freq) NVIC_SetPriority(tim->TIM_IRQn, 7); } -static void disable_tim_clock(TIM_TypeDef* TIMx) -{ - if (TIMx == TIM1) { - LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_TIM1); - } else if (TIMx == TIM2) { - LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM2); - } else if (TIMx == TIM3) { - LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM3); - } else if (TIMx == TIM4) { - LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM4); - } else if (TIMx == TIM8) { - LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_TIM8); - } -} - void stm32_pulse_deinit(const stm32_pulse_timer_t* tim) { // Disable IRQs @@ -118,7 +89,7 @@ void stm32_pulse_deinit(const stm32_pulse_timer_t* tim) } LL_TIM_DeInit(tim->TIMx); - disable_tim_clock(tim->TIMx); + stm32_timer_disable_clock(tim->TIMx); // Reconfigure pin as input LL_GPIO_InitTypeDef pinInit; diff --git a/radio/src/targets/common/arm/stm32/stm32_timer.cpp b/radio/src/targets/common/arm/stm32/stm32_timer.cpp new file mode 100644 index 000000000..11c1b08b6 --- /dev/null +++ b/radio/src/targets/common/arm/stm32/stm32_timer.cpp @@ -0,0 +1,56 @@ +/* + * 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 "stm32_timer.h" + +void stm32_timer_enable_clock(TIM_TypeDef *TIMx) +{ + if (TIMx == TIM1) { + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM1); + } else if (TIMx == TIM2) { + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); + } else if (TIMx == TIM3) { + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3); + } else if (TIMx == TIM4) { + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM4); + } else if (TIMx == TIM5) { + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM5); + } else if (TIMx == TIM8) { + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_TIM8); + } +} + +void stm32_timer_disable_clock(TIM_TypeDef *TIMx) +{ + if (TIMx == TIM1) { + LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_TIM1); + } else if (TIMx == TIM2) { + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM2); + } else if (TIMx == TIM3) { + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM3); + } else if (TIMx == TIM4) { + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM4); + } else if (TIMx == TIM5) { + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_TIM5); + } else if (TIMx == TIM8) { + LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_TIM8); + } +} diff --git a/radio/src/targets/common/arm/stm32/stm32_timer.h b/radio/src/targets/common/arm/stm32/stm32_timer.h new file mode 100644 index 000000000..e597fd1a5 --- /dev/null +++ b/radio/src/targets/common/arm/stm32/stm32_timer.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#pragma once + +#include "stm32_hal_ll.h" + +void stm32_timer_enable_clock(TIM_TypeDef *TIMx); +void stm32_timer_disable_clock(TIM_TypeDef *TIMx); diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index 49b33ff8e..beddbf399 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -24,6 +24,8 @@ #include "hal/switch_driver.h" #include "hal/rotary_encoder.h" +#include "sticks_pwm_driver.h" + #include "board.h" #include "boards/generic_stm32/module_ports.h" #include "boards/generic_stm32/intmodule_heartbeat.h" @@ -38,10 +40,6 @@ #include -#if defined(PWM_STICKS) - #include "sticks_pwm_driver.h" -#endif - #if defined(RADIO_FAMILY_T16) || defined(PCBNV14) #include "flysky_gimbal_driver.h" #endif diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h index 2cd0e3755..9bb3d82b6 100644 --- a/radio/src/targets/horus/hal.h +++ b/radio/src/targets/horus/hal.h @@ -325,8 +325,8 @@ #define ADC_RCC_APB2Periph 0 #define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_0 // PA.00 #define ADC_GPIO_PIN_STICK_LV LL_GPIO_PIN_1 // PA.01 - #define ADC_GPIO_PIN_STICK_RH LL_GPIO_PIN_2 // PA.02 #define ADC_GPIO_PIN_STICK_RV LL_GPIO_PIN_3 // PA.03 + #define ADC_GPIO_PIN_STICK_RH LL_GPIO_PIN_2 // PA.02 #define ADC_GPIO_PIN_POT1 LL_GPIO_PIN_0 // PC.00 #define ADC_GPIO_PIN_POT2 LL_GPIO_PIN_1 // PC.01 #define ADC_GPIO_PIN_POT3 LL_GPIO_PIN_2 // PC.02 // @@ -345,6 +345,10 @@ #define PWM_IRQHandler TIM5_IRQHandler #define PWM_IRQn TIM5_IRQn #define PWM_GPIOA_PINS (ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_RV) + #define STICK_PWM_CHANNEL_LH 0 + #define STICK_PWM_CHANNEL_LV 1 + #define STICK_PWM_CHANNEL_RV 3 + #define STICK_PWM_CHANNEL_RH 2 #endif #define ADC_GPIOA_PINS_FS (LL_GPIO_PIN_2 | LL_GPIO_PIN_3) #define ADC_GPIOA_PINS (ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_RV) @@ -393,7 +397,7 @@ #elif defined(RADIO_TX16S) #define ADC_DIRECTION {1,-1,1,-1, 1,1,1, -1,1,1,1, -1,1 } #elif defined(PCBX10) - #define ADC_DIRECTION {1,-1,1,-1, -1,1,-1, 1,1,1,1, 1,-1 } + #define ADC_DIRECTION {1,-1,1,-1, -1,1,-1, 1,-1,1,1, 1,-1 } #elif defined(PCBX12S) #define ADC_DIRECTION {1,-1,1,-1, -1,1,-1, 1,-1, -1,-1, 0,0,0} #else diff --git a/radio/src/targets/taranis/board.cpp b/radio/src/targets/taranis/board.cpp index 17bd5bc83..82711ebc6 100644 --- a/radio/src/targets/taranis/board.cpp +++ b/radio/src/targets/taranis/board.cpp @@ -21,17 +21,16 @@ #include "hal/adc_driver.h" #include "hal/switch_driver.h" +#include "hal/module_port.h" #include "board.h" #include "boards/generic_stm32/module_ports.h" #include "boards/generic_stm32/intmodule_heartbeat.h" +#include "boards/generic_stm32/analog_inputs.h" #include "debug.h" #include "rtc.h" -#include "hal/adc_driver.h" -#include "hal/module_port.h" - #include "../common/arm/stm32/timers_driver.h" #include "dataconstants.h" @@ -47,10 +46,6 @@ #include "bluetooth_driver.h" #endif -#if defined(PWM_STICKS) - #include "sticks_pwm_driver.h" -#endif - #if defined(__cplusplus) extern "C" { #endif @@ -70,9 +65,6 @@ bool UNEXPECTED_SHUTDOWN() HardwareOptions hardwareOptions; -// adc_driver.cpp -extern const etx_hal_adc_driver_t _adc_driver; - void watchdogInit(unsigned int duration) { IWDG->KR = 0x5555; // Unlock registers diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h index a3eaa3d1a..0d4737bf8 100644 --- a/radio/src/targets/taranis/hal.h +++ b/radio/src/targets/taranis/hal.h @@ -1474,10 +1474,10 @@ #define ADC_RCC_AHB1Periph (RCC_AHB1Periph_DMA2) #define ADC_RCC_APB1Periph RCC_APB1Periph_TIM5 #define ADC_RCC_APB2Periph 0 + #define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_3 // PA.03 + #define ADC_GPIO_PIN_STICK_LV LL_GPIO_PIN_2 // PA.02 #define ADC_GPIO_PIN_STICK_RV LL_GPIO_PIN_0 // PA.00 #define ADC_GPIO_PIN_STICK_RH LL_GPIO_PIN_1 // PA.01 - #define ADC_GPIO_PIN_STICK_LV LL_GPIO_PIN_2 // PA.02 - #define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_3 // PA.03 #define ADC_GPIO_PIN_POT1 LL_GPIO_PIN_1 // PC.01 #define ADC_GPIO_PIN_POT2 LL_GPIO_PIN_2 // PC.02 #define ADC_GPIO_PIN_BATT LL_GPIO_PIN_0 // PC.00 @@ -1488,12 +1488,16 @@ #define PWM_IRQHandler TIM5_IRQHandler #define PWM_IRQn TIM5_IRQn #define PWM_GPIOA_PINS (ADC_GPIO_PIN_STICK_RV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_LV | ADC_GPIO_PIN_STICK_LH) + #define STICK_PWM_CHANNEL_LH 3 + #define STICK_PWM_CHANNEL_LV 2 + #define STICK_PWM_CHANNEL_RV 0 + #define STICK_PWM_CHANNEL_RH 1 #define ADC_GPIOA_PINS (ADC_GPIO_PIN_STICK_RV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_LV | ADC_GPIO_PIN_STICK_LH) #define ADC_GPIOC_PINS (ADC_GPIO_PIN_POT1 | ADC_GPIO_PIN_POT2 | ADC_GPIO_PIN_BATT) + #define ADC_CHANNEL_STICK_LH LL_ADC_CHANNEL_0 // ADC1_IN0 + #define ADC_CHANNEL_STICK_LV LL_ADC_CHANNEL_1 // ADC1_IN1 #define ADC_CHANNEL_STICK_RV LL_ADC_CHANNEL_3 // ADC1_IN3 #define ADC_CHANNEL_STICK_RH LL_ADC_CHANNEL_2 // ADC1_IN2 - #define ADC_CHANNEL_STICK_LV LL_ADC_CHANNEL_1 // ADC1_IN1 - #define ADC_CHANNEL_STICK_LH LL_ADC_CHANNEL_0 // ADC1_IN0 #define ADC_CHANNEL_POT1 LL_ADC_CHANNEL_11 // ADC1_IN11 #define ADC_CHANNEL_POT2 LL_ADC_CHANNEL_12 // ADC1_IN12 #define ADC_CHANNEL_BATT LL_ADC_CHANNEL_10 // ADC1_IN10 @@ -1521,10 +1525,10 @@ #define ADC_RCC_AHB1Periph (RCC_AHB1Periph_DMA2) #define ADC_RCC_APB1Periph RCC_APB1Periph_TIM5 #define ADC_RCC_APB2Periph 0 + #define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_1 // PA.01 + #define ADC_GPIO_PIN_STICK_LV LL_GPIO_PIN_0 // PA.00 #define ADC_GPIO_PIN_STICK_RV LL_GPIO_PIN_2 // PA.02 #define ADC_GPIO_PIN_STICK_RH LL_GPIO_PIN_3 // PA.03 - #define ADC_GPIO_PIN_STICK_LV LL_GPIO_PIN_0 // PA.00 - #define ADC_GPIO_PIN_STICK_LH LL_GPIO_PIN_1 // PA.01 #define ADC_CHANNEL_STICK_RV LL_ADC_CHANNEL_2 // ADC1_IN2 #define ADC_CHANNEL_STICK_RH LL_ADC_CHANNEL_3 // ADC1_IN3 #define ADC_CHANNEL_STICK_LV LL_ADC_CHANNEL_0 // ADC1_IN0 @@ -1535,18 +1539,17 @@ #define ADC_CHANNEL_BATT LL_ADC_CHANNEL_15 #define ADC_VREF_PREC2 320 #define ADC_GPIOA_PINS (ADC_GPIO_PIN_STICK_RV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV) - #define PWM_IRQHandler TIM5_IRQHandler #define PWM_STICKS + #define PWM_IRQHandler TIM5_IRQHandler #define PWM_TIMER TIM5 #define PWM_GPIO GPIOA #define PWM_GPIO_AF GPIO_AF_TIM5 #define PWM_IRQn TIM5_IRQn #define PWM_GPIOA_PINS (ADC_GPIO_PIN_STICK_RV | ADC_GPIO_PIN_STICK_RH | ADC_GPIO_PIN_STICK_LH | ADC_GPIO_PIN_STICK_LV) - #define STICK_CHANNEL_CHANGE - #define STICK_PWM_CHANNEL_0 1 - #define STICK_PWM_CHANNEL_1 0 - #define STICK_PWM_CHANNEL_2 2 - #define STICK_PWM_CHANNEL_3 3 + #define STICK_PWM_CHANNEL_LH 1 + #define STICK_PWM_CHANNEL_LV 0 + #define STICK_PWM_CHANNEL_RV 2 + #define STICK_PWM_CHANNEL_RH 3 #elif defined(RADIO_TLITE) || defined(RADIO_LR3PRO) #define ADC_RCC_AHB1Periph (RCC_AHB1Periph_DMA2) #define ADC_RCC_APB1Periph 0 diff --git a/radio/util/hw_defs/hal_adc.py b/radio/util/hw_defs/hal_adc.py index 2eb6faa83..d2b996b14 100644 --- a/radio/util/hw_defs/hal_adc.py +++ b/radio/util/hw_defs/hal_adc.py @@ -224,8 +224,13 @@ class ADCInputParser: def _add_input(self, adc_input): if adc_input is not None: + idx = len(self.inputs) + if adc_input.type == 'STICK': + if 'PWM_STICKS' in self.hw_defs: + ch = self.hw_defs.get(f'STICK_PWM_CHANNEL_{adc_input.name}') + adc_input.pwm_channel = idx if ch is None else ch if adc_input.type != 'VBAT' and adc_input.type != 'RTC_BAT': - d = self.dirs[len(self.inputs)] + d = self.dirs[idx] if d < 0: adc_input.inverted = True if adc_input.type == 'POT': diff --git a/radio/util/hw_defs/stm32_adc_inputs.jinja b/radio/util/hw_defs/stm32_adc_inputs.jinja index e9e8780c3..3fc0d0dfd 100644 --- a/radio/util/hw_defs/stm32_adc_inputs.jinja +++ b/radio/util/hw_defs/stm32_adc_inputs.jinja @@ -6,7 +6,6 @@ static const stm32_adc_input_t _ADC_inputs[] = { {% for input in adc_inputs.inputs %} { - "{{ input.name }}", // ADC_INPUT_{{ input.type }}, {{ input.gpio if input.gpio else 'nullptr' }}, {{ input.pin if input.gpio else '0' }}, diff --git a/radio/util/hw_defs/stm32_pwm_inputs.jinja b/radio/util/hw_defs/stm32_pwm_inputs.jinja new file mode 100644 index 000000000..f2fcfd177 --- /dev/null +++ b/radio/util/hw_defs/stm32_pwm_inputs.jinja @@ -0,0 +1,15 @@ +// +// WARNING: DO NOT EDIT THIS FILE +// This file has been generated from the target's JSON hardware description +// + +{% set pwm_inputs = adc_inputs.inputs | selectattr('pwm_channel', 'defined') | list %} +static const stick_pwm_input_t _PWM_inputs[] = { +{% for input in pwm_inputs %} + { + // ADC_INPUT_{{ input.type }}, {{ input.name }} + {{ input.pwm_channel }}, // channel + {{ '1 // inverted' if input.inverted else '0 // normal' }} + }, +{% endfor %} +};