drv_lptim.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * Copyright (c) 2006-2024 RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-05-06 Zero-Free first version
  9. * 2024-07-04 wdfk-prog lptimer is register with hwtimer, only supports pm calls,the timer function is not supported
  10. */
  11. #include <board.h>
  12. #include <drv_lptim.h>
  13. #include <rtdevice.h>
  14. #include "drv_config.h"
  15. /*#define DRV_DEBUG*/
  16. #define LOG_TAG "drv.lptim"
  17. #include <drv_log.h>
  18. #ifdef BSP_USING_LPTIM
  19. #define LPTIM_REG_MAX_VALUE (0xFFFF)
  20. enum
  21. {
  22. #ifdef BSP_USING_LPTIM1
  23. LPTIM1_INDEX,
  24. #endif
  25. #ifdef BSP_USING_LPTIM2
  26. LPTIM2_INDEX,
  27. #endif
  28. #ifdef BSP_USING_LPTIM3
  29. LPTIM3_INDEX,
  30. #endif
  31. };
  32. struct stm32_hw_lptimer
  33. {
  34. rt_hwtimer_t time_device;
  35. LPTIM_HandleTypeDef tim_handle;
  36. IRQn_Type tim_irqn;
  37. char *name;
  38. };
  39. static struct stm32_hw_lptimer stm32_hw_lptimer_obj[] =
  40. {
  41. #ifdef BSP_USING_LPTIM1
  42. LPTIM1_CONFIG,
  43. #endif
  44. #ifdef BSP_USING_LPTIM2
  45. LPTIM2_CONFIG,
  46. #endif
  47. #ifdef BSP_USING_LPTIM3
  48. LPTIM3_CONFIG,
  49. #endif
  50. };
  51. static const struct rt_hwtimer_info _info = LPTIM_DEV_INFO_CONFIG;
  52. static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
  53. {
  54. if(timer == RT_NULL)
  55. {
  56. LOG_E("init timer is NULL");
  57. return;
  58. }
  59. if (state)
  60. {
  61. struct stm32_hw_lptimer *tim_device = rt_container_of(timer, struct stm32_hw_lptimer, time_device);
  62. LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data;
  63. if(tim_device == RT_NULL)
  64. {
  65. LOG_E("start tim_device is NULL");
  66. return;
  67. }
  68. if(tim == RT_NULL)
  69. {
  70. LOG_E("start %s LPTIM_Handle is NULL", tim_device->name);
  71. return;
  72. }
  73. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  74. RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
  75. /* Enable LSI clock */
  76. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
  77. RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  78. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  79. HAL_RCC_OscConfig(&RCC_OscInitStruct);
  80. /* Select the LSI clock as LPTIM peripheral clock */
  81. RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
  82. RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSI;
  83. HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);
  84. tim->Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
  85. tim->Init.Clock.Prescaler = LPTIM_PRESCALER_DIV32;
  86. tim->Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
  87. tim->Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
  88. tim->Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
  89. tim->Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;
  90. HAL_StatusTypeDef ret = HAL_LPTIM_Init(tim);
  91. if (ret != HAL_OK)
  92. {
  93. LOG_E("%s init failed %d", tim_device->name, ret);
  94. }
  95. else
  96. {
  97. NVIC_ClearPendingIRQ(LPTIM1_IRQn);
  98. NVIC_SetPriority(LPTIM1_IRQn, 0);
  99. NVIC_EnableIRQ(LPTIM1_IRQn);
  100. LOG_D("%s init success", tim_device->name);
  101. }
  102. }
  103. }
  104. static rt_err_t timer_start(rt_hwtimer_t *timer, rt_uint32_t t, rt_hwtimer_mode_t opmode)
  105. {
  106. if(timer == RT_NULL)
  107. {
  108. LOG_E("start timer is NULL");
  109. return -RT_EINVAL;
  110. }
  111. struct stm32_hw_lptimer *tim_device = rt_container_of(timer, struct stm32_hw_lptimer, time_device);
  112. LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data;
  113. if(tim_device == RT_NULL)
  114. {
  115. LOG_E("start tim_device is NULL");
  116. return -RT_EINVAL;
  117. }
  118. if(tim == RT_NULL)
  119. {
  120. LOG_E("start %s LPTIM_Handle is NULL", tim_device->name);
  121. return -RT_EINVAL;
  122. }
  123. HAL_StatusTypeDef ret = HAL_LPTIM_TimeOut_Start_IT(tim, LPTIM_REG_MAX_VALUE, t);
  124. if(ret != HAL_OK)
  125. {
  126. LOG_E("start %s failed %d", tim_device->name, ret);
  127. return -RT_ERROR;
  128. }
  129. else
  130. {
  131. LOG_D("start %s success", tim_device->name);
  132. return RT_EOK;
  133. }
  134. }
  135. static void timer_stop(rt_hwtimer_t *timer)
  136. {
  137. if(timer == RT_NULL)
  138. {
  139. LOG_E("stop timer is NULL");
  140. return;
  141. }
  142. struct stm32_hw_lptimer *tim_device = rt_container_of(timer, struct stm32_hw_lptimer, time_device);
  143. LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data;
  144. if(tim_device == RT_NULL)
  145. {
  146. LOG_E("stop tim_device is NULL");
  147. return;
  148. }
  149. if(tim == RT_NULL)
  150. {
  151. LOG_E("stop %s LPTIM_Handle is NULL", tim_device->name);
  152. return;
  153. }
  154. HAL_StatusTypeDef ret = HAL_LPTIM_TimeOut_Stop_IT(tim);
  155. if(ret != HAL_OK)
  156. {
  157. LOG_E("stop %s failed %d", tim_device->name, ret);
  158. }
  159. else
  160. {
  161. LOG_D("stop %s success", tim_device->name);
  162. }
  163. }
  164. static rt_uint32_t timer_get_freq(LPTIM_HandleTypeDef *tim)
  165. {
  166. /*No calculation is performed. The default initial configuration is 1000hz*/
  167. return 1000;
  168. }
  169. static rt_uint32_t timer_counter_get(rt_hwtimer_t *timer)
  170. {
  171. LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data;
  172. return HAL_LPTIM_ReadCounter(tim);
  173. }
  174. static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
  175. {
  176. if(timer == RT_NULL)
  177. {
  178. LOG_E("start timer is NULL");
  179. return -RT_EINVAL;
  180. }
  181. struct stm32_hw_lptimer *tim_device = rt_container_of(timer, struct stm32_hw_lptimer, time_device);
  182. LPTIM_HandleTypeDef *tim = (LPTIM_HandleTypeDef *)timer->parent.user_data;
  183. if(tim_device == RT_NULL)
  184. {
  185. LOG_E("start tim_device is NULL");
  186. return -RT_EINVAL;
  187. }
  188. if(tim == RT_NULL)
  189. {
  190. LOG_E("start %s LPTIM_Handle is NULL", tim_device->name);
  191. return -RT_EINVAL;
  192. }
  193. rt_err_t result = RT_EOK;
  194. switch (cmd)
  195. {
  196. case DRV_HW_LPTIMER_CTRL_GET_TICK_MAX:
  197. {
  198. *(rt_uint32_t *)arg = LPTIM_REG_MAX_VALUE;
  199. break;
  200. }
  201. case DRV_HW_LPTIMER_CTRL_GET_FREQ:
  202. {
  203. *(rt_uint32_t *)arg = timer_get_freq(tim);
  204. break;
  205. }
  206. case DRV_HW_LPTIMER_CTRL_START:
  207. {
  208. timer_start(timer, *(rt_uint32_t *)arg, HWTIMER_MODE_ONESHOT);
  209. break;
  210. }
  211. case DRV_HW_LPTIMER_CTRL_GET_COUNT:
  212. {
  213. *(rt_uint32_t *)arg = timer_counter_get(timer);
  214. break;
  215. }
  216. default:
  217. {
  218. result = -RT_ENOSYS;
  219. }
  220. break;
  221. }
  222. return result;
  223. }
  224. #ifdef BSP_USING_LPTIM1
  225. void LPTIM1_IRQHandler(void)
  226. {
  227. rt_interrupt_enter();
  228. HAL_LPTIM_IRQHandler(&stm32_hw_lptimer_obj[LPTIM1_INDEX].tim_handle);
  229. rt_interrupt_leave();
  230. }
  231. #endif
  232. #ifdef BSP_USING_LPTIM2
  233. void LPTIM2_IRQHandler(void)
  234. {
  235. rt_interrupt_enter();
  236. HAL_LPTIM_IRQHandler(&stm32_hw_lptimer_obj[LPTIM2_INDEX].tim_handle);
  237. rt_interrupt_leave();
  238. }
  239. #endif
  240. #ifdef BSP_USING_LPTIM3
  241. void LPTIM3_IRQHandler(void)
  242. {
  243. rt_interrupt_enter();
  244. HAL_LPTIM_IRQHandler(&stm32_hw_lptimer_obj[LPTIM3_INDEX].tim_handle);
  245. rt_interrupt_leave();
  246. }
  247. #endif
  248. static const struct rt_hwtimer_ops _ops =
  249. {
  250. .init = timer_init,
  251. .start = timer_start,
  252. .stop = timer_stop,
  253. .count_get = timer_counter_get,
  254. .control = timer_ctrl,
  255. };
  256. /**
  257. * This function initialize the lptim
  258. */
  259. static int stm32_hw_lptim_init(void)
  260. {
  261. int i = 0;
  262. int result = RT_EOK;
  263. for (i = 0; i < sizeof(stm32_hw_lptimer_obj) / sizeof(stm32_hw_lptimer_obj[0]); i++)
  264. {
  265. stm32_hw_lptimer_obj[i].time_device.info = &_info;
  266. stm32_hw_lptimer_obj[i].time_device.ops = &_ops;
  267. if (rt_device_hwtimer_register(&stm32_hw_lptimer_obj[i].time_device, stm32_hw_lptimer_obj[i].name, &stm32_hw_lptimer_obj[i].tim_handle) == RT_EOK)
  268. {
  269. LOG_D("%s register success", stm32_hw_lptimer_obj[i].name);
  270. }
  271. else
  272. {
  273. LOG_E("%s register failed", stm32_hw_lptimer_obj[i].name);
  274. result = -RT_ERROR;
  275. }
  276. }
  277. return result;
  278. }
  279. INIT_BOARD_EXPORT(stm32_hw_lptim_init);
  280. #endif /* BSP_USING_LPTIM */