us_ticker.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. /* mbed Microcontroller Library
  2. * Copyright (c) 2006-2018 ARM Limited
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <stddef.h>
  17. #include "us_ticker_api.h"
  18. #include "PeripheralNames.h"
  19. #include "us_ticker_data.h"
  20. TIM_HandleTypeDef TimMasterHandle;
  21. uint32_t timer_cnt_reg;
  22. uint32_t timer_ccr1_reg;
  23. uint32_t timer_dier_reg;
  24. const ticker_info_t *us_ticker_get_info()
  25. {
  26. static const ticker_info_t info = {
  27. 1000000,
  28. TIM_MST_BIT_WIDTH
  29. };
  30. return &info;
  31. }
  32. void us_ticker_irq_handler(void);
  33. // ************************************ 16-bit timer ************************************
  34. #if TIM_MST_BIT_WIDTH == 16
  35. extern uint32_t prev_time;
  36. extern uint32_t elapsed_time;
  37. #if defined(TARGET_STM32F0)
  38. void timer_update_irq_handler(void)
  39. {
  40. #else
  41. void timer_irq_handler(void)
  42. {
  43. #endif
  44. TimMasterHandle.Instance = TIM_MST;
  45. #if defined(TARGET_STM32F0)
  46. } // end timer_update_irq_handler function
  47. void timer_oc_irq_handler(void)
  48. {
  49. TimMasterHandle.Instance = TIM_MST;
  50. #endif
  51. if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET) {
  52. if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_CC1) == SET) {
  53. __HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC1);
  54. us_ticker_irq_handler();
  55. }
  56. }
  57. }
  58. void init_16bit_timer(void)
  59. {
  60. // Enable timer clock
  61. TIM_MST_RCC;
  62. // Reset timer
  63. TIM_MST_RESET_ON;
  64. TIM_MST_RESET_OFF;
  65. // Update the SystemCoreClock variable
  66. SystemCoreClockUpdate();
  67. // Configure time base
  68. TimMasterHandle.Instance = TIM_MST;
  69. TimMasterHandle.Init.Period = 0xFFFF;
  70. TimMasterHandle.Init.Prescaler = (uint32_t)(SystemCoreClock / 1000000) - 1; // 1 us tick
  71. TimMasterHandle.Init.ClockDivision = 0;
  72. TimMasterHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
  73. #if !defined(TARGET_STM32L0) && !defined(TARGET_STM32L1)
  74. TimMasterHandle.Init.RepetitionCounter = 0;
  75. #endif
  76. #ifdef TIM_AUTORELOAD_PRELOAD_DISABLE
  77. TimMasterHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  78. #endif
  79. HAL_TIM_Base_Init(&TimMasterHandle);
  80. // Configure output compare channel 1 for mbed timeout (enabled later when used)
  81. HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_1);
  82. // Output compare channel 1 interrupt for mbed timeout
  83. #if defined(TARGET_STM32F0)
  84. NVIC_SetVector(TIM_MST_UP_IRQ, (uint32_t)timer_update_irq_handler);
  85. NVIC_EnableIRQ(TIM_MST_UP_IRQ);
  86. NVIC_SetPriority(TIM_MST_UP_IRQ, 0);
  87. NVIC_SetVector(TIM_MST_OC_IRQ, (uint32_t)timer_oc_irq_handler);
  88. NVIC_EnableIRQ(TIM_MST_OC_IRQ);
  89. NVIC_SetPriority(TIM_MST_OC_IRQ, 1);
  90. #else
  91. NVIC_SetVector(TIM_MST_IRQ, (uint32_t)timer_irq_handler);
  92. NVIC_EnableIRQ(TIM_MST_IRQ);
  93. #endif
  94. // Enable timer
  95. HAL_TIM_Base_Start(&TimMasterHandle);
  96. // Freeze timer on stop/breakpoint
  97. // Define the FREEZE_TIMER_ON_DEBUG macro in mbed_app.json for example
  98. #if !defined(NDEBUG) && defined(FREEZE_TIMER_ON_DEBUG) && defined(TIM_MST_DBGMCU_FREEZE)
  99. TIM_MST_DBGMCU_FREEZE;
  100. #endif
  101. __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1);
  102. // Used by HAL_GetTick()
  103. prev_time = 0;
  104. elapsed_time = 0;
  105. }
  106. // ************************************ 32-bit timer ************************************
  107. #else
  108. void timer_irq_handler(void)
  109. {
  110. TimMasterHandle.Instance = TIM_MST;
  111. if (__HAL_TIM_GET_FLAG(&TimMasterHandle, TIM_FLAG_CC1) == SET) {
  112. if (__HAL_TIM_GET_IT_SOURCE(&TimMasterHandle, TIM_IT_CC1) == SET) {
  113. __HAL_TIM_CLEAR_IT(&TimMasterHandle, TIM_IT_CC1);
  114. us_ticker_irq_handler();
  115. }
  116. }
  117. }
  118. void init_32bit_timer(void)
  119. {
  120. RCC_ClkInitTypeDef RCC_ClkInitStruct;
  121. uint32_t PclkFreq;
  122. // Get clock configuration
  123. // Note: PclkFreq contains here the Latency (not used after)
  124. HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &PclkFreq);
  125. // Get timer clock value
  126. #if TIM_MST_PCLK == 1
  127. PclkFreq = HAL_RCC_GetPCLK1Freq();
  128. #else
  129. PclkFreq = HAL_RCC_GetPCLK2Freq();
  130. #endif
  131. // Enable timer clock
  132. TIM_MST_RCC;
  133. // Reset timer
  134. TIM_MST_RESET_ON;
  135. TIM_MST_RESET_OFF;
  136. // Configure time base
  137. TimMasterHandle.Instance = TIM_MST;
  138. TimMasterHandle.Init.Period = 0xFFFFFFFF;
  139. // TIMxCLK = PCLKx when the APB prescaler = 1 else TIMxCLK = 2 * PCLKx
  140. #if TIM_MST_PCLK == 1
  141. if (RCC_ClkInitStruct.APB1CLKDivider == RCC_HCLK_DIV1) {
  142. #else
  143. if (RCC_ClkInitStruct.APB2CLKDivider == RCC_HCLK_DIV1) {
  144. #endif
  145. TimMasterHandle.Init.Prescaler = (uint16_t)((PclkFreq) / 1000000) - 1; // 1 us tick
  146. } else {
  147. TimMasterHandle.Init.Prescaler = (uint16_t)((PclkFreq * 2) / 1000000) - 1; // 1 us tick
  148. }
  149. TimMasterHandle.Init.ClockDivision = 0;
  150. TimMasterHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
  151. #if !TARGET_STM32L1
  152. TimMasterHandle.Init.RepetitionCounter = 0;
  153. #endif
  154. #ifdef TIM_AUTORELOAD_PRELOAD_DISABLE
  155. TimMasterHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  156. #endif
  157. HAL_TIM_OC_Init(&TimMasterHandle);
  158. NVIC_SetVector(TIM_MST_IRQ, (uint32_t)timer_irq_handler);
  159. NVIC_EnableIRQ(TIM_MST_IRQ);
  160. // Channel 1 for mbed timeout
  161. HAL_TIM_OC_Start(&TimMasterHandle, TIM_CHANNEL_1);
  162. // Freeze timer on stop/breakpoint
  163. // Define the FREEZE_TIMER_ON_DEBUG macro in mbed_app.json for example
  164. #if !defined(NDEBUG) && defined(FREEZE_TIMER_ON_DEBUG) && defined(TIM_MST_DBGMCU_FREEZE)
  165. TIM_MST_DBGMCU_FREEZE;
  166. #endif
  167. __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1);
  168. }
  169. #endif // 16-bit/32-bit timer
  170. void us_ticker_init(void)
  171. {
  172. // Timer is already initialized in HAL_InitTick()
  173. __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1);
  174. }
  175. uint32_t us_ticker_read()
  176. {
  177. return TIM_MST->CNT;
  178. }
  179. void us_ticker_set_interrupt(timestamp_t timestamp)
  180. {
  181. // NOTE: This function must be called with interrupts disabled to keep our
  182. // timer interrupt setup atomic
  183. // Set new output compare value
  184. __HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1, (uint32_t)timestamp);
  185. // Ensure the compare event starts clear
  186. __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1);
  187. // Enable IT
  188. __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1);
  189. }
  190. void us_ticker_fire_interrupt(void)
  191. {
  192. __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1);
  193. LL_TIM_GenerateEvent_CC1(TimMasterHandle.Instance);
  194. __HAL_TIM_ENABLE_IT(&TimMasterHandle, TIM_IT_CC1);
  195. }
  196. void us_ticker_disable_interrupt(void)
  197. {
  198. __HAL_TIM_DISABLE_IT(&TimMasterHandle, TIM_IT_CC1);
  199. }
  200. /* NOTE: must be called with interrupts disabled! */
  201. void us_ticker_clear_interrupt(void)
  202. {
  203. __HAL_TIM_CLEAR_FLAG(&TimMasterHandle, TIM_FLAG_CC1);
  204. }
  205. void save_timer_ctx(void)
  206. {
  207. timer_cnt_reg = __HAL_TIM_GET_COUNTER(&TimMasterHandle);
  208. timer_ccr1_reg = __HAL_TIM_GET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1);
  209. timer_dier_reg = TIM_MST->DIER;
  210. }
  211. void restore_timer_ctx(void)
  212. {
  213. __HAL_TIM_SET_COUNTER(&TimMasterHandle, timer_cnt_reg);
  214. __HAL_TIM_SET_COMPARE(&TimMasterHandle, TIM_CHANNEL_1, timer_ccr1_reg);
  215. TIM_MST->DIER = timer_dier_reg;
  216. }