timeslot.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. //需要使用的头文件
  2. #include <stdint.h>
  3. #include <stdbool.h>
  4. #include "nrf.h"
  5. #include "app_error.h"
  6. #include "nrf_gpio.h"
  7. #include "boards.h"
  8. #include "nrf_nvic.h"
  9. #include "ble_comm.h"
  10. // 定义一个timeSlot的变量,该变量用来设置 请求的timeSlot的特性。
  11. static nrf_radio_request_t m_timeslot_request;
  12. // 请求的timeSlot的时间间隙长度
  13. static uint32_t m_slot_length;
  14. // 信号处理函数的返回值。
  15. static nrf_radio_signal_callback_return_param_t signal_callback_return_param;
  16. //请求一个earliest possible 类型的timeSlot,第一次请求timeSLot的时候总是以该类型发起
  17. // timeSlot时间长度为 5000 us
  18. // timeSlot的请求优先级为正常优先级
  19. // 这里设置了在timeSlot运行过程中会打开外部高频晶振时钟源,不过其实不是必须的。
  20. // timeout_us表示请求timeSlot发出后,系统接收这个请求的最大延迟。
  21. // timeSLot的时间长度为5000us
  22. uint32_t request_next_event_earliest(void)
  23. {
  24. m_slot_length = 5000;
  25. m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
  26. m_timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
  27. m_timeslot_request.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
  28. m_timeslot_request.params.earliest.length_us = m_slot_length;
  29. m_timeslot_request.params.earliest.timeout_us = 1000000;
  30. return sd_radio_request(&m_timeslot_request);
  31. }
  32. // 配置 earliest possible的类型的 timeSlot
  33. void configure_next_event_earliest(void)
  34. {
  35. m_slot_length = 5000;
  36. m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
  37. m_timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
  38. m_timeslot_request.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
  39. m_timeslot_request.params.earliest.length_us = m_slot_length;
  40. m_timeslot_request.params.earliest.timeout_us = 1000000;
  41. }
  42. // 配置normal类型的timeSlot
  43. void configure_next_event_normal(void)
  44. {
  45. m_slot_length = 5000;
  46. m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_NORMAL;
  47. m_timeslot_request.params.normal.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
  48. m_timeslot_request.params.normal.priority = NRF_RADIO_PRIORITY_HIGH;
  49. // norma类型的timeSlot 的开始时间为距离上一个 timeSlot的开始时间 distance_us后
  50. m_timeslot_request.params.normal.distance_us = 100000;
  51. m_timeslot_request.params.normal.length_us = m_slot_length;
  52. }
  53. // timeSlot 会话相关的 一些事件的处理
  54. // 这里的主要处理是,在收到 IDLE事件,即申请的这段会话中没有 timeSlot需要处理后会
  55. // 产生这个事件,那么就可以 通过sd_radio_session_close 函数关闭这个 会话了
  56. // 另外请求的timeSlot可能因为和协议栈运行产生冲突,那么就可以被阻塞或去掉,所以
  57. // NRF_EVT_RADIO_BLOCKED 和 NRF_EVT_RADIO_CANCELED 事件的处理都是重新发起请求
  58. void nrf_evt_signal_handler(uint32_t evt_id)
  59. {
  60. uint32_t err_code;
  61. switch (evt_id)
  62. {
  63. case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
  64. BLE_PRINT("NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN\r\n");
  65. break;
  66. case NRF_EVT_RADIO_SESSION_IDLE:
  67. BLE_PRINT("NRF_EVT_RADIO_SESSION_IDLE\r\n");
  68. sd_radio_session_close();
  69. break;
  70. case NRF_EVT_RADIO_SESSION_CLOSED:
  71. BLE_PRINT("NRF_EVT_RADIO_SESSION_CLOSED\r\n");
  72. break;
  73. case NRF_EVT_RADIO_BLOCKED:
  74. BLE_PRINT("NRF_EVT_RADIO_BLOCKED\r\n");
  75. //注意这里没有break,所以 这两个事件的处理都是重新发起请求
  76. case NRF_EVT_RADIO_CANCELED:
  77. BLE_PRINT("NRF_EVT_RADIO_CANCELED\r\n");
  78. err_code = request_next_event_earliest();
  79. APP_ERROR_CHECK(err_code);
  80. break;
  81. default:
  82. break;
  83. }
  84. }
  85. // timeSlot相关的信号处理函数。
  86. // 当请求的timeSlot 被安排开始后,就会收到 START信号,在这个信号处理里面实现
  87. // 实现翻转 LED灯同时设置 Timer0的超时时间,time0在timeSLot开始后会被自动重置为
  88. // 1MH运行从0 计数,所以这里设置time0的超时时间比 timeSlot的时间长度短1000us,//这样在timeSLot
  89. // 结束之前就可以收到 NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0信号,然后在这信号处
  90. // 理里做一些收尾工作,在这里我们实现的是请求下一个timeSlot
  91. // NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO信号不需要处理,因为我们没有在timeSLot
  92. // 中使用Radio,所以不会有这个信号。
  93. nrf_radio_signal_callback_return_param_t * radio_callback(uint8_t signal_type)
  94. {
  95. static uint8_t start_count = 0;
  96. static uint8_t timer0_count = 0;
  97. switch(signal_type)
  98. {
  99. case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
  100. signal_callback_return_param.params.request.p_next = NULL;
  101. signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
  102. NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
  103. NRF_TIMER0->CC[0] = m_slot_length - 1000;
  104. NVIC_EnableIRQ(TIMER0_IRQn);
  105. nrf_gpio_pin_toggle(16);
  106. //避免打印太快
  107. if(start_count++ >10 ){
  108. BLE_PRINT("NRF_RADIO_CALLBACK_SIGNAL_TYPE_START\r\n");
  109. start_count = 0;
  110. }
  111. break;
  112. case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:
  113. signal_callback_return_param.params.request.p_next = NULL;
  114. signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
  115. break;
  116. case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:
  117. configure_next_event_normal();
  118. signal_callback_return_param.params.request.p_next = &m_timeslot_request;
  119. signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
  120. if(timer0_count++ >10 ){
  121. BLE_PRINT("NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0\r\n");
  122. timer0_count = 0;
  123. }
  124. break;
  125. case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:
  126. BLE_PRINT("NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED\r\n");
  127. break;
  128. case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED:
  129. BLE_PRINT("NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED\r\n");
  130. configure_next_event_earliest();
  131. signal_callback_return_param.params.request.p_next = &m_timeslot_request;
  132. signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
  133. break;
  134. default:
  135. //No implementation needed
  136. break;
  137. }
  138. return (&signal_callback_return_param);
  139. }
  140. // timeSlot初始化函数。
  141. uint32_t timeslot_sd_init(void)
  142. {
  143. uint32_t err_code;
  144. err_code = sd_radio_session_open(radio_callback);
  145. if (err_code != NRF_SUCCESS)
  146. {
  147. return err_code;
  148. }
  149. err_code = request_next_event_earliest();
  150. if (err_code != NRF_SUCCESS)
  151. {
  152. (void)sd_radio_session_close();
  153. return err_code;
  154. }
  155. nrf_gpio_cfg_output(16);
  156. return NRF_SUCCESS;
  157. }