update credits
[librepilot.git] / flight / pios / stm32f10x / pios_tim.c
blobae442eaa103b72153ba1e1ccb6e243b5ef756c10
1 #include "pios.h"
3 #ifdef PIOS_INCLUDE_TIM
5 #include "pios_tim_priv.h"
7 enum pios_tim_dev_magic {
8 PIOS_TIM_DEV_MAGIC = 0x87654098,
9 };
11 struct pios_tim_dev {
12 enum pios_tim_dev_magic magic;
14 const struct pios_tim_channel *channels;
15 uint8_t num_channels;
17 const struct pios_tim_callbacks *callbacks;
18 uint32_t context;
21 #if 0
22 static bool PIOS_TIM_validate(struct pios_tim_dev *tim_dev)
24 return tim_dev->magic == PIOS_TIM_DEV_MAGIC;
26 #endif
28 #if defined(PIOS_INCLUDE_FREERTOS) && 0
29 static struct pios_tim_dev *PIOS_TIM_alloc(void)
31 struct pios_tim_dev *tim_dev;
33 tim_dev = (struct pios_tim_dev *)pios_malloc(sizeof(*tim_dev));
34 if (!tim_dev) {
35 return NULL;
38 tim_dev->magic = PIOS_TIM_DEV_MAGIC;
39 return tim_dev;
41 #else
42 static struct pios_tim_dev pios_tim_devs[PIOS_TIM_MAX_DEVS];
43 static uint8_t pios_tim_num_devs;
44 static struct pios_tim_dev *PIOS_TIM_alloc(void)
46 struct pios_tim_dev *tim_dev;
48 if (pios_tim_num_devs >= PIOS_TIM_MAX_DEVS) {
49 return NULL;
52 tim_dev = &pios_tim_devs[pios_tim_num_devs++];
53 tim_dev->magic = PIOS_TIM_DEV_MAGIC;
55 return tim_dev;
57 #endif /* if defined(PIOS_INCLUDE_FREERTOS) && 0 */
60 int32_t PIOS_TIM_InitClock(const struct pios_tim_clock_cfg *cfg)
62 PIOS_DEBUG_Assert(cfg);
64 /* Enable appropriate clock to timer module */
65 switch ((uint32_t)cfg->timer) {
66 case (uint32_t)TIM1:
67 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
68 break;
69 case (uint32_t)TIM2:
70 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
71 break;
72 case (uint32_t)TIM3:
73 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
74 break;
75 case (uint32_t)TIM4:
76 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
77 break;
78 #ifdef STM32F10X_HD
79 case (uint32_t)TIM5:
80 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
81 break;
82 case (uint32_t)TIM6:
83 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
84 break;
85 case (uint32_t)TIM7:
86 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
87 break;
88 case (uint32_t)TIM8:
89 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
90 break;
91 #endif
94 /* Configure the dividers for this timer */
95 TIM_TimeBaseInit(cfg->timer, cfg->time_base_init);
97 /* Configure internal timer clocks */
98 TIM_InternalClockConfig(cfg->timer);
100 /* Enable timers */
101 TIM_Cmd(cfg->timer, ENABLE);
103 /* Enable Interrupts */
104 NVIC_Init(&cfg->irq.init);
106 /* Advanced TIM1 has additional IRQ */
107 if (cfg->timer == TIM1) {
108 NVIC_InitTypeDef init = cfg->irq.init;
109 init.NVIC_IRQChannel = TIM1_UP_IRQn;
110 NVIC_Init(&init);
113 return 0;
116 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)
118 PIOS_Assert(channels);
119 PIOS_Assert(num_channels);
121 struct pios_tim_dev *tim_dev;
122 tim_dev = (struct pios_tim_dev *)PIOS_TIM_alloc();
123 if (!tim_dev) {
124 goto out_fail;
127 /* Bind the configuration to the device instance */
128 tim_dev->channels = channels;
129 tim_dev->num_channels = num_channels;
130 tim_dev->callbacks = callbacks;
131 tim_dev->context = context;
133 /* Configure the pins */
134 for (uint8_t i = 0; i < num_channels; i++) {
135 const struct pios_tim_channel *chan = &(channels[i]);
137 /* Enable the peripheral clock for the GPIO */
138 switch ((uint32_t)chan->pin.gpio) {
139 case (uint32_t)GPIOA:
140 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
141 break;
142 case (uint32_t)GPIOB:
143 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
144 break;
145 case (uint32_t)GPIOC:
146 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
147 break;
148 default:
149 PIOS_Assert(0);
150 break;
152 GPIO_Init(chan->pin.gpio, &chan->pin.init);
154 if (chan->remap) {
155 GPIO_PinRemapConfig(chan->remap, ENABLE);
159 *tim_id = (uint32_t)tim_dev;
161 return 0;
163 out_fail:
164 return -1;
167 static void PIOS_TIM_generic_irq_handler(TIM_TypeDef *timer)
169 /* Check for an overflow event on this timer */
170 bool overflow_event = 0;
171 uint16_t overflow_count = false;
173 if (TIM_GetITStatus(timer, TIM_IT_Update) == SET) {
174 TIM_ClearITPendingBit(timer, TIM_IT_Update);
175 overflow_count = timer->ARR;
176 overflow_event = true;
179 /* Iterate over all registered clients of the TIM layer to find channels on this timer */
180 for (uint8_t i = 0; i < pios_tim_num_devs; i++) {
181 const struct pios_tim_dev *tim_dev = &pios_tim_devs[i];
183 if (!tim_dev->channels || tim_dev->num_channels == 0) {
184 /* No channels to process on this client */
185 continue;
188 for (uint8_t j = 0; j < tim_dev->num_channels; j++) {
189 const struct pios_tim_channel *chan = &tim_dev->channels[j];
191 if (chan->timer != timer) {
192 /* channel is not on this timer */
193 continue;
196 /* Figure out which interrupt bit we should be looking at */
197 uint16_t timer_it;
198 switch (chan->timer_chan) {
199 case TIM_Channel_1:
200 timer_it = TIM_IT_CC1;
201 break;
202 case TIM_Channel_2:
203 timer_it = TIM_IT_CC2;
204 break;
205 case TIM_Channel_3:
206 timer_it = TIM_IT_CC3;
207 break;
208 case TIM_Channel_4:
209 timer_it = TIM_IT_CC4;
210 break;
211 default:
212 PIOS_Assert(0);
213 break;
216 bool edge_event;
217 uint16_t edge_count;
218 if (TIM_GetITStatus(chan->timer, timer_it) == SET) {
219 TIM_ClearITPendingBit(chan->timer, timer_it);
221 /* Read the current counter */
222 switch (chan->timer_chan) {
223 case TIM_Channel_1:
224 edge_count = TIM_GetCapture1(chan->timer);
225 break;
226 case TIM_Channel_2:
227 edge_count = TIM_GetCapture2(chan->timer);
228 break;
229 case TIM_Channel_3:
230 edge_count = TIM_GetCapture3(chan->timer);
231 break;
232 case TIM_Channel_4:
233 edge_count = TIM_GetCapture4(chan->timer);
234 break;
235 default:
236 PIOS_Assert(0);
237 break;
239 edge_event = true;
240 } else {
241 edge_event = false;
242 edge_count = 0;
245 if (!tim_dev->callbacks) {
246 /* No callbacks registered, we're done with this channel */
247 continue;
250 /* Generate the appropriate callbacks */
251 if (overflow_event & edge_event) {
253 * When both edge and overflow happen in the same interrupt, we
254 * need a heuristic to determine the order of the edge and overflow
255 * events so that the callbacks happen in the right order. If we
256 * get the order wrong, our pulse width calculations could be off by up
257 * to ARR ticks. That could be bad.
259 * Heuristic: If the edge_count is < 32 ticks above zero then we assume the
260 * edge happened just after the overflow.
263 if (edge_count < 32) {
264 /* Call the overflow callback first */
265 if (tim_dev->callbacks->overflow) {
266 (*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
267 tim_dev->context,
269 overflow_count);
271 /* Call the edge callback second */
272 if (tim_dev->callbacks->edge) {
273 (*tim_dev->callbacks->edge)((uint32_t)tim_dev,
274 tim_dev->context,
276 edge_count);
278 } else {
279 /* Call the edge callback first */
280 if (tim_dev->callbacks->edge) {
281 (*tim_dev->callbacks->edge)((uint32_t)tim_dev,
282 tim_dev->context,
284 edge_count);
286 /* Call the overflow callback second */
287 if (tim_dev->callbacks->overflow) {
288 (*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
289 tim_dev->context,
291 overflow_count);
294 } else if (overflow_event && tim_dev->callbacks->overflow) {
295 (*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
296 tim_dev->context,
298 overflow_count);
299 } else if (edge_event && tim_dev->callbacks->edge) {
300 (*tim_dev->callbacks->edge)((uint32_t)tim_dev,
301 tim_dev->context,
303 edge_count);
309 /* Bind Interrupt Handlers
311 * Map all valid TIM IRQs to the common interrupt handler
312 * and give it enough context to properly demux the various timers
314 void TIM1_UP_IRQHandler(void) __attribute__((alias("PIOS_TIM_1_UP_irq_handler")));
315 static void PIOS_TIM_1_UP_irq_handler(void)
317 PIOS_TIM_generic_irq_handler(TIM1);
320 void TIM1_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_1_CC_irq_handler")));
321 static void PIOS_TIM_1_CC_irq_handler(void)
323 PIOS_TIM_generic_irq_handler(TIM1);
326 void TIM2_IRQHandler(void) __attribute__((alias("PIOS_TIM_2_irq_handler")));
327 static void PIOS_TIM_2_irq_handler(void)
329 PIOS_TIM_generic_irq_handler(TIM2);
332 void TIM3_IRQHandler(void) __attribute__((alias("PIOS_TIM_3_irq_handler")));
333 static void PIOS_TIM_3_irq_handler(void)
335 PIOS_TIM_generic_irq_handler(TIM3);
338 void TIM4_IRQHandler(void) __attribute__((alias("PIOS_TIM_4_irq_handler")));
339 static void PIOS_TIM_4_irq_handler(void)
341 PIOS_TIM_generic_irq_handler(TIM4);
344 void TIM5_IRQHandler(void) __attribute__((alias("PIOS_TIM_5_irq_handler")));
345 static void PIOS_TIM_5_irq_handler(void)
347 PIOS_TIM_generic_irq_handler(TIM5);
350 void TIM6_IRQHandler(void) __attribute__((alias("PIOS_TIM_6_irq_handler")));
351 static void PIOS_TIM_6_irq_handler(void)
353 PIOS_TIM_generic_irq_handler(TIM6);
356 void TIM7_IRQHandler(void) __attribute__((alias("PIOS_TIM_7_irq_handler")));
357 static void PIOS_TIM_7_irq_handler(void)
359 PIOS_TIM_generic_irq_handler(TIM7);
362 void TIM8_UP_IRQHandler(void) __attribute__((alias("PIOS_TIM_8_UP_irq_handler")));
363 static void PIOS_TIM_8_UP_irq_handler(void)
365 PIOS_TIM_generic_irq_handler(TIM8);
368 void TIM8_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_8_CC_irq_handler")));
369 static void PIOS_TIM_8_CC_irq_handler(void)
371 PIOS_TIM_generic_irq_handler(TIM8);
374 #endif /* PIOS_INCLUDE_TIM */