port_cmsis_systick.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * FreeRTOS Kernel V10.0.0
  3. * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy of
  6. * this software and associated documentation files (the "Software"), to deal in
  7. * the Software without restriction, including without limitation the rights to
  8. * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  9. * the Software, and to permit persons to whom the Software is furnished to do so,
  10. * subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in all
  13. * copies or substantial portions of the Software. If you wish to use our Amazon
  14. * FreeRTOS name, please do so in a fair use way that does not cause confusion.
  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, FITNESS
  18. * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19. * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20. * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. *
  23. * http://www.FreeRTOS.org
  24. * http://aws.amazon.com/freertos
  25. *
  26. * 1 tab == 4 spaces!
  27. */
  28. /* Scheduler includes. */
  29. #include "FreeRTOS.h"
  30. #include "task.h"
  31. /*-----------------------------------------------------------
  32. * Implementation of functions defined in portable.h for the ARM CM0 port.
  33. * CMSIS compatible layer to menage SysTick ticking source.
  34. *----------------------------------------------------------*/
  35. #if configTICK_SOURCE == FREERTOS_USE_SYSTICK
  36. #error NRF51 does not support SysTick module
  37. /*-----------------------------------------------------------*/
  38. #elif configTICK_SOURCE == FREERTOS_USE_RTC
  39. #if configUSE_16_BIT_TICKS == 1
  40. #error This port does not support 16 bit ticks.
  41. #endif
  42. #include "nrf_rtc.h"
  43. #include "nrf_drv_clock.h"
  44. /*-----------------------------------------------------------*/
  45. void xPortSysTickHandler( void )
  46. {
  47. #if configUSE_TICKLESS_IDLE == 1
  48. nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
  49. #endif
  50. BaseType_t switch_req = pdFALSE;
  51. uint32_t isrstate = portSET_INTERRUPT_MASK_FROM_ISR();
  52. uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
  53. nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
  54. if (configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG == 0)
  55. {
  56. /* check FreeRTOSConfig.h file for more details on configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG */
  57. TickType_t diff;
  58. diff = (systick_counter - xTaskGetTickCount()) & portNRF_RTC_MAXTICKS;
  59. /* At most 1 step if scheduler is suspended - the xTaskIncrementTick
  60. * would return the tick state from the moment when suspend function was called. */
  61. if ((diff > 1) && (xTaskGetSchedulerState() != taskSCHEDULER_RUNNING))
  62. {
  63. diff = 1;
  64. }
  65. while ((diff--) > 0)
  66. {
  67. switch_req |= xTaskIncrementTick();
  68. }
  69. }
  70. else
  71. {
  72. switch_req = xTaskIncrementTick();
  73. }
  74. /* Increment the RTOS tick as usual which checks if there is a need for rescheduling */
  75. if ( switch_req != pdFALSE )
  76. {
  77. /* A context switch is required. Context switching is performed in
  78. the PendSV interrupt. Pend the PendSV interrupt. */
  79. SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
  80. __SEV();
  81. }
  82. portCLEAR_INTERRUPT_MASK_FROM_ISR( isrstate );
  83. }
  84. /*
  85. * Setup the RTC time to generate the tick interrupts at the required
  86. * frequency.
  87. */
  88. void vPortSetupTimerInterrupt( void )
  89. {
  90. /* Request LF clock */
  91. nrf_drv_clock_lfclk_request(NULL);
  92. /* Configure SysTick to interrupt at the requested rate. */
  93. nrf_rtc_prescaler_set(portNRF_RTC_REG, portNRF_RTC_PRESCALER);
  94. nrf_rtc_int_enable (portNRF_RTC_REG, RTC_INTENSET_TICK_Msk);
  95. nrf_rtc_task_trigger (portNRF_RTC_REG, NRF_RTC_TASK_CLEAR);
  96. nrf_rtc_task_trigger (portNRF_RTC_REG, NRF_RTC_TASK_START);
  97. nrf_rtc_event_enable(portNRF_RTC_REG, RTC_EVTEN_OVRFLW_Msk);
  98. NVIC_SetPriority(portNRF_RTC_IRQn, configKERNEL_INTERRUPT_PRIORITY);
  99. NVIC_EnableIRQ(portNRF_RTC_IRQn);
  100. }
  101. #if configUSE_TICKLESS_IDLE == 1
  102. void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
  103. {
  104. /*
  105. * Implementation note:
  106. *
  107. * To help debugging the option configUSE_TICKLESS_IDLE_SIMPLE_DEBUG was presented.
  108. * This option would make sure that even if program execution was stopped inside
  109. * this function no more than expected number of ticks would be skipped.
  110. *
  111. * Normally RTC works all the time even if firmware execution was stopped
  112. * and that may lead to skipping too much of ticks.
  113. */
  114. TickType_t enterTime;
  115. /* Make sure the SysTick reload value does not overflow the counter. */
  116. if ( xExpectedIdleTime > portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
  117. {
  118. xExpectedIdleTime = portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP;
  119. }
  120. /* Block all the interrupts globally */
  121. #ifdef SOFTDEVICE_PRESENT
  122. do{
  123. uint8_t dummy = 0;
  124. uint32_t err_code = sd_nvic_critical_region_enter(&dummy);
  125. APP_ERROR_CHECK(err_code);
  126. }while (0);
  127. #else
  128. __disable_irq();
  129. #endif
  130. /* Configure CTC interrupt */
  131. enterTime = nrf_rtc_counter_get(portNRF_RTC_REG);
  132. if ( eTaskConfirmSleepModeStatus() != eAbortSleep )
  133. {
  134. TickType_t xModifiableIdleTime;
  135. TickType_t wakeupTime = (enterTime + xExpectedIdleTime) & portNRF_RTC_MAXTICKS;
  136. /* Stop tick events */
  137. nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
  138. /* Configure CTC interrupt */
  139. nrf_rtc_cc_set(portNRF_RTC_REG, 0, wakeupTime);
  140. nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
  141. nrf_rtc_int_enable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
  142. __DSB();
  143. /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
  144. * set its parameter to 0 to indicate that its implementation contains
  145. * its own wait for interrupt or wait for event instruction, and so wfi
  146. * should not be executed again. However, the original expected idle
  147. * time variable must remain unmodified, so a copy is taken. */
  148. xModifiableIdleTime = xExpectedIdleTime;
  149. configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
  150. if ( xModifiableIdleTime > 0 )
  151. {
  152. #ifdef SOFTDEVICE_PRESENT
  153. uint32_t err_code = sd_app_evt_wait();
  154. APP_ERROR_CHECK(err_code);
  155. #else
  156. /* No SD - we would just block interrupts globally.
  157. * BASEPRI cannot be used for that because it would prevent WFE from wake up.
  158. */
  159. do{
  160. __WFE();
  161. } while (0 == (NVIC->ISPR[0]));
  162. #endif
  163. }
  164. configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
  165. nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
  166. nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
  167. /* Correct the system ticks */
  168. {
  169. TickType_t diff;
  170. TickType_t exitTime;
  171. nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
  172. nrf_rtc_int_enable (portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
  173. exitTime = nrf_rtc_counter_get(portNRF_RTC_REG);
  174. diff = (exitTime - enterTime) & portNRF_RTC_MAXTICKS;
  175. /* It is important that we clear pending here so that our corrections are latest and in sync with tick_interrupt handler */
  176. NVIC_ClearPendingIRQ(portNRF_RTC_IRQn);
  177. if ((configUSE_TICKLESS_IDLE_SIMPLE_DEBUG) && (diff > xExpectedIdleTime))
  178. {
  179. diff = xExpectedIdleTime;
  180. }
  181. if (diff > 0)
  182. {
  183. vTaskStepTick(diff);
  184. }
  185. }
  186. }
  187. #ifdef SOFTDEVICE_PRESENT
  188. uint32_t err_code = sd_nvic_critical_region_exit(0);
  189. APP_ERROR_CHECK(err_code);
  190. #else
  191. __enable_irq();
  192. #endif
  193. }
  194. #endif // configUSE_TICKLESS_IDLE
  195. #else // configTICK_SOURCE
  196. #error Unsupported configTICK_SOURCE value
  197. #endif // configTICK_SOURCE == FREERTOS_USE_SYSTICK