nrf21540.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /**
  2. * Copyright (c) 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 "nrf21540.h"
  41. #include "nrf_assert.h"
  42. #include "nrf21540_defs.h"
  43. #include "nrf21540_macro.h"
  44. #include "nrf_radio.h"
  45. #include "nrf_ppi.h"
  46. #include "nrf_gpiote.h"
  47. #include "nrf_timer.h"
  48. #include "boards.h"
  49. #if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
  50. #include "nrf_egu.h"
  51. #endif
  52. #define NRF21540_BUSY_CHECK(mode) \
  53. if (mode == NRF21540_EXEC_MODE_BLOCKING) \
  54. { \
  55. while(is_driver_busy()) \
  56. { \
  57. \
  58. } \
  59. } \
  60. else if (is_driver_busy()) \
  61. { \
  62. return NRF_ERROR_BUSY; \
  63. }
  64. #define NRF21540_ERROR_CHECK(invalid_state_condition) \
  65. if (device_state_get() == NRF21540_STATE_ERROR) \
  66. { \
  67. m_nrf21540_data.busy = false; \
  68. return NRF_ERROR_INTERNAL; \
  69. } \
  70. if (invalid_state_condition) \
  71. { \
  72. m_nrf21540_data.busy = false; \
  73. return NRF_ERROR_INVALID_STATE; \
  74. }
  75. /**@brief nRF21540 chip state.
  76. *
  77. * @details driver state variable possible values.
  78. */
  79. typedef enum {
  80. NRF21540_STATE_OFF, ///< Chip inactive, line PDN is low, SPI communication impossible.
  81. NRF21540_STATE_READY, ///< SPI is active, but nether transmit nor receive can be performed.
  82. NRF21540_STATE_TX, ///< Transmit state - chip can perform transmiting data.
  83. NRF21540_STATE_RX, ///< Receive state - chip can receive data.
  84. NRF21540_STATE_ERROR, ///< Invalid state - requires reinit.
  85. } nrf21540_state_t;
  86. /**@brief nRF21540 static data. */
  87. static struct
  88. {
  89. volatile nrf21540_state_t cur_state; ///< driver state variable.
  90. volatile nrf21540_trx_t cur_direction; ///< currently serviced radio communication direction.
  91. volatile bool busy; ///< driver is busy at the moment (during changing state phase).
  92. #if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
  93. volatile uint32_t shorts;
  94. #endif
  95. } m_nrf21540_data;
  96. /**@brief Function checks if nRF21540 driver is busy now.
  97. *
  98. * @details Based on driver busy variable.
  99. *
  100. * @return true if nRF21540 driver is busy.
  101. */
  102. static inline bool is_driver_busy(void)
  103. {
  104. return m_nrf21540_data.busy;
  105. }
  106. /**@brief Function checks if nRF21540 is powered down.
  107. *
  108. * @details Based on driver state variable.
  109. *
  110. * @return true if nRF21540 is in power down state.
  111. */
  112. static inline bool is_device_off(void)
  113. {
  114. return m_nrf21540_data.cur_state == NRF21540_STATE_OFF;
  115. }
  116. /**@brief Function checks if nRF21540 is powered up state.
  117. *
  118. * @details Based on driver state variable.
  119. *
  120. * @return true if nRF21540 is in power up state.
  121. */
  122. static inline bool is_device_on(void)
  123. {
  124. return m_nrf21540_data.cur_state != NRF21540_STATE_OFF;
  125. }
  126. /**@brief Function checks if nRF21540 can transmit or receive data.
  127. *
  128. * @details Based on driver state variable.
  129. *
  130. * @return true if nRF21540 is in TX or RX mode.
  131. */
  132. static inline bool is_device_ready_for_transmission(void)
  133. {
  134. return (m_nrf21540_data.cur_state == NRF21540_STATE_TX ||
  135. m_nrf21540_data.cur_state == NRF21540_STATE_RX);
  136. }
  137. /**@brief Function changes driver state.
  138. *
  139. * @details Changes driver state variable value.
  140. *
  141. * @param[in] new_state state that will be store.
  142. */
  143. static inline void device_state_set(nrf21540_state_t new_state)
  144. {
  145. m_nrf21540_data.cur_state = new_state;
  146. }
  147. /**@brief Function returns driver state variable value.
  148. *
  149. * @details Based on driver state variable.
  150. *
  151. * @return @ref nrf21540_state_t based state variable value.
  152. */
  153. static inline nrf21540_state_t device_state_get(void)
  154. {
  155. return m_nrf21540_data.cur_state;
  156. }
  157. /**@brief Function returns task related to transmission direction.
  158. *
  159. * @param[in] dir direction of radio transfer. See @nrf21540_trx_t.
  160. *
  161. * @return task corresponding to given transmission direction.
  162. */
  163. static inline nrf_radio_task_t nrf21540_task_get(nrf21540_trx_t dir)
  164. {
  165. return dir == NRF21540_TX ? NRF_RADIO_TASK_TXEN : NRF_RADIO_TASK_RXEN;
  166. }
  167. /**@brief Function clears and disbles all PPI connections used by nRF21540 driver.
  168. *
  169. * @details Changes driver state variable value.
  170. */
  171. static void ppi_cleanup(void)
  172. {
  173. nrf_ppi_channel_disable(NRF21540_PDN_PPI_CHANNEL);
  174. nrf_ppi_channel_disable(NRF21540_USER_PPI_CHANNEL);
  175. nrf_ppi_channel_disable(NRF21540_TRX_PPI_CHANNEL);
  176. nrf_ppi_channel_and_fork_endpoint_setup(NRF21540_PDN_PPI_CHANNEL, 0, 0, 0);
  177. nrf_ppi_channel_and_fork_endpoint_setup(NRF21540_USER_PPI_CHANNEL, 0, 0, 0);
  178. nrf_ppi_channel_and_fork_endpoint_setup(NRF21540_TRX_PPI_CHANNEL, 0, 0, 0);
  179. }
  180. /**@brief Function clears nRF21540 driver events. */
  181. static void events_clear()
  182. {
  183. nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT);
  184. nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_START_TO_PDN_UP_EVENT);
  185. NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_READY);
  186. NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_DISABLED);
  187. }
  188. /**@brief Timer interrupt handler.
  189. *
  190. * @details checking time related events occurences and changing driver state if necessary.
  191. */
  192. void NRF21540_TIMER_IRQ_HANDLER(void)
  193. {
  194. if (nrf_timer_event_check(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT))
  195. {
  196. nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT);
  197. if (is_device_off() && nrf_gpio_pin_read(NRF21540_PDN_PIN) == 1)
  198. {
  199. device_state_set(NRF21540_STATE_READY);
  200. }
  201. else if (is_device_on() && nrf_gpio_pin_read(NRF21540_PDN_PIN) == 0)
  202. {
  203. device_state_set(NRF21540_STATE_OFF);
  204. ppi_cleanup();
  205. m_nrf21540_data.busy = false;
  206. }
  207. else
  208. {
  209. device_state_set(NRF21540_STATE_ERROR);
  210. ppi_cleanup();
  211. m_nrf21540_data.busy = false;
  212. }
  213. }
  214. }
  215. /**@brief nRF21540 interrupt handler.
  216. *
  217. * @details checking radio related events occurences and changing driver state if necessary.
  218. */
  219. void NRF21540_RADIO_IRQ_HANDLER(void)
  220. {
  221. if (NRF21540_RADIO_EVENT_CHECK(NRF21540_RADIO_EVENT_READY))
  222. {
  223. NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_READY);
  224. nrf_ppi_channel_disable(NRF21540_USER_PPI_CHANNEL);
  225. #if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
  226. if (NRF21540_RADIO_SHORTS_ENABLE_CHECK(RADIO_SHORTS_READY_START_Msk))
  227. {
  228. nrf_radio_task_trigger(NRF_RADIO_TASK_START);
  229. }
  230. #endif
  231. if (device_state_get() == NRF21540_STATE_READY)
  232. {
  233. device_state_set(m_nrf21540_data.cur_direction == NRF21540_TX ?
  234. NRF21540_STATE_TX : NRF21540_STATE_RX);
  235. ppi_cleanup();
  236. NRF21540_RADIO_INT_DISABLE(NRF21540_RADIO_READY_Msk);
  237. m_nrf21540_data.busy = false;
  238. }
  239. }
  240. if (NRF21540_RADIO_EVENT_CHECK(NRF21540_RADIO_EVENT_DISABLED))
  241. {
  242. NRF21540_RADIO_EVENT_CLEAR(NRF21540_RADIO_EVENT_DISABLED);
  243. nrf_ppi_channel_disable(NRF21540_USER_PPI_CHANNEL);
  244. nrf_timer_task_trigger(NRF21540_TIMER, NRF_TIMER_TASK_START);
  245. if (is_device_ready_for_transmission())
  246. {
  247. NRF21540_RADIO_INT_DISABLE(NRF21540_RADIO_DISABLED_Msk);
  248. device_state_set(NRF21540_STATE_READY);
  249. }
  250. }
  251. }
  252. /**@brief Function resets nRF21540 driver.
  253. *
  254. * @details sets driver state variable to NRF21540_STATE_OFF value,
  255. * cleans all used PPIs and events.
  256. */
  257. static void driver_reset(void)
  258. {
  259. device_state_set(NRF21540_STATE_OFF);
  260. ppi_cleanup();
  261. events_clear();
  262. NRF21540_RADIO_INT_DISABLE(NRF21540_RADIO_INTERRUPT_MASK);
  263. m_nrf21540_data.busy = false;
  264. }
  265. /**@brief Function sets either TX or RX direction.
  266. *
  267. * @details Configuration of all necessarily peripherals to transmit or receive data,
  268. * dependenly on interface used (SPI, or GPIO). Procedure configures nRF21540 chip and
  269. * starts transmitting/receiving. Procedure will be started immediately if
  270. * @ref trigger_event is 0. Otherwise event which address is @ref trigger_event value
  271. * will start procedure.
  272. *
  273. * @param[in] dir RX or TX communication that will be performed.
  274. * @param[in] trigger_event address of event which will trigger the procedure.
  275. * @param[in] mode if NRF21540_EXEC_MODE_BLOCKING the function will wait for tx/rx
  276. * possibility.
  277. * @return NRF_ERROR_INTERNAL when driver is in error state.
  278. * Reinitialization is required.
  279. * NRF_ERROR_INVALID_STATE when nRF21540's state isn't proper
  280. * to perform the operation (@sa nrf21540_state_t).
  281. * NRF_ERROR_BUSY when driver performs another operation at
  282. * the moment.
  283. * NRF_SUCCESS on success.
  284. */
  285. static ret_code_t trx_set(nrf21540_trx_t dir, uint32_t trigger_event,
  286. nrf21540_execution_mode_t mode)
  287. {
  288. ASSERT(!(mode == NRF21540_EXEC_MODE_BLOCKING && trigger_event != 0));
  289. NRF21540_BUSY_CHECK(mode);
  290. NRF21540_ERROR_CHECK((dir == NRF21540_TX && device_state_get() == NRF21540_STATE_TX) ||
  291. (dir == NRF21540_RX && device_state_get() == NRF21540_STATE_RX));
  292. uint32_t ramp_up_time = nrf_radio_modecnf0_ru_get() ? FAST_RAMP_UP_TIME : RAMP_UP_TIME;
  293. nrf_radio_task_t radio_task_to_start = nrf21540_task_get(dir);
  294. m_nrf21540_data.busy = true;
  295. events_clear();
  296. NRF21540_RADIO_INT_ENABLE(NRF21540_RADIO_READY_Msk);
  297. if (is_device_off())
  298. {
  299. nrf_ppi_channel_endpoint_setup(NRF21540_PDN_PPI_CHANNEL,
  300. (uint32_t)nrf_timer_event_address_get(NRF21540_TIMER,
  301. NRF21540_TIMER_CC_START_TO_PDN_UP_EVENT),
  302. nrf_gpiote_task_addr_get(NRF21540_PDN_GPIOTE_TASK_SET));
  303. nrf_ppi_channel_enable(NRF21540_PDN_PPI_CHANNEL);
  304. nrf_timer_cc_write(NRF21540_TIMER,
  305. NRF21540_TIMER_CC_PD_PG_CHANNEL,
  306. ramp_up_time - NRF21540_PA_PG_TRX_TIME_US);
  307. nrf_timer_cc_write(NRF21540_TIMER,
  308. NRF21540_TIMER_CC_START_TO_PDN_UP_CHANNEL,
  309. ramp_up_time - NRF21540_PA_PG_TRX_TIME_US - NRF21540_PD_PG_TIME_US);
  310. #if NRF21540_USE_GPIO_MANAGEMENT
  311. nrf21540_gpio_trx_enable(dir);
  312. #elif NRF21540_USE_SPI_MANAGEMENT
  313. nrf21540_spim_for_trx_configure(dir, NRF21540_ENABLE);
  314. #endif
  315. nrf_timer_shorts_enable(NRF21540_TIMER,
  316. NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK |
  317. NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK);
  318. NRF21540_RADIO_SHORTS_ENABLE(RADIO_SHORTS_READY_START_Msk);
  319. if (trigger_event == 0)
  320. {
  321. //start immediately.
  322. nrf_timer_task_trigger(NRF21540_TIMER, NRF_TIMER_TASK_START);
  323. nrf_radio_task_trigger(radio_task_to_start);
  324. }
  325. else
  326. {
  327. //start when user event occurs.
  328. nrf_ppi_channel_and_fork_endpoint_setup(
  329. NRF21540_USER_PPI_CHANNEL,
  330. trigger_event,
  331. (uint32_t) nrf_timer_task_address_get(NRF21540_TIMER, NRF_TIMER_TASK_START),
  332. (uint32_t) nrf_radio_task_address_get(radio_task_to_start));
  333. nrf_ppi_channel_enable(NRF21540_USER_PPI_CHANNEL);
  334. }
  335. }
  336. else
  337. {
  338. // at the moment we are not able to switch direction on the fly.
  339. // @todo switching between RXEN and TXEN.
  340. NRF21540_ERROR_CHECK(device_state_get() == NRF21540_STATE_RX);
  341. if (trigger_event == 0)
  342. {
  343. nrf_radio_task_trigger(radio_task_to_start);
  344. }
  345. else
  346. {
  347. // start when user event occurs
  348. nrf_ppi_channel_endpoint_setup(
  349. NRF21540_USER_PPI_CHANNEL,
  350. trigger_event,
  351. (uint32_t) nrf_radio_task_address_get(radio_task_to_start));
  352. nrf_ppi_channel_enable(NRF21540_USER_PPI_CHANNEL);
  353. }
  354. }
  355. m_nrf21540_data.cur_direction = dir;
  356. if (mode == NRF21540_EXEC_MODE_BLOCKING)
  357. {
  358. while (!is_device_ready_for_transmission());
  359. }
  360. return NRF_SUCCESS;
  361. }
  362. ret_code_t nrf21540_init(void)
  363. {
  364. driver_reset();
  365. // GPIOTE for PDN pin configuration
  366. nrf_gpiote_task_configure(NRF21540_PDN_GPIOTE_CHANNEL_NO,
  367. NRF21540_PDN_PIN,
  368. (nrf_gpiote_polarity_t) GPIOTE_CONFIG_POLARITY_None,
  369. NRF_GPIOTE_INITIAL_VALUE_LOW);
  370. nrf_gpiote_task_enable(NRF21540_PDN_GPIOTE_CHANNEL_NO);
  371. nrf21540_gpio_init();
  372. NVIC_SetPriority(NRF21540_TIMER_IRQn, NRF21540_INTERRUPT_PRIORITY);
  373. NVIC_EnableIRQ(NRF21540_TIMER_IRQn);
  374. nrf_timer_int_enable(NRF21540_TIMER, NRF21540_TIM_INTERRUPT_MASK);
  375. #if NRF21540_USE_SPI_MANAGEMENT
  376. ret_code_t ret = NRF_SUCCESS;
  377. ret = nrf21540_spi_init();
  378. if (ret != NRF_SUCCESS)
  379. {
  380. device_state_set(NRF21540_STATE_ERROR);
  381. return ret;
  382. }
  383. #endif //NRF21540_USE_SPI_MANAGEMENT
  384. #if NRF21540_DO_NOT_USE_NATIVE_RADIO_IRQ_HANDLER
  385. nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL,
  386. nrf_radio_event_address_get(NRF_RADIO_EVENT_READY),
  387. (uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_READY_EGU_TASK));
  388. nrf_ppi_channel_enable(NRF21540_RADIO_READY_TO_EGU_PPI_CHANNEL);
  389. nrf_ppi_channel_endpoint_setup(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL,
  390. nrf_radio_event_address_get(NRF_RADIO_EVENT_DISABLED),
  391. (uint32_t)nrf_egu_task_address_get(NRF21540_EGU, NRF21540_RADIO_DISABLED_EGU_TASK));
  392. nrf_ppi_channel_enable(NRF21540_RADIO_DISABLED_TO_EGU_PPI_CHANNEL);
  393. #endif
  394. NVIC_SetPriority(NRF21540_RADIO_IRQn, NRF21540_INTERRUPT_PRIORITY);
  395. NVIC_EnableIRQ(NRF21540_RADIO_IRQn);
  396. return NRF_SUCCESS;
  397. }
  398. ret_code_t nrf21540_pdn_drive(bool state, nrf21540_execution_mode_t mode)
  399. {
  400. NRF21540_BUSY_CHECK(mode);
  401. NRF21540_ERROR_CHECK((state == true && is_device_on()) ||
  402. (state == false && is_device_off()));
  403. nrf21540_state_t final_state;
  404. if (state)
  405. {
  406. final_state = NRF21540_STATE_READY;
  407. }
  408. else
  409. {
  410. final_state = NRF21540_STATE_OFF;
  411. }
  412. nrf_timer_cc_write(NRF21540_TIMER,
  413. NRF21540_TIMER_CC_PD_PG_CHANNEL,
  414. state ? NRF21540_PD_PG_TIME_US : 0);
  415. nrf_timer_shorts_enable(NRF21540_TIMER,
  416. NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK |
  417. NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK);
  418. nrf_timer_event_clear(NRF21540_TIMER, NRF21540_TIMER_CC_PD_PG_EVENT);
  419. nrf_gpiote_task_force(NRF21540_PDN_GPIOTE_CHANNEL_NO,
  420. !state ? NRF_GPIOTE_INITIAL_VALUE_LOW : NRF_GPIOTE_INITIAL_VALUE_HIGH);
  421. nrf_timer_task_trigger(NRF21540_TIMER, NRF_TIMER_TASK_START);
  422. if (mode == NRF21540_EXEC_MODE_BLOCKING)
  423. {
  424. while (device_state_get() != final_state)
  425. {
  426. }
  427. }
  428. return NRF_SUCCESS;
  429. }
  430. ret_code_t nrf21540_tx_set(uint32_t user_trigger_event, nrf21540_execution_mode_t mode)
  431. {
  432. NRF21540_ERROR_CHECK(device_state_get() == NRF21540_STATE_TX);
  433. return trx_set(NRF21540_TX, user_trigger_event, mode);
  434. }
  435. ret_code_t nrf21540_rx_set(uint32_t user_trigger_event, nrf21540_execution_mode_t mode)
  436. {
  437. NRF21540_ERROR_CHECK(device_state_get() == NRF21540_STATE_RX);
  438. return trx_set(NRF21540_RX, user_trigger_event, mode);
  439. }
  440. bool nrf21540_is_error(void)
  441. {
  442. return device_state_get() == NRF21540_STATE_ERROR ? true : false;
  443. }
  444. ret_code_t nrf21540_ant_set(nrf21540_antenna_t antenna)
  445. {
  446. NRF21540_BUSY_CHECK(NRF21540_EXEC_MODE_NON_BLOCKING);
  447. return nrf21540_gpio_ant_set(antenna);
  448. }
  449. ret_code_t nrf21540_pwr_mode_set(nrf21540_pwr_mode_t mode)
  450. {
  451. NRF21540_BUSY_CHECK(NRF21540_EXEC_MODE_NON_BLOCKING);
  452. #if NRF21540_USE_GPIO_MANAGEMENT
  453. return nrf21540_gpio_pwr_mode_set(mode);
  454. #elif NRF21540_USE_SPI_MANAGEMENT
  455. return nrf21540_spi_pwr_mode_set(mode);
  456. #endif
  457. }
  458. ret_code_t nrf21540_power_down(uint32_t user_trigger_event, nrf21540_execution_mode_t mode)
  459. {
  460. ASSERT(!(mode == NRF21540_EXEC_MODE_BLOCKING && user_trigger_event != 0));
  461. NRF21540_ERROR_CHECK(is_device_off());
  462. NRF21540_BUSY_CHECK(mode);
  463. m_nrf21540_data.busy = true;
  464. events_clear();
  465. NRF21540_RADIO_INT_ENABLE(NRF21540_RADIO_DISABLED_Msk);
  466. if (device_state_get() == NRF21540_STATE_READY)
  467. {
  468. // when device is in ready state we jus driving PDN line down and switch off the radio.
  469. (void)nrf21540_pdn_drive(false, NRF21540_EXEC_MODE_NON_BLOCKING);
  470. nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
  471. }
  472. else
  473. {
  474. // When device is in tx/rx state we have to leave it and then drive PDN down.
  475. // Line PDN should be driven low after 5us from triggering TXEN/RXEN.
  476. uint32_t * trx_drv_task_address;
  477. nrf21540_trx_t cur_direction;
  478. if (device_state_get() == NRF21540_STATE_TX)
  479. {
  480. cur_direction = NRF21540_TX;
  481. }
  482. else if (device_state_get() == NRF21540_STATE_RX)
  483. {
  484. cur_direction = NRF21540_RX;
  485. }
  486. else
  487. {
  488. return NRF_ERROR_INTERNAL;
  489. }
  490. nrf_ppi_channel_endpoint_setup(NRF21540_PDN_PPI_CHANNEL,
  491. (uint32_t)nrf_timer_event_address_get(NRF21540_TIMER,
  492. NRF21540_TIMER_CC_TRX_PG_EVENT),
  493. nrf_gpiote_task_addr_get(NRF21540_PDN_GPIOTE_TASK_CLR));
  494. nrf_ppi_channel_enable(NRF21540_PDN_PPI_CHANNEL);
  495. nrf_timer_shorts_enable(NRF21540_TIMER,
  496. NRF21540_TIMER_CC_FINISHED_CHANNEL_STOP_MASK |
  497. NRF21540_TIMER_CC_FINISHED_CHANNEL_CLEAR_MASK);
  498. nrf_timer_cc_write(NRF21540_TIMER,
  499. NRF21540_TIMER_CC_TRX_PG_CHANNEL,
  500. NRF21540_TRX_PG_TIME_US);
  501. #if NRF21540_USE_GPIO_MANAGEMENT
  502. trx_drv_task_address = (uint32_t*) nrf21540_gpio_trx_task_start_address_get(cur_direction,
  503. NRF21540_DISABLE);
  504. #elif NRF21540_USE_SPI_MANAGEMENT
  505. nrf21540_spim_for_trx_configure(cur_direction, NRF21540_DISABLE);
  506. trx_drv_task_address = (uint32_t*) nrf21540_spim_trx_task_start_address_get();
  507. #endif
  508. if (user_trigger_event == 0)
  509. {
  510. *trx_drv_task_address = 1;
  511. nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
  512. }
  513. else
  514. {
  515. // start when user event occurs.
  516. nrf_ppi_channel_and_fork_endpoint_setup(
  517. NRF21540_USER_PPI_CHANNEL,
  518. user_trigger_event,
  519. (uint32_t)nrf_radio_task_address_get(NRF_RADIO_TASK_DISABLE),
  520. (uint32_t) trx_drv_task_address);
  521. nrf_ppi_channel_enable(NRF21540_USER_PPI_CHANNEL);
  522. }
  523. if (mode == NRF21540_EXEC_MODE_BLOCKING)
  524. {
  525. while (is_device_on());
  526. }
  527. }
  528. return NRF_SUCCESS;
  529. }