diff --git a/conf/modules/AOA_pwm.xml b/conf/modules/AOA_pwm.xml index 4c548f28ed..63797e9011 100644 --- a/conf/modules/AOA_pwm.xml +++ b/conf/modules/AOA_pwm.xml @@ -33,7 +33,7 @@ - + diff --git a/conf/modules/meteo_stick.xml b/conf/modules/meteo_stick.xml index 3ef28a1a9d..ac1893158b 100644 --- a/conf/modules/meteo_stick.xml +++ b/conf/modules/meteo_stick.xml @@ -71,8 +71,8 @@ MS_SPI_DEV_LOWER=$(shell echo $(MS_SPI_DEV) | tr A-Z a-z) - - + + diff --git a/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.c b/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.c index c13320892f..0da7150250 100644 --- a/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.c +++ b/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.c @@ -25,7 +25,7 @@ * * handling of smt32 PWM input using a timer with capture. */ -#include "mcu_periph/pwm_input_arch.h" +#include "mcu_periph/pwm_input.h" #include BOARD_CONFIG #include "generated/airframe.h" @@ -48,13 +48,18 @@ #define PWM_INPUT_IRQ_PRIO 2 #endif -static inline void pwm_input_set_timer(uint32_t tim) +static const uint32_t pwm_input_ticks_per_usec[] = { + PWM_INPUT1_TICKS_PER_USEC, + PWM_INPUT2_TICKS_PER_USEC +}; + +static inline void pwm_input_set_timer(uint32_t tim, uint32_t ticks_per_usec) { timer_reset(tim); timer_set_mode(tim, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); timer_set_period(tim, 0xFFFF); uint32_t timer_clk = timer_get_frequency(tim); - timer_set_prescaler(tim, (timer_clk / (PWM_INPUT_TICKS_PER_USEC * ONE_MHZ_CLK)) - 1); + timer_set_prescaler(tim, (timer_clk / (ticks_per_usec * ONE_MHZ_CLK)) - 1); timer_enable_counter(tim); } @@ -76,15 +81,27 @@ void pwm_input_init(void) */ #if USE_PWM_INPUT_TIM1 rcc_periph_clock_enable(RCC_TIM1); - pwm_input_set_timer(TIM1); + pwm_input_set_timer(TIM1, PWM_INPUT_TIM1_TICKS_PER_USEC); #endif #if USE_PWM_INPUT_TIM2 rcc_periph_clock_enable(RCC_TIM2); - pwm_input_set_timer(TIM2); + pwm_input_set_timer(TIM2, PWM_INPUT_TIM2_TICKS_PER_USEC); #endif #if USE_PWM_INPUT_TIM3 rcc_periph_clock_enable(RCC_TIM3); - pwm_input_set_timer(TIM3); + pwm_input_set_timer(TIM3, PWM_INPUT_TIM3_TICKS_PER_USEC); +#endif +#if USE_PWM_INPUT_TIM5 + rcc_periph_clock_enable(RCC_TIM5); + pwm_input_set_timer(TIM5, PWM_INPUT_TIM5_TICKS_PER_USEC); +#endif +#if USE_PWM_INPUT_TIM8 + rcc_periph_clock_enable(RCC_TIM8); + pwm_input_set_timer(TIM8, PWM_INPUT_TIM8_TICKS_PER_USEC); +#endif +#if USE_PWM_INPUT_TIM9 + rcc_periph_clock_enable(RCC_TIM9); + pwm_input_set_timer(TIM9, PWM_INPUT_TIM9_TICKS_PER_USEC); #endif #ifdef USE_PWM_INPUT1 @@ -165,6 +182,14 @@ void pwm_input_init(void) } +uint32_t get_pwm_input_duty_in_usec(uint32_t channel) { + return pwm_input_duty_tics[channel] / pwm_input_ticks_per_usec[channel]; +} + +uint32_t get_pwm_input_period_in_usec(uint32_t channel) { + return pwm_input_period_tics[channel] / pwm_input_ticks_per_usec[channel]; +} + #if USE_PWM_INPUT_TIM1 #if defined(STM32F1) @@ -235,3 +260,76 @@ void tim3_isr(void) { } #endif + +#if USE_PWM_INPUT_TIM5 + +void tim5_isr(void) { + if ((TIM5_SR & TIM5_CC_IF_PERIOD) != 0) { + timer_clear_flag(TIM5, TIM5_CC_IF_PERIOD); + pwm_input_period_tics[TIM5_PWM_INPUT_IDX] = TIM5_CCR_PERIOD; + pwm_input_period_valid[TIM5_PWM_INPUT_IDX] = TRUE; + } + if ((TIM5_SR & TIM5_CC_IF_DUTY) != 0) { + timer_clear_flag(TIM5, TIM5_CC_IF_DUTY); + pwm_input_duty_tics[TIM5_PWM_INPUT_IDX] = TIM5_CCR_DUTY; + pwm_input_duty_valid[TIM5_PWM_INPUT_IDX] = TRUE; + } + if ((TIM5_SR & TIM_SR_UIF) != 0) { + timer_clear_flag(TIM5, TIM_SR_UIF); + // FIXME clear overflow interrupt but what else ? + } +} + +#endif + +#if USE_PWM_INPUT_TIM8 + +#if defined(STM32F1) +void tim8_up_isr(void) +{ +#elif defined(STM32F4) +void tim8_up_tim13_isr(void) { +#endif + if ((TIM8_SR & TIM_SR_UIF) != 0) { + timer_clear_flag(TIM8, TIM_SR_UIF); + // FIXME clear overflow interrupt but what else ? + } +} + +void tim8_cc_isr(void) { + if ((TIM8_SR & TIM8_CC_IF_PERIOD) != 0) { + timer_clear_flag(TIM8, TIM8_CC_IF_PERIOD); + pwm_input_period_tics[TIM8_PWM_INPUT_IDX] = TIM8_CCR_PERIOD; + pwm_input_period_valid[TIM8_PWM_INPUT_IDX] = TRUE; + } + if ((TIM8_SR & TIM8_CC_IF_DUTY) != 0) { + timer_clear_flag(TIM8, TIM8_CC_IF_DUTY); + pwm_input_duty_tics[TIM8_PWM_INPUT_IDX] = TIM8_CCR_DUTY; + pwm_input_duty_valid[TIM8_PWM_INPUT_IDX] = TRUE; + } +} + +#endif + +#if USE_PWM_INPUT_TIM9 + +// TIM1 break interrupt (which we don't care here) and TIM9 global interrupt +void tim1_brk_tim9_isr(void) { + if ((TIM9_SR & TIM9_CC_IF_PERIOD) != 0) { + timer_clear_flag(TIM9, TIM9_CC_IF_PERIOD); + pwm_input_period_tics[TIM9_PWM_INPUT_IDX] = TIM9_CCR_PERIOD; + pwm_input_period_valid[TIM9_PWM_INPUT_IDX] = TRUE; + } + if ((TIM9_SR & TIM9_CC_IF_DUTY) != 0) { + timer_clear_flag(TIM9, TIM9_CC_IF_DUTY); + pwm_input_duty_tics[TIM9_PWM_INPUT_IDX] = TIM9_CCR_DUTY; + pwm_input_duty_valid[TIM9_PWM_INPUT_IDX] = TRUE; + } + if ((TIM9_SR & TIM_SR_UIF) != 0) { + timer_clear_flag(TIM9, TIM_SR_UIF); + // FIXME clear overflow interrupt but what else ? + } +} + +#endif + diff --git a/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.h b/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.h index be748c192c..8529d87b38 100644 --- a/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.h +++ b/sw/airborne/arch/stm32/mcu_periph/pwm_input_arch.h @@ -49,15 +49,13 @@ enum pwm_input_channels { * TIM1 -> 2 * APB2 = 2 * 84MHz = 168MHz * TIM2 -> 2 * APB1 = 2 * 42MHz = 84MHz */ -#ifndef PWM_INPUT_TICKS_PER_USEC -#define PWM_INPUT_TICKS_PER_USEC 6 +#ifndef PWM_INPUT1_TICKS_PER_USEC +#define PWM_INPUT1_TICKS_PER_USEC 6 #endif -#define PWM_INPUT_TICKS_OF_USEC(_v) ((_v)*PWM_INPUT_TICKS_PER_USEC) -#define PWM_INPUT_SIGNED_TICKS_OF_USEC(_v) (int32_t)((_v)*PWM_INPUT_TICKS_PER_USEC) -#define USEC_OF_PWM_INPUT_TICKS(_v) ((_v)/PWM_INPUT_TICKS_PER_USEC) - -#include "mcu_periph/pwm_input.h" +#ifndef PWM_INPUT2_TICKS_PER_USEC +#define PWM_INPUT2_TICKS_PER_USEC 6 +#endif #endif /* PWM_INPUT_ARCH_H */ diff --git a/sw/airborne/boards/apogee_1.0.h b/sw/airborne/boards/apogee_1.0.h index b4702f77eb..84da460cf0 100644 --- a/sw/airborne/boards/apogee_1.0.h +++ b/sw/airborne/boards/apogee_1.0.h @@ -355,7 +355,11 @@ /* * PWM input */ +// PWM_INPUT1 on TIM1 #define PWM_INPUT1_TIMER TIM1 +#ifdef PWM_INPUT1_TICKS_PER_USEC +#define PWM_INPUT_TIM1_TICKS_PER_USEC PWM_INPUT1_TICKS_PER_USEC +#endif #define PWM_INPUT1_CHANNEL_PERIOD TIM_IC1 #define PWM_INPUT1_CHANNEL_DUTY TIM_IC2 #define PWM_INPUT1_TIMER_INPUT TIM_IC_IN_TI1 @@ -374,6 +378,35 @@ #define PWM_INPUT1_GPIO_PIN GPIO8 #define PWM_INPUT1_GPIO_AF GPIO_AF1 +// PWM_INPUT2 on TIM9 +#define PWM_INPUT2_TIMER TIM9 +#ifdef PWM_INPUT2_TICKS_PER_USEC +#define PWM_INPUT_TIM9_TICKS_PER_USEC PWM_INPUT2_TICKS_PER_USEC +#endif +#define PWM_INPUT2_CHANNEL_PERIOD TIM_IC1 +#define PWM_INPUT2_CHANNEL_DUTY TIM_IC2 +#define PWM_INPUT2_TIMER_INPUT TIM_IC_IN_TI1 +#define PWM_INPUT2_SLAVE_TRIG TIM_SMCR_TS_IT1FP1 +#define PWM_INPUT2_IRQ NVIC_TIM1_BRK_TIM9_IRQ +#define PWM_INPUT2_CC_IE (TIM_DIER_CC3IE | TIM_DIER_CC4IE) +#ifdef USE_PWM_INPUT2 +#define USE_PWM_INPUT_TIM9 TRUE +#else +#define USE_PWM_INPUT_TIM9 FALSE +#endif +#define TIM9_PWM_INPUT_IDX 1 +#define TIM9_CC_IF_PERIOD TIM_SR_CC1IF +#define TIM9_CC_IF_DUTY TIM_SR_CC2IF +#define TIM9_CCR_PERIOD TIM9_CCR1 +#define TIM9_CCR_DUTY TIM9_CCR2 +// Servo 1 (aka PA2) is used: not compatible with PWM1 (and should be disabled) +#if (USE_PWM1 && USE_PWM_INPUT2) +#error "PW1 and PWM_INPUT2 are not compatible" +#endif +#define PWM_INPUT2_GPIO_PORT GPIOA +#define PWM_INPUT2_GPIO_PIN GPIO2 +#define PWM_INPUT2_GPIO_AF GPIO_AF3 + /* * Spektrum */ diff --git a/sw/airborne/mcu_periph/pwm_input.c b/sw/airborne/mcu_periph/pwm_input.c index ee02d32dc9..b39c877b30 100644 --- a/sw/airborne/mcu_periph/pwm_input.c +++ b/sw/airborne/mcu_periph/pwm_input.c @@ -30,3 +30,6 @@ volatile uint32_t pwm_input_duty_tics[PWM_INPUT_NB]; volatile uint8_t pwm_input_duty_valid[PWM_INPUT_NB]; volatile uint32_t pwm_input_period_tics[PWM_INPUT_NB]; volatile uint8_t pwm_input_period_valid[PWM_INPUT_NB]; + +__attribute__((weak)) uint32_t get_pwm_input_duty_in_usec(uint32_t channel __attribute__((unused))) { return 0; } +__attribute__((weak)) uint32_t get_pwm_input_period_in_usec(uint32_t channel __attribute__((unused))) { return 0; } diff --git a/sw/airborne/mcu_periph/pwm_input.h b/sw/airborne/mcu_periph/pwm_input.h index 88f8e727fd..621948e13e 100644 --- a/sw/airborne/mcu_periph/pwm_input.h +++ b/sw/airborne/mcu_periph/pwm_input.h @@ -41,6 +41,8 @@ extern volatile uint32_t pwm_input_period_tics[PWM_INPUT_NB]; extern volatile uint8_t pwm_input_period_valid[PWM_INPUT_NB]; extern void pwm_input_init(void); +extern uint32_t get_pwm_input_duty_in_usec(uint32_t channel); +extern uint32_t get_pwm_input_period_in_usec(uint32_t channel); #endif /* USE_PWM_INPUT */ diff --git a/sw/airborne/modules/sensors/aoa_pwm.c b/sw/airborne/modules/sensors/aoa_pwm.c index bde6e0f065..0ce31d7345 100644 --- a/sw/airborne/modules/sensors/aoa_pwm.c +++ b/sw/airborne/modules/sensors/aoa_pwm.c @@ -113,7 +113,7 @@ void aoa_pwm_update(void) { static float prev_aoa = 0.0f; // raw duty cycle in usec - uint32_t duty_raw = pwm_input_duty_tics[AOA_PWM_CHANNEL] / PWM_INPUT_TICKS_PER_USEC; + uint32_t duty_raw = get_pwm_input_duty_in_usec(AOA_PWM_CHANNEL); // remove some offset if needed aoa_pwm.raw = duty_raw - AOA_PWM_OFFSET;