diff --git a/src/drivers/boards/aerocore/aerocore_pwm_servo.c b/src/drivers/boards/aerocore/aerocore_timer_config.c similarity index 59% rename from src/drivers/boards/aerocore/aerocore_pwm_servo.c rename to src/drivers/boards/aerocore/aerocore_timer_config.c index 251eaff7b4..7fdc3f4836 100644 --- a/src/drivers/boards/aerocore/aerocore_pwm_servo.c +++ b/src/drivers/boards/aerocore/aerocore_timer_config.c @@ -32,9 +32,9 @@ ****************************************************************************/ /* - * @file aerocore_pwm_servo.c + * @file aerocore_timer_config.c * - * Configuration data for the stm32 pwm_servo driver. + * Configuration data for the stm32 pwm_servo, input capture and pwm input driver. * * Note that these arrays must always be fully-sized. */ @@ -42,76 +42,100 @@ #include #include -#include +#include #include -#include +#include #include #include "board_config.h" -__EXPORT const struct pwm_servo_timer pwm_timers[PWM_SERVO_MAX_TIMERS] = { +__EXPORT const io_timers_t io_timers[MAX_IO_TIMERS] = { { .base = STM32_TIM1_BASE, .clock_register = STM32_RCC_APB2ENR, .clock_bit = RCC_APB2ENR_TIM1EN, - .clock_freq = STM32_APB2_TIM1_CLKIN + .clock_freq = STM32_APB2_TIM1_CLKIN, + .first_channel_index = 0, + .last_channel_index = 3, + .handler = io_timer_handler0, + .vectorno = STM32_IRQ_TIM1CC, }, { .base = STM32_TIM3_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM3EN, .clock_freq = STM32_APB1_TIM3_CLKIN + .first_channel_index = 4, + .last_channel_index = 7, + .handler = io_timer_handler1, + .vectorno = STM32_IRQ_TIM3, } }; -__EXPORT const struct pwm_servo_channel pwm_channels[PWM_SERVO_MAX_CHANNELS] = { +__EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { { - .gpio = GPIO_TIM1_CH1OUT, + .gpio_out = GPIO_TIM1_CH1OUT, + .gpio_in = GPIO_TIM1_CH1IN, .timer_index = 0, .timer_channel = 1, - .default_value = 1500, + .ccr_offset = STM32_GTIM_CCR1_OFFSET, + .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF }, { - .gpio = GPIO_TIM1_CH2OUT, + .gpio_out = GPIO_TIM1_CH2OUT, + .gpio_in = GPIO_TIM1_CH2IN, .timer_index = 0, .timer_channel = 2, - .default_value = 1500, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM1_CH3OUT, + .gpio_out = GPIO_TIM1_CH3OUT, + .gpio_in = GPIO_TIM1_CH3IN, .timer_index = 0, .timer_channel = 3, - .default_value = 1500, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF }, { - .gpio = GPIO_TIM1_CH4OUT, + .gpio_out = GPIO_TIM1_CH4OUT, + .gpio_in = GPIO_TIM1_CH4IN, .timer_index = 0, .timer_channel = 4, - .default_value = 1500, + .ccr_offset = STM32_GTIM_CCR4_OFFSET, + .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF }, { - .gpio = GPIO_TIM3_CH1OUT, + .gpio_out = GPIO_TIM3_CH1OUT, + .gpio_out = GPIO_TIM3_CH1IN, .timer_index = 1, .timer_channel = 1, - .default_value = 1500, + .ccr_offset = STM32_GTIM_CCR1_OFFSET, + .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF }, { - .gpio = GPIO_TIM3_CH2OUT, + .gpio_out = GPIO_TIM3_CH2OUT, + .gpio_out = GPIO_TIM3_CH2IN, .timer_index = 1, .timer_channel = 2, - .default_value = 1500, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM3_CH3OUT, + .gpio_out = GPIO_TIM3_CH3OUT, + .gpio_out = GPIO_TIM3_CH3IN, .timer_index = 1, .timer_channel = 3, - .default_value = 1500, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF }, { - .gpio = GPIO_TIM3_CH4OUT, + .gpio_out = GPIO_TIM3_CH4OUT, + .gpio_out = GPIO_TIM3_CH4IN, .timer_index = 1, .timer_channel = 4, - .default_value = 1500, + .ccr_offset = STM32_GTIM_CCR4_OFFSET, + .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF } }; diff --git a/src/drivers/boards/aerocore/board_config.h b/src/drivers/boards/aerocore/board_config.h index d6932c713d..d89b383c62 100644 --- a/src/drivers/boards/aerocore/board_config.h +++ b/src/drivers/boards/aerocore/board_config.h @@ -152,6 +152,16 @@ __BEGIN_DECLS #define GPIO_TIM3_CH4OUT GPIO_TIM3_CH4OUT_2 #define DIRECT_PWM_OUTPUT_CHANNELS 8 +#define GPIO_TIM1_CH1IN GPIO_TIM1_CH1IN_2 +#define GPIO_TIM1_CH2IN GPIO_TIM1_CH2IN_2 +#define GPIO_TIM1_CH3IN GPIO_TIM1_CH3IN_2 +#define GPIO_TIM1_CH4IN GPIO_TIM1_CH4IN_2 +#define GPIO_TIM3_CH1IN GPIO_TIM3_CH1IN_3 +#define GPIO_TIM3_CH2IN GPIO_TIM3_CH2IN_3 +#define GPIO_TIM3_CH3IN GPIO_TIM3_CH3IN_2 +#define GPIO_TIM3_CH4IN GPIO_TIM3_CH4IN_2 +#define DIRECT_INPUT_TIMER_CHANNELS 8 + /* High-resolution timer */ #define HRT_TIMER 8 /* use timer 8 for the HRT */ #define HRT_TIMER_CHANNEL 1 /* use capture/compare channel */ diff --git a/src/drivers/boards/px4fmu-v1/CMakeLists.txt b/src/drivers/boards/px4fmu-v1/CMakeLists.txt index 8807ed6730..3402556f4b 100644 --- a/src/drivers/boards/px4fmu-v1/CMakeLists.txt +++ b/src/drivers/boards/px4fmu-v1/CMakeLists.txt @@ -37,7 +37,7 @@ px4_add_module( SRCS px4fmu_can.c px4fmu_init.c - px4fmu_pwm_servo.c + px4fmu_timer_config.c px4fmu_spi.c px4fmu_usb.c px4fmu_led.c diff --git a/src/drivers/boards/px4fmu-v1/board_config.h b/src/drivers/boards/px4fmu-v1/board_config.h index 2c14788ee6..d1e42a8c6f 100644 --- a/src/drivers/boards/px4fmu-v1/board_config.h +++ b/src/drivers/boards/px4fmu-v1/board_config.h @@ -184,6 +184,12 @@ __BEGIN_DECLS #define GPIO_TIM2_CH4OUT GPIO_TIM2_CH4OUT_1 #define DIRECT_PWM_OUTPUT_CHANNELS 4 +#define GPIO_TIM2_CH1IN GPIO_TIM2_CH1IN_1 +#define GPIO_TIM2_CH2IN GPIO_TIM2_CH2IN_1 +#define GPIO_TIM2_CH3IN GPIO_TIM2_CH3IN_1 +#define GPIO_TIM2_CH4IN GPIO_TIM2_CH4IN_1 +#define DIRECT_INPUT_TIMER_CHANNELS 4 + /* USB OTG FS * * PA9 OTG_FS_VBUS VBUS sensing (also connected to the green LED) diff --git a/src/drivers/boards/px4fmu-v1/px4fmu_pwm_servo.c b/src/drivers/boards/px4fmu-v1/px4fmu_timer_config.c similarity index 68% rename from src/drivers/boards/px4fmu-v1/px4fmu_pwm_servo.c rename to src/drivers/boards/px4fmu-v1/px4fmu_timer_config.c index 49c0fa42d2..3ee84a9ef0 100644 --- a/src/drivers/boards/px4fmu-v1/px4fmu_pwm_servo.c +++ b/src/drivers/boards/px4fmu-v1/px4fmu_timer_config.c @@ -32,9 +32,9 @@ ****************************************************************************/ /* - * @file px4fmu_pwm_servo.c + * @file px4fmu_timer_config.c * - * Configuration data for the stm32 pwm_servo driver. + * Configuration data for the stm32 pwm_servo, input capture and pwm input driver. * * Note that these arrays must always be fully-sized. */ @@ -45,43 +45,55 @@ #include #include -#include #include +#include #include "board_config.h" -__EXPORT const struct pwm_servo_timer pwm_timers[PWM_SERVO_MAX_TIMERS] = { +__EXPORT const io_timers_t io_timers[MAX_IO_TIMERS] = { { .base = STM32_TIM2_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM2EN, - .clock_freq = STM32_APB1_TIM2_CLKIN + .clock_freq = STM32_APB1_TIM2_CLKIN, + .first_channel_index = 0, + .last_channel_index = 3, + .handler = io_timer_handler0, + .vectorno = STM32_IRQ_TIM2, } }; -__EXPORT const struct pwm_servo_channel pwm_channels[PWM_SERVO_MAX_CHANNELS] = { +__EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { { - .gpio = GPIO_TIM2_CH1OUT, + .gpio_out = GPIO_TIM2_CH1OUT, + .gpio_in = GPIO_TIM2_CH1IN, .timer_index = 0, .timer_channel = 1, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR1_OFFSET, + .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF }, { - .gpio = GPIO_TIM2_CH2OUT, + .gpio_out = GPIO_TIM2_CH2OUT, + .gpio_in = GPIO_TIM2_CH2IN, .timer_index = 0, .timer_channel = 2, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM2_CH3OUT, + .gpio_out = GPIO_TIM2_CH3OUT, + .gpio_in = GPIO_TIM2_CH3IN, .timer_index = 0, .timer_channel = 3, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF }, { - .gpio = GPIO_TIM2_CH4OUT, + .gpio_out = GPIO_TIM2_CH4OUT, + .gpio_in = GPIO_TIM2_CH4IN, .timer_index = 0, .timer_channel = 4, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR4_OFFSET, + .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF } }; diff --git a/src/drivers/boards/px4fmu-v2/CMakeLists.txt b/src/drivers/boards/px4fmu-v2/CMakeLists.txt index 19b3f02754..7e20979100 100644 --- a/src/drivers/boards/px4fmu-v2/CMakeLists.txt +++ b/src/drivers/boards/px4fmu-v2/CMakeLists.txt @@ -37,7 +37,7 @@ px4_add_module( SRCS px4fmu_can.c px4fmu2_init.c - px4fmu_pwm_servo.c + px4fmu_timer_config.c px4fmu_spi.c px4fmu_usb.c px4fmu2_led.c diff --git a/src/drivers/boards/px4fmu-v2/board_config.h b/src/drivers/boards/px4fmu-v2/board_config.h index 87fce378a9..0d26790972 100644 --- a/src/drivers/boards/px4fmu-v2/board_config.h +++ b/src/drivers/boards/px4fmu-v2/board_config.h @@ -213,6 +213,14 @@ __BEGIN_DECLS #define GPIO_TIM4_CH3OUT GPIO_TIM4_CH3OUT_2 #define DIRECT_PWM_OUTPUT_CHANNELS 6 +#define GPIO_TIM1_CH1IN GPIO_TIM1_CH1IN_2 +#define GPIO_TIM1_CH2IN GPIO_TIM1_CH2IN_2 +#define GPIO_TIM1_CH3IN GPIO_TIM1_CH3IN_2 +#define GPIO_TIM1_CH4IN GPIO_TIM1_CH4IN_2 +#define GPIO_TIM4_CH2IN GPIO_TIM4_CH2IN_2 +#define GPIO_TIM4_CH3IN GPIO_TIM4_CH3IN_2 +#define DIRECT_INPUT_TIMER_CHANNELS 6 + /* USB OTG FS * * PA9 OTG_FS_VBUS VBUS sensing (also connected to the green LED) diff --git a/src/drivers/boards/px4fmu-v2/px4fmu_pwm_servo.c b/src/drivers/boards/px4fmu-v2/px4fmu_timer_config.c similarity index 62% rename from src/drivers/boards/px4fmu-v2/px4fmu_pwm_servo.c rename to src/drivers/boards/px4fmu-v2/px4fmu_timer_config.c index 2cae6b49e1..5adc4260db 100644 --- a/src/drivers/boards/px4fmu-v2/px4fmu_pwm_servo.c +++ b/src/drivers/boards/px4fmu-v2/px4fmu_timer_config.c @@ -32,9 +32,9 @@ ****************************************************************************/ /* - * @file px4fmu_pwm_servo.c + * @file px4fmu_timer_config.c * - * Configuration data for the stm32 pwm_servo driver. + * Configuration data for the stm32 pwm_servo, input capture and pwm input driver. * * Note that these arrays must always be fully-sized. */ @@ -45,61 +45,82 @@ #include #include -#include #include +#include #include "board_config.h" -__EXPORT const struct pwm_servo_timer pwm_timers[PWM_SERVO_MAX_TIMERS] = { +__EXPORT const io_timers_t io_timers[MAX_IO_TIMERS] = { { .base = STM32_TIM1_BASE, .clock_register = STM32_RCC_APB2ENR, .clock_bit = RCC_APB2ENR_TIM1EN, - .clock_freq = STM32_APB2_TIM1_CLKIN + .clock_freq = STM32_APB2_TIM1_CLKIN, + .first_channel_index = 0, + .last_channel_index = 3, + .handler = io_timer_handler0, + .vectorno = STM32_IRQ_TIM1CC, + }, { .base = STM32_TIM4_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM4EN, - .clock_freq = STM32_APB1_TIM4_CLKIN + .clock_freq = STM32_APB1_TIM4_CLKIN, + .first_channel_index = 4, + .last_channel_index = 5, + .handler = io_timer_handler1, + .vectorno = STM32_IRQ_TIM4 } }; -__EXPORT const struct pwm_servo_channel pwm_channels[PWM_SERVO_MAX_CHANNELS] = { +__EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { { - .gpio = GPIO_TIM1_CH4OUT, + .gpio_out = GPIO_TIM1_CH4OUT, + .gpio_in = GPIO_TIM1_CH4IN, .timer_index = 0, .timer_channel = 4, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR4_OFFSET, + .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF }, { - .gpio = GPIO_TIM1_CH3OUT, + .gpio_out = GPIO_TIM1_CH3OUT, + .gpio_in = GPIO_TIM1_CH3IN, .timer_index = 0, .timer_channel = 3, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF }, { - .gpio = GPIO_TIM1_CH2OUT, + .gpio_out = GPIO_TIM1_CH2OUT, + .gpio_in = GPIO_TIM1_CH2IN, .timer_index = 0, .timer_channel = 2, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM1_CH1OUT, + .gpio_out = GPIO_TIM1_CH1OUT, + .gpio_in = GPIO_TIM1_CH1IN, .timer_index = 0, .timer_channel = 1, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR1_OFFSET, + .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF }, { - .gpio = GPIO_TIM4_CH2OUT, + .gpio_out = GPIO_TIM4_CH2OUT, + .gpio_in = GPIO_TIM4_CH2IN, .timer_index = 1, .timer_channel = 2, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM4_CH3OUT, + .gpio_out = GPIO_TIM4_CH3OUT, + .gpio_in = GPIO_TIM4_CH3IN, .timer_index = 1, .timer_channel = 3, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF } }; diff --git a/src/drivers/boards/px4fmu-v4/CMakeLists.txt b/src/drivers/boards/px4fmu-v4/CMakeLists.txt index b16a991331..00b2b41c41 100644 --- a/src/drivers/boards/px4fmu-v4/CMakeLists.txt +++ b/src/drivers/boards/px4fmu-v4/CMakeLists.txt @@ -37,7 +37,7 @@ px4_add_module( SRCS px4fmu_can.c px4fmu_init.c - px4fmu_pwm_servo.c + px4fmu_timer_config.c px4fmu_spi.c px4fmu_usb.c px4fmu_led.c diff --git a/src/drivers/boards/px4fmu-v4/board_config.h b/src/drivers/boards/px4fmu-v4/board_config.h index ea82a7a031..3c03680c8c 100644 --- a/src/drivers/boards/px4fmu-v4/board_config.h +++ b/src/drivers/boards/px4fmu-v4/board_config.h @@ -210,6 +210,14 @@ __BEGIN_DECLS #define GPIO_TIM4_CH3OUT GPIO_TIM4_CH3OUT_2 #define DIRECT_PWM_OUTPUT_CHANNELS 6 +#define GPIO_TIM1_CH1IN GPIO_TIM1_CH1IN_2 +#define GPIO_TIM1_CH2IN GPIO_TIM1_CH2IN_2 +#define GPIO_TIM1_CH3IN GPIO_TIM1_CH3IN_2 +#define GPIO_TIM1_CH4IN GPIO_TIM1_CH4IN_2 +#define GPIO_TIM4_CH2IN GPIO_TIM4_CH2IN_2 +#define GPIO_TIM4_CH3IN GPIO_TIM4_CH3IN_2 +#define DIRECT_INPUT_TIMER_CHANNELS 6 + /* USB OTG FS * * PA9 OTG_FS_VBUS VBUS sensing diff --git a/src/drivers/boards/px4fmu-v4/px4fmu_pwm_servo.c b/src/drivers/boards/px4fmu-v4/px4fmu_timer_config.c similarity index 62% rename from src/drivers/boards/px4fmu-v4/px4fmu_pwm_servo.c rename to src/drivers/boards/px4fmu-v4/px4fmu_timer_config.c index 2cae6b49e1..c2a778b793 100644 --- a/src/drivers/boards/px4fmu-v4/px4fmu_pwm_servo.c +++ b/src/drivers/boards/px4fmu-v4/px4fmu_timer_config.c @@ -32,9 +32,9 @@ ****************************************************************************/ /* - * @file px4fmu_pwm_servo.c + * @file px4fmu_timer_config.c * - * Configuration data for the stm32 pwm_servo driver. + * Configuration data for the stm32 pwm_servo, input capture and pwm input driver. * * Note that these arrays must always be fully-sized. */ @@ -45,61 +45,82 @@ #include #include -#include #include +#include #include "board_config.h" -__EXPORT const struct pwm_servo_timer pwm_timers[PWM_SERVO_MAX_TIMERS] = { +__EXPORT const io_timers_t io_timers[MAX_IO_TIMERS] = { { .base = STM32_TIM1_BASE, .clock_register = STM32_RCC_APB2ENR, .clock_bit = RCC_APB2ENR_TIM1EN, - .clock_freq = STM32_APB2_TIM1_CLKIN + .clock_freq = STM32_APB2_TIM1_CLKIN, + .first_channel_index = 0, + .last_channel_index = 3, + .handler = io_timer_handler0, + .vectorno = STM32_IRQ_TIM1CC, + }, { .base = STM32_TIM4_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM4EN, - .clock_freq = STM32_APB1_TIM4_CLKIN + .clock_freq = STM32_APB1_TIM4_CLKIN, + .first_channel_index = 4, + .last_channel_index = 5, + .handler = io_timer_handler1, + .vectorno = STM32_IRQ_TIM4, } }; -__EXPORT const struct pwm_servo_channel pwm_channels[PWM_SERVO_MAX_CHANNELS] = { +__EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { { - .gpio = GPIO_TIM1_CH4OUT, + .gpio_out = GPIO_TIM1_CH4OUT, + .gpio_in = GPIO_TIM1_CH4IN, .timer_index = 0, .timer_channel = 4, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR4_OFFSET, + .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF }, { - .gpio = GPIO_TIM1_CH3OUT, + .gpio_out = GPIO_TIM1_CH3OUT, + .gpio_in = GPIO_TIM1_CH3IN, .timer_index = 0, .timer_channel = 3, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF }, { - .gpio = GPIO_TIM1_CH2OUT, + .gpio_out = GPIO_TIM1_CH2OUT, + .gpio_in = GPIO_TIM1_CH2IN, .timer_index = 0, .timer_channel = 2, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM1_CH1OUT, + .gpio_out = GPIO_TIM1_CH1OUT, + .gpio_in = GPIO_TIM1_CH1IN, .timer_index = 0, .timer_channel = 1, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR1_OFFSET, + .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF }, { - .gpio = GPIO_TIM4_CH2OUT, + .gpio_out = GPIO_TIM4_CH2OUT, + .gpio_in = GPIO_TIM4_CH2IN, .timer_index = 1, .timer_channel = 2, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM4_CH3OUT, + .gpio_out = GPIO_TIM4_CH3OUT, + .gpio_in = GPIO_TIM4_CH3IN, .timer_index = 1, .timer_channel = 3, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF } }; diff --git a/src/drivers/boards/px4io-v1/CMakeLists.txt b/src/drivers/boards/px4io-v1/CMakeLists.txt index 0806a1e049..420d7d2ac7 100644 --- a/src/drivers/boards/px4io-v1/CMakeLists.txt +++ b/src/drivers/boards/px4io-v1/CMakeLists.txt @@ -36,7 +36,7 @@ px4_add_module( -Os SRCS px4io_init.c - px4io_pwm_servo.c + px4io_timer_config.c DEPENDS platforms__common ) diff --git a/src/drivers/boards/px4io-v1/px4io_pwm_servo.c b/src/drivers/boards/px4io-v1/px4io_timer_config.c similarity index 59% rename from src/drivers/boards/px4io-v1/px4io_pwm_servo.c rename to src/drivers/boards/px4io-v1/px4io_timer_config.c index 250b0ac26f..c1e386e839 100644 --- a/src/drivers/boards/px4io-v1/px4io_pwm_servo.c +++ b/src/drivers/boards/px4io-v1/px4io_timer_config.c @@ -32,7 +32,7 @@ ****************************************************************************/ /* - * @file px4fmu_pwm_servo.c + * @file px4fmu_timer_config.c * * Configuration data for the stm32 pwm_servo driver. * @@ -41,83 +41,111 @@ #include -#include +#include +#include #include -#include #include #include #include -__EXPORT const struct pwm_servo_timer pwm_timers[PWM_SERVO_MAX_TIMERS] = { +__EXPORT const io_timers_t io_timers[MAX_IO_TIMERS] = { { .base = STM32_TIM2_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM2EN, - .clock_freq = STM32_APB1_TIM2_CLKIN + .clock_freq = STM32_APB1_TIM2_CLKIN, + .first_channel_index = 0, + .last_channel_index = 1, + .handler = io_timer_handler0, + .vectorno = STM32_IRQ_TIM2, }, { .base = STM32_TIM3_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM3EN, - .clock_freq = STM32_APB1_TIM3_CLKIN + .clock_freq = STM32_APB1_TIM3_CLKIN, + .first_channel_index = 2, + .last_channel_index = 3, + .handler = io_timer_handler1, + .vectorno = STM32_IRQ_TIM3, }, { .base = STM32_TIM4_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM4EN, - .clock_freq = STM32_APB1_TIM4_CLKIN + .clock_freq = STM32_APB1_TIM4_CLKIN, + .first_channel_index = 4, + .last_channel_index = 7, + .handler = io_timer_handler2, + .vectorno = STM32_IRQ_TIM4, } }; -__EXPORT const struct pwm_servo_channel pwm_channels[PWM_SERVO_MAX_CHANNELS] = { +__EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { { - .gpio = GPIO_TIM2_CH1OUT, + .gpio_out = GPIO_TIM2_CH1OUT, + .gpio_in = GPIO_TIM2_CH1IN, .timer_index = 0, .timer_channel = 1, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR1_OFFSET, + .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF }, { - .gpio = GPIO_TIM2_CH2OUT, + .gpio_out = GPIO_TIM2_CH2OUT, + .gpio_in = GPIO_TIM2_CH2IN, .timer_index = 0, .timer_channel = 2, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM4_CH3OUT, + .gpio_out = GPIO_TIM4_CH3OUT, + .gpio_in = GPIO_TIM4_CH3IN, .timer_index = 2, .timer_channel = 3, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF }, { - .gpio = GPIO_TIM4_CH4OUT, + .gpio_out = GPIO_TIM4_CH4OUT, + .gpio_in = GPIO_TIM4_CH4IN, .timer_index = 2, .timer_channel = 4, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR4_OFFSET, + .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF }, { - .gpio = GPIO_TIM3_CH1OUT, + .gpio_out = GPIO_TIM3_CH1OUT, + .gpio_in = GPIO_TIM3_CH1IN, .timer_index = 1, .timer_channel = 1, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR1_OFFSET, + .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF }, { - .gpio = GPIO_TIM3_CH2OUT, + .gpio_out = GPIO_TIM3_CH2OUT, + .gpio_in = GPIO_TIM3_CH2IN, .timer_index = 1, .timer_channel = 2, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM3_CH3OUT, + .gpio_out = GPIO_TIM3_CH3OUT, + .gpio_in = GPIO_TIM3_CH3IN, .timer_index = 1, .timer_channel = 3, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF }, { - .gpio = GPIO_TIM3_CH4OUT, + .gpio_out = GPIO_TIM3_CH4OUT, + .gpio_in = GPIO_TIM3_CH4IN, .timer_index = 1, .timer_channel = 4, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR4_OFFSET, + .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF } }; diff --git a/src/drivers/boards/px4io-v2/CMakeLists.txt b/src/drivers/boards/px4io-v2/CMakeLists.txt index 8969b90a29..5dc1324604 100644 --- a/src/drivers/boards/px4io-v2/CMakeLists.txt +++ b/src/drivers/boards/px4io-v2/CMakeLists.txt @@ -36,7 +36,7 @@ px4_add_module( -Os SRCS px4iov2_init.c - px4iov2_pwm_servo.c + px4iov2_timer_config.c DEPENDS platforms__common ) diff --git a/src/drivers/boards/px4io-v2/px4io_pwm_servo.c b/src/drivers/boards/px4io-v2/px4io_timer_config.c similarity index 59% rename from src/drivers/boards/px4io-v2/px4io_pwm_servo.c rename to src/drivers/boards/px4io-v2/px4io_timer_config.c index 2f212bd1c4..c10f03ff15 100644 --- a/src/drivers/boards/px4io-v2/px4io_pwm_servo.c +++ b/src/drivers/boards/px4io-v2/px4io_timer_config.c @@ -32,7 +32,7 @@ ****************************************************************************/ /* - * @file px4iov2_pwm_servo.c + * @file px4iov2_timer_config.c * * Configuration data for the stm32 pwm_servo driver. * @@ -41,83 +41,111 @@ #include -#include +#include +#include #include -#include #include #include #include -__EXPORT const struct pwm_servo_timer pwm_timers[PWM_SERVO_MAX_TIMERS] = { +__EXPORT const io_timers_t io_timers[MAX_IO_TIMERS] = { { .base = STM32_TIM2_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM2EN, - .clock_freq = STM32_APB1_TIM2_CLKIN + .clock_freq = STM32_APB1_TIM2_CLKIN, + .first_channel_index = 0, + .last_channel_index = 1, + .handler = io_timer_handler0, + .vectorno = STM32_IRQ_TIM2, }, { .base = STM32_TIM3_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM3EN, - .clock_freq = STM32_APB1_TIM3_CLKIN + .clock_freq = STM32_APB1_TIM3_CLKIN, + .first_channel_index = 2, + .last_channel_index = 3, + .handler = io_timer_handler1, + .vectorno = STM32_IRQ_TIM3, }, { .base = STM32_TIM4_BASE, .clock_register = STM32_RCC_APB1ENR, .clock_bit = RCC_APB1ENR_TIM4EN, - .clock_freq = STM32_APB1_TIM4_CLKIN + .clock_freq = STM32_APB1_TIM4_CLKIN, + .first_channel_index = 4, + .last_channel_index = 7, + .handler = io_timer_handler2, + .vectorno = STM32_IRQ_TIM4, } }; -__EXPORT const struct pwm_servo_channel pwm_channels[PWM_SERVO_MAX_CHANNELS] = { +__EXPORT const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS] = { { - .gpio = GPIO_TIM2_CH1OUT, + .gpio_out = GPIO_TIM2_CH1OUT, + .gpio_in = GPIO_TIM2_CH1IN, .timer_index = 0, .timer_channel = 1, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR1_OFFSET, + .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF }, { - .gpio = GPIO_TIM2_CH2OUT, + .gpio_out = GPIO_TIM2_CH2OUT, + .gpio_in = GPIO_TIM2_CH2IN, .timer_index = 0, .timer_channel = 2, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM4_CH3OUT, + .gpio_out = GPIO_TIM4_CH3OUT, + .gpio_in = GPIO_TIM4_CH3IN, .timer_index = 2, .timer_channel = 3, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF }, { - .gpio = GPIO_TIM4_CH4OUT, + .gpio_out = GPIO_TIM4_CH4OUT, + .gpio_in = GPIO_TIM4_CH4IN, .timer_index = 2, .timer_channel = 4, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR4_OFFSET, + .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF }, { - .gpio = GPIO_TIM3_CH1OUT, + .gpio_out = GPIO_TIM3_CH1OUT, + .gpio_in = GPIO_TIM3_CH1IN, .timer_index = 1, .timer_channel = 1, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR1_OFFSET, + .masks = GTIM_SR_CC1IF | GTIM_SR_CC1OF }, { - .gpio = GPIO_TIM3_CH2OUT, + .gpio_out = GPIO_TIM3_CH2OUT, + .gpio_in = GPIO_TIM3_CH2IN, .timer_index = 1, .timer_channel = 2, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR2_OFFSET, + .masks = GTIM_SR_CC2IF | GTIM_SR_CC2OF }, { - .gpio = GPIO_TIM3_CH3OUT, + .gpio_out = GPIO_TIM3_CH3OUT, + .gpio_in = GPIO_TIM3_CH3IN, .timer_index = 1, .timer_channel = 3, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR3_OFFSET, + .masks = GTIM_SR_CC3IF | GTIM_SR_CC3OF }, { - .gpio = GPIO_TIM3_CH4OUT, + .gpio_out = GPIO_TIM3_CH4OUT, + .gpio_in = GPIO_TIM3_CH4IN, .timer_index = 1, .timer_channel = 4, - .default_value = 0, + .ccr_offset = STM32_GTIM_CCR4_OFFSET, + .masks = GTIM_SR_CC4IF | GTIM_SR_CC4OF } }; diff --git a/src/drivers/stm32/CMakeLists.txt b/src/drivers/stm32/CMakeLists.txt index e81bf50277..35bafe2f36 100644 --- a/src/drivers/stm32/CMakeLists.txt +++ b/src/drivers/stm32/CMakeLists.txt @@ -36,6 +36,7 @@ px4_add_module( -Os SRCS drv_hrt.c + drv_io_timer.c drv_pwm_servo.c DEPENDS platforms__common diff --git a/src/drivers/stm32/drv_io_timer.c b/src/drivers/stm32/drv_io_timer.c new file mode 100644 index 0000000000..887024ddde --- /dev/null +++ b/src/drivers/stm32/drv_io_timer.c @@ -0,0 +1,193 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 Development Team. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name PX4 nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/* + * @file drv_pwm_servo.c + * + * Servo driver supporting PWM servos connected to STM32 timer blocks. + * + * Works with any of the 'generic' or 'advanced' STM32 timers that + * have output pins, does not require an interrupt. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "drv_io_timer.h" + +#include +#include +#include + +#include +#include +#include + +#define arraySize(a) (sizeof((a))/sizeof(((a)[0]))) + +#define MAX_CHANNELS_PER_TIMER 4 + +#define _REG32(_base, _reg) (*(volatile uint32_t *)(_base + _reg)) +#define REG(_tmr, _reg) _REG32(io_timers[_tmr].base, _reg) + +#define rCR1(_tmr) REG(_tmr, STM32_GTIM_CR1_OFFSET) +#define rCR2(_tmr) REG(_tmr, STM32_GTIM_CR2_OFFSET) +#define rSMCR(_tmr) REG(_tmr, STM32_GTIM_SMCR_OFFSET) +#define rDIER(_tmr) REG(_tmr, STM32_GTIM_DIER_OFFSET) +#define rSR(_tmr) REG(_tmr, STM32_GTIM_SR_OFFSET) +#define rEGR(_tmr) REG(_tmr, STM32_GTIM_EGR_OFFSET) +#define rCCMR1(_tmr) REG(_tmr, STM32_GTIM_CCMR1_OFFSET) +#define rCCMR2(_tmr) REG(_tmr, STM32_GTIM_CCMR2_OFFSET) +#define rCCER(_tmr) REG(_tmr, STM32_GTIM_CCER_OFFSET) +#define rCNT(_tmr) REG(_tmr, STM32_GTIM_CNT_OFFSET) +#define rPSC(_tmr) REG(_tmr, STM32_GTIM_PSC_OFFSET) +#define rARR(_tmr) REG(_tmr, STM32_GTIM_ARR_OFFSET) +#define rCCR1(_tmr) REG(_tmr, STM32_GTIM_CCR1_OFFSET) +#define rCCR2(_tmr) REG(_tmr, STM32_GTIM_CCR2_OFFSET) +#define rCCR3(_tmr) REG(_tmr, STM32_GTIM_CCR3_OFFSET) +#define rCCR4(_tmr) REG(_tmr, STM32_GTIM_CCR4_OFFSET) +#define rDCR(_tmr) REG(_tmr, STM32_GTIM_DCR_OFFSET) +#define rDMAR(_tmr) REG(_tmr, STM32_GTIM_DMAR_OFFSET) +#define rBDTR(_tmr) REG(_tmr, STM32_ATIM_BDTR_OFFSET) + +#define GTIM_SR_CCIF (GTIM_SR_CC4IF|GTIM_SR_CC3IF|GTIM_SR_CC2IF|GTIM_SR_CC1IF) +#define GTIM_SR_CCOF (GTIM_SR_CC4OF|GTIM_SR_CC3OF|GTIM_SR_CC2OF|GTIM_SR_CC1OF) + + +typedef struct channel_stat_t { + uint32_t isr_cout; + uint32_t overflows; +} channel_stat_t; + +static channel_stat_t io_timer_channel_stats[MAX_TIMER_IO_CHANNELS]; + +static struct channel_handler_entry { + channel_handler_t callback; + void *context; +} channel_handlers[MAX_TIMER_IO_CHANNELS]; + + +static int io_timer_handler(uint16_t timer_index) +{ + /* Read the count at the time of the interrupt */ + + uint16_t count = rCNT(timer_index); + + /* Read the HRT at the time of the interrupt */ + + hrt_abstime now = hrt_absolute_time(); + + const io_timers_t *tmr = &io_timers[timer_index]; + + /* What is pending and enabled? */ + + uint16_t statusr = rSR(timer_index); + uint16_t enabled = rDIER(timer_index) & GTIM_SR_CCIF; + + /* Iterate over the timer_io_channels table */ + + for (int chan_index = tmr->first_channel_index; chan_index <= tmr->last_channel_index; chan_index++) { + + uint16_t masks = timer_io_channels[chan_index].masks; + + /* Do we have an enabled channel */ + + if (enabled & masks) { + + + if (statusr & masks & GTIM_SR_CCIF) { + + io_timer_channel_stats[chan_index].isr_cout++; + + /* Call the client to read the CCxR etc and clear the CCxIF */ + + if (channel_handlers[chan_index].callback) { + channel_handlers[chan_index].callback(channel_handlers[chan_index].context, tmr, + chan_index, &timer_io_channels[chan_index], + now , count); + } + } + + if (statusr & masks & GTIM_SR_CCOF) { + + /* Error we has a second edge before we cleared CCxR */ + + io_timer_channel_stats[chan_index].overflows++; + } + } + } + + /* Clear all the SR bits for interrupt enabled channels only */ + + rSR(timer_index) = ~(statusr & (enabled | enabled << 8)); + return 0; +} + +int io_timer_handler0(int irq, void *context) +{ + + return io_timer_handler(0); +} + +int io_timer_handler1(int irq, void *context) +{ + return io_timer_handler(1); + +} + +int io_timer_handler2(int irq, void *context) +{ + return io_timer_handler(2); + +} + +int io_timer_handler3(int irq, void *context) +{ + return io_timer_handler(3); + +} diff --git a/src/drivers/stm32/drv_pwm_servo.h b/src/drivers/stm32/drv_io_timer.h similarity index 64% rename from src/drivers/stm32/drv_pwm_servo.h rename to src/drivers/stm32/drv_io_timer.h index 5dd4cf70c7..8876291467 100644 --- a/src/drivers/stm32/drv_pwm_servo.h +++ b/src/drivers/stm32/drv_io_timer.h @@ -32,35 +32,55 @@ ****************************************************************************/ /** - * @file drv_pwm_servo.h + * @file drv_io_timer.h * * stm32-specific PWM output data. */ +#include +#include +#include + +#include #pragma once -#include - /* configuration limits */ -#define PWM_SERVO_MAX_TIMERS 4 -#define PWM_SERVO_MAX_CHANNELS 8 +#define MAX_IO_TIMERS 4 +#define MAX_TIMER_IO_CHANNELS 8 +#define IO_TIMER_ALL_MODES_CHANNELS 0 -/* array of timers dedicated to PWM servo use */ -struct pwm_servo_timer { +/* array of timers dedicated to PWM in and out and capture use */ +typedef struct io_timers_t { uint32_t base; uint32_t clock_register; uint32_t clock_bit; uint32_t clock_freq; -}; + uint32_t vectorno; + uint32_t first_channel_index; + uint32_t last_channel_index; + xcpt_t handler; +} io_timers_t; /* array of channels in logical order */ -struct pwm_servo_channel { - uint32_t gpio; +typedef struct timer_io_channels_t { + uint32_t gpio_out; + uint32_t gpio_in; uint8_t timer_index; uint8_t timer_channel; - servo_position_t default_value; -}; + uint16_t masks; + uint8_t ccr_offset; +} timer_io_channels_t; + + +typedef void (*channel_handler_t)(void *context, const io_timers_t *timer, uint32_t chan_index, + const timer_io_channels_t *chan, + hrt_abstime isrs_time , uint16_t isrs_rcnt); + /* supplied by board-specific code */ -__EXPORT extern const struct pwm_servo_timer pwm_timers[PWM_SERVO_MAX_TIMERS]; -__EXPORT extern const struct pwm_servo_channel pwm_channels[PWM_SERVO_MAX_CHANNELS]; +__EXPORT extern const io_timers_t io_timers[MAX_IO_TIMERS]; +__EXPORT extern const timer_io_channels_t timer_io_channels[MAX_TIMER_IO_CHANNELS]; +__EXPORT int io_timer_handler0(int irq, void *context); +__EXPORT int io_timer_handler1(int irq, void *context); +__EXPORT int io_timer_handler2(int irq, void *context); +__EXPORT int io_timer_handler3(int irq, void *context); diff --git a/src/drivers/stm32/drv_pwm_servo.c b/src/drivers/stm32/drv_pwm_servo.c index 89f67e0503..5dee4e5853 100644 --- a/src/drivers/stm32/drv_pwm_servo.c +++ b/src/drivers/stm32/drv_pwm_servo.c @@ -58,7 +58,7 @@ #include #include -#include "drv_pwm_servo.h" +#include "drv_io_timer.h" #include #include @@ -68,7 +68,7 @@ #include #include -#define REG(_tmr, _reg) (*(volatile uint32_t *)(pwm_timers[_tmr].base + _reg)) +#define REG(_tmr, _reg) (*(volatile uint32_t *)(io_timers[_tmr].base + _reg)) #define rCR1(_tmr) REG(_tmr, STM32_GTIM_CR1_OFFSET) #define rCR2(_tmr) REG(_tmr, STM32_GTIM_CR2_OFFSET) @@ -98,7 +98,7 @@ static void pwm_timer_init(unsigned timer) { /* enable the timer clock before we try to talk to it */ - modifyreg32(pwm_timers[timer].clock_register, 0, pwm_timers[timer].clock_bit); + modifyreg32(io_timers[timer].clock_register, 0, io_timers[timer].clock_bit); /* disable and configure the timer */ rCR1(timer) = 0; @@ -108,16 +108,20 @@ pwm_timer_init(unsigned timer) rCCER(timer) = 0; rCCMR1(timer) = 0; rCCMR2(timer) = 0; + rCCR1(timer) = 0; + rCCR2(timer) = 0; + rCCR3(timer) = 0; + rCCR4(timer) = 0; rCCER(timer) = 0; rDCR(timer) = 0; - if ((pwm_timers[timer].base == STM32_TIM1_BASE) || (pwm_timers[timer].base == STM32_TIM8_BASE)) { + if ((io_timers[timer].base == STM32_TIM1_BASE) || (io_timers[timer].base == STM32_TIM8_BASE)) { /* master output enable = on */ rBDTR(timer) = ATIM_BDTR_MOE; } /* configure the timer to free-run at 1MHz */ - rPSC(timer) = (pwm_timers[timer].clock_freq / 1000000) - 1; + rPSC(timer) = (io_timers[timer].clock_freq / 1000000) - 1; /* default to updating at 50Hz */ pwm_timer_set_rate(timer, 50); @@ -138,31 +142,27 @@ pwm_timer_set_rate(unsigned timer, unsigned rate) static void pwm_channel_init(unsigned channel) { - unsigned timer = pwm_channels[channel].timer_index; + unsigned timer = timer_io_channels[channel].timer_index; /* configure the channel */ - switch (pwm_channels[channel].timer_channel) { + switch (timer_io_channels[channel].timer_channel) { case 1: rCCMR1(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR1_OC1M_SHIFT) | GTIM_CCMR1_OC1PE; - rCCR1(timer) = pwm_channels[channel].default_value; rCCER(timer) |= GTIM_CCER_CC1E; break; case 2: rCCMR1(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR1_OC2M_SHIFT) | GTIM_CCMR1_OC2PE; - rCCR2(timer) = pwm_channels[channel].default_value; rCCER(timer) |= GTIM_CCER_CC2E; break; case 3: rCCMR2(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR2_OC3M_SHIFT) | GTIM_CCMR2_OC3PE; - rCCR3(timer) = pwm_channels[channel].default_value; rCCER(timer) |= GTIM_CCER_CC3E; break; case 4: rCCMR2(timer) |= (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR2_OC4M_SHIFT) | GTIM_CCMR2_OC4PE; - rCCR4(timer) = pwm_channels[channel].default_value; rCCER(timer) |= GTIM_CCER_CC4E; break; } @@ -171,15 +171,15 @@ pwm_channel_init(unsigned channel) int up_pwm_servo_set(unsigned channel, servo_position_t value) { - if (channel >= PWM_SERVO_MAX_CHANNELS) { + if (channel >= MAX_TIMER_IO_CHANNELS) { return -1; } - unsigned timer = pwm_channels[channel].timer_index; + unsigned timer = timer_io_channels[channel].timer_index; /* test timer for validity */ - if ((pwm_timers[timer].base == 0) || - (pwm_channels[channel].gpio == 0)) { + if ((io_timers[timer].base == 0) || + (timer_io_channels[channel].gpio_out == 0)) { return -1; } @@ -188,7 +188,7 @@ up_pwm_servo_set(unsigned channel, servo_position_t value) value--; } - switch (pwm_channels[channel].timer_channel) { + switch (timer_io_channels[channel].timer_channel) { case 1: rCCR1(timer) = value; break; @@ -215,21 +215,21 @@ up_pwm_servo_set(unsigned channel, servo_position_t value) servo_position_t up_pwm_servo_get(unsigned channel) { - if (channel >= PWM_SERVO_MAX_CHANNELS) { + if (channel >= MAX_TIMER_IO_CHANNELS) { return 0; } - unsigned timer = pwm_channels[channel].timer_index; + unsigned timer = timer_io_channels[channel].timer_index; servo_position_t value = 0; /* test timer for validity */ - if ((pwm_timers[timer].base == 0) || - (pwm_channels[channel].timer_channel == 0)) { + if ((io_timers[timer].base == 0) || + (timer_io_channels[channel].timer_channel == 0)) { return 0; } /* configure the channel */ - switch (pwm_channels[channel].timer_channel) { + switch (timer_io_channels[channel].timer_channel) { case 1: value = rCCR1(timer); break; @@ -254,16 +254,16 @@ int up_pwm_servo_init(uint32_t channel_mask) { /* do basic timer initialisation first */ - for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) { - if (pwm_timers[i].base != 0) { + for (unsigned i = 0; i < MAX_IO_TIMERS; i++) { + if (io_timers[i].base != 0) { pwm_timer_init(i); } } /* now init channels */ - for (unsigned i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) { + for (unsigned i = 0; i < MAX_TIMER_IO_CHANNELS; i++) { /* don't do init for disabled channels; this leaves the pin configs alone */ - if (((1 << i) & channel_mask) && (pwm_channels[i].timer_channel != 0)) { + if (((1 << i) & channel_mask) && (timer_io_channels[i].timer_channel != 0)) { pwm_channel_init(i); } } @@ -290,7 +290,7 @@ up_pwm_servo_set_rate_group_update(unsigned group, unsigned rate) return -ERANGE; } - if ((group >= PWM_SERVO_MAX_TIMERS) || (pwm_timers[group].base == 0)) { + if ((group >= MAX_IO_TIMERS) || (io_timers[group].base == 0)) { return ERROR; } @@ -302,7 +302,7 @@ up_pwm_servo_set_rate_group_update(unsigned group, unsigned rate) int up_pwm_servo_set_rate(unsigned rate) { - for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) { + for (unsigned i = 0; i < MAX_IO_TIMERS; i++) { up_pwm_servo_set_rate_group_update(i, rate); } @@ -314,8 +314,8 @@ up_pwm_servo_get_rate_group(unsigned group) { unsigned channels = 0; - for (unsigned i = 0; i < PWM_SERVO_MAX_CHANNELS; i++) { - if ((pwm_channels[i].gpio != 0) && (pwm_channels[i].timer_index == group)) { + for (unsigned i = 0; i < MAX_TIMER_IO_CHANNELS; i++) { + if ((timer_io_channels[i].gpio_out != 0) && (timer_io_channels[i].timer_index == group)) { channels |= (1 << i); } } @@ -327,16 +327,16 @@ void up_pwm_servo_arm(bool armed) { /* iterate timers and arm/disarm appropriately */ - for (unsigned i = 0; i < PWM_SERVO_MAX_TIMERS; i++) { - if (pwm_timers[i].base != 0) { + for (unsigned i = 0; i < MAX_IO_TIMERS; i++) { + if (io_timers[i].base != 0) { if (armed) { /* force an update to preload all registers */ rEGR(i) = GTIM_EGR_UG; - for (unsigned c = 0; c < PWM_SERVO_MAX_CHANNELS; c++) { - if (pwm_channels[c].gpio) { - stm32_configgpio(pwm_channels[c].gpio); + for (unsigned c = 0; c < MAX_TIMER_IO_CHANNELS; c++) { + if (timer_io_channels[c].gpio_out) { + stm32_configgpio(timer_io_channels[c].gpio_out); } } diff --git a/src/modules/px4iofirmware/CMakeLists.txt b/src/modules/px4iofirmware/CMakeLists.txt index 854bbdcc80..ab2778711c 100644 --- a/src/modules/px4iofirmware/CMakeLists.txt +++ b/src/modules/px4iofirmware/CMakeLists.txt @@ -88,9 +88,10 @@ set(srcs ../../lib/rc/sbus.c ../../lib/rc/dsm.c ../../drivers/stm32/drv_hrt.c + ../../drivers/stm32/drv_io_timer.c ../../drivers/stm32/drv_pwm_servo.c ../../drivers/boards/${config_io_board}/px4io_init.c - ../../drivers/boards/${config_io_board}/px4io_pwm_servo.c + ../../drivers/boards/${config_io_board}/px4io_timer_config.c ) if(${config_io_board} STREQUAL "px4io-v1")