lp_ticker.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /* mbed Microcontroller Library
  2. *******************************************************************************
  3. * Copyright (c) 2018, STMicroelectronics
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. * 3. Neither the name of STMicroelectronics nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  27. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *******************************************************************************
  29. */
  30. #if DEVICE_LPTICKER
  31. /***********************************************************************/
  32. /* lpticker_lptim config is 1 in json config file */
  33. /* LPTICKER is based on LPTIM feature from ST drivers. RTC is not used */
  34. #if MBED_CONF_TARGET_LPTICKER_LPTIM
  35. #include "lp_ticker_api.h"
  36. #include "mbed_error.h"
  37. LPTIM_HandleTypeDef LptimHandle;
  38. const ticker_info_t *lp_ticker_get_info()
  39. {
  40. static const ticker_info_t info = {
  41. #if MBED_CONF_TARGET_LSE_AVAILABLE
  42. LSE_VALUE,
  43. #else
  44. LSI_VALUE,
  45. #endif
  46. 16
  47. };
  48. return &info;
  49. }
  50. volatile uint8_t lp_Fired = 0;
  51. static void LPTIM1_IRQHandler(void);
  52. static void (*irq_handler)(void);
  53. void lp_ticker_init(void)
  54. {
  55. /* Check if LPTIM is already configured */
  56. if (__HAL_RCC_LPTIM1_IS_CLK_ENABLED()) {
  57. lp_ticker_disable_interrupt();
  58. return;
  59. }
  60. RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
  61. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  62. #if MBED_CONF_TARGET_LSE_AVAILABLE
  63. /* Enable LSE clock */
  64. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
  65. RCC_OscInitStruct.LSEState = RCC_LSE_ON;
  66. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  67. /* Select the LSE clock as LPTIM peripheral clock */
  68. RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
  69. #if (TARGET_STM32L0)
  70. RCC_PeriphCLKInitStruct.LptimClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
  71. #else
  72. RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
  73. #endif
  74. #else /* MBED_CONF_TARGET_LSE_AVAILABLE */
  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. /* Select the LSI clock as LPTIM peripheral clock */
  80. RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
  81. #if (TARGET_STM32L0)
  82. RCC_PeriphCLKInitStruct.LptimClockSelection = RCC_LPTIM1CLKSOURCE_LSI;
  83. #else
  84. RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSI;
  85. #endif
  86. #endif /* MBED_CONF_TARGET_LSE_AVAILABLE */
  87. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
  88. error("HAL_RCC_OscConfig ERROR\n");
  89. return;
  90. }
  91. if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct) != HAL_OK) {
  92. error("HAL_RCCEx_PeriphCLKConfig ERROR\n");
  93. return;
  94. }
  95. __HAL_RCC_LPTIM1_CLK_ENABLE();
  96. __HAL_RCC_LPTIM1_FORCE_RESET();
  97. __HAL_RCC_LPTIM1_RELEASE_RESET();
  98. /* Initialize the LPTIM peripheral */
  99. LptimHandle.Instance = LPTIM1;
  100. LptimHandle.State = HAL_LPTIM_STATE_RESET;
  101. LptimHandle.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
  102. LptimHandle.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV1;
  103. LptimHandle.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
  104. LptimHandle.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
  105. LptimHandle.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
  106. LptimHandle.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;
  107. #if (TARGET_STM32L4)
  108. LptimHandle.Init.Input1Source = LPTIM_INPUT1SOURCE_GPIO;
  109. LptimHandle.Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO;
  110. #endif /* TARGET_STM32L4 */
  111. if (HAL_LPTIM_Init(&LptimHandle) != HAL_OK) {
  112. error("HAL_LPTIM_Init ERROR\n");
  113. return;
  114. }
  115. NVIC_SetVector(LPTIM1_IRQn, (uint32_t)LPTIM1_IRQHandler);
  116. #if !(TARGET_STM32L4)
  117. /* EXTI lines are not configured by default */
  118. __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_IT();
  119. __HAL_LPTIM_WAKEUPTIMER_EXTI_ENABLE_RISING_EDGE();
  120. #endif
  121. __HAL_LPTIM_ENABLE_IT(&LptimHandle, LPTIM_IT_CMPM);
  122. HAL_LPTIM_Counter_Start(&LptimHandle, 0xFFFF);
  123. /* Need to write a compare value in order to get LPTIM_FLAG_CMPOK in set_interrupt */
  124. __HAL_LPTIM_COMPARE_SET(&LptimHandle, 0);
  125. }
  126. static void LPTIM1_IRQHandler(void)
  127. {
  128. LptimHandle.Instance = LPTIM1;
  129. if (lp_Fired) {
  130. lp_Fired = 0;
  131. if (irq_handler) {
  132. irq_handler();
  133. }
  134. }
  135. /* Compare match interrupt */
  136. if (__HAL_LPTIM_GET_FLAG(&LptimHandle, LPTIM_FLAG_CMPM) != RESET) {
  137. if (__HAL_LPTIM_GET_IT_SOURCE(&LptimHandle, LPTIM_IT_CMPM) != RESET) {
  138. /* Clear Compare match flag */
  139. __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPM);
  140. if (irq_handler) {
  141. irq_handler();
  142. }
  143. }
  144. }
  145. #if !(TARGET_STM32L4)
  146. __HAL_LPTIM_WAKEUPTIMER_EXTI_CLEAR_FLAG();
  147. #endif
  148. }
  149. uint32_t lp_ticker_read(void)
  150. {
  151. uint32_t lp_time = LPTIM1->CNT;
  152. /* Reading the LPTIM_CNT register may return unreliable values.
  153. It is necessary to perform two consecutive read accesses and verify that the two returned values are identical */
  154. while (lp_time != LPTIM1->CNT) {
  155. lp_time = LPTIM1->CNT;
  156. }
  157. return lp_time;
  158. }
  159. void lp_ticker_set_interrupt(timestamp_t timestamp)
  160. {
  161. LptimHandle.Instance = LPTIM1;
  162. irq_handler = (void (*)(void))lp_ticker_irq_handler;
  163. /* CMPOK is set by hardware to inform application that the APB bus write operation to the LPTIM_CMP register has been successfully completed */
  164. /* Any successive write before the CMPOK flag be set, will lead to unpredictable results */
  165. while (__HAL_LPTIM_GET_FLAG(&LptimHandle, LPTIM_FLAG_CMPOK) == RESET) {
  166. }
  167. __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPOK);
  168. __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPM);
  169. __HAL_LPTIM_COMPARE_SET(&LptimHandle, timestamp);
  170. NVIC_EnableIRQ(LPTIM1_IRQn);
  171. }
  172. void lp_ticker_fire_interrupt(void)
  173. {
  174. lp_Fired = 1;
  175. NVIC_SetPendingIRQ(LPTIM1_IRQn);
  176. NVIC_EnableIRQ(LPTIM1_IRQn);
  177. }
  178. void lp_ticker_disable_interrupt(void)
  179. {
  180. NVIC_DisableIRQ(LPTIM1_IRQn);
  181. LptimHandle.Instance = LPTIM1;
  182. /* Waiting last write operation completion */
  183. while (__HAL_LPTIM_GET_FLAG(&LptimHandle, LPTIM_FLAG_CMPOK) == RESET) {
  184. }
  185. }
  186. void lp_ticker_clear_interrupt(void)
  187. {
  188. LptimHandle.Instance = LPTIM1;
  189. __HAL_LPTIM_CLEAR_FLAG(&LptimHandle, LPTIM_FLAG_CMPM);
  190. NVIC_ClearPendingIRQ(LPTIM1_IRQn);
  191. }
  192. /*****************************************************************/
  193. /* lpticker_lptim config is 0 or not defined in json config file */
  194. /* LPTICKER is based on RTC wake up feature from ST drivers */
  195. #else /* MBED_CONF_TARGET_LPTICKER_LPTIM */
  196. #include "rtc_api_hal.h"
  197. const ticker_info_t *lp_ticker_get_info()
  198. {
  199. static const ticker_info_t info = {
  200. RTC_CLOCK / 4, // RTC_WAKEUPCLOCK_RTCCLK_DIV4
  201. 32
  202. };
  203. return &info;
  204. }
  205. void lp_ticker_init(void)
  206. {
  207. rtc_init();
  208. lp_ticker_disable_interrupt();
  209. }
  210. uint32_t lp_ticker_read(void)
  211. {
  212. return rtc_read_lp();
  213. }
  214. void lp_ticker_set_interrupt(timestamp_t timestamp)
  215. {
  216. lp_ticker_disable_interrupt();
  217. rtc_set_wake_up_timer(timestamp);
  218. }
  219. void lp_ticker_fire_interrupt(void)
  220. {
  221. rtc_fire_interrupt();
  222. }
  223. void lp_ticker_disable_interrupt(void)
  224. {
  225. rtc_deactivate_wake_up_timer();
  226. }
  227. void lp_ticker_clear_interrupt(void)
  228. {
  229. NVIC_DisableIRQ(RTC_WKUP_IRQn);
  230. }
  231. #endif /* MBED_CONF_TARGET_LPTICKER_LPTIM */
  232. #endif /* DEVICE_LPTICKER */