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
);
133 // Advanced timers TIM1 & TIM8 need special handling:
134 // There are up to 4 separate interrupts handlers for each advanced timer, but
135 // pios_tim_clock_cfg has provision for only one irq init, so we take care here
136 // to enable additional irq channels that we intend to use.
139 if (cfg
->timer
== TIM1
) {
140 NVIC_InitTypeDef init
= cfg
->irq
.init
;
141 init
.NVIC_IRQChannel
= TIM1_UP_TIM10_IRQn
;
143 #if !defined(STM32F401xx) && !defined(STM32F411xE)
144 } else if (cfg
->timer
== TIM8
) {
145 NVIC_InitTypeDef init
= cfg
->irq
.init
;
146 init
.NVIC_IRQChannel
= TIM8_UP_TIM13_IRQn
;
154 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
)
156 PIOS_Assert(channels
);
157 PIOS_Assert(num_channels
);
159 struct pios_tim_dev
*tim_dev
;
160 tim_dev
= (struct pios_tim_dev
*)PIOS_TIM_alloc();
165 /* Bind the configuration to the device instance */
166 tim_dev
->channels
= channels
;
167 tim_dev
->num_channels
= num_channels
;
168 tim_dev
->callbacks
= callbacks
;
169 tim_dev
->context
= context
;
171 /* Configure the pins */
172 for (uint8_t i
= 0; i
< num_channels
; i
++) {
173 const struct pios_tim_channel
*chan
= &(channels
[i
]);
175 /* Enable the peripheral clock for the GPIO */
176 /* switch ((uint32_t)chan->pin.gpio) {
177 case (uint32_t) GPIOA:
178 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
180 case (uint32_t) GPIOB:
181 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
183 case (uint32_t) GPIOC:
184 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
190 */ // commented out for now as f4 starts all clocks
191 GPIO_Init(chan
->pin
.gpio
, &chan
->pin
.init
);
193 PIOS_DEBUG_Assert(chan
->remap
);
195 // Second parameter should technically be PinSource but they are numerically the same
196 GPIO_PinAFConfig(chan
->pin
.gpio
, chan
->pin
.pin_source
, chan
->remap
);
199 *tim_id
= (uint32_t)tim_dev
;
207 static void PIOS_TIM_generic_irq_handler(TIM_TypeDef
*timer
)
209 /* Iterate over all registered clients of the TIM layer to find channels on this timer */
210 for (uint8_t i
= 0; i
< pios_tim_num_devs
; i
++) {
211 const struct pios_tim_dev
*tim_dev
= &pios_tim_devs
[i
];
213 if (!tim_dev
->channels
|| tim_dev
->num_channels
== 0) {
214 /* No channels to process on this client */
218 /* Check for an overflow event on this timer */
220 uint16_t overflow_count
;
221 if (TIM_GetITStatus(timer
, TIM_IT_Update
) == SET
) {
222 TIM_ClearITPendingBit(timer
, TIM_IT_Update
);
223 overflow_count
= timer
->ARR
;
224 overflow_event
= true;
227 overflow_event
= false;
230 for (uint8_t j
= 0; j
< tim_dev
->num_channels
; j
++) {
231 const struct pios_tim_channel
*chan
= &tim_dev
->channels
[j
];
233 if (chan
->timer
!= timer
) {
234 /* channel is not on this timer */
238 /* Figure out which interrupt bit we should be looking at */
240 switch (chan
->timer_chan
) {
242 timer_it
= TIM_IT_CC1
;
245 timer_it
= TIM_IT_CC2
;
248 timer_it
= TIM_IT_CC3
;
251 timer_it
= TIM_IT_CC4
;
260 if (TIM_GetITStatus(chan
->timer
, timer_it
) == SET
) {
261 TIM_ClearITPendingBit(chan
->timer
, timer_it
);
263 /* Read the current counter */
264 switch (chan
->timer_chan
) {
266 edge_count
= TIM_GetCapture1(chan
->timer
);
269 edge_count
= TIM_GetCapture2(chan
->timer
);
272 edge_count
= TIM_GetCapture3(chan
->timer
);
275 edge_count
= TIM_GetCapture4(chan
->timer
);
287 if (!tim_dev
->callbacks
) {
288 /* No callbacks registered, we're done with this channel */
292 /* Generate the appropriate callbacks */
293 if (overflow_event
& edge_event
) {
295 * When both edge and overflow happen in the same interrupt, we
296 * need a heuristic to determine the order of the edge and overflow
297 * events so that the callbacks happen in the right order. If we
298 * get the order wrong, our pulse width calculations could be off by up
299 * to ARR ticks. That could be bad.
301 * Heuristic: If the edge_count is < 16 ticks above zero then we assume the
302 * edge happened just after the overflow.
305 if (edge_count
< 16) {
306 /* Call the overflow callback first */
307 if (tim_dev
->callbacks
->overflow
) {
308 (*tim_dev
->callbacks
->overflow
)((uint32_t)tim_dev
,
313 /* Call the edge callback second */
314 if (tim_dev
->callbacks
->edge
) {
315 (*tim_dev
->callbacks
->edge
)((uint32_t)tim_dev
,
321 /* Call the edge callback first */
322 if (tim_dev
->callbacks
->edge
) {
323 (*tim_dev
->callbacks
->edge
)((uint32_t)tim_dev
,
328 /* Call the overflow callback second */
329 if (tim_dev
->callbacks
->overflow
) {
330 (*tim_dev
->callbacks
->overflow
)((uint32_t)tim_dev
,
336 } else if (overflow_event
&& tim_dev
->callbacks
->overflow
) {
337 (*tim_dev
->callbacks
->overflow
)((uint32_t)tim_dev
,
341 } else if (edge_event
&& tim_dev
->callbacks
->edge
) {
342 (*tim_dev
->callbacks
->edge
)((uint32_t)tim_dev
,
351 /* Bind Interrupt Handlers
353 * Map all valid TIM IRQs to the common interrupt handler
354 * and give it enough context to properly demux the various timers
356 void TIM1_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_1_CC_irq_handler")));
357 static void PIOS_TIM_1_CC_irq_handler(void)
359 PIOS_TIM_generic_irq_handler(TIM1
);
362 void TIM2_IRQHandler(void) __attribute__((alias("PIOS_TIM_2_irq_handler")));
363 static void PIOS_TIM_2_irq_handler(void)
365 PIOS_TIM_generic_irq_handler(TIM2
);
368 void TIM3_IRQHandler(void) __attribute__((alias("PIOS_TIM_3_irq_handler")));
369 static void PIOS_TIM_3_irq_handler(void)
371 PIOS_TIM_generic_irq_handler(TIM3
);
374 void TIM4_IRQHandler(void) __attribute__((alias("PIOS_TIM_4_irq_handler")));
375 static void PIOS_TIM_4_irq_handler(void)
377 PIOS_TIM_generic_irq_handler(TIM4
);
380 void TIM5_IRQHandler(void) __attribute__((alias("PIOS_TIM_5_irq_handler")));
381 static void PIOS_TIM_5_irq_handler(void)
383 PIOS_TIM_generic_irq_handler(TIM5
);
386 void TIM6_IRQHandler(void) __attribute__((alias("PIOS_TIM_6_irq_handler")));
387 static void PIOS_TIM_6_irq_handler(void)
389 PIOS_TIM_generic_irq_handler(TIM6
);
392 void TIM7_IRQHandler(void) __attribute__((alias("PIOS_TIM_7_irq_handler")));
393 static void PIOS_TIM_7_irq_handler(void)
395 PIOS_TIM_generic_irq_handler(TIM7
);
398 void TIM8_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_8_CC_irq_handler")));
399 static void PIOS_TIM_8_CC_irq_handler(void)
401 PIOS_TIM_generic_irq_handler(TIM8
);
404 // The rest of TIM1 interrupts are overlapped
405 void TIM1_BRK_TIM9_IRQHandler(void) __attribute__((alias("PIOS_TIM_9_CC_irq_handler")));
406 static void PIOS_TIM_9_CC_irq_handler(void)
408 if (TIM_GetITStatus(TIM1
, TIM_IT_Break
)) {
409 PIOS_TIM_generic_irq_handler(TIM1
);
410 } else if (TIM_GetITStatus(TIM9
, PIOS_TIM_ALL_FLAGS
)) {
411 PIOS_TIM_generic_irq_handler(TIM9
);
415 void TIM1_UP_TIM10_IRQHandler(void) __attribute__((alias("PIOS_TIM_10_CC_irq_handler")));
416 static void PIOS_TIM_10_CC_irq_handler(void)
418 if (TIM_GetITStatus(TIM1
, TIM_IT_Update
)) {
419 PIOS_TIM_generic_irq_handler(TIM1
);
420 } else if (TIM_GetITStatus(TIM10
, PIOS_TIM_ALL_FLAGS
)) {
421 PIOS_TIM_generic_irq_handler(TIM10
);
425 void TIM1_TRG_COM_TIM11_IRQHandler(void) __attribute__((alias("PIOS_TIM_11_CC_irq_handler")));
426 static void PIOS_TIM_11_CC_irq_handler(void)
428 if (TIM_GetITStatus(TIM1
, TIM_IT_COM
| TIM_IT_Trigger
)) {
429 PIOS_TIM_generic_irq_handler(TIM1
);
430 } else if (TIM_GetITStatus(TIM11
, PIOS_TIM_ALL_FLAGS
)) {
431 PIOS_TIM_generic_irq_handler(TIM11
);
435 void TIM8_BRK_TIM12_IRQHandler(void) __attribute__((alias("PIOS_TIM_12_irq_handler")));
436 static void PIOS_TIM_12_irq_handler(void)
438 if (TIM_GetITStatus(TIM8
, TIM_IT_Break
)) {
439 PIOS_TIM_generic_irq_handler(TIM8
);
440 } else if (TIM_GetITStatus(TIM12
, PIOS_TIM_ALL_FLAGS
)) {
441 PIOS_TIM_generic_irq_handler(TIM12
);
445 void TIM8_UP_TIM13_IRQHandler(void) __attribute__((alias("PIOS_TIM8_UP_TIM13_IRQHandler")));
446 static void PIOS_TIM8_UP_TIM13_IRQHandler(void)
448 if (TIM_GetITStatus(TIM8
, TIM_IT_Update
)) {
449 PIOS_TIM_generic_irq_handler(TIM8
);
450 } else if (TIM_GetITStatus(TIM13
, PIOS_TIM_ALL_FLAGS
)) {
451 PIOS_TIM_generic_irq_handler(TIM13
);
455 void TIM8_TRG_COM_TIM14_IRQHandler(void) __attribute__((alias("PIOS_TIM8_TRG_COM_TIM14_IRQHandler")));
456 static void PIOS_TIM8_TRG_COM_TIM14_IRQHandler(void)
458 if (TIM_GetITStatus(TIM8
, TIM_IT_COM
| TIM_IT_Trigger
)) {
459 PIOS_TIM_generic_irq_handler(TIM8
);
460 } else if (TIM_GetITStatus(TIM14
, PIOS_TIM_ALL_FLAGS
)) {
461 PIOS_TIM_generic_irq_handler(TIM14
);
465 #endif /* PIOS_INCLUDE_TIM */