Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
ppm_arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010-2014 The Paparazzi Team
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
35 
36 #include BOARD_CONFIG
37 
38 #include <libopencm3/stm32/rcc.h>
39 #include <libopencm3/stm32/gpio.h>
40 #include <libopencm3/stm32/timer.h>
41 #include <libopencm3/cm3/nvic.h>
42 
43 #include "mcu_periph/gpio.h"
44 
45 // for timer_get_frequency
46 #include "mcu_arch.h"
47 
48 #define ONE_MHZ_CLK 1000000
49 #ifdef NVIC_TIM_IRQ_PRIO
50 #define PPM_IRQ_PRIO NVIC_TIM_IRQ_PRIO
51 #else
52 #define PPM_IRQ_PRIO 2
53 #endif
54 
55 
57 
58 
59 #if USE_PPM_TIM2
60 
61 PRINT_CONFIG_MSG("Using TIM2 for PPM input.")
62 #define PPM_TIMER TIM2
63 #define RCC_TIM_PPM RCC_TIM2
64 
65 #elif USE_PPM_TIM3
66 
67 PRINT_CONFIG_MSG("Using TIM3 for PPM input.")
68 #define PPM_TIMER TIM3
69 #define RCC_TIM_PPM RCC_TIM3
70 
71 #elif USE_PPM_TIM4
72 
73 PRINT_CONFIG_MSG("Using TIM4 for PPM input.")
74 #define PPM_TIMER TIM4
75 #define RCC_TIM_PPM RCC_TIM4
76 
77 #elif USE_PPM_TIM5
78 
79 PRINT_CONFIG_MSG("Using TIM5 for PPM input.")
80 #define PPM_TIMER TIM5
81 #define RCC_TIM_PPM RCC_TIM5
82 
83 #elif USE_PPM_TIM1
84 
85 PRINT_CONFIG_MSG("Using TIM1 for PPM input.")
86 #define PPM_TIMER TIM1
87 #define RCC_TIM_PPM RCC_TIM1
88 
89 #elif USE_PPM_TIM8
90 
91 PRINT_CONFIG_MSG("Using TIM8 for PPM input.")
92 #define PPM_TIMER TIM8
93 #define RCC_TIM_PPM RCC_TIM8
94 
95 #else
96 #error Unknown PPM input timer configuration.
97 #endif
98 
99 void ppm_arch_init(void)
100 {
101  /* timer clock enable */
102  rcc_periph_clock_enable(RCC_TIM_PPM);
103 
104  /* GPIO configuration as input capture for timer */
106 
107  /* Time Base configuration */
108  timer_reset(PPM_TIMER);
109  timer_set_mode(PPM_TIMER, TIM_CR1_CKD_CK_INT,
110  TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
111  timer_set_period(PPM_TIMER, 0xFFFF);
112  uint32_t timer_clk = timer_get_frequency(PPM_TIMER);
113  timer_set_prescaler(PPM_TIMER, (timer_clk / (RC_PPM_TICKS_PER_USEC * ONE_MHZ_CLK)) - 1);
114 
115  /* TIM configuration: Input Capture mode ---------------------
116  The Rising edge is used as active edge
117  ------------------------------------------------------------ */
118 #if defined PPM_PULSE_TYPE && PPM_PULSE_TYPE == PPM_PULSE_TYPE_POSITIVE
119  timer_ic_set_polarity(PPM_TIMER, PPM_CHANNEL, TIM_IC_RISING);
120 #elif defined PPM_PULSE_TYPE && PPM_PULSE_TYPE == PPM_PULSE_TYPE_NEGATIVE
121  timer_ic_set_polarity(PPM_TIMER, PPM_CHANNEL, TIM_IC_FALLING);
122 #else
123 #error "Unknown PPM_PULSE_TYPE"
124 #endif
125  timer_ic_set_input(PPM_TIMER, PPM_CHANNEL, PPM_TIMER_INPUT);
126  timer_ic_set_prescaler(PPM_TIMER, PPM_CHANNEL, TIM_IC_PSC_OFF);
127  timer_ic_set_filter(PPM_TIMER, PPM_CHANNEL, TIM_IC_OFF);
128 
129  /* Enable timer Interrupt(s). */
130  nvic_set_priority(PPM_IRQ, PPM_IRQ_PRIO);
131  nvic_enable_irq(PPM_IRQ);
132 
133 #ifdef PPM_IRQ2
134  nvic_set_priority(PPM_IRQ2, PPM_IRQ_PRIO);
135  nvic_enable_irq(PPM_IRQ2);
136 #endif
137 
138  /* Enable the Capture/Compare and Update interrupt requests. */
139  timer_enable_irq(PPM_TIMER, (PPM_CC_IE | TIM_DIER_UIE));
140 
141  /* Enable capture channel. */
142  timer_ic_enable(PPM_TIMER, PPM_CHANNEL);
143 
144  /* TIM enable counter */
145  timer_enable_counter(PPM_TIMER);
146 
147  timer_rollover_cnt = 0;
148 }
149 
150 #if USE_PPM_TIM2
151 
152 void tim2_isr(void)
153 {
154  if ((TIM2_SR & PPM_CC_IF) != 0) {
155  timer_clear_flag(TIM2, PPM_CC_IF);
156 
157  uint32_t now = timer_get_counter(TIM2) + timer_rollover_cnt;
158  ppm_decode_frame(now);
159  } else if ((TIM2_SR & TIM_SR_UIF) != 0) {
160  timer_rollover_cnt += (1 << 16);
161  timer_clear_flag(TIM2, TIM_SR_UIF);
162  }
163 }
164 
165 
166 #elif USE_PPM_TIM3
167 
168 void tim3_isr(void)
169 {
170  if ((TIM3_SR & PPM_CC_IF) != 0) {
171  timer_clear_flag(TIM3, PPM_CC_IF);
172 
173  uint32_t now = timer_get_counter(TIM3) + timer_rollover_cnt;
174  ppm_decode_frame(now);
175  } else if ((TIM3_SR & TIM_SR_UIF) != 0) {
176  timer_rollover_cnt += (1 << 16);
177  timer_clear_flag(TIM3, TIM_SR_UIF);
178  }
179 }
180 
181 #elif USE_PPM_TIM4
182 
183 void tim4_isr(void)
184 {
185  if ((TIM4_SR & PPM_CC_IF) != 0) {
186  timer_clear_flag(TIM4, PPM_CC_IF);
187 
188  uint32_t now = timer_get_counter(TIM4) + timer_rollover_cnt;
189  ppm_decode_frame(now);
190  } else if ((TIM4_SR & TIM_SR_UIF) != 0) {
191  timer_rollover_cnt += (1 << 16);
192  timer_clear_flag(TIM4, TIM_SR_UIF);
193  }
194 }
195 
196 #elif USE_PPM_TIM5
197 
198 void tim5_isr(void)
199 {
200  if ((TIM5_SR & PPM_CC_IF) != 0) {
201  timer_clear_flag(TIM5, PPM_CC_IF);
202 
203  uint32_t now = timer_get_counter(TIM5) + timer_rollover_cnt;
204  ppm_decode_frame(now);
205  } else if ((TIM5_SR & TIM_SR_UIF) != 0) {
206  timer_rollover_cnt += (1 << 16);
207  timer_clear_flag(TIM5, TIM_SR_UIF);
208  }
209 }
210 
211 
212 #elif USE_PPM_TIM1
213 
214 #if defined(STM32F1)
215 void tim1_up_isr(void)
216 {
217 #elif defined(STM32F4)
218 void tim1_up_tim10_isr(void) {
219 #endif
220  if ((TIM1_SR & TIM_SR_UIF) != 0) {
221  timer_rollover_cnt += (1 << 16);
222  timer_clear_flag(TIM1, TIM_SR_UIF);
223  }
224 }
225 
226 void tim1_cc_isr(void) {
227  if ((TIM1_SR & PPM_CC_IF) != 0) {
228  timer_clear_flag(TIM1, PPM_CC_IF);
229 
230  uint32_t now = timer_get_counter(TIM1) + timer_rollover_cnt;
231  ppm_decode_frame(now);
232  }
233 }
234 
235 #elif USE_PPM_TIM8 && defined(STM32F4)
236 
237 #if defined(STM32F1)
238 void tim8_up_isr(void) {
239 #elif defined(STM32F4)
240 void tim8_up_tim13_isr(void) {
241 #endif
242  if ((TIM8_SR & TIM_SR_UIF) != 0) {
243  timer_rollover_cnt += (1 << 16);
244  timer_clear_flag(TIM8, TIM_SR_UIF);
245  }
246 }
247 
248 void tim8_cc_isr(void) {
249  if ((TIM8_SR & PPM_CC_IF) != 0) {
250  timer_clear_flag(TIM8, PPM_CC_IF);
251 
252  uint32_t now = timer_get_counter(TIM8) + timer_rollover_cnt;
253  ppm_decode_frame(now);
254  }
255 }
256 
257 #endif /* USE_PPM_TIM1 */
258 
CM3_WEAK tim8_cc_isr(void)
#define PPM_CC_IE
Definition: apogee_1.0.h:349
timer_clear_flag(TIM6, TIM_SR_UIF)
CM3_WEAK tim2_isr(void)
#define PPM_IRQ2
Definition: apogee_1.0.h:347
void ppm_arch_init(void)
Architecture dependant code.
Definition: ppm_arch.c:32
CM3_WEAK tim3_isr(void)
#define RC_PPM_TICKS_PER_USEC
The ppm counter is set-up to have 1/6 us resolution.
Definition: ppm_arch.h:43
Some architecture independent helper functions for GPIOs.
CM3_WEAK tim1_cc_isr(void)
#define ONE_MHZ_CLK
Definition: ppm_arch.c:48
#define PPM_GPIO_PORT
Definition: apogee_1.0.h:351
#define PPM_GPIO_AF
Definition: apogee_1.0.h:353
uint32_t timer_get_frequency(uint32_t timer_peripheral)
Get Timer clock frequency (before prescaling) Only valid if using the internal clock for the timer...
Definition: mcu_arch.c:179
#define PPM_CC_IF
Definition: apogee_1.0.h:350
#define PPM_CHANNEL
Definition: apogee_1.0.h:344
#define FALSE
Definition: std.h:5
CM3_WEAK tim1_up_tim10_isr(void)
#define PPM_IRQ
Definition: apogee_1.0.h:346
unsigned long uint32_t
Definition: types.h:18
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
#define PPM_GPIO_PIN
Definition: apogee_1.0.h:352
void gpio_setup_pin_af(uint32_t port, uint16_t pin, uint8_t af, bool_t is_output)
Setup a gpio for input or output with alternate function.
#define PPM_IRQ_PRIO
Definition: ppm_arch.c:52
CM3_WEAK tim4_isr(void)
#define PPM_TIMER_INPUT
Definition: apogee_1.0.h:345
static uint32_t timer_rollover_cnt
Definition: ppm_arch.c:56
CM3_WEAK tim8_up_tim13_isr(void)
CM3_WEAK tim5_isr(void)
void ppm_decode_frame(uint32_t ppm_time)
Decode a PPM frame.
Definition: ppm.c:103