2 ******************************************************************************
3 * @addtogroup PIOS PIOS Core hardware abstraction layer
5 * @addtogroup PIOS_TIM Timer Functions
6 * @brief PIOS Timer control code
10 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
11 * @brief Sets up timers and ways to register callbacks on them
12 * @see The GNU Public License (GPL) Version 3
14 *****************************************************************************/
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful, but
22 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #ifdef PIOS_INCLUDE_TIM
36 #include "pios_tim_priv.h"
38 enum pios_tim_dev_magic
{
39 PIOS_TIM_DEV_MAGIC
= 0x87654098,
43 enum pios_tim_dev_magic magic
;
45 const struct pios_tim_channel
*channels
;
48 const struct pios_tim_callbacks
*callbacks
;
51 #define PIOS_TIM_ALL_FLAGS TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 | TIM_IT_Trigger | TIM_IT_Update
53 static struct pios_tim_dev pios_tim_devs
[PIOS_TIM_MAX_DEVS
];
54 static uint8_t pios_tim_num_devs
;
55 static struct pios_tim_dev
*PIOS_TIM_alloc(void)
57 struct pios_tim_dev
*tim_dev
;
59 if (pios_tim_num_devs
>= PIOS_TIM_MAX_DEVS
) {
63 tim_dev
= &pios_tim_devs
[pios_tim_num_devs
++];
64 tim_dev
->magic
= PIOS_TIM_DEV_MAGIC
;
70 int32_t PIOS_TIM_InitClock(const struct pios_tim_clock_cfg
*cfg
)
72 PIOS_DEBUG_Assert(cfg
);
74 /* Enable appropriate clock to timer module */
75 switch ((uint32_t)cfg
->timer
) {
77 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1
, ENABLE
);
80 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2
, ENABLE
);
83 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3
, ENABLE
);
86 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4
, ENABLE
);
89 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5
, ENABLE
);
92 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6
, ENABLE
);
95 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7
, ENABLE
);
98 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8
, ENABLE
);
101 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9
, ENABLE
);
103 case (uint32_t)TIM10
:
104 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10
, ENABLE
);
106 case (uint32_t)TIM11
:
107 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11
, ENABLE
);
109 case (uint32_t)TIM12
:
110 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12
, ENABLE
);
112 case (uint32_t)TIM13
:
113 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM13
, ENABLE
);
115 case (uint32_t)TIM14
:
116 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14
, ENABLE
);
120 /* Configure the dividers for this timer */
121 TIM_TimeBaseInit(cfg
->timer
, cfg
->time_base_init
);
123 /* Configure internal timer clocks */
124 TIM_InternalClockConfig(cfg
->timer
);
127 TIM_Cmd(cfg
->timer
, ENABLE
);
129 /* Enable Interrupts */
130 NVIC_Init(&cfg
->irq
.init
);
135 int32_t PIOS_TIM_InitChannels(uint32_t *tim_id
, const struct pios_tim_channel
*channels
, uint8_t num_channels
, const struct pios_tim_callbacks
*callbacks
, uint32_t context
)
137 PIOS_Assert(channels
);
138 PIOS_Assert(num_channels
);
140 struct pios_tim_dev
*tim_dev
;
141 tim_dev
= (struct pios_tim_dev
*)PIOS_TIM_alloc();
146 /* Bind the configuration to the device instance */
147 tim_dev
->channels
= channels
;
148 tim_dev
->num_channels
= num_channels
;
149 tim_dev
->callbacks
= callbacks
;
150 tim_dev
->context
= context
;
152 /* Configure the pins */
153 for (uint8_t i
= 0; i
< num_channels
; i
++) {
154 const struct pios_tim_channel
*chan
= &(channels
[i
]);
156 /* Enable the peripheral clock for the GPIO */
157 /* switch ((uint32_t)chan->pin.gpio) {
158 case (uint32_t) GPIOA:
159 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
161 case (uint32_t) GPIOB:
162 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
164 case (uint32_t) GPIOC:
165 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
171 */ // commented out for now as f4 starts all clocks
172 GPIO_Init(chan
->pin
.gpio
, &chan
->pin
.init
);
174 PIOS_DEBUG_Assert(chan
->remap
);
176 // Second parameter should technically be PinSource but they are numerically the same
177 GPIO_PinAFConfig(chan
->pin
.gpio
, chan
->pin
.pin_source
, chan
->remap
);
180 *tim_id
= (uint32_t)tim_dev
;
188 static void PIOS_TIM_generic_irq_handler(TIM_TypeDef
*timer
)
190 /* Iterate over all registered clients of the TIM layer to find channels on this timer */
191 for (uint8_t i
= 0; i
< pios_tim_num_devs
; i
++) {
192 const struct pios_tim_dev
*tim_dev
= &pios_tim_devs
[i
];
194 if (!tim_dev
->channels
|| tim_dev
->num_channels
== 0) {
195 /* No channels to process on this client */
199 /* Check for an overflow event on this timer */
201 uint16_t overflow_count
;
202 if (TIM_GetITStatus(timer
, TIM_IT_Update
) == SET
) {
203 TIM_ClearITPendingBit(timer
, TIM_IT_Update
);
204 overflow_count
= timer
->ARR
;
205 overflow_event
= true;
208 overflow_event
= false;
211 for (uint8_t j
= 0; j
< tim_dev
->num_channels
; j
++) {
212 const struct pios_tim_channel
*chan
= &tim_dev
->channels
[j
];
214 if (chan
->timer
!= timer
) {
215 /* channel is not on this timer */
219 /* Figure out which interrupt bit we should be looking at */
221 switch (chan
->timer_chan
) {
223 timer_it
= TIM_IT_CC1
;
226 timer_it
= TIM_IT_CC2
;
229 timer_it
= TIM_IT_CC3
;
232 timer_it
= TIM_IT_CC4
;
241 if (TIM_GetITStatus(chan
->timer
, timer_it
) == SET
) {
242 TIM_ClearITPendingBit(chan
->timer
, timer_it
);
244 /* Read the current counter */
245 switch (chan
->timer_chan
) {
247 edge_count
= TIM_GetCapture1(chan
->timer
);
250 edge_count
= TIM_GetCapture2(chan
->timer
);
253 edge_count
= TIM_GetCapture3(chan
->timer
);
256 edge_count
= TIM_GetCapture4(chan
->timer
);
268 if (!tim_dev
->callbacks
) {
269 /* No callbacks registered, we're done with this channel */
273 /* Generate the appropriate callbacks */
274 if (overflow_event
& edge_event
) {
276 * When both edge and overflow happen in the same interrupt, we
277 * need a heuristic to determine the order of the edge and overflow
278 * events so that the callbacks happen in the right order. If we
279 * get the order wrong, our pulse width calculations could be off by up
280 * to ARR ticks. That could be bad.
282 * Heuristic: If the edge_count is < 16 ticks above zero then we assume the
283 * edge happened just after the overflow.
286 if (edge_count
< 16) {
287 /* Call the overflow callback first */
288 if (tim_dev
->callbacks
->overflow
) {
289 (*tim_dev
->callbacks
->overflow
)((uint32_t)tim_dev
,
294 /* Call the edge callback second */
295 if (tim_dev
->callbacks
->edge
) {
296 (*tim_dev
->callbacks
->edge
)((uint32_t)tim_dev
,
302 /* Call the edge callback first */
303 if (tim_dev
->callbacks
->edge
) {
304 (*tim_dev
->callbacks
->edge
)((uint32_t)tim_dev
,
309 /* Call the overflow callback second */
310 if (tim_dev
->callbacks
->overflow
) {
311 (*tim_dev
->callbacks
->overflow
)((uint32_t)tim_dev
,
317 } else if (overflow_event
&& tim_dev
->callbacks
->overflow
) {
318 (*tim_dev
->callbacks
->overflow
)((uint32_t)tim_dev
,
322 } else if (edge_event
&& tim_dev
->callbacks
->edge
) {
323 (*tim_dev
->callbacks
->edge
)((uint32_t)tim_dev
,
332 /* Bind Interrupt Handlers
334 * Map all valid TIM IRQs to the common interrupt handler
335 * and give it enough context to properly demux the various timers
337 void TIM1_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_1_CC_irq_handler")));
338 static void PIOS_TIM_1_CC_irq_handler(void)
340 PIOS_TIM_generic_irq_handler(TIM1
);
343 void TIM2_IRQHandler(void) __attribute__((alias("PIOS_TIM_2_irq_handler")));
344 static void PIOS_TIM_2_irq_handler(void)
346 PIOS_TIM_generic_irq_handler(TIM2
);
349 void TIM3_IRQHandler(void) __attribute__((alias("PIOS_TIM_3_irq_handler")));
350 static void PIOS_TIM_3_irq_handler(void)
352 PIOS_TIM_generic_irq_handler(TIM3
);
355 void TIM4_IRQHandler(void) __attribute__((alias("PIOS_TIM_4_irq_handler")));
356 static void PIOS_TIM_4_irq_handler(void)
358 PIOS_TIM_generic_irq_handler(TIM4
);
361 void TIM5_IRQHandler(void) __attribute__((alias("PIOS_TIM_5_irq_handler")));
362 static void PIOS_TIM_5_irq_handler(void)
364 PIOS_TIM_generic_irq_handler(TIM5
);
367 void TIM6_IRQHandler(void) __attribute__((alias("PIOS_TIM_6_irq_handler")));
368 static void PIOS_TIM_6_irq_handler(void)
370 PIOS_TIM_generic_irq_handler(TIM6
);
373 void TIM7_IRQHandler(void) __attribute__((alias("PIOS_TIM_7_irq_handler")));
374 static void PIOS_TIM_7_irq_handler(void)
376 PIOS_TIM_generic_irq_handler(TIM7
);
379 void TIM8_UP_IRQHandler(void) __attribute__((alias("PIOS_TIM_8_UP_irq_handler")));
380 static void PIOS_TIM_8_UP_irq_handler(void)
382 PIOS_TIM_generic_irq_handler(TIM8
);
385 void TIM8_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_8_CC_irq_handler")));
386 static void PIOS_TIM_8_CC_irq_handler(void)
388 PIOS_TIM_generic_irq_handler(TIM8
);
391 // The rest of TIM1 interrupts are overlapped
392 void TIM1_BRK_TIM9_IRQHandler(void) __attribute__((alias("PIOS_TIM_9_CC_irq_handler")));
393 static void PIOS_TIM_9_CC_irq_handler(void)
395 if (TIM_GetITStatus(TIM1
, TIM_IT_Break
)) {
396 PIOS_TIM_generic_irq_handler(TIM1
);
397 } else if (TIM_GetITStatus(TIM9
, PIOS_TIM_ALL_FLAGS
)) {
398 PIOS_TIM_generic_irq_handler(TIM9
);
402 void TIM1_UP_TIM10_IRQHandler(void) __attribute__((alias("PIOS_TIM_10_CC_irq_handler")));
403 static void PIOS_TIM_10_CC_irq_handler(void)
405 if (TIM_GetITStatus(TIM1
, TIM_IT_Update
)) {
406 PIOS_TIM_generic_irq_handler(TIM1
);
407 } else if (TIM_GetITStatus(TIM10
, PIOS_TIM_ALL_FLAGS
)) {
408 PIOS_TIM_generic_irq_handler(TIM10
);
412 void TIM1_TRG_COM_TIM11_IRQHandler(void) __attribute__((alias("PIOS_TIM_11_CC_irq_handler")));
413 static void PIOS_TIM_11_CC_irq_handler(void)
415 if (TIM_GetITStatus(TIM1
, TIM_IT_COM
| TIM_IT_Trigger
)) {
416 PIOS_TIM_generic_irq_handler(TIM1
);
417 } else if (TIM_GetITStatus(TIM11
, PIOS_TIM_ALL_FLAGS
)) {
418 PIOS_TIM_generic_irq_handler(TIM11
);
422 void TIM8_BRK_TIM12_IRQHandler(void) __attribute__((alias("PIOS_TIM_12_irq_handler")));
423 static void PIOS_TIM_12_irq_handler(void)
425 if (TIM_GetITStatus(TIM8
, TIM_IT_Break
)) {
426 PIOS_TIM_generic_irq_handler(TIM8
);
427 } else if (TIM_GetITStatus(TIM12
, PIOS_TIM_ALL_FLAGS
)) {
428 PIOS_TIM_generic_irq_handler(TIM12
);
432 void TIM8_UP_TIM13_IRQHandler(void) __attribute__((alias("PIOS_TIM8_UP_TIM13_IRQHandler")));
433 static void PIOS_TIM8_UP_TIM13_IRQHandler(void)
435 if (TIM_GetITStatus(TIM8
, TIM_IT_Update
)) {
436 PIOS_TIM_generic_irq_handler(TIM8
);
437 } else if (TIM_GetITStatus(TIM13
, PIOS_TIM_ALL_FLAGS
)) {
438 PIOS_TIM_generic_irq_handler(TIM13
);
442 void TIM8_TRG_COM_TIM14_IRQHandler(void) __attribute__((alias("PIOS_TIM8_TRG_COM_TIM14_IRQHandler")));
443 static void PIOS_TIM8_TRG_COM_TIM14_IRQHandler(void)
445 if (TIM_GetITStatus(TIM8
, TIM_IT_COM
| TIM_IT_Trigger
)) {
446 PIOS_TIM_generic_irq_handler(TIM8
);
447 } else if (TIM_GetITStatus(TIM14
, PIOS_TIM_ALL_FLAGS
)) {
448 PIOS_TIM_generic_irq_handler(TIM14
);
452 #endif /* PIOS_INCLUDE_TIM */