PageRenderTime 135ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 0ms

/flight/pios/stm32f10x/pios_tim.c

https://bitbucket.org/qbingx/librepilot
C | 374 lines | 284 code | 54 blank | 36 comment | 39 complexity | c25bfbd1b6cbc8887be1c7f5523e4485 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, GPL-3.0
  1. #include "pios.h"
  2. #ifdef PIOS_INCLUDE_TIM
  3. #include "pios_tim_priv.h"
  4. enum pios_tim_dev_magic {
  5. PIOS_TIM_DEV_MAGIC = 0x87654098,
  6. };
  7. struct pios_tim_dev {
  8. enum pios_tim_dev_magic magic;
  9. const struct pios_tim_channel *channels;
  10. uint8_t num_channels;
  11. const struct pios_tim_callbacks *callbacks;
  12. uint32_t context;
  13. };
  14. #if 0
  15. static bool PIOS_TIM_validate(struct pios_tim_dev *tim_dev)
  16. {
  17. return tim_dev->magic == PIOS_TIM_DEV_MAGIC;
  18. }
  19. #endif
  20. #if defined(PIOS_INCLUDE_FREERTOS) && 0
  21. static struct pios_tim_dev *PIOS_TIM_alloc(void)
  22. {
  23. struct pios_tim_dev *tim_dev;
  24. tim_dev = (struct pios_tim_dev *)pios_malloc(sizeof(*tim_dev));
  25. if (!tim_dev) {
  26. return NULL;
  27. }
  28. tim_dev->magic = PIOS_TIM_DEV_MAGIC;
  29. return tim_dev;
  30. }
  31. #else
  32. static struct pios_tim_dev pios_tim_devs[PIOS_TIM_MAX_DEVS];
  33. static uint8_t pios_tim_num_devs;
  34. static struct pios_tim_dev *PIOS_TIM_alloc(void)
  35. {
  36. struct pios_tim_dev *tim_dev;
  37. if (pios_tim_num_devs >= PIOS_TIM_MAX_DEVS) {
  38. return NULL;
  39. }
  40. tim_dev = &pios_tim_devs[pios_tim_num_devs++];
  41. tim_dev->magic = PIOS_TIM_DEV_MAGIC;
  42. return tim_dev;
  43. }
  44. #endif /* if defined(PIOS_INCLUDE_FREERTOS) && 0 */
  45. int32_t PIOS_TIM_InitClock(const struct pios_tim_clock_cfg *cfg)
  46. {
  47. PIOS_DEBUG_Assert(cfg);
  48. /* Enable appropriate clock to timer module */
  49. switch ((uint32_t)cfg->timer) {
  50. case (uint32_t)TIM1:
  51. RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  52. break;
  53. case (uint32_t)TIM2:
  54. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  55. break;
  56. case (uint32_t)TIM3:
  57. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  58. break;
  59. case (uint32_t)TIM4:
  60. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
  61. break;
  62. #ifdef STM32F10X_HD
  63. case (uint32_t)TIM5:
  64. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
  65. break;
  66. case (uint32_t)TIM6:
  67. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
  68. break;
  69. case (uint32_t)TIM7:
  70. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);
  71. break;
  72. case (uint32_t)TIM8:
  73. RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
  74. break;
  75. #endif
  76. }
  77. /* Configure the dividers for this timer */
  78. TIM_TimeBaseInit(cfg->timer, cfg->time_base_init);
  79. /* Configure internal timer clocks */
  80. TIM_InternalClockConfig(cfg->timer);
  81. /* Enable timers */
  82. TIM_Cmd(cfg->timer, ENABLE);
  83. /* Enable Interrupts */
  84. NVIC_Init(&cfg->irq.init);
  85. /* Advanced TIM1 has additional IRQ */
  86. if (cfg->timer == TIM1) {
  87. NVIC_InitTypeDef init = cfg->irq.init;
  88. init.NVIC_IRQChannel = TIM1_UP_IRQn;
  89. NVIC_Init(&init);
  90. }
  91. return 0;
  92. }
  93. 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)
  94. {
  95. PIOS_Assert(channels);
  96. PIOS_Assert(num_channels);
  97. struct pios_tim_dev *tim_dev;
  98. tim_dev = (struct pios_tim_dev *)PIOS_TIM_alloc();
  99. if (!tim_dev) {
  100. goto out_fail;
  101. }
  102. /* Bind the configuration to the device instance */
  103. tim_dev->channels = channels;
  104. tim_dev->num_channels = num_channels;
  105. tim_dev->callbacks = callbacks;
  106. tim_dev->context = context;
  107. /* Configure the pins */
  108. for (uint8_t i = 0; i < num_channels; i++) {
  109. const struct pios_tim_channel *chan = &(channels[i]);
  110. /* Enable the peripheral clock for the GPIO */
  111. switch ((uint32_t)chan->pin.gpio) {
  112. case (uint32_t)GPIOA:
  113. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  114. break;
  115. case (uint32_t)GPIOB:
  116. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  117. break;
  118. case (uint32_t)GPIOC:
  119. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  120. break;
  121. default:
  122. PIOS_Assert(0);
  123. break;
  124. }
  125. GPIO_Init(chan->pin.gpio, &chan->pin.init);
  126. if (chan->remap) {
  127. GPIO_PinRemapConfig(chan->remap, ENABLE);
  128. }
  129. }
  130. *tim_id = (uint32_t)tim_dev;
  131. return 0;
  132. out_fail:
  133. return -1;
  134. }
  135. static void PIOS_TIM_generic_irq_handler(TIM_TypeDef *timer)
  136. {
  137. /* Check for an overflow event on this timer */
  138. bool overflow_event = 0;
  139. uint16_t overflow_count = false;
  140. if (TIM_GetITStatus(timer, TIM_IT_Update) == SET) {
  141. TIM_ClearITPendingBit(timer, TIM_IT_Update);
  142. overflow_count = timer->ARR;
  143. overflow_event = true;
  144. }
  145. /* Iterate over all registered clients of the TIM layer to find channels on this timer */
  146. for (uint8_t i = 0; i < pios_tim_num_devs; i++) {
  147. const struct pios_tim_dev *tim_dev = &pios_tim_devs[i];
  148. if (!tim_dev->channels || tim_dev->num_channels == 0) {
  149. /* No channels to process on this client */
  150. continue;
  151. }
  152. for (uint8_t j = 0; j < tim_dev->num_channels; j++) {
  153. const struct pios_tim_channel *chan = &tim_dev->channels[j];
  154. if (chan->timer != timer) {
  155. /* channel is not on this timer */
  156. continue;
  157. }
  158. /* Figure out which interrupt bit we should be looking at */
  159. uint16_t timer_it;
  160. switch (chan->timer_chan) {
  161. case TIM_Channel_1:
  162. timer_it = TIM_IT_CC1;
  163. break;
  164. case TIM_Channel_2:
  165. timer_it = TIM_IT_CC2;
  166. break;
  167. case TIM_Channel_3:
  168. timer_it = TIM_IT_CC3;
  169. break;
  170. case TIM_Channel_4:
  171. timer_it = TIM_IT_CC4;
  172. break;
  173. default:
  174. PIOS_Assert(0);
  175. break;
  176. }
  177. bool edge_event;
  178. uint16_t edge_count;
  179. if (TIM_GetITStatus(chan->timer, timer_it) == SET) {
  180. TIM_ClearITPendingBit(chan->timer, timer_it);
  181. /* Read the current counter */
  182. switch (chan->timer_chan) {
  183. case TIM_Channel_1:
  184. edge_count = TIM_GetCapture1(chan->timer);
  185. break;
  186. case TIM_Channel_2:
  187. edge_count = TIM_GetCapture2(chan->timer);
  188. break;
  189. case TIM_Channel_3:
  190. edge_count = TIM_GetCapture3(chan->timer);
  191. break;
  192. case TIM_Channel_4:
  193. edge_count = TIM_GetCapture4(chan->timer);
  194. break;
  195. default:
  196. PIOS_Assert(0);
  197. break;
  198. }
  199. edge_event = true;
  200. } else {
  201. edge_event = false;
  202. edge_count = 0;
  203. }
  204. if (!tim_dev->callbacks) {
  205. /* No callbacks registered, we're done with this channel */
  206. continue;
  207. }
  208. /* Generate the appropriate callbacks */
  209. if (overflow_event & edge_event) {
  210. /*
  211. * When both edge and overflow happen in the same interrupt, we
  212. * need a heuristic to determine the order of the edge and overflow
  213. * events so that the callbacks happen in the right order. If we
  214. * get the order wrong, our pulse width calculations could be off by up
  215. * to ARR ticks. That could be bad.
  216. *
  217. * Heuristic: If the edge_count is < 32 ticks above zero then we assume the
  218. * edge happened just after the overflow.
  219. */
  220. if (edge_count < 32) {
  221. /* Call the overflow callback first */
  222. if (tim_dev->callbacks->overflow) {
  223. (*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
  224. tim_dev->context,
  225. j,
  226. overflow_count);
  227. }
  228. /* Call the edge callback second */
  229. if (tim_dev->callbacks->edge) {
  230. (*tim_dev->callbacks->edge)((uint32_t)tim_dev,
  231. tim_dev->context,
  232. j,
  233. edge_count);
  234. }
  235. } else {
  236. /* Call the edge callback first */
  237. if (tim_dev->callbacks->edge) {
  238. (*tim_dev->callbacks->edge)((uint32_t)tim_dev,
  239. tim_dev->context,
  240. j,
  241. edge_count);
  242. }
  243. /* Call the overflow callback second */
  244. if (tim_dev->callbacks->overflow) {
  245. (*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
  246. tim_dev->context,
  247. j,
  248. overflow_count);
  249. }
  250. }
  251. } else if (overflow_event && tim_dev->callbacks->overflow) {
  252. (*tim_dev->callbacks->overflow)((uint32_t)tim_dev,
  253. tim_dev->context,
  254. j,
  255. overflow_count);
  256. } else if (edge_event && tim_dev->callbacks->edge) {
  257. (*tim_dev->callbacks->edge)((uint32_t)tim_dev,
  258. tim_dev->context,
  259. j,
  260. edge_count);
  261. }
  262. }
  263. }
  264. }
  265. /* Bind Interrupt Handlers
  266. *
  267. * Map all valid TIM IRQs to the common interrupt handler
  268. * and give it enough context to properly demux the various timers
  269. */
  270. void TIM1_UP_IRQHandler(void) __attribute__((alias("PIOS_TIM_1_UP_irq_handler")));
  271. static void PIOS_TIM_1_UP_irq_handler(void)
  272. {
  273. PIOS_TIM_generic_irq_handler(TIM1);
  274. }
  275. void TIM1_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_1_CC_irq_handler")));
  276. static void PIOS_TIM_1_CC_irq_handler(void)
  277. {
  278. PIOS_TIM_generic_irq_handler(TIM1);
  279. }
  280. void TIM2_IRQHandler(void) __attribute__((alias("PIOS_TIM_2_irq_handler")));
  281. static void PIOS_TIM_2_irq_handler(void)
  282. {
  283. PIOS_TIM_generic_irq_handler(TIM2);
  284. }
  285. void TIM3_IRQHandler(void) __attribute__((alias("PIOS_TIM_3_irq_handler")));
  286. static void PIOS_TIM_3_irq_handler(void)
  287. {
  288. PIOS_TIM_generic_irq_handler(TIM3);
  289. }
  290. void TIM4_IRQHandler(void) __attribute__((alias("PIOS_TIM_4_irq_handler")));
  291. static void PIOS_TIM_4_irq_handler(void)
  292. {
  293. PIOS_TIM_generic_irq_handler(TIM4);
  294. }
  295. void TIM5_IRQHandler(void) __attribute__((alias("PIOS_TIM_5_irq_handler")));
  296. static void PIOS_TIM_5_irq_handler(void)
  297. {
  298. PIOS_TIM_generic_irq_handler(TIM5);
  299. }
  300. void TIM6_IRQHandler(void) __attribute__((alias("PIOS_TIM_6_irq_handler")));
  301. static void PIOS_TIM_6_irq_handler(void)
  302. {
  303. PIOS_TIM_generic_irq_handler(TIM6);
  304. }
  305. void TIM7_IRQHandler(void) __attribute__((alias("PIOS_TIM_7_irq_handler")));
  306. static void PIOS_TIM_7_irq_handler(void)
  307. {
  308. PIOS_TIM_generic_irq_handler(TIM7);
  309. }
  310. void TIM8_UP_IRQHandler(void) __attribute__((alias("PIOS_TIM_8_UP_irq_handler")));
  311. static void PIOS_TIM_8_UP_irq_handler(void)
  312. {
  313. PIOS_TIM_generic_irq_handler(TIM8);
  314. }
  315. void TIM8_CC_IRQHandler(void) __attribute__((alias("PIOS_TIM_8_CC_irq_handler")));
  316. static void PIOS_TIM_8_CC_irq_handler(void)
  317. {
  318. PIOS_TIM_generic_irq_handler(TIM8);
  319. }
  320. #endif /* PIOS_INCLUDE_TIM */