nrf_drv_clock.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include "nrf_drv_clock.h"
  13. #include "nrf_error.h"
  14. #include "nordic_common.h"
  15. #ifdef SOFTDEVICE_PRESENT
  16. #include "nrf_sdm.h"
  17. #include "nrf_soc.h"
  18. #include "app_util_platform.h"
  19. #else
  20. #include "app_util_platform.h"
  21. #endif // SOFTDEVICE_PRESENT
  22. /*lint -save -e652 */
  23. #define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC
  24. #define NRF_CLOCK_LFCLK_Xtal CLOCK_LFCLKSRC_SRC_Xtal
  25. #define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth
  26. /*lint -restore */
  27. #define INT_MAX 0xFFFFFFFF
  28. #if (CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC) && !defined(SOFTDEVICE_PRESENT)
  29. #define CALIBRATION_SUPPORT 1
  30. #else
  31. #define CALIBRATION_SUPPORT 0
  32. #endif
  33. typedef enum
  34. {
  35. CAL_STATE_IDLE,
  36. CAL_STATE_CT,
  37. CAL_STATE_HFCLK_REQ,
  38. CAL_STATE_CAL,
  39. CAL_STATE_ABORT,
  40. } nrf_drv_clock_cal_state_t;
  41. /**@brief CLOCK control block. */
  42. typedef struct
  43. {
  44. volatile uint32_t hfclk_requests; /*< High-frequency clock request counter. */
  45. volatile nrf_drv_clock_handler_item_t * p_hf_head;
  46. bool module_initialized; /*< Indicate the state of module */
  47. volatile bool hfclk_on; /*< High-frequency clock state. */
  48. #ifndef SOFTDEVICE_PRESENT
  49. volatile bool lfclk_on; /*< Low-frequency clock state. */
  50. uint32_t lfclk_requests; /*< Low-frequency clock request counter. */
  51. volatile nrf_drv_clock_handler_item_t * p_lf_head;
  52. #if CALIBRATION_SUPPORT
  53. nrf_drv_clock_handler_item_t cal_hfclk_started_handler_item;
  54. nrf_drv_clock_event_handler_t cal_done_handler;
  55. volatile nrf_drv_clock_cal_state_t cal_state;
  56. #endif //CALIBRATION_SUPPORT
  57. #endif //SOFTDEVICE_PRESENT
  58. }nrf_drv_clock_cb_t;
  59. static nrf_drv_clock_cb_t m_clock_cb;
  60. #ifndef SOFTDEVICE_PRESENT
  61. /**@brief Function for starting LFCLK. This function will return immediately without waiting for start.
  62. */
  63. static void lfclk_start(void)
  64. {
  65. nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
  66. nrf_clock_int_enable(NRF_CLOCK_INT_LF_STARTED_MASK);
  67. nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
  68. }
  69. /**@brief Function for stopping LFCLK and calibration (if it was set up).
  70. */
  71. static void lfclk_stop(void)
  72. {
  73. #if CALIBRATION_SUPPORT
  74. (void)nrf_drv_clock_calibration_abort();
  75. #endif //CALIBRATION_SUPPORT
  76. nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTOP);
  77. while (nrf_clock_lf_is_running())
  78. {}
  79. }
  80. #endif
  81. static void hfclk_start(void)
  82. {
  83. #ifndef SOFTDEVICE_PRESENT
  84. nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
  85. nrf_clock_int_enable(NRF_CLOCK_INT_HF_STARTED_MASK);
  86. nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART);
  87. #else
  88. UNUSED_VARIABLE(sd_clock_hfclk_request());
  89. #endif
  90. }
  91. static void hfclk_stop(void)
  92. {
  93. #ifndef SOFTDEVICE_PRESENT
  94. nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP);
  95. while (nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY))
  96. {}
  97. #else
  98. UNUSED_VARIABLE(sd_clock_hfclk_release());
  99. #endif
  100. }
  101. ret_code_t nrf_drv_clock_init(void)
  102. {
  103. uint32_t result = NRF_SUCCESS;
  104. if (m_clock_cb.module_initialized)
  105. {
  106. return MODULE_ALREADY_INITIALIZED;
  107. }
  108. m_clock_cb.p_hf_head = NULL;
  109. m_clock_cb.hfclk_requests = 0;
  110. #ifndef SOFTDEVICE_PRESENT
  111. m_clock_cb.p_lf_head = NULL;
  112. m_clock_cb.lfclk_requests = 0;
  113. nrf_clock_xtalfreq_set(CLOCK_CONFIG_XTAL_FREQ);
  114. nrf_clock_lf_src_set((nrf_clock_lfclk_t)CLOCK_CONFIG_LF_SRC);
  115. nrf_drv_common_irq_enable(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY);
  116. #if CALIBRATION_SUPPORT
  117. m_clock_cb.cal_state = CAL_STATE_IDLE;
  118. #endif // CALIBRATION_SUPPORT
  119. #else // SOFTDEVICE_PRESENT
  120. uint8_t is_enabled;
  121. result = sd_softdevice_is_enabled(&is_enabled);
  122. if((result == NRF_SUCCESS) && !is_enabled)
  123. {
  124. result = NRF_ERROR_SOFTDEVICE_NOT_ENABLED;
  125. }
  126. #endif // SOFTDEVICE_PRESENT
  127. m_clock_cb.module_initialized = true;
  128. return result;
  129. }
  130. void nrf_drv_clock_uninit(void)
  131. {
  132. ASSERT(m_clock_cb.module_initialized);
  133. #ifndef SOFTDEVICE_PRESENT
  134. nrf_drv_common_irq_disable(POWER_CLOCK_IRQn);
  135. nrf_clock_int_disable(0xFFFFFFFF);
  136. lfclk_stop();
  137. #endif
  138. hfclk_stop();
  139. m_clock_cb.module_initialized = false;
  140. }
  141. static void item_enqueue(nrf_drv_clock_handler_item_t ** p_head,
  142. nrf_drv_clock_handler_item_t * p_item)
  143. {
  144. if (*p_head)
  145. {
  146. p_item->p_next = *p_head;
  147. *p_head = p_item;
  148. }
  149. else
  150. {
  151. p_item->p_next = NULL;
  152. *p_head = p_item;
  153. }
  154. }
  155. static nrf_drv_clock_handler_item_t * item_dequeue(nrf_drv_clock_handler_item_t ** p_head)
  156. {
  157. nrf_drv_clock_handler_item_t * p_item = *p_head;
  158. if (p_item)
  159. {
  160. *p_head = p_item->p_next;
  161. }
  162. return p_item;
  163. }
  164. void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item)
  165. {
  166. ASSERT(m_clock_cb.module_initialized);
  167. #ifndef SOFTDEVICE_PRESENT
  168. ASSERT(m_clock_cb.lfclk_requests != INT_MAX);
  169. CRITICAL_REGION_ENTER();
  170. if (m_clock_cb.lfclk_on)
  171. {
  172. if (p_handler_item)
  173. {
  174. p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED);
  175. }
  176. }
  177. else
  178. {
  179. if (p_handler_item)
  180. {
  181. item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, p_handler_item);
  182. }
  183. if (m_clock_cb.lfclk_requests == 0)
  184. {
  185. lfclk_start();
  186. }
  187. }
  188. m_clock_cb.lfclk_requests++;
  189. CRITICAL_REGION_EXIT();
  190. #else
  191. if (p_handler_item)
  192. {
  193. p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED);
  194. }
  195. #endif // SOFTDEVICE_PRESENT
  196. }
  197. void nrf_drv_clock_lfclk_release(void)
  198. {
  199. ASSERT(m_clock_cb.module_initialized);
  200. #ifndef SOFTDEVICE_PRESENT
  201. ASSERT(m_clock_cb.lfclk_requests > 0);
  202. CRITICAL_REGION_ENTER();
  203. m_clock_cb.lfclk_requests--;
  204. if (m_clock_cb.lfclk_requests == 0)
  205. {
  206. lfclk_stop();
  207. m_clock_cb.lfclk_on = false;
  208. m_clock_cb.p_lf_head = NULL;
  209. }
  210. CRITICAL_REGION_EXIT();
  211. #endif // SOFTDEVICE_PRESENT
  212. }
  213. bool nrf_drv_clock_lfclk_is_running(void)
  214. {
  215. ASSERT(m_clock_cb.module_initialized);
  216. bool result;
  217. #ifndef SOFTDEVICE_PRESENT
  218. result = nrf_clock_lf_is_running();
  219. #else
  220. result = true;
  221. #endif
  222. return result;
  223. }
  224. void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item)
  225. {
  226. ASSERT(m_clock_cb.module_initialized);
  227. ASSERT(m_clock_cb.hfclk_requests != INT_MAX);
  228. CRITICAL_REGION_ENTER();
  229. if (m_clock_cb.hfclk_on)
  230. {
  231. if (p_handler_item)
  232. {
  233. p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
  234. }
  235. }
  236. else
  237. {
  238. if (p_handler_item)
  239. {
  240. item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, p_handler_item);
  241. }
  242. if (m_clock_cb.hfclk_requests == 0)
  243. {
  244. hfclk_start();
  245. }
  246. }
  247. m_clock_cb.hfclk_requests++;
  248. CRITICAL_REGION_EXIT();
  249. }
  250. void nrf_drv_clock_hfclk_release(void)
  251. {
  252. ASSERT(m_clock_cb.module_initialized);
  253. ASSERT(m_clock_cb.hfclk_requests > 0);
  254. //disable interrupts CLOCK or SoftDevice events
  255. CRITICAL_REGION_ENTER();
  256. m_clock_cb.hfclk_requests--;
  257. if (m_clock_cb.hfclk_requests == 0)
  258. {
  259. hfclk_stop();
  260. m_clock_cb.hfclk_on = false;
  261. m_clock_cb.p_hf_head = NULL;
  262. }
  263. CRITICAL_REGION_EXIT();
  264. //enable interrupts CLOCK or SoftDevice events
  265. }
  266. bool nrf_drv_clock_hfclk_is_running(void)
  267. {
  268. bool result;
  269. ASSERT(m_clock_cb.module_initialized);
  270. #ifndef SOFTDEVICE_PRESENT
  271. result = nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY);
  272. #else
  273. uint32_t is_running;
  274. UNUSED_VARIABLE(sd_clock_hfclk_is_running(&is_running));
  275. result = is_running ? true : false;
  276. #endif
  277. return result;
  278. }
  279. #if CALIBRATION_SUPPORT
  280. static void clock_calibration_hf_started(nrf_drv_clock_evt_type_t event)
  281. {
  282. if (m_clock_cb.cal_state == CAL_STATE_ABORT)
  283. {
  284. nrf_drv_clock_hfclk_release();
  285. m_clock_cb.cal_state = CAL_STATE_IDLE;
  286. if (m_clock_cb.cal_done_handler)
  287. {
  288. m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED);
  289. }
  290. }
  291. else
  292. {
  293. nrf_clock_int_enable(NRF_CLOCK_INT_DONE_MASK);
  294. m_clock_cb.cal_state = CAL_STATE_CAL;
  295. nrf_clock_task_trigger(NRF_CLOCK_TASK_CAL);
  296. }
  297. }
  298. #endif
  299. ret_code_t nrf_drv_clock_calibration_start(uint8_t interval, nrf_drv_clock_event_handler_t handler)
  300. {
  301. #if CALIBRATION_SUPPORT
  302. ASSERT(m_clock_cb.cal_state == CAL_STATE_IDLE);
  303. ret_code_t ret = NRF_SUCCESS;
  304. if (m_clock_cb.lfclk_on == false)
  305. {
  306. ret = NRF_ERROR_INVALID_STATE;
  307. }
  308. else if (m_clock_cb.cal_state == CAL_STATE_IDLE)
  309. {
  310. m_clock_cb.cal_done_handler = handler;
  311. m_clock_cb.cal_hfclk_started_handler_item.event_handler = clock_calibration_hf_started;
  312. if (interval == 0)
  313. {
  314. m_clock_cb.cal_state = CAL_STATE_HFCLK_REQ;
  315. nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item);
  316. }
  317. else
  318. {
  319. m_clock_cb.cal_state = CAL_STATE_CT;
  320. nrf_clock_cal_timer_timeout_set(interval);
  321. nrf_clock_int_enable(NRF_CLOCK_INT_CTTO_MASK);
  322. nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTART);
  323. }
  324. }
  325. else
  326. {
  327. ret = NRF_ERROR_BUSY;
  328. }
  329. return ret;
  330. #else //CALIBRATION_SUPPORT
  331. return NRF_ERROR_FORBIDDEN;
  332. #endif
  333. }
  334. ret_code_t nrf_drv_clock_calibration_abort(void)
  335. {
  336. #if CALIBRATION_SUPPORT
  337. CRITICAL_REGION_ENTER();
  338. switch(m_clock_cb.cal_state)
  339. {
  340. case CAL_STATE_CT:
  341. nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);
  342. nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTOP);
  343. m_clock_cb.cal_state = CAL_STATE_IDLE;
  344. if (m_clock_cb.cal_done_handler)
  345. {
  346. m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED);
  347. }
  348. break;
  349. case CAL_STATE_HFCLK_REQ:
  350. /* fall through. */
  351. case CAL_STATE_CAL:
  352. m_clock_cb.cal_state = CAL_STATE_ABORT;
  353. break;
  354. default:
  355. break;
  356. }
  357. CRITICAL_REGION_EXIT();
  358. return NRF_SUCCESS;
  359. #else //CALIBRATION_SUPPORT
  360. return NRF_ERROR_FORBIDDEN;
  361. #endif
  362. }
  363. ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating)
  364. {
  365. #if CALIBRATION_SUPPORT
  366. ASSERT(m_clock_cb.module_initialized);
  367. *p_is_calibrating = (m_clock_cb.cal_state != CAL_STATE_IDLE);
  368. return NRF_SUCCESS;
  369. #else //CALIBRATION_SUPPORT
  370. return NRF_ERROR_FORBIDDEN;
  371. #endif
  372. }
  373. static __INLINE void clock_clk_started_notify(nrf_drv_clock_handler_item_t **p_head,
  374. nrf_drv_clock_evt_type_t evt_type)
  375. {
  376. while(1)
  377. {
  378. nrf_drv_clock_handler_item_t * p_item = item_dequeue(p_head);
  379. if (p_item)
  380. {
  381. p_item->event_handler(evt_type);
  382. }
  383. else
  384. {
  385. break;
  386. }
  387. }
  388. }
  389. #ifndef SOFTDEVICE_PRESENT
  390. void POWER_CLOCK_IRQHandler(void)
  391. {
  392. if (nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED))
  393. {
  394. nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
  395. nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK);
  396. m_clock_cb.hfclk_on = true;
  397. clock_clk_started_notify((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
  398. }
  399. if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED))
  400. {
  401. nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
  402. nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK);
  403. m_clock_cb.lfclk_on = true;
  404. clock_clk_started_notify((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, NRF_DRV_CLOCK_EVT_LFCLK_STARTED);
  405. }
  406. #if CALIBRATION_SUPPORT
  407. if (nrf_clock_event_check(NRF_CLOCK_EVENT_CTTO))
  408. {
  409. nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO);
  410. nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);
  411. nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item);
  412. }
  413. if (nrf_clock_event_check(NRF_CLOCK_EVENT_DONE))
  414. {
  415. nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE);
  416. nrf_clock_int_disable(NRF_CLOCK_INT_DONE_MASK);
  417. nrf_drv_clock_hfclk_release();
  418. nrf_drv_clock_evt_type_t evt_type = (m_clock_cb.cal_state == CAL_STATE_ABORT) ?
  419. NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE;
  420. m_clock_cb.cal_state = CAL_STATE_IDLE;
  421. if (m_clock_cb.cal_done_handler)
  422. {
  423. m_clock_cb.cal_done_handler(evt_type);
  424. }
  425. }
  426. #endif //CALIBRATION_SUPPORT
  427. }
  428. #else
  429. void nrf_drv_clock_on_soc_event(uint32_t evt_id)
  430. {
  431. if (evt_id == NRF_EVT_HFCLKSTARTED)
  432. {
  433. clock_clk_started_notify((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
  434. }
  435. }
  436. #endif // SOFTDEVICE_PRESENT
  437. #undef NRF_CLOCK_LFCLK_RC
  438. #undef NRF_CLOCK_LFCLK_Xtal
  439. #undef NRF_CLOCK_LFCLK_Synth