From 0eeacb44bd2a8ed9b646463833dd5262f39bf176 Mon Sep 17 00:00:00 2001 From: sambas Date: Tue, 8 Mar 2011 18:08:13 +0000 Subject: [PATCH] PPM driver for OP, first test git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@3007 ebee16cc-31ac-478f-84a7-5cbb03baadba --- flight/OpenPilot/System/pios_board.c | 76 ++++++++++++++ flight/PiOS/Boards/STM3210E_OP.h | 8 +- flight/PiOS/STM32F10x/pios_ppm.c | 152 +++++++++++++++++++++++++-- flight/PiOS/inc/pios_ppm_priv.h | 67 ++++++++++++ 4 files changed, 293 insertions(+), 10 deletions(-) create mode 100644 flight/PiOS/inc/pios_ppm_priv.h diff --git a/flight/OpenPilot/System/pios_board.c b/flight/OpenPilot/System/pios_board.c index abd85da44..89b3bb64f 100644 --- a/flight/OpenPilot/System/pios_board.c +++ b/flight/OpenPilot/System/pios_board.c @@ -772,6 +772,82 @@ void PIOS_TIM5_irq_handler() } #endif +/* + * PPM Input + */ +#if defined(PIOS_INCLUDE_PPM) +#include +void TIM6_IRQHandler(); +void TIM6_IRQHandler() __attribute__ ((alias ("PIOS_TIM6_irq_handler"))); +const struct pios_ppmsv_cfg pios_ppmsv_cfg = { + .tim_base_init = { + .TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, /* For 1 uS accuracy */ + .TIM_ClockDivision = TIM_CKD_DIV1, + .TIM_CounterMode = TIM_CounterMode_Up, + .TIM_Period = ((1000000 / 25) - 1), /* 25 Hz */ + .TIM_RepetitionCounter = 0x0000, + }, + .irq = { + .handler = TIM6_IRQHandler, + .init = { + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + }, + }, + .timer = TIM6, + .ccr = TIM_IT_Update, +}; + +void PIOS_TIM6_irq_handler() +{ + PIOS_PPMSV_irq_handler(); +} + +void TIM1_CC_IRQHandler(); +void TIM1_CC_IRQHandler() __attribute__ ((alias ("PIOS_TIM1_CC_irq_handler"))); +const struct pios_ppm_cfg pios_ppm_cfg = { + .tim_base_init = { + .TIM_Prescaler = (PIOS_MASTER_CLOCK / 1000000) - 1, /* For 1 uS accuracy */ + .TIM_ClockDivision = TIM_CKD_DIV1, + .TIM_CounterMode = TIM_CounterMode_Up, + .TIM_Period = 0xFFFF, + .TIM_RepetitionCounter = 0x0000, + }, + .tim_ic_init = { + .TIM_ICPolarity = TIM_ICPolarity_Rising, + .TIM_ICSelection = TIM_ICSelection_DirectTI, + .TIM_ICPrescaler = TIM_ICPSC_DIV1, + .TIM_ICFilter = 0x0, + .TIM_Channel = TIM_Channel_2, + }, + .gpio_init = { + .GPIO_Mode = GPIO_Mode_IPD, + .GPIO_Speed = GPIO_Speed_2MHz, + .GPIO_Pin = GPIO_Pin_9, + }, + .remap = 0, + .irq = { + .handler = TIM1_CC_IRQHandler, + .init = { + .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID, + .NVIC_IRQChannelSubPriority = 0, + .NVIC_IRQChannelCmd = ENABLE, + .NVIC_IRQChannel = TIM1_CC_IRQn, + }, + }, + .timer = TIM1, + .port = GPIOA, + .ccr = TIM_IT_CC2, +}; + +void PIOS_TIM1_CC_irq_handler() +{ + PIOS_PPM_irq_handler(); +} + +#endif //PPM + #if defined(PIOS_INCLUDE_I2C) #include diff --git a/flight/PiOS/Boards/STM3210E_OP.h b/flight/PiOS/Boards/STM3210E_OP.h index 441e1d071..cbebe5b4d 100644 --- a/flight/PiOS/Boards/STM3210E_OP.h +++ b/flight/PiOS/Boards/STM3210E_OP.h @@ -228,21 +228,21 @@ extern uint32_t pios_com_spektrum_id; //------------------------- // Receiver PPM input //------------------------- -#define PIOS_PPM_GPIO_PORT GPIOA +/*#define PIOS_PPM_GPIO_PORT GPIOA #define PIOS_PPM_GPIO_PIN GPIO_Pin_9 #define PIOS_PPM_TIM_PORT TIM1 #define PIOS_PPM_TIM_CHANNEL TIM_Channel_2 #define PIOS_PPM_TIM_CCR TIM_IT_CC2 #define PIOS_PPM_TIM TIM1 -#define PIOS_PPM_TIM_IRQ TIM1_CC_IRQn +#define PIOS_PPM_TIM_IRQ TIM1_CC_IRQn*/ #define PIOS_PPM_NUM_INPUTS 8 //Could be more if needed -#define PIOS_PPM_SUPV_ENABLED 1 +/*#define PIOS_PPM_SUPV_ENABLED 1 #define PIOS_PPM_SUPV_TIMER TIM6 #define PIOS_PPM_SUPV_TIMER_RCC_FUNC RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE) #define PIOS_PPM_SUPV_HZ 25 #define PIOS_PPM_SUPV_IRQ_CHANNEL TIM6_IRQn #define PIOS_PPM_SUPV_IRQ_FUNC void TIM6_IRQHandler(void) - +*/ //------------------------- // SPEKTRUM input //------------------------- diff --git a/flight/PiOS/STM32F10x/pios_ppm.c b/flight/PiOS/STM32F10x/pios_ppm.c index 107da6ba0..d8f549dd2 100644 --- a/flight/PiOS/STM32F10x/pios_ppm.c +++ b/flight/PiOS/STM32F10x/pios_ppm.c @@ -30,6 +30,7 @@ /* Project Includes */ #include "pios.h" +#include "pios_ppm_priv.h" #if defined(PIOS_INCLUDE_PPM) @@ -62,6 +63,68 @@ void PIOS_PPM_Init(void) for (i = 0; i < PIOS_PPM_NUM_INPUTS; i++) { CaptureValue[i] = 0; } + //////////////////////////////// + + NVIC_InitTypeDef NVIC_InitStructure = pios_ppm_cfg.irq.init; + + /* Enable appropriate clock to timer module */ + switch((int32_t) pios_ppm_cfg.timer) { + case (int32_t)TIM1: + NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); + break; + case (int32_t)TIM2: + NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); + break; + case (int32_t)TIM3: + NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); + break; + case (int32_t)TIM4: + NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); + break; +#ifdef STM32F10X_HD + + case (int32_t)TIM5: + NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); + break; + case (int32_t)TIM6: + NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); + break; + case (int32_t)TIM7: + NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); + break; + case (int32_t)TIM8: + NVIC_InitStructure.NVIC_IRQChannel = TIM8_CC_IRQn; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); + break; +#endif + } + NVIC_Init(&NVIC_InitStructure); + + GPIO_InitTypeDef GPIO_InitStructure = pios_ppm_cfg.gpio_init; + GPIO_Init(pios_ppm_cfg.port, &GPIO_InitStructure); + + TIM_ICInitStructure = pios_ppm_cfg.tim_ic_init; + TIM_ICInit(pios_ppm_cfg.timer, &TIM_ICInitStructure); + + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure = pios_ppm_cfg.tim_base_init; + TIM_InternalClockConfig(pios_ppm_cfg.timer); + TIM_TimeBaseInit(pios_ppm_cfg.timer, &TIM_TimeBaseStructure); + + /* Enable the Capture Compare Interrupt Request */ + TIM_ITConfig(pios_ppm_cfg.timer, pios_ppm_cfg.ccr, ENABLE); + + /* Enable timers */ + TIM_Cmd(pios_ppm_cfg.timer, ENABLE); + + ///////////////////////////////// +#if 0 /* Setup RCC */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); @@ -104,6 +167,7 @@ void PIOS_PPM_Init(void) /* Enable timers */ TIM_Cmd(PIOS_PPM_TIM, ENABLE); +#endif /* Supervisor Setup */ #if (PIOS_PPM_SUPV_ENABLED) @@ -114,7 +178,67 @@ void PIOS_PPM_Init(void) for (i = 0; i < PIOS_PPM_NUM_INPUTS; i++) { CapCounterPrev[i] = 0; } +/////////////// + NVIC_InitStructure = pios_ppmsv_cfg.irq.init; + + /* Enable appropriate clock to timer module */ + switch((int32_t) pios_ppmsv_cfg.timer) { + case (int32_t)TIM1: + NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); + break; + case (int32_t)TIM2: + NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); + break; + case (int32_t)TIM3: + NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); + break; + case (int32_t)TIM4: + NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); + break; +#ifdef STM32F10X_HD + + case (int32_t)TIM5: + NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); + break; + case (int32_t)TIM6: + NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); + break; + case (int32_t)TIM7: + NVIC_InitStructure.NVIC_IRQChannel = TIM7_IRQn; + RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE); + break; + case (int32_t)TIM8: + NVIC_InitStructure.NVIC_IRQChannel = TIM8_CC_IRQn; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); + break; +#endif + } + + /* Configure interrupts */ + NVIC_Init(&NVIC_InitStructure); + /* Time base configuration */ + TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); + TIM_TimeBaseStructure = pios_ppmsv_cfg.tim_base_init; + TIM_TimeBaseInit(pios_ppmsv_cfg.timer, &TIM_TimeBaseStructure); + + /* Enable the CC2 Interrupt Request */ + TIM_ITConfig(pios_ppmsv_cfg.timer, pios_ppmsv_cfg.ccr, ENABLE); + + /* Clear update pending flag */ + TIM_ClearFlag(pios_ppmsv_cfg.timer, TIM_FLAG_Update); + + /* Enable counter */ + TIM_Cmd(pios_ppmsv_cfg.timer, ENABLE); + +////////////////// +#if 0 /* Enable timer clock */ PIOS_PPM_SUPV_TIMER_RCC_FUNC; @@ -141,6 +265,7 @@ void PIOS_PPM_Init(void) /* Enable counter */ TIM_Cmd(PIOS_PPM_SUPV_TIMER, ENABLE); +#endif #endif /* Setup local variable which stays in this scope */ @@ -170,16 +295,30 @@ int32_t PIOS_PPM_Get(int8_t Channel) * Some work and testing still needed, need to detect start of frame and decode pulses * */ -void TIM1_CC_IRQHandler(void) +void PIOS_PPM_irq_handler(void) +//void TIM1_CC_IRQHandler(void) { /* Do this as it's more efficient */ - if (TIM_GetITStatus(PIOS_PPM_TIM_PORT, PIOS_PPM_TIM_CCR) == SET) { + if (TIM_GetITStatus(pios_ppm_cfg.timer, pios_ppm_cfg.ccr) == SET) { PreviousValue = CurrentValue; - CurrentValue = TIM_GetCapture2(PIOS_PPM_TIM_PORT); + switch((int32_t) pios_ppm_cfg.ccr) { + case (int32_t)TIM_IT_CC1: + CurrentValue = TIM_GetCapture1(pios_ppm_cfg.timer); + break; + case (int32_t)TIM_IT_CC2: + CurrentValue = TIM_GetCapture2(pios_ppm_cfg.timer); + break; + case (int32_t)TIM_IT_CC3: + CurrentValue = TIM_GetCapture3(pios_ppm_cfg.timer); + break; + case (int32_t)TIM_IT_CC4: + CurrentValue = TIM_GetCapture4(pios_ppm_cfg.timer); + break; + } } /* Clear TIM3 Capture compare interrupt pending bit */ - TIM_ClearITPendingBit(PIOS_PPM_TIM_PORT, PIOS_PPM_TIM_CCR); + TIM_ClearITPendingBit(pios_ppm_cfg.timer, pios_ppm_cfg.ccr); /* Capture computation */ if (CurrentValue > PreviousValue) { @@ -204,9 +343,10 @@ void TIM1_CC_IRQHandler(void) /** * This function handles TIM3 global interrupt request. */ -PIOS_PPM_SUPV_IRQ_FUNC { +void PIOS_PPMSV_irq_handler(void){ +//PIOS_PPM_SUPV_IRQ_FUNC { /* Clear timer interrupt pending bit */ - TIM_ClearITPendingBit(PIOS_PPM_SUPV_TIMER, TIM_IT_Update); + TIM_ClearITPendingBit(pios_ppmsv_cfg.timer, pios_ppmsv_cfg.ccr); /* Simple state machine */ if (SupervisorState == 0) { diff --git a/flight/PiOS/inc/pios_ppm_priv.h b/flight/PiOS/inc/pios_ppm_priv.h new file mode 100644 index 000000000..5fdcd73e1 --- /dev/null +++ b/flight/PiOS/inc/pios_ppm_priv.h @@ -0,0 +1,67 @@ +/** + ****************************************************************************** + * @addtogroup PIOS PIOS Core hardware abstraction layer + * @{ + * @addtogroup PIOS_PPM PPM Functions + * @brief PIOS interface to read and write from ppm port + * @{ + * + * @file pios_ppm_priv.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. + * @brief ppm private structures. + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_PPM_PRIV_H +#define PIOS_PPM_PRIV_H + +#include +#include + +struct pios_ppmsv_cfg { + TIM_TimeBaseInitTypeDef tim_base_init; + struct stm32_irq irq; + TIM_TypeDef * timer; + uint16_t ccr; +}; + +struct pios_ppm_cfg { + TIM_TimeBaseInitTypeDef tim_base_init; + TIM_ICInitTypeDef tim_ic_init; + GPIO_InitTypeDef gpio_init; + uint32_t remap; /* GPIO_Remap_* */ + struct stm32_irq irq; + TIM_TypeDef * timer; + GPIO_TypeDef * port; + uint16_t ccr; +}; + +extern void PIOS_PPM_irq_handler(); +extern void PIOS_PPMSV_irq_handler(); + +extern uint8_t pios_ppm_num_channels; +extern const struct pios_ppm_cfg pios_ppm_cfg; +extern const struct pios_ppmsv_cfg pios_ppmsv_cfg; + +#endif /* PIOS_PPM_PRIV_H */ + +/** + * @} + * @} + */