fix WhatsNew for release
[librepilot.git] / flight / pios / stm32f10x / pios_tim.c
blob4df0932996fb6d8a5ce3c1a88edf867e337f1774
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 return 0;
109 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)
111 PIOS_Assert(channels);
112 PIOS_Assert(num_channels);
114 struct pios_tim_dev *tim_dev;
115 tim_dev = (struct pios_tim_dev *)PIOS_TIM_alloc();
116 if (!tim_dev) {
117 goto out_fail;
120 /* Bind the configuration to the device instance */
121 tim_dev->channels = channels;
122 tim_dev->num_channels = num_channels;
123 tim_dev->callbacks = callbacks;
124 tim_dev->context = context;
126 /* Configure the pins */
127 for (uint8_t i = 0; i < num_channels; i++) {
128 const struct pios_tim_channel *chan = &(channels[i]);
130 /* Enable the peripheral clock for the GPIO */
131 switch ((uint32_t)chan->pin.gpio) {
132 case (uint32_t)GPIOA:
133 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
134 break;
135 case (uint32_t)GPIOB:
136 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
137 break;
138 case (uint32_t)GPIOC:
139 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
140 break;
141 default:
142 PIOS_Assert(0);
143 break;
145 GPIO_Init(chan->pin.gpio, &chan->pin.init);
147 if (chan->remap) {
148 GPIO_PinRemapConfig(chan->remap, ENABLE);
152 *tim_id = (uint32_t)tim_dev;
154 return 0;
156 out_fail:
157 return -1;
160 static void PIOS_TIM_generic_irq_handler(TIM_TypeDef *timer)
162 /* Check for an overflow event on this timer */
163 bool overflow_event = 0;
164 uint16_t overflow_count = false;
166 if (TIM_GetITStatus(timer, TIM_IT_Update) == SET) {
167 TIM_ClearITPendingBit(timer, TIM_IT_Update);
168 overflow_count = timer->ARR;
169 overflow_event = true;
172 /* Iterate over all registered clients of the TIM layer to find channels on this timer */
173 for (uint8_t i = 0; i < pios_tim_num_devs; i++) {
174 const struct pios_tim_dev *tim_dev = &pios_tim_devs[i];
176 if (!tim_dev->channels || tim_dev->num_channels == 0) {
177 /* No channels to process on this client */
178 continue;
181 for (uint8_t j = 0; j < tim_dev->num_channels; j++) {
182 const struct pios_tim_channel *chan = &tim_dev->channels[j];
184 if (chan->timer != timer) {
185 /* channel is not on this timer */
186 continue;
189 /* Figure out which interrupt bit we should be looking at */
190 uint16_t timer_it;
191 switch (chan->timer_chan) {
192 case TIM_Channel_1:
193 timer_it = TIM_IT_CC1;
194 break;
195 case TIM_Channel_2:
196 timer_it = TIM_IT_CC2;
197 break;
198 case TIM_Channel_3:
199 timer_it = TIM_IT_CC3;
200 break;
201 case TIM_Channel_4:
202 timer_it = TIM_IT_CC4;
203 break;
204 default:
205 PIOS_Assert(0);
206 break;
209 bool edge_event;
210 uint16_t edge_count;
211 if (TIM_GetITStatus(chan->timer, timer_it) == SET) {
212 TIM_ClearITPendingBit(chan->timer, timer_it);
214 /* Read the current counter */
215 switch (chan->timer_chan) {
216 case TIM_Channel_1:
217 edge_count = TIM_GetCapture1(chan->timer);
218 break;
219 case TIM_Channel_2:
220 edge_count = TIM_GetCapture2(chan->timer);
221 break;
222 case TIM_Channel_3:
223 edge_count = TIM_GetCapture3(chan->timer);
224 break;
225 case TIM_Channel_4:
226 edge_count = TIM_GetCapture4(chan->timer);
227 break;
228 default:
229 PIOS_Assert(0);
230 break;
232 edge_event = true;
233 } else {
234 edge_event = false;
235 edge_count = 0;
238 if (!tim_dev->callbacks) {
239 /* No callbacks registered, we're done with this channel */
240 continue;
243 /* Generate the appropriate callbacks */
244 if (overflow_event & edge_event) {
246 * When both edge and overflow happen in the same interrupt, we
247 * need a heuristic to determine the order of the edge and overflow
248 * events so that the callbacks happen in the right order. If we
249 * get the order wrong, our pulse width calculations could be off by up
250 * to ARR ticks. That could be bad.
252 * Heuristic: If the edge_count is < 32 ticks above zero then we assume the
253 * edge happened just after the overflow.
256 if (edge_count < 32) {
257 /* Call the overflow callback first */
258 if (tim_dev->callbacks->overflow) {
259 (*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
260 tim_dev->context,
262 overflow_count);
264 /* Call the edge callback second */
265 if (tim_dev->callbacks->edge) {
266 (*tim_dev->callbacks->edge)((uint32_t)tim_dev,
267 tim_dev->context,
269 edge_count);
271 } else {
272 /* Call the edge callback first */
273 if (tim_dev->callbacks->edge) {
274 (*tim_dev->callbacks->edge)((uint32_t)tim_dev,
275 tim_dev->context,
277 edge_count);
279 /* Call the overflow callback second */
280 if (tim_dev->callbacks->overflow) {
281 (*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
282 tim_dev->context,
284 overflow_count);
287 } else if (overflow_event && tim_dev->callbacks->overflow) {
288 (*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
289 tim_dev->context,
291 overflow_count);
292 } else if (edge_event && tim_dev->callbacks->edge) {
293 (*tim_dev->callbacks->edge)((uint32_t)tim_dev,
294 tim_dev->context,
296 edge_count);
302 /* Bind Interrupt Handlers
304 * Map all valid TIM IRQs to the common interrupt handler
305 * and give it enough context to properly demux the various timers
307 void TIM1_UP_IRQHandler(void) __attribute__((alias("PIOS_TIM_1_UP_irq_handler")));
308 static void PIOS_TIM_1_UP_irq_handler(void)
310 PIOS_TIM_generic_irq_handler(TIM1);
313 void TIM1_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_1_CC_irq_handler")));
314 static void PIOS_TIM_1_CC_irq_handler(void)
316 PIOS_TIM_generic_irq_handler(TIM1);
319 void TIM2_IRQHandler(void) __attribute__((alias("PIOS_TIM_2_irq_handler")));
320 static void PIOS_TIM_2_irq_handler(void)
322 PIOS_TIM_generic_irq_handler(TIM2);
325 void TIM3_IRQHandler(void) __attribute__((alias("PIOS_TIM_3_irq_handler")));
326 static void PIOS_TIM_3_irq_handler(void)
328 PIOS_TIM_generic_irq_handler(TIM3);
331 void TIM4_IRQHandler(void) __attribute__((alias("PIOS_TIM_4_irq_handler")));
332 static void PIOS_TIM_4_irq_handler(void)
334 PIOS_TIM_generic_irq_handler(TIM4);
337 void TIM5_IRQHandler(void) __attribute__((alias("PIOS_TIM_5_irq_handler")));
338 static void PIOS_TIM_5_irq_handler(void)
340 PIOS_TIM_generic_irq_handler(TIM5);
343 void TIM6_IRQHandler(void) __attribute__((alias("PIOS_TIM_6_irq_handler")));
344 static void PIOS_TIM_6_irq_handler(void)
346 PIOS_TIM_generic_irq_handler(TIM6);
349 void TIM7_IRQHandler(void) __attribute__((alias("PIOS_TIM_7_irq_handler")));
350 static void PIOS_TIM_7_irq_handler(void)
352 PIOS_TIM_generic_irq_handler(TIM7);
355 void TIM8_UP_IRQHandler(void) __attribute__((alias("PIOS_TIM_8_UP_irq_handler")));
356 static void PIOS_TIM_8_UP_irq_handler(void)
358 PIOS_TIM_generic_irq_handler(TIM8);
361 void TIM8_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_8_CC_irq_handler")));
362 static void PIOS_TIM_8_CC_irq_handler(void)
364 PIOS_TIM_generic_irq_handler(TIM8);
367 #endif /* PIOS_INCLUDE_TIM */