dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_tim.c
Go to the documentation of this file.
1 
17 /*
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful, but
24  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
25  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
26  * for more details.
27  *
28  * You should have received a copy of the GNU General Public License along
29  * with this program; if not, see <http://www.gnu.org/licenses/>
30  */
31 
32 
33 #include "pios.h"
34 
35 #include "pios_tim.h"
36 #include "pios_tim_priv.h"
37 
39  PIOS_TIM_DEV_MAGIC = 0x87654098,
40 };
41 
42 struct pios_tim_dev {
44 
45  const struct pios_tim_channel * channels;
46  uint8_t num_channels;
47 
48  const struct pios_tim_callbacks * callbacks;
49  uintptr_t context;
50 };
51 
53 static uint8_t pios_tim_num_devs;
54 static struct pios_tim_dev * PIOS_TIM_alloc(void)
55 {
56  struct pios_tim_dev * tim_dev;
57 
59  return (NULL);
60  }
61 
62  tim_dev = &pios_tim_devs[pios_tim_num_devs++];
63  tim_dev->magic = PIOS_TIM_DEV_MAGIC;
64 
65  return (tim_dev);
66 }
67 
68 int32_t PIOS_TIM_InitClock(const struct pios_tim_clock_cfg * cfg)
69 {
70  PIOS_DEBUG_Assert(cfg);
71 
72  /* Configure the dividers for this timer */
73  TIM_TimeBaseInit(cfg->timer, (TIM_TimeBaseInitTypeDef*)cfg->time_base_init);
74 
75  /* Configure internal timer clocks */
76  TIM_InternalClockConfig(cfg->timer);
77 
78  /* Enable timers */
79  TIM_Cmd(cfg->timer, ENABLE);
80 
81  /* Enable Interrupts */
82  NVIC_Init((NVIC_InitTypeDef*)&cfg->irq.init);
83 
84  /* Check for optional second vector (dirty hack)
85  * This is needed for timers 1 and 8 when requiring more than one event
86  * to generate an interrupt. Actually up to 4 interrupts may be necessary.
87  */
88  if (cfg->irq2.init.NVIC_IRQChannel != 0)
89  NVIC_Init((NVIC_InitTypeDef*)&cfg->irq2.init);
90 
91  return 0;
92 }
93 
94 void PIOS_TIM_InitTimerPin(uintptr_t tim_id, int idx)
95 {
96  struct pios_tim_dev * tim_dev = (struct pios_tim_dev *) tim_id;
97 
98  PIOS_Assert(idx < tim_dev->num_channels);
99 
100  const struct pios_tim_channel * chan = &tim_dev->channels[idx];
101 
102  GPIO_Init(chan->pin.gpio, (GPIO_InitTypeDef*)&chan->pin.init);
103 
104  PIOS_DEBUG_Assert(chan->remap);
105 
106  GPIO_PinAFConfig(chan->pin.gpio, chan->pin.pin_source, chan->remap);
107 }
108 
109 void PIOS_TIM_InitAllTimerPins(uintptr_t tim_id)
110 {
111  struct pios_tim_dev * tim_dev = (struct pios_tim_dev *) tim_id;
112 
113  /* Configure the pins */
114  for (uint8_t i = 0; i < tim_dev->num_channels; i++) {
115  PIOS_TIM_InitTimerPin(tim_id, i);
116  }
117 }
118 
119 void PIOS_TIM_SetBankToGPOut(uintptr_t tim_id, TIM_TypeDef *timer)
120 {
121  struct pios_tim_dev * tim_dev = (struct pios_tim_dev *) tim_id;
122 
123  GPIO_InitTypeDef gpio_inf;
124  gpio_inf.GPIO_Speed = GPIO_Speed_25MHz;
125  gpio_inf.GPIO_Mode = GPIO_Mode_OUT;
126  gpio_inf.GPIO_OType = GPIO_OType_PP;
127  gpio_inf.GPIO_PuPd = GPIO_PuPd_DOWN;
128 
129  for (uint8_t i = 0; i < tim_dev->num_channels; i++) {
130  const struct pios_tim_channel * chan = &tim_dev->channels[i];
131 
132  if (chan->timer != timer) {
133  continue;
134  }
135 
136  // Only steal the pin info from the matching pin
137  gpio_inf.GPIO_Pin = chan->pin.init.GPIO_Pin;
138  GPIO_Init(chan->pin.gpio, &gpio_inf);
139  }
140 }
141 
142 int32_t PIOS_TIM_InitChannels(uintptr_t * tim_id, const struct pios_tim_channel * channels, uint8_t num_channels, const struct pios_tim_callbacks * callbacks, uintptr_t context)
143 {
144  PIOS_Assert(channels);
145  PIOS_Assert(num_channels);
146 
147  struct pios_tim_dev * tim_dev;
148  tim_dev = (struct pios_tim_dev *) PIOS_TIM_alloc();
149  if (!tim_dev) goto out_fail;
150 
151  /* Bind the configuration to the device instance */
152  tim_dev->channels = channels;
153  tim_dev->num_channels = num_channels;
154  tim_dev->callbacks = callbacks;
155  tim_dev->context = context;
156 
157  *tim_id = (uintptr_t)tim_dev;
158 
159  PIOS_TIM_InitAllTimerPins(*tim_id);
160 
161  return(0);
162 
163 out_fail:
164  return(-1);
165 }
166 
167 static void PIOS_TIM_generic_irq_handler(TIM_TypeDef * timer)
168 {
169  /* Iterate over all registered clients of the TIM layer to find channels on this timer */
170  for (uint8_t i = 0; i < pios_tim_num_devs; i++) {
171  const struct pios_tim_dev * tim_dev = &pios_tim_devs[i];
172 
173  if (!tim_dev->channels || tim_dev->num_channels == 0) {
174  /* No channels to process on this client */
175  continue;
176  }
177 
178  /* Check for an overflow event on this timer */
179  bool overflow_event;
180  uint16_t overflow_count;
181  if (TIM_GetITStatus(timer, TIM_IT_Update) == SET) {
182  TIM_ClearITPendingBit(timer, TIM_IT_Update);
183  overflow_count = timer->ARR;
184  overflow_event = true;
185  } else {
186  overflow_count = 0;
187  overflow_event = false;
188  }
189 
190  for (uint8_t j = 0; j < tim_dev->num_channels; j++) {
191  const struct pios_tim_channel * chan = &tim_dev->channels[j];
192 
193  if (chan->timer != timer) {
194  /* channel is not on this timer */
195  continue;
196  }
197 
198  /* Figure out which interrupt bit we should be looking at */
199  uint16_t timer_it;
200  switch (chan->timer_chan) {
201  case TIM_Channel_1:
202  timer_it = TIM_IT_CC1;
203  break;
204  case TIM_Channel_2:
205  timer_it = TIM_IT_CC2;
206  break;
207  case TIM_Channel_3:
208  timer_it = TIM_IT_CC3;
209  break;
210  case TIM_Channel_4:
211  timer_it = TIM_IT_CC4;
212  break;
213  default:
214  PIOS_Assert(0);
215  break;
216  }
217 
218  bool edge_event;
219  uint16_t edge_count;
220  if (TIM_GetITStatus(chan->timer, timer_it) == SET) {
221  TIM_ClearITPendingBit(chan->timer, timer_it);
222 
223  /* Read the current counter */
224  switch(chan->timer_chan) {
225  case TIM_Channel_1:
226  edge_count = TIM_GetCapture1(chan->timer);
227  break;
228  case TIM_Channel_2:
229  edge_count = TIM_GetCapture2(chan->timer);
230  break;
231  case TIM_Channel_3:
232  edge_count = TIM_GetCapture3(chan->timer);
233  break;
234  case TIM_Channel_4:
235  edge_count = TIM_GetCapture4(chan->timer);
236  break;
237  default:
238  PIOS_Assert(0);
239  break;
240  }
241  edge_event = true;
242  } else {
243  edge_event = false;
244  edge_count = 0;
245  }
246 
247  if (!tim_dev->callbacks) {
248  /* No callbacks registered, we're done with this channel */
249  continue;
250  }
251 
252  /* Generate the appropriate callbacks */
253  if (overflow_event && edge_event) {
254  /*
255  * When both edge and overflow happen in the same interrupt, we
256  * need a heuristic to determine the order of the edge and overflow
257  * events so that the callbacks happen in the right order. If we
258  * get the order wrong, our pulse width calculations could be off by up
259  * to ARR ticks. That could be bad.
260  *
261  * Heuristic: If the edge_count is < 16 ticks above zero then we assume the
262  * edge happened just after the overflow.
263  */
264 
265  if (edge_count < 16) {
266  /* Call the overflow callback first */
267  if (tim_dev->callbacks->overflow) {
268  (*tim_dev->callbacks->overflow)((uintptr_t)tim_dev,
269  tim_dev->context,
270  j,
271  overflow_count);
272  }
273  /* Call the edge callback second */
274  if (tim_dev->callbacks->edge) {
275  (*tim_dev->callbacks->edge)((uintptr_t)tim_dev,
276  tim_dev->context,
277  j,
278  edge_count);
279  }
280  } else {
281  /* Call the edge callback first */
282  if (tim_dev->callbacks->edge) {
283  (*tim_dev->callbacks->edge)((uintptr_t)tim_dev,
284  tim_dev->context,
285  j,
286  edge_count);
287  }
288  /* Call the overflow callback second */
289  if (tim_dev->callbacks->overflow) {
290  (*tim_dev->callbacks->overflow)((uintptr_t)tim_dev,
291  tim_dev->context,
292  j,
293  overflow_count);
294  }
295  }
296  } else if (overflow_event && tim_dev->callbacks->overflow) {
297  (*tim_dev->callbacks->overflow)((uintptr_t)tim_dev,
298  tim_dev->context,
299  j,
300  overflow_count);
301  } else if (edge_event && tim_dev->callbacks->edge) {
302  (*tim_dev->callbacks->edge)((uintptr_t)tim_dev,
303  tim_dev->context,
304  j,
305  edge_count);
306  }
307  }
308  }
309 }
310 
311 /* Bind Interrupt Handlers
312  *
313  * Map all valid TIM IRQs to the common interrupt handler
314  * and give it enough context to properly demux the various timers
315  */
316 void TIM1_CC_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_1_CC_irq_handler")));
317 static void PIOS_TIM_1_CC_irq_handler (void)
318 {
322 }
323 
324 // The rest of TIM1 interrupts are overlapped
325 void TIM1_BRK_TIM9_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_1_BRK_TIM_9_irq_handler")));
326 static void PIOS_TIM_1_BRK_TIM_9_irq_handler (void)
327 {
329 
330  if (TIM_GetITStatus(TIM1, TIM_IT_Break)) {
332  } else if (TIM_GetITStatus(TIM9, TIM_IT_Update | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 | TIM_IT_COM | TIM_IT_Trigger | TIM_IT_Break)) {
334  }
335 
337 }
338 
339 void TIM1_UP_TIM10_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_1_UP_TIM_10_irq_handler")));
340 static void PIOS_TIM_1_UP_TIM_10_irq_handler (void)
341 {
343 
344  if (TIM_GetITStatus(TIM1, TIM_IT_Update)) {
346  } else if (TIM_GetITStatus(TIM10, TIM_IT_Update | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 | TIM_IT_COM | TIM_IT_Trigger | TIM_IT_Break)) {
348  }
349 
351 }
352 void TIM1_TRG_COM_TIM11_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_1_TRG_COM_TIM_11_irq_handler")));
353 static void PIOS_TIM_1_TRG_COM_TIM_11_irq_handler (void)
354 {
356 
357  if (TIM_GetITStatus(TIM1, TIM_IT_Trigger | TIM_IT_COM)) {
359  } else if (TIM_GetITStatus(TIM11, TIM_IT_Update | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 | TIM_IT_COM | TIM_IT_Trigger | TIM_IT_Break)) {
361  }
362 
364 }
365 
366 #ifndef PIOS_OMIT_TIM2IRQ
367 void TIM2_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_2_irq_handler")));
368 static void PIOS_TIM_2_irq_handler (void)
369 {
373 }
374 #endif
375 
376 void TIM3_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_3_irq_handler")));
377 static void PIOS_TIM_3_irq_handler (void)
378 {
382 }
383 
384 #if !defined(PIOS_VIDEO_TIM4_COUNTER)
385 void TIM4_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_4_irq_handler")));
386 static void PIOS_TIM_4_irq_handler (void)
387 {
391 }
392 #endif /* !defined(PIOS_VIDEO_TIM4_COUNTER) */
393 
394 void TIM5_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_5_irq_handler")));
395 static void PIOS_TIM_5_irq_handler (void)
396 {
400 }
401 
402 void TIM6_DAC_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_6_DAC_irq_handler")));
403 static void PIOS_TIM_6_DAC_irq_handler (void)
404 {
406  // TODO: Check for DAC
409 }
410 
411 void TIM7_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_7_irq_handler")));
412 static void PIOS_TIM_7_irq_handler (void)
413 {
417 }
418 
419 void TIM8_CC_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_8_CC_irq_handler")));
420 static void PIOS_TIM_8_CC_irq_handler (void)
421 {
425 }
426 
427 // The rest of TIM8 interrupts are overlapped
428 void TIM8_BRK_TIM12_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_8_BRK_TIM_12_irq_handler")));
429 static void PIOS_TIM_8_BRK_TIM_12_irq_handler (void)
430 {
432 
433  if (TIM_GetITStatus(TIM8, TIM_IT_Break)) {
435  } else if (TIM_GetITStatus(TIM12, TIM_IT_Update | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 | TIM_IT_COM | TIM_IT_Trigger | TIM_IT_Break)) {
437  }
438 
440 }
441 
442 void TIM8_UP_TIM13_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_8_UP_TIM_13_irq_handler")));
443 static void PIOS_TIM_8_UP_TIM_13_irq_handler (void)
444 {
446 
447  if (TIM_GetITStatus(TIM8, TIM_IT_Update)) {
449  } else if (TIM_GetITStatus(TIM13, TIM_IT_Update | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 | TIM_IT_COM | TIM_IT_Trigger | TIM_IT_Break)) {
451  }
452 
454 }
455 
456 void TIM8_TRG_COM_TIM14_IRQHandler(void) __attribute__ ((alias ("PIOS_TIM_8_TRG_COM_TIM_14_irq_handler")));
457 static void PIOS_TIM_8_TRG_COM_TIM_14_irq_handler (void)
458 {
460 
461  if (TIM_GetITStatus(TIM8, TIM_IT_Trigger | TIM_IT_COM)) {
463  } else if (TIM_GetITStatus(TIM14, TIM_IT_Update | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 | TIM_IT_COM | TIM_IT_Trigger | TIM_IT_Break)) {
465  }
466 
468 }
469 
void TIM8_TRG_COM_TIM14_IRQHandler(void)
Definition: pios_tim.c:456
void TIM3_IRQHandler(void)
Definition: pios_tim.c:335
const TIM_TimeBaseInitTypeDef * time_base_init
Definition: pios_tim_priv.h:8
static void PIOS_TIM_generic_irq_handler(TIM_TypeDef *timer)
Definition: pios_tim.c:167
void TIM1_UP_TIM10_IRQHandler(void)
Definition: pios_tim.c:339
void TIM1_TRG_COM_TIM11_IRQHandler(void)
Definition: pios_tim.c:352
Main PiOS header to include all the compiled in PiOS options.
uint8_t num_channels
Definition: pios_tim.c:46
GPIO_InitTypeDef init
Definition: pios_stm32.h:61
void TIM5_IRQHandler(void)
Definition: pios_tim.c:384
static uint8_t pios_tim_num_devs
Definition: pios_tim.c:53
#define PIOS_TIM_MAX_DEVS
Definition: pios_board.h:215
GPIO_TypeDef * gpio
Definition: pios_stm32.h:60
void TIM8_BRK_TIM12_IRQHandler(void)
Definition: pios_tim.c:428
void PIOS_TIM_InitTimerPin(uintptr_t tim_id, int idx)
Definition: pios_tim.c:94
void TIM6_DAC_IRQHandler(void)
Definition: pios_tim.c:389
#define PIOS_DEBUG_Assert(test)
Definition: pios_debug.h:51
#define PIOS_IRQ_Epilogue()
Definition: pios_irq.h:46
pios_tim_dev_magic
Definition: pios_tim.c:38
volatile int j
Definition: loadabletest.c:12
void(* overflow)(uintptr_t tim_id, uintptr_t context, uint8_t chan_idx, uint16_t count)
Definition: pios_tim_priv.h:22
const struct pios_tim_channel * channels
Definition: pios_tim.c:45
struct stm32_irq irq2
Definition: pios_tim_priv.h:10
void PIOS_TIM_InitAllTimerPins(uintptr_t tim_id)
Definition: pios_tim.c:109
struct stm32_gpio pin
Definition: pios_tim_priv.h:17
uintptr_t context
Definition: pios_tim.c:49
void TIM7_IRQHandler(void)
Definition: pios_tim.c:396
enum pios_tim_dev_magic magic
Definition: pios_tim.c:43
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
TIM_TypeDef * timer
Definition: pios_tim_priv.h:7
void TIM4_IRQHandler(void)
Definition: pios_tim.c:378
static struct pios_tim_dev pios_tim_devs[PIOS_TIM_MAX_DEVS]
Definition: pios_tim.c:52
int32_t PIOS_TIM_InitClock(const struct pios_tim_clock_cfg *cfg)
Definition: pios_tim.c:68
static struct pios_tim_dev * PIOS_TIM_alloc(void)
Definition: pios_tim.c:54
uint8_t i
Definition: msp_messages.h:97
NVIC_InitTypeDef init
Definition: pios_stm32.h:36
uint8_t pin_source
Definition: pios_stm32.h:62
void TIM2_IRQHandler(void)
Definition: pios_tim.c:327
const struct pios_tim_callbacks * callbacks
Definition: pios_tim.c:48
void TIM8_UP_TIM13_IRQHandler(void)
Definition: pios_tim.c:442
void TIM8_CC_IRQHandler(void)
Definition: pios_tim.c:408
int32_t PIOS_TIM_InitChannels(uintptr_t *tim_id, const struct pios_tim_channel *channels, uint8_t num_channels, const struct pios_tim_callbacks *callbacks, uintptr_t context)
Definition: pios_tim.c:142
void PIOS_TIM_SetBankToGPOut(uintptr_t tim_id, TIM_TypeDef *timer)
Definition: pios_tim.c:119
void TIM1_BRK_TIM9_IRQHandler(void)
Definition: pios_tim.c:325
#define PIOS_IRQ_Prologue()
Definition: pios_irq.h:45
void TIM1_CC_IRQHandler(void)
Definition: pios_tim.c:317
TIM_TypeDef * timer
Definition: pios_tim_priv.h:14
void(* edge)(uintptr_t tim_id, uintptr_t context, uint8_t chan_idx, uint16_t count)
Definition: pios_tim_priv.h:23
#define PIOS_Assert(test)
Definition: pios_debug.h:52
struct stm32_irq irq
Definition: pios_tim_priv.h:9