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