pal_os.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /**
  2. * MIT License
  3. *
  4. * Copyright (c) 2018 Infineon Technologies AG
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in all
  14. * copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE
  23. *
  24. *
  25. * \file
  26. *
  27. * \brief This file implements the platform abstraction layer APIs for os event/scheduler.
  28. *
  29. * \addtogroup grPAL
  30. * @{
  31. */
  32. /**********************************************************************************************************************
  33. * HEADER FILES
  34. *********************************************************************************************************************/
  35. #include <stdbool.h>
  36. #include "stdlib.h"
  37. #include "stdio.h"
  38. #include "optiga/pal/pal_os_event.h"
  39. #include "nrf_rtc.h"
  40. #include "nrf_drv_rtc.h"
  41. #include "nrf_delay.h"
  42. #include "nrf_pwr_mgmt.h"
  43. /**********************************************************************************************************************
  44. * MACROS
  45. *********************************************************************************************************************/
  46. /*********************************************************************************************************************
  47. * LOCAL DATA
  48. *********************************************************************************************************************/
  49. /// @cond hidden
  50. /// Callback function when timer elapses
  51. static volatile register_callback callback_registered = NULL;
  52. /// Pointer to store upper layer callback context (For example: Ifx i2c context)
  53. static void * callback_ctx;
  54. /// Flag to indicate to the delay function when the timer has elapsed
  55. static volatile bool timer_elapsed = false;
  56. /// Flag to indicate if the the RTC was already initialized, re-init. causes an NRF_ERROR
  57. static bool m_rtc2_is_initialized = false;
  58. static const nrf_drv_rtc_t rtc2 = NRF_DRV_RTC_INSTANCE(2);
  59. static nrf_drv_rtc_config_t m_rtc2_config = NRF_DRV_RTC_DEFAULT_CONFIG;
  60. #define RTC_CLOCK_FREQUENCY 32768
  61. // Set the prescaler to approximately get 0.25 ms intervals
  62. // 32768Hz/8 = 4096 Hz -> 0.2441us
  63. // it's a 24bit counter, so it will overflow every ~68min
  64. #define RTC_PRESCALER 8
  65. #define RTC_TICK_FREQ (RTC_CLOCK_FREQUENCY/RTC_PRESCALER)
  66. /**
  67. * Timer callback handler.
  68. *
  69. * This get called from the TIMER elapse event.<br>
  70. * Once the timer expires, the registered callback funtion gets called from the timer event handler, if
  71. * the call back is not NULL.<br>
  72. *
  73. *\param[in] args Callback argument
  74. *
  75. */
  76. static void ifx_rtc_handler(nrf_drv_rtc_int_type_t int_type)
  77. {
  78. volatile register_callback callback;
  79. (void)nrf_drv_rtc_cc_disable(&rtc2, int_type);
  80. switch(int_type)
  81. {
  82. case NRF_DRV_RTC_INT_COMPARE0:
  83. // handler for register_callback_oneshot
  84. if (callback_registered != NULL)
  85. {
  86. callback = callback_registered;
  87. callback_registered = NULL;
  88. callback(callback_ctx);
  89. }
  90. break;
  91. case NRF_DRV_RTC_INT_COMPARE1:
  92. // handler for delay_in_milliseconds
  93. timer_elapsed = true;
  94. break;
  95. default:
  96. // Do nothing
  97. break;
  98. }
  99. }
  100. /// @endcond
  101. void pal_os_event_init()
  102. {
  103. if (m_rtc2_is_initialized == true)
  104. {
  105. return;
  106. }
  107. // set prescaler so that a tick is approximately 1ms
  108. m_rtc2_config.prescaler = RTC_PRESCALER;
  109. // Initialize the RTC2 driver instance
  110. APP_ERROR_CHECK(nrf_drv_rtc_init(&rtc2, &m_rtc2_config, ifx_rtc_handler));
  111. // Power on RTC instance
  112. nrf_drv_rtc_enable(&rtc2);
  113. m_rtc2_is_initialized = true;
  114. }
  115. /**
  116. * Platform specific event call back registration function to trigger once when timer expires.
  117. * <br>
  118. *
  119. * <b>API Details:</b>
  120. * This function registers the callback function supplied by the caller.<br>
  121. * It triggers a timer with the supplied time interval in microseconds.<br>
  122. * Once the timer expires, the registered callback function gets called.<br>
  123. *
  124. * \param[in] callback Callback function pointer
  125. * \param[in] callback_args Callback arguments
  126. * \param[in] time_us time in micro seconds to trigger the call back
  127. *
  128. */
  129. void pal_os_event_register_callback_oneshot(register_callback callback,
  130. void* callback_args,
  131. uint32_t time_us)
  132. {
  133. callback_registered = callback;
  134. callback_ctx = callback_args;
  135. // parentheses are set this way to avoid overflow when multiplying time_us with something
  136. uint32_t future_ticks = (time_us/(1000*1000/RTC_TICK_FREQ));
  137. // we can't reliably set an interrupt less than two ticks ahead, as per NRF52832 datasheet, p. 245
  138. // do busy waiting instead
  139. if(future_ticks < 2) {
  140. nrf_delay_us(time_us);
  141. ifx_rtc_handler(NRF_DRV_RTC_INT_COMPARE0);
  142. return;
  143. }
  144. // add current tick value
  145. future_ticks += nrf_drv_rtc_counter_get(&rtc2);
  146. // Set the compare register to trigger approximately at time_us
  147. APP_ERROR_CHECK(nrf_drv_rtc_cc_set(&rtc2, NRF_DRV_RTC_INT_COMPARE0, future_ticks, true));
  148. }
  149. /**
  150. * Get the current time in milliseconds<br>
  151. *
  152. *
  153. * \retval uint32_t time in milliseconds
  154. */
  155. uint32_t pal_os_timer_get_time_in_milliseconds(void)
  156. {
  157. return nrf_drv_rtc_counter_get(&rtc2)*1000/RTC_TICK_FREQ;
  158. }
  159. /**
  160. * Function to wait or delay until the given milliseconds time
  161. *
  162. * \param[in] milliseconds Delay value in milliseconds
  163. *
  164. */
  165. void pal_os_timer_delay_in_milliseconds(uint16_t milliseconds)
  166. {
  167. timer_elapsed = false;
  168. uint32_t future_ticks = milliseconds*(RTC_TICK_FREQ/1000);
  169. // we can't reliably set an interrupt less than two ticks ahead, as per NRF52832 datasheet, p. 245
  170. // do busy waiting instead
  171. if(future_ticks < 2) {
  172. nrf_delay_ms(milliseconds);
  173. return;
  174. }
  175. // add current tick value
  176. future_ticks += nrf_drv_rtc_counter_get(&rtc2);
  177. // Set the compare register to trigger in approximately milliseconds
  178. APP_ERROR_CHECK(nrf_drv_rtc_cc_set(&rtc2, NRF_DRV_RTC_INT_COMPARE1, future_ticks, true));
  179. while(!timer_elapsed)
  180. {
  181. nrf_pwr_mgmt_run();
  182. }
  183. timer_elapsed = false;
  184. }
  185. /**
  186. * @}
  187. */