nrf_drv_clock.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  1. /**
  2. * Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include <nordic_common.h>
  41. #include "nrf_drv_clock.h"
  42. #if NRF_MODULE_ENABLED(NRF_CLOCK)
  43. #ifdef SOFTDEVICE_PRESENT
  44. #include "nrf_sdh.h"
  45. #include "nrf_sdh_soc.h"
  46. #endif
  47. #include <hal/nrf_wdt.h>
  48. #define NRF_LOG_MODULE_NAME clock
  49. #if CLOCK_CONFIG_LOG_ENABLED
  50. #define NRF_LOG_LEVEL CLOCK_CONFIG_LOG_LEVEL
  51. #define NRF_LOG_INFO_COLOR CLOCK_CONFIG_INFO_COLOR
  52. #define NRF_LOG_DEBUG_COLOR CLOCK_CONFIG_DEBUG_COLOR
  53. #else //CLOCK_CONFIG_LOG_ENABLED
  54. #define NRF_LOG_LEVEL 0
  55. #endif //CLOCK_CONFIG_LOG_ENABLED
  56. #include "nrf_log.h"
  57. NRF_LOG_MODULE_REGISTER();
  58. #define EVT_TO_STR(event) \
  59. (event == NRF_CLOCK_EVENT_HFCLKSTARTED ? "NRF_CLOCK_EVENT_HFCLKSTARTED" : \
  60. (event == NRF_CLOCK_EVENT_LFCLKSTARTED ? "NRF_CLOCK_EVENT_LFCLKSTARTED" : \
  61. (event == NRF_CLOCK_EVENT_DONE ? "NRF_CLOCK_EVENT_DONE" : \
  62. (event == NRF_CLOCK_EVENT_CTTO ? "NRF_CLOCK_EVENT_CTTO" : \
  63. "UNKNOWN EVENT"))))
  64. /*lint -save -e652 */
  65. #define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC
  66. #define NRF_CLOCK_LFCLK_Xtal CLOCK_LFCLKSRC_SRC_Xtal
  67. #define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth
  68. /*lint -restore */
  69. #if (CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC) && !defined(SOFTDEVICE_PRESENT)
  70. #define CALIBRATION_SUPPORT 1
  71. #else
  72. #define CALIBRATION_SUPPORT 0
  73. #endif
  74. typedef enum
  75. {
  76. CAL_STATE_IDLE,
  77. CAL_STATE_CT,
  78. CAL_STATE_HFCLK_REQ,
  79. CAL_STATE_CAL,
  80. CAL_STATE_ABORT,
  81. } nrf_drv_clock_cal_state_t;
  82. /**@brief CLOCK control block. */
  83. typedef struct
  84. {
  85. bool module_initialized; /*< Indicate the state of module */
  86. volatile bool hfclk_on; /*< High-frequency clock state. */
  87. volatile bool lfclk_on; /*< Low-frequency clock state. */
  88. volatile uint32_t hfclk_requests; /*< High-frequency clock request counter. */
  89. volatile nrf_drv_clock_handler_item_t * p_hf_head;
  90. volatile uint32_t lfclk_requests; /*< Low-frequency clock request counter. */
  91. volatile nrf_drv_clock_handler_item_t * p_lf_head;
  92. #if CALIBRATION_SUPPORT
  93. nrf_drv_clock_handler_item_t cal_hfclk_started_handler_item;
  94. nrf_drv_clock_event_handler_t cal_done_handler;
  95. volatile nrf_drv_clock_cal_state_t cal_state;
  96. #endif // CALIBRATION_SUPPORT
  97. } nrf_drv_clock_cb_t;
  98. static nrf_drv_clock_cb_t m_clock_cb;
  99. static void clock_irq_handler(nrfx_clock_evt_type_t evt);
  100. static void lfclk_stop(void)
  101. {
  102. #if CALIBRATION_SUPPORT
  103. nrfx_clock_calibration_timer_stop();
  104. #endif
  105. #ifdef SOFTDEVICE_PRESENT
  106. // If LFCLK is requested to stop while SD is still enabled,
  107. // it indicates an error in the application.
  108. // Enabling SD should increment the LFCLK request.
  109. ASSERT(!nrf_sdh_is_enabled());
  110. #endif // SOFTDEVICE_PRESENT
  111. // LFCLK can be started independently by the watchdog and cannot be stopped
  112. // by the CLOCK peripheral. This code handles this situation and prevents LFCLK to be stopped.
  113. // Otherwise driver can stuck when waiting for the operation to complete.
  114. if (!nrf_wdt_started())
  115. {
  116. nrfx_clock_lfclk_stop();
  117. m_clock_cb.lfclk_on = false;
  118. }
  119. }
  120. static void hfclk_start(void)
  121. {
  122. #ifdef SOFTDEVICE_PRESENT
  123. if (nrf_sdh_is_enabled())
  124. {
  125. (void)sd_clock_hfclk_request();
  126. return;
  127. }
  128. #endif // SOFTDEVICE_PRESENT
  129. nrfx_clock_hfclk_start();
  130. }
  131. static void hfclk_stop(void)
  132. {
  133. #ifdef SOFTDEVICE_PRESENT
  134. if (nrf_sdh_is_enabled())
  135. {
  136. (void)sd_clock_hfclk_release();
  137. m_clock_cb.hfclk_on = false;
  138. return;
  139. }
  140. #endif // SOFTDEVICE_PRESENT
  141. nrfx_clock_hfclk_stop();
  142. m_clock_cb.hfclk_on = false;
  143. }
  144. bool nrf_drv_clock_init_check(void)
  145. {
  146. return m_clock_cb.module_initialized;
  147. }
  148. ret_code_t nrf_drv_clock_init(void)
  149. {
  150. ret_code_t err_code = NRF_SUCCESS;
  151. if (m_clock_cb.module_initialized)
  152. {
  153. err_code = NRF_ERROR_MODULE_ALREADY_INITIALIZED;
  154. }
  155. else
  156. {
  157. m_clock_cb.p_hf_head = NULL;
  158. m_clock_cb.hfclk_requests = 0;
  159. m_clock_cb.p_lf_head = NULL;
  160. m_clock_cb.lfclk_requests = 0;
  161. err_code = nrfx_clock_init(clock_irq_handler);
  162. #ifdef SOFTDEVICE_PRESENT
  163. if (!nrf_sdh_is_enabled())
  164. #endif
  165. {
  166. nrfx_clock_enable();
  167. }
  168. #if CALIBRATION_SUPPORT
  169. m_clock_cb.cal_state = CAL_STATE_IDLE;
  170. #endif
  171. m_clock_cb.module_initialized = true;
  172. }
  173. if (nrf_wdt_started())
  174. {
  175. m_clock_cb.lfclk_on = true;
  176. }
  177. NRF_LOG_INFO("Function: %s, error code: %s.",
  178. (uint32_t)__func__,
  179. (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
  180. return err_code;
  181. }
  182. void nrf_drv_clock_uninit(void)
  183. {
  184. ASSERT(m_clock_cb.module_initialized);
  185. nrfx_clock_disable();
  186. nrfx_clock_uninit();
  187. m_clock_cb.module_initialized = false;
  188. }
  189. static void item_enqueue(nrf_drv_clock_handler_item_t ** p_head,
  190. nrf_drv_clock_handler_item_t * p_item)
  191. {
  192. nrf_drv_clock_handler_item_t * p_next = *p_head;
  193. while (p_next)
  194. {
  195. if (p_next == p_item)
  196. {
  197. return;
  198. }
  199. p_next = p_next->p_next;
  200. }
  201. p_item->p_next = (*p_head ? *p_head : NULL);
  202. *p_head = p_item;
  203. }
  204. static nrf_drv_clock_handler_item_t * item_dequeue(nrf_drv_clock_handler_item_t ** p_head)
  205. {
  206. nrf_drv_clock_handler_item_t * p_item = *p_head;
  207. if (p_item)
  208. {
  209. *p_head = p_item->p_next;
  210. }
  211. return p_item;
  212. }
  213. void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item)
  214. {
  215. ASSERT(m_clock_cb.module_initialized);
  216. if (m_clock_cb.lfclk_on)
  217. {
  218. if (p_handler_item)
  219. {
  220. p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED);
  221. }
  222. CRITICAL_REGION_ENTER();
  223. ++(m_clock_cb.lfclk_requests);
  224. CRITICAL_REGION_EXIT();
  225. }
  226. else
  227. {
  228. CRITICAL_REGION_ENTER();
  229. if (p_handler_item)
  230. {
  231. item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head,
  232. p_handler_item);
  233. }
  234. if (m_clock_cb.lfclk_requests == 0)
  235. {
  236. nrfx_clock_lfclk_start();
  237. }
  238. ++(m_clock_cb.lfclk_requests);
  239. CRITICAL_REGION_EXIT();
  240. }
  241. ASSERT(m_clock_cb.lfclk_requests > 0);
  242. }
  243. void nrf_drv_clock_lfclk_release(void)
  244. {
  245. ASSERT(m_clock_cb.module_initialized);
  246. ASSERT(m_clock_cb.lfclk_requests > 0);
  247. CRITICAL_REGION_ENTER();
  248. --(m_clock_cb.lfclk_requests);
  249. if (m_clock_cb.lfclk_requests == 0)
  250. {
  251. lfclk_stop();
  252. }
  253. CRITICAL_REGION_EXIT();
  254. }
  255. bool nrf_drv_clock_lfclk_is_running(void)
  256. {
  257. ASSERT(m_clock_cb.module_initialized);
  258. #ifdef SOFTDEVICE_PRESENT
  259. if (nrf_sdh_is_enabled())
  260. {
  261. return true;
  262. }
  263. #endif // SOFTDEVICE_PRESENT
  264. return nrfx_clock_lfclk_is_running();
  265. }
  266. void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item)
  267. {
  268. ASSERT(m_clock_cb.module_initialized);
  269. if (m_clock_cb.hfclk_on)
  270. {
  271. if (p_handler_item)
  272. {
  273. p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
  274. }
  275. CRITICAL_REGION_ENTER();
  276. ++(m_clock_cb.hfclk_requests);
  277. CRITICAL_REGION_EXIT();
  278. }
  279. else
  280. {
  281. CRITICAL_REGION_ENTER();
  282. if (p_handler_item)
  283. {
  284. item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head,
  285. p_handler_item);
  286. }
  287. if (m_clock_cb.hfclk_requests == 0)
  288. {
  289. hfclk_start();
  290. }
  291. ++(m_clock_cb.hfclk_requests);
  292. CRITICAL_REGION_EXIT();
  293. }
  294. ASSERT(m_clock_cb.hfclk_requests > 0);
  295. }
  296. void nrf_drv_clock_hfclk_release(void)
  297. {
  298. ASSERT(m_clock_cb.module_initialized);
  299. ASSERT(m_clock_cb.hfclk_requests > 0);
  300. CRITICAL_REGION_ENTER();
  301. --(m_clock_cb.hfclk_requests);
  302. if (m_clock_cb.hfclk_requests == 0)
  303. {
  304. hfclk_stop();
  305. }
  306. CRITICAL_REGION_EXIT();
  307. }
  308. bool nrf_drv_clock_hfclk_is_running(void)
  309. {
  310. ASSERT(m_clock_cb.module_initialized);
  311. #ifdef SOFTDEVICE_PRESENT
  312. if (nrf_sdh_is_enabled())
  313. {
  314. uint32_t is_running;
  315. UNUSED_VARIABLE(sd_clock_hfclk_is_running(&is_running));
  316. return (is_running ? true : false);
  317. }
  318. #endif // SOFTDEVICE_PRESENT
  319. return nrfx_clock_hfclk_is_running();
  320. }
  321. #if CALIBRATION_SUPPORT
  322. static void clock_calibration_hf_started(nrf_drv_clock_evt_type_t event)
  323. {
  324. if (m_clock_cb.cal_state == CAL_STATE_ABORT)
  325. {
  326. nrf_drv_clock_hfclk_release();
  327. m_clock_cb.cal_state = CAL_STATE_IDLE;
  328. if (m_clock_cb.cal_done_handler)
  329. {
  330. m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED);
  331. }
  332. }
  333. else
  334. {
  335. ASSERT(event == NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
  336. if (nrfx_clock_calibration_start() != NRFX_SUCCESS)
  337. {
  338. ASSERT(false);
  339. }
  340. }
  341. }
  342. #endif // CALIBRATION_SUPPORT
  343. ret_code_t nrf_drv_clock_calibration_start(uint8_t interval, nrf_drv_clock_event_handler_t handler)
  344. {
  345. ret_code_t err_code = NRF_SUCCESS;
  346. #if CALIBRATION_SUPPORT
  347. ASSERT(m_clock_cb.cal_state == CAL_STATE_IDLE);
  348. if (m_clock_cb.lfclk_on == false)
  349. {
  350. err_code = NRF_ERROR_INVALID_STATE;
  351. }
  352. else if (m_clock_cb.cal_state == CAL_STATE_IDLE)
  353. {
  354. m_clock_cb.cal_done_handler = handler;
  355. m_clock_cb.cal_hfclk_started_handler_item.event_handler = clock_calibration_hf_started;
  356. if (interval == 0)
  357. {
  358. m_clock_cb.cal_state = CAL_STATE_HFCLK_REQ;
  359. nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item);
  360. }
  361. else
  362. {
  363. m_clock_cb.cal_state = CAL_STATE_CT;
  364. nrfx_clock_calibration_timer_start(interval);
  365. }
  366. }
  367. else
  368. {
  369. err_code = NRF_ERROR_BUSY;
  370. }
  371. NRF_LOG_WARNING("Function: %s, error code: %s.",
  372. (uint32_t)__func__,
  373. (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
  374. return err_code;
  375. #else
  376. UNUSED_PARAMETER(interval);
  377. UNUSED_PARAMETER(handler);
  378. err_code = NRF_ERROR_FORBIDDEN;
  379. NRF_LOG_WARNING("Function: %s, error code: %s.",
  380. (uint32_t)__func__,
  381. (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
  382. return err_code;
  383. #endif // CALIBRATION_SUPPORT
  384. }
  385. ret_code_t nrf_drv_clock_calibration_abort(void)
  386. {
  387. ret_code_t err_code = NRF_SUCCESS;
  388. #if CALIBRATION_SUPPORT
  389. CRITICAL_REGION_ENTER();
  390. switch (m_clock_cb.cal_state)
  391. {
  392. case CAL_STATE_CT:
  393. nrfx_clock_calibration_timer_stop();
  394. m_clock_cb.cal_state = CAL_STATE_IDLE;
  395. if (m_clock_cb.cal_done_handler)
  396. {
  397. m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED);
  398. }
  399. break;
  400. case CAL_STATE_HFCLK_REQ:
  401. /* fall through. */
  402. case CAL_STATE_CAL:
  403. m_clock_cb.cal_state = CAL_STATE_ABORT;
  404. break;
  405. default:
  406. break;
  407. }
  408. CRITICAL_REGION_EXIT();
  409. NRF_LOG_INFO("Function: %s, error code: %s.",
  410. (uint32_t)__func__,
  411. (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
  412. return err_code;
  413. #else
  414. err_code = NRF_ERROR_FORBIDDEN;
  415. NRF_LOG_WARNING("Function: %s, error code: %s.",
  416. (uint32_t)__func__,
  417. (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
  418. return err_code;
  419. #endif // CALIBRATION_SUPPORT
  420. }
  421. ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating)
  422. {
  423. ret_code_t err_code = NRF_SUCCESS;
  424. #if CALIBRATION_SUPPORT
  425. ASSERT(m_clock_cb.module_initialized);
  426. *p_is_calibrating = (m_clock_cb.cal_state != CAL_STATE_IDLE);
  427. NRF_LOG_INFO("Function: %s, error code: %s.",
  428. (uint32_t)__func__,
  429. (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
  430. return err_code;
  431. #else
  432. UNUSED_PARAMETER(p_is_calibrating);
  433. err_code = NRF_ERROR_FORBIDDEN;
  434. NRF_LOG_WARNING("Function: %s, error code: %s.",
  435. (uint32_t)__func__,
  436. (uint32_t)NRF_LOG_ERROR_STRING_GET(err_code));
  437. return err_code;
  438. #endif // CALIBRATION_SUPPORT
  439. }
  440. __STATIC_INLINE void clock_clk_started_notify(nrf_drv_clock_evt_type_t evt_type)
  441. {
  442. nrf_drv_clock_handler_item_t **p_head;
  443. if (evt_type == NRF_DRV_CLOCK_EVT_HFCLK_STARTED)
  444. {
  445. p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head;
  446. }
  447. else
  448. {
  449. p_head = (nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head;
  450. }
  451. while (1)
  452. {
  453. nrf_drv_clock_handler_item_t * p_item = item_dequeue(p_head);
  454. if (!p_item)
  455. {
  456. break;
  457. }
  458. p_item->event_handler(evt_type);
  459. }
  460. }
  461. static void clock_irq_handler(nrfx_clock_evt_type_t evt)
  462. {
  463. if (evt == NRFX_CLOCK_EVT_HFCLK_STARTED)
  464. {
  465. m_clock_cb.hfclk_on = true;
  466. clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
  467. }
  468. if (evt == NRFX_CLOCK_EVT_LFCLK_STARTED)
  469. {
  470. m_clock_cb.lfclk_on = true;
  471. clock_clk_started_notify(NRF_DRV_CLOCK_EVT_LFCLK_STARTED);
  472. }
  473. #if CALIBRATION_SUPPORT
  474. if (evt == NRFX_CLOCK_EVT_CTTO)
  475. {
  476. nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item);
  477. }
  478. if (evt == NRFX_CLOCK_EVT_CAL_DONE)
  479. {
  480. nrf_drv_clock_hfclk_release();
  481. bool aborted = (m_clock_cb.cal_state == CAL_STATE_ABORT);
  482. m_clock_cb.cal_state = CAL_STATE_IDLE;
  483. if (m_clock_cb.cal_done_handler)
  484. {
  485. m_clock_cb.cal_done_handler(aborted ?
  486. NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE);
  487. }
  488. }
  489. #endif // CALIBRATION_SUPPORT
  490. }
  491. #ifdef SOFTDEVICE_PRESENT
  492. /**
  493. * @brief SoftDevice SoC event handler.
  494. *
  495. * @param[in] evt_id SoC event.
  496. * @param[in] p_context Context.
  497. */
  498. static void soc_evt_handler(uint32_t evt_id, void * p_context)
  499. {
  500. if (evt_id == NRF_EVT_HFCLKSTARTED)
  501. {
  502. m_clock_cb.hfclk_on = true;
  503. clock_clk_started_notify(NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
  504. }
  505. }
  506. NRF_SDH_SOC_OBSERVER(m_soc_evt_observer, CLOCK_CONFIG_SOC_OBSERVER_PRIO, soc_evt_handler, NULL);
  507. /**
  508. * @brief SoftDevice enable/disable state handler.
  509. *
  510. * @param[in] state State.
  511. * @param[in] p_context Context.
  512. */
  513. static void sd_state_evt_handler(nrf_sdh_state_evt_t state, void * p_context)
  514. {
  515. switch (state)
  516. {
  517. case NRF_SDH_EVT_STATE_ENABLE_PREPARE:
  518. NVIC_DisableIRQ(POWER_CLOCK_IRQn);
  519. break;
  520. case NRF_SDH_EVT_STATE_ENABLED:
  521. CRITICAL_REGION_ENTER();
  522. /* Make sure that nrf_drv_clock module is initialized */
  523. if (!m_clock_cb.module_initialized)
  524. {
  525. (void)nrf_drv_clock_init();
  526. }
  527. /* SD is one of the LFCLK requesters, but it will enable it by itself. */
  528. ++(m_clock_cb.lfclk_requests);
  529. m_clock_cb.lfclk_on = true;
  530. CRITICAL_REGION_EXIT();
  531. break;
  532. case NRF_SDH_EVT_STATE_DISABLED:
  533. /* Reinit interrupts */
  534. ASSERT(m_clock_cb.module_initialized);
  535. nrfx_clock_enable();
  536. /* SD leaves LFCLK enabled - disable it if it is no longer required. */
  537. nrf_drv_clock_lfclk_release();
  538. break;
  539. default:
  540. break;
  541. }
  542. }
  543. NRF_SDH_STATE_OBSERVER(m_sd_state_observer, CLOCK_CONFIG_STATE_OBSERVER_PRIO) =
  544. {
  545. .handler = sd_state_evt_handler,
  546. .p_context = NULL,
  547. };
  548. #endif // SOFTDEVICE_PRESENT
  549. #undef NRF_CLOCK_LFCLK_RC
  550. #undef NRF_CLOCK_LFCLK_Xtal
  551. #undef NRF_CLOCK_LFCLK_Synth
  552. #endif // NRF_MODULE_ENABLED(NRF_CLOCK)