Paparazzi UAS  v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
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_TIM1
60 
61 PRINT_CONFIG_MSG("Using TIM1 for PPM input.")
62 #define PPM_TIMER TIM1
63 #define RCC_TIM_PPM RCC_TIM1
64 
65 #elif USE_PPM_TIM2
66 
67 PRINT_CONFIG_MSG("Using TIM2 for PPM input.")
68 #define PPM_TIMER TIM2
69 #define RCC_TIM_PPM RCC_TIM2
70 
71 #elif USE_PPM_TIM3
72 
73 PRINT_CONFIG_MSG("Using TIM3 for PPM input.")
74 #define PPM_TIMER TIM3
75 #define RCC_TIM_PPM RCC_TIM3
76 
77 #elif USE_PPM_TIM4
78 
79 PRINT_CONFIG_MSG("Using TIM4 for PPM input.")
80 #define PPM_TIMER TIM4
81 #define RCC_TIM_PPM RCC_TIM4
82 
83 #elif USE_PPM_TIM5
84 
85 PRINT_CONFIG_MSG("Using TIM5 for PPM input.")
86 #define PPM_TIMER TIM5
87 #define RCC_TIM_PPM RCC_TIM5
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 #elif USE_PPM_TIM9
96 
97 PRINT_CONFIG_MSG("Using TIM9 for PPM input.")
98 #define PPM_TIMER TIM9
99 #define RCC_TIM_PPM RCC_TIM9
100 
101 #elif USE_PPM_TIM12
102 
103 PRINT_CONFIG_MSG("Using TIM12 for PPM input.")
104 #define PPM_TIMER TIM12
105 #define RCC_TIM_PPM RCC_TIM12
106 
107 #else
108 #error Unknown PPM input timer configuration.
109 #endif
110 
111 void ppm_arch_init(void)
112 {
113  /* timer clock enable */
114  rcc_periph_clock_enable(RCC_TIM_PPM);
115 
116  /* GPIO configuration as input capture for timer */
118 
119  /* Time Base configuration */
120  timer_reset(PPM_TIMER);
121  timer_set_mode(PPM_TIMER, TIM_CR1_CKD_CK_INT,
122  TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
123  timer_set_period(PPM_TIMER, 0xFFFF);
125  timer_set_prescaler(PPM_TIMER, (timer_clk / (RC_PPM_TICKS_PER_USEC * ONE_MHZ_CLK)) - 1);
126 
127  /* TIM configuration: Input Capture mode ---------------------
128  The Rising edge is used as active edge
129  ------------------------------------------------------------ */
130 #if defined PPM_PULSE_TYPE && PPM_PULSE_TYPE == PPM_PULSE_TYPE_POSITIVE
131  timer_ic_set_polarity(PPM_TIMER, PPM_CHANNEL, TIM_IC_RISING);
132 #elif defined PPM_PULSE_TYPE && PPM_PULSE_TYPE == PPM_PULSE_TYPE_NEGATIVE
133  timer_ic_set_polarity(PPM_TIMER, PPM_CHANNEL, TIM_IC_FALLING);
134 #else
135 #error "Unknown PPM_PULSE_TYPE"
136 #endif
137  timer_ic_set_input(PPM_TIMER, PPM_CHANNEL, PPM_TIMER_INPUT);
138  timer_ic_set_prescaler(PPM_TIMER, PPM_CHANNEL, TIM_IC_PSC_OFF);
139  timer_ic_set_filter(PPM_TIMER, PPM_CHANNEL, TIM_IC_OFF);
140 
141  /* Enable timer Interrupt(s). */
142  nvic_set_priority(PPM_IRQ, PPM_IRQ_PRIO);
143  nvic_enable_irq(PPM_IRQ);
144 
145 #ifdef PPM_IRQ2
146  nvic_set_priority(PPM_IRQ2, PPM_IRQ_PRIO);
147  nvic_enable_irq(PPM_IRQ2);
148 #endif
149 
150  /* Enable the Capture/Compare and Update interrupt requests. */
151  timer_enable_irq(PPM_TIMER, (PPM_CC_IE | TIM_DIER_UIE));
152 
153  /* Enable capture channel. */
154  timer_ic_enable(PPM_TIMER, PPM_CHANNEL);
155 
156  /* TIM enable counter */
157  timer_enable_counter(PPM_TIMER);
158 
159  timer_rollover_cnt = 0;
160 }
161 
162 #if USE_PPM_TIM2
163 
164 void tim2_isr(void)
165 {
166  if ((TIM2_SR & PPM_CC_IF) != 0) {
167  timer_clear_flag(TIM2, PPM_CC_IF);
168 
169  uint32_t now = timer_get_counter(TIM2) + timer_rollover_cnt;
170  ppm_decode_frame(now);
171  } else if ((TIM2_SR & TIM_SR_UIF) != 0) {
172  timer_rollover_cnt += (1 << 16);
173  timer_clear_flag(TIM2, TIM_SR_UIF);
174  }
175 }
176 
177 
178 #elif USE_PPM_TIM3
179 
180 void tim3_isr(void)
181 {
182  if ((TIM3_SR & PPM_CC_IF) != 0) {
183  timer_clear_flag(TIM3, PPM_CC_IF);
184 
185  uint32_t now = timer_get_counter(TIM3) + timer_rollover_cnt;
186  ppm_decode_frame(now);
187  } else if ((TIM3_SR & TIM_SR_UIF) != 0) {
188  timer_rollover_cnt += (1 << 16);
189  timer_clear_flag(TIM3, TIM_SR_UIF);
190  }
191 }
192 
193 #elif USE_PPM_TIM4
194 
195 void tim4_isr(void)
196 {
197  if ((TIM4_SR & PPM_CC_IF) != 0) {
198  timer_clear_flag(TIM4, PPM_CC_IF);
199 
200  uint32_t now = timer_get_counter(TIM4) + timer_rollover_cnt;
201  ppm_decode_frame(now);
202  } else if ((TIM4_SR & TIM_SR_UIF) != 0) {
203  timer_rollover_cnt += (1 << 16);
204  timer_clear_flag(TIM4, TIM_SR_UIF);
205  }
206 }
207 
208 #elif USE_PPM_TIM5
209 
210 void tim5_isr(void)
211 {
212  if ((TIM5_SR & PPM_CC_IF) != 0) {
213  timer_clear_flag(TIM5, PPM_CC_IF);
214 
215  uint32_t now = timer_get_counter(TIM5) + timer_rollover_cnt;
216  ppm_decode_frame(now);
217  } else if ((TIM5_SR & TIM_SR_UIF) != 0) {
218  timer_rollover_cnt += (1 << 16);
219  timer_clear_flag(TIM5, TIM_SR_UIF);
220  }
221 }
222 
223 
224 #elif USE_PPM_TIM1
225 
226 #if defined(STM32F1)
227 void tim1_up_isr(void)
228 {
229 #elif defined(STM32F4)
230 void tim1_up_tim10_isr(void) {
231 #endif
232  if ((TIM1_SR & TIM_SR_UIF) != 0) {
233  timer_rollover_cnt += (1 << 16);
234  timer_clear_flag(TIM1, TIM_SR_UIF);
235  }
236 }
237 
238 void tim1_cc_isr(void) {
239  if ((TIM1_SR & PPM_CC_IF) != 0) {
240  timer_clear_flag(TIM1, PPM_CC_IF);
241 
242  uint32_t now = timer_get_counter(TIM1) + timer_rollover_cnt;
243  ppm_decode_frame(now);
244  }
245 }
246 
247 #elif USE_PPM_TIM8
248 
249 #if defined(STM32F1)
250 void tim8_up_isr(void) {
251 #elif defined(STM32F4)
252 void tim8_up_tim13_isr(void) {
253 #endif
254  if ((TIM8_SR & TIM_SR_UIF) != 0) {
255  timer_rollover_cnt += (1 << 16);
256  timer_clear_flag(TIM8, TIM_SR_UIF);
257  }
258 }
259 
260 void tim8_cc_isr(void) {
261  if ((TIM8_SR & PPM_CC_IF) != 0) {
262  timer_clear_flag(TIM8, PPM_CC_IF);
263 
264  uint32_t now = timer_get_counter(TIM8) + timer_rollover_cnt;
265  ppm_decode_frame(now);
266  }
267 }
268 
269 #elif USE_PPM_TIM9 && defined(STM32F4)
270 
271 void tim1_brk_tim9_isr(void)
272 {
273  if ((TIM9_SR & PPM_CC_IF) != 0) {
274  timer_clear_flag(TIM9, PPM_CC_IF);
275 
276  uint32_t now = timer_get_counter(TIM9) + timer_rollover_cnt;
277  ppm_decode_frame(now);
278 
279  } else if ((TIM9_SR & TIM_SR_UIF) != 0) {
280  timer_rollover_cnt += (1 << 16);
281  timer_clear_flag(TIM9, TIM_SR_UIF);
282  }
283 }
284 
285 #elif USE_PPM_TIM12 && defined(STM32F4)
286 
287 void tim8_brk_tim12_isr(void)
288 {
289  if ((TIM12_SR & PPM_CC_IF) != 0) {
290  timer_clear_flag(TIM12, PPM_CC_IF);
291 
292  uint32_t now = timer_get_counter(TIM12) + timer_rollover_cnt;
293  ppm_decode_frame(now);
294 
295  } else if ((TIM12_SR & TIM_SR_UIF) != 0) {
296  timer_rollover_cnt += (1 << 16);
297  timer_clear_flag(TIM12, TIM_SR_UIF);
298  }
299 }
300 
301 
302 
303 #endif /* USE_PPM_TIM1 */
304 
radio_control.h
ONE_MHZ_CLK
#define ONE_MHZ_CLK
Definition: ppm_arch.c:48
PPM_IRQ
#define PPM_IRQ
Definition: apogee_1.0.h:346
PPM_CHANNEL
#define PPM_CHANNEL
Definition: board.h:447
timer_rollover_cnt
static uint32_t timer_rollover_cnt
Definition: ppm_arch.c:56
PPM_TIMER
#define PPM_TIMER
Definition: board.h:448
PPM_GPIO_PIN
#define PPM_GPIO_PIN
Definition: apogee_1.0.h:352
timer_get_frequency
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:311
uint32_t
unsigned long uint32_t
Definition: types.h:18
PPM_TIMER_INPUT
#define PPM_TIMER_INPUT
Definition: apogee_1.0.h:345
PPM_IRQ_PRIO
#define PPM_IRQ_PRIO
Definition: ppm_arch.c:52
PPM_CC_IE
#define PPM_CC_IE
Definition: apogee_1.0.h:349
PPM_IRQ2
#define PPM_IRQ2
Definition: apogee_1.0.h:347
PPM_CC_IF
#define PPM_CC_IF
Definition: apogee_1.0.h:350
gpio_setup_pin_af
void gpio_setup_pin_af(ioportid_t port, uint16_t pin, uint8_t af, bool is_output)
Setup a gpio for input or output with alternate function.
Definition: gpio_arch.c:61
PRINT_CONFIG_MSG
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
ppm.h
gpio.h
PPM_GPIO_PORT
#define PPM_GPIO_PORT
Definition: apogee_1.0.h:351
ppm_arch_init
void ppm_arch_init(void)
Architecture dependant code.
Definition: ppm_arch.c:90
ppm_decode_frame
void ppm_decode_frame(uint32_t ppm_time)
Decode a PPM frame from global timer value.
Definition: ppm.c:99
PPM_GPIO_AF
#define PPM_GPIO_AF
Definition: apogee_1.0.h:353
FALSE
#define FALSE
Definition: std.h:5
RC_PPM_TICKS_PER_USEC
#define RC_PPM_TICKS_PER_USEC
The ppm counter is set-up to have 1/6 us resolution.
Definition: ppm_arch.h:43