board.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. #include "board.h"
  2. #include "uart.h"
  3. #include "app_util_platform.h"
  4. #include "nrf_drv_common.h"
  5. #include "nrf_systick.h"
  6. #include "nrf_rtc.h"
  7. #include "nrf_drv_clock.h"
  8. #include "softdevice_handler.h"
  9. #include "nrf_drv_uart.h"
  10. #include "nrf_gpio.h"
  11. #include <rtthread.h>
  12. #include <rthw.h>
  13. #if 0
  14. /*******************************************************************************
  15. * Function Name : SysTick_Configuration
  16. * Description : Configures the SysTick for OS tick.
  17. * Input : None
  18. * Output : None
  19. * Return : None
  20. *******************************************************************************/
  21. void SysTick_Configuration(void)
  22. {
  23. nrf_drv_common_irq_enable(SysTick_IRQn, APP_TIMER_CONFIG_IRQ_PRIORITY);
  24. nrf_systick_load_set(SystemCoreClock / RT_TICK_PER_SECOND);
  25. nrf_systick_val_clear();
  26. nrf_systick_csr_set(NRF_SYSTICK_CSR_CLKSOURCE_CPU | NRF_SYSTICK_CSR_TICKINT_ENABLE
  27. | NRF_SYSTICK_CSR_ENABLE);
  28. }
  29. /**
  30. * This is the timer interrupt service routine.
  31. *
  32. */
  33. void SysTick_Handler(void)
  34. {
  35. if (rt_thread_self() != RT_NULL)
  36. {
  37. /* enter interrupt */
  38. rt_interrupt_enter();
  39. rt_tick_increase();
  40. /* leave interrupt */
  41. rt_interrupt_leave();
  42. }
  43. }
  44. #else
  45. #define TICK_RATE_HZ RT_TICK_PER_SECOND
  46. #define SYSTICK_CLOCK_HZ ( 32768UL )
  47. #define NRF_RTC_REG NRF_RTC1
  48. /* IRQn used by the selected RTC */
  49. #define NRF_RTC_IRQn RTC1_IRQn
  50. /* Constants required to manipulate the NVIC. */
  51. #define NRF_RTC_PRESCALER ( (uint32_t) (ROUNDED_DIV(SYSTICK_CLOCK_HZ, TICK_RATE_HZ) - 1) )
  52. /* Maximum RTC ticks */
  53. #define NRF_RTC_MAXTICKS ((1U<<24)-1U)
  54. static volatile uint32_t m_tick_overflow_count = 0;
  55. #define NRF_RTC_BITWIDTH 24
  56. #define OSTick_Handler RTC1_IRQHandler
  57. #define EXPECTED_IDLE_TIME_BEFORE_SLEEP 2
  58. void SysTick_Configuration(void)
  59. {
  60. nrf_drv_clock_lfclk_request(NULL);
  61. /* Configure SysTick to interrupt at the requested rate. */
  62. nrf_rtc_prescaler_set(NRF_RTC_REG, NRF_RTC_PRESCALER);
  63. nrf_rtc_int_enable (NRF_RTC_REG, RTC_INTENSET_TICK_Msk);
  64. nrf_rtc_task_trigger (NRF_RTC_REG, NRF_RTC_TASK_CLEAR);
  65. nrf_rtc_task_trigger (NRF_RTC_REG, NRF_RTC_TASK_START);
  66. nrf_rtc_event_enable(NRF_RTC_REG, RTC_EVTEN_OVRFLW_Msk);
  67. NVIC_SetPriority(NRF_RTC_IRQn, 0xF);
  68. NVIC_EnableIRQ(NRF_RTC_IRQn);
  69. }
  70. static rt_tick_t _tick_distance(void)
  71. {
  72. nrf_rtc_event_clear(NRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
  73. uint32_t systick_counter = nrf_rtc_counter_get(NRF_RTC_REG);
  74. nrf_rtc_event_clear(NRF_RTC_REG, NRF_RTC_EVENT_TICK);
  75. /* check for overflow in TICK counter */
  76. if(nrf_rtc_event_pending(NRF_RTC_REG, NRF_RTC_EVENT_OVERFLOW))
  77. {
  78. nrf_rtc_event_clear(NRF_RTC_REG, NRF_RTC_EVENT_OVERFLOW);
  79. m_tick_overflow_count++;
  80. }
  81. return ((m_tick_overflow_count << NRF_RTC_BITWIDTH) + systick_counter) - rt_tick_get();
  82. }
  83. void OSTick_Handler( void )
  84. {
  85. uint32_t diff;
  86. diff = _tick_distance();
  87. while((diff--) > 0)
  88. {
  89. if (rt_thread_self() != RT_NULL)
  90. {
  91. /* enter interrupt */
  92. rt_interrupt_enter();
  93. rt_tick_increase();
  94. /* leave interrupt */
  95. rt_interrupt_leave();
  96. }
  97. }
  98. }
  99. static void _wakeup_tick_adjust(void)
  100. {
  101. uint32_t diff;
  102. uint32_t level;
  103. level = rt_hw_interrupt_disable();
  104. diff = _tick_distance();
  105. rt_tick_set(rt_tick_get() + diff);
  106. if (rt_thread_self() != RT_NULL)
  107. {
  108. struct rt_thread *thread;
  109. /* check time slice */
  110. thread = rt_thread_self();
  111. if (thread->remaining_tick <= diff)
  112. {
  113. /* change to initialized tick */
  114. thread->remaining_tick = thread->init_tick;
  115. /* yield */
  116. rt_thread_yield();
  117. }
  118. else
  119. {
  120. thread->remaining_tick -= diff;
  121. }
  122. /* check timer */
  123. rt_timer_check();
  124. }
  125. rt_hw_interrupt_enable(level);
  126. }
  127. static void _sleep_ongo( uint32_t sleep_tick )
  128. {
  129. uint32_t enterTime;
  130. uint32_t entry_tick;
  131. /* Make sure the SysTick reload value does not overflow the counter. */
  132. if ( sleep_tick > NRF_RTC_MAXTICKS - EXPECTED_IDLE_TIME_BEFORE_SLEEP )
  133. {
  134. sleep_tick = NRF_RTC_MAXTICKS - EXPECTED_IDLE_TIME_BEFORE_SLEEP;
  135. }
  136. rt_enter_critical();
  137. enterTime = nrf_rtc_counter_get(NRF_RTC_REG);
  138. {
  139. uint32_t wakeupTime = (enterTime + sleep_tick) & NRF_RTC_MAXTICKS;
  140. /* Stop tick events */
  141. nrf_rtc_int_disable(NRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
  142. /* Configure CTC interrupt */
  143. nrf_rtc_cc_set(NRF_RTC_REG, 0, wakeupTime);
  144. nrf_rtc_event_clear(NRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
  145. nrf_rtc_int_enable(NRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
  146. entry_tick = rt_tick_get();
  147. __DSB();
  148. if ( sleep_tick > 0 )
  149. {
  150. #ifdef SOFTDEVICE_PRESENT
  151. if (softdevice_handler_is_enabled())
  152. {
  153. uint32_t err_code = sd_app_evt_wait();
  154. APP_ERROR_CHECK(err_code);
  155. }
  156. else
  157. #endif
  158. {
  159. /* No SD - we would just block interrupts globally.
  160. * BASEPRI cannot be used for that because it would prevent WFE from wake up.
  161. */
  162. do{
  163. __WFE();
  164. } while (0 == (NVIC->ISPR[0] | NVIC->ISPR[1]));
  165. }
  166. }
  167. nrf_rtc_int_disable(NRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
  168. nrf_rtc_event_clear(NRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
  169. _wakeup_tick_adjust();
  170. /* Correct the system ticks */
  171. {
  172. nrf_rtc_event_clear(NRF_RTC_REG, NRF_RTC_EVENT_TICK);
  173. nrf_rtc_int_enable (NRF_RTC_REG, NRF_RTC_INT_TICK_MASK);
  174. /* It is important that we clear pending here so that our corrections are latest and in sync with tick_interrupt handler */
  175. NVIC_ClearPendingIRQ(NRF_RTC_IRQn);
  176. }
  177. rt_kprintf("entry tick:%u, expected:%u, current tick:%u\n", entry_tick, sleep_tick, rt_tick_get());
  178. }
  179. rt_exit_critical();
  180. }
  181. #endif
  182. void rt_hw_system_powersave(void)
  183. {
  184. uint32_t sleep_tick;
  185. sleep_tick = rt_timer_next_timeout_tick() - rt_tick_get();
  186. if ( sleep_tick >= EXPECTED_IDLE_TIME_BEFORE_SLEEP)
  187. {
  188. // rt_kprintf("sleep entry:%u\n", rt_tick_get());
  189. _sleep_ongo( sleep_tick );
  190. }
  191. }
  192. void rt_hw_board_init(void)
  193. {
  194. // sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE);
  195. /* Activate deep sleep mode */
  196. SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
  197. nrf_drv_clock_init();
  198. // nrf_drv_clock_hfclk_request(0);
  199. SysTick_Configuration();
  200. rt_thread_idle_sethook(rt_hw_system_powersave);
  201. rt_hw_uart_init();
  202. #ifdef RT_USING_CONSOLE
  203. rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
  204. #endif
  205. #ifdef RT_USING_COMPONENTS_INIT
  206. rt_components_board_init();
  207. #endif
  208. }