nrfx_ppi.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. /**
  2. * Copyright (c) 2015 - 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 <nrfx.h>
  41. #if NRFX_CHECK(NRFX_PPI_ENABLED)
  42. #include <nrfx_ppi.h>
  43. #define NRFX_LOG_MODULE PPI
  44. #include <nrfx_log.h>
  45. static uint32_t m_channels_allocated; /**< Bitmap representing channels availability. 1 when a channel is allocated, 0 otherwise. */
  46. static uint8_t m_groups_allocated; /**< Bitmap representing groups availability. 1 when a group is allocated, 0 otherwise.*/
  47. /**
  48. * @brief Compute a group mask (needed for driver internals, not used for NRF_PPI registers).
  49. *
  50. * @param[in] group Group number to transform to a mask.
  51. *
  52. * @retval Group mask.
  53. */
  54. __STATIC_INLINE uint32_t group_to_mask(nrf_ppi_channel_group_t group)
  55. {
  56. return (1uL << (uint32_t) group);
  57. }
  58. /**
  59. * @brief Check whether a channel is a programmable channel and can be used by an application.
  60. *
  61. * @param[in] channel Channel to check.
  62. *
  63. * @retval true The channel is a programmable application channel.
  64. * @retval false The channel is used by a stack (for example SoftDevice) or is preprogrammed.
  65. */
  66. __STATIC_INLINE bool is_programmable_app_channel(nrf_ppi_channel_t channel)
  67. {
  68. return ((NRFX_PPI_PROG_APP_CHANNELS_MASK & nrfx_ppi_channel_to_mask(channel)) != 0);
  69. }
  70. /**
  71. * @brief Check whether channels can be used by an application.
  72. *
  73. * @param[in] channel_mask Channel mask to check.
  74. *
  75. * @retval true All specified channels can be used by an application.
  76. * @retval false At least one specified channel is used by a stack (for example SoftDevice).
  77. */
  78. __STATIC_INLINE bool are_app_channels(uint32_t channel_mask)
  79. {
  80. //lint -e(587)
  81. return ((~(NRFX_PPI_ALL_APP_CHANNELS_MASK) & channel_mask) == 0);
  82. }
  83. /**
  84. * @brief Check whether a channel can be used by an application.
  85. *
  86. * @param[in] channel Channel to check.
  87. *
  88. * @retval true The channel can be used by an application.
  89. * @retval false The channel is used by a stack (for example SoftDevice).
  90. */
  91. __STATIC_INLINE bool is_app_channel(nrf_ppi_channel_t channel)
  92. {
  93. return are_app_channels(nrfx_ppi_channel_to_mask(channel));
  94. }
  95. /**
  96. * @brief Check whether a channel group can be used by an application.
  97. *
  98. * @param[in] group Group to check.
  99. *
  100. * @retval true The group is an application group.
  101. * @retval false The group is not an application group (this group either does not exist or
  102. * it is used by a stack (for example SoftDevice)).
  103. */
  104. __STATIC_INLINE bool is_app_group(nrf_ppi_channel_group_t group)
  105. {
  106. return ((NRFX_PPI_ALL_APP_GROUPS_MASK & group_to_mask(group)) != 0);
  107. }
  108. /**
  109. * @brief Check whether a channel is allocated.
  110. *
  111. * @param[in] channel_num Channel number to check.
  112. *
  113. * @retval true The channel is allocated.
  114. * @retval false The channel is not allocated.
  115. */
  116. __STATIC_INLINE bool is_allocated_channel(nrf_ppi_channel_t channel)
  117. {
  118. return ((m_channels_allocated & nrfx_ppi_channel_to_mask(channel)) != 0);
  119. }
  120. /**
  121. * @brief Set channel allocated indication.
  122. *
  123. * @param[in] channel_num Specifies the channel to set the "allocated" indication.
  124. */
  125. __STATIC_INLINE void channel_allocated_set(nrf_ppi_channel_t channel)
  126. {
  127. m_channels_allocated |= nrfx_ppi_channel_to_mask(channel);
  128. }
  129. /**
  130. * @brief Clear channel allocated indication.
  131. *
  132. * @param[in] channel_num Specifies the channel to clear the "allocated" indication.
  133. */
  134. __STATIC_INLINE void channel_allocated_clr(nrf_ppi_channel_t channel)
  135. {
  136. m_channels_allocated &= ~nrfx_ppi_channel_to_mask(channel);
  137. }
  138. /**
  139. * @brief Clear all allocated channels.
  140. */
  141. __STATIC_INLINE void channel_allocated_clr_all(void)
  142. {
  143. m_channels_allocated &= ~NRFX_PPI_ALL_APP_CHANNELS_MASK;
  144. }
  145. /**
  146. * @brief Check whether a group is allocated.
  147. *
  148. * @param[in] group_num Group number to check.
  149. *
  150. * @retval true The group is allocated.
  151. * false The group is not allocated.
  152. */
  153. __STATIC_INLINE bool is_allocated_group(nrf_ppi_channel_group_t group)
  154. {
  155. return ((m_groups_allocated & group_to_mask(group)) != 0);
  156. }
  157. /**
  158. * @brief Set group allocated indication.
  159. *
  160. * @param[in] group_num Specifies the group to set the "allocated" indication.
  161. */
  162. __STATIC_INLINE void group_allocated_set(nrf_ppi_channel_group_t group)
  163. {
  164. m_groups_allocated |= group_to_mask(group);
  165. }
  166. /**
  167. * @brief Clear group allocated indication.
  168. *
  169. * @param[in] group_num Specifies the group to clear the "allocated" indication.
  170. */
  171. __STATIC_INLINE void group_allocated_clr(nrf_ppi_channel_group_t group)
  172. {
  173. m_groups_allocated &= ~group_to_mask(group);
  174. }
  175. /**
  176. * @brief Clear all allocated groups.
  177. */
  178. __STATIC_INLINE void group_allocated_clr_all()
  179. {
  180. m_groups_allocated &= ~NRFX_PPI_ALL_APP_GROUPS_MASK;
  181. }
  182. void nrfx_ppi_free_all(void)
  183. {
  184. uint32_t mask = NRFX_PPI_ALL_APP_GROUPS_MASK;
  185. nrf_ppi_channel_group_t group;
  186. // Disable all channels and groups
  187. nrf_ppi_channels_disable(NRFX_PPI_ALL_APP_CHANNELS_MASK);
  188. for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++)
  189. {
  190. if (mask & group_to_mask(group))
  191. {
  192. nrf_ppi_channel_group_clear(group);
  193. }
  194. }
  195. channel_allocated_clr_all();
  196. group_allocated_clr_all();
  197. }
  198. nrfx_err_t nrfx_ppi_channel_alloc(nrf_ppi_channel_t * p_channel)
  199. {
  200. nrfx_err_t err_code = NRFX_SUCCESS;
  201. nrf_ppi_channel_t channel;
  202. uint32_t mask = 0;
  203. err_code = NRFX_ERROR_NO_MEM;
  204. mask = NRFX_PPI_PROG_APP_CHANNELS_MASK;
  205. for (channel = NRF_PPI_CHANNEL0;
  206. mask != 0;
  207. mask &= ~nrfx_ppi_channel_to_mask(channel), channel++)
  208. {
  209. NRFX_CRITICAL_SECTION_ENTER();
  210. if ((mask & nrfx_ppi_channel_to_mask(channel)) && (!is_allocated_channel(channel)))
  211. {
  212. channel_allocated_set(channel);
  213. *p_channel = channel;
  214. err_code = NRFX_SUCCESS;
  215. }
  216. NRFX_CRITICAL_SECTION_EXIT();
  217. if (err_code == NRFX_SUCCESS)
  218. {
  219. NRFX_LOG_INFO("Allocated channel: %d.", channel);
  220. break;
  221. }
  222. }
  223. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  224. return err_code;
  225. }
  226. nrfx_err_t nrfx_ppi_channel_free(nrf_ppi_channel_t channel)
  227. {
  228. nrfx_err_t err_code = NRFX_SUCCESS;
  229. if (!is_programmable_app_channel(channel))
  230. {
  231. err_code = NRFX_ERROR_INVALID_PARAM;
  232. }
  233. else
  234. {
  235. // First disable this channel
  236. nrf_ppi_channel_disable(channel);
  237. NRFX_CRITICAL_SECTION_ENTER();
  238. channel_allocated_clr(channel);
  239. NRFX_CRITICAL_SECTION_EXIT();
  240. }
  241. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  242. return err_code;
  243. }
  244. nrfx_err_t nrfx_ppi_channel_assign(nrf_ppi_channel_t channel, uint32_t eep, uint32_t tep)
  245. {
  246. if ((uint32_t *)eep == NULL || (uint32_t *)tep == NULL)
  247. {
  248. return NRFX_ERROR_NULL;
  249. }
  250. nrfx_err_t err_code = NRFX_SUCCESS;
  251. if (!is_programmable_app_channel(channel))
  252. {
  253. err_code = NRFX_ERROR_INVALID_PARAM;
  254. }
  255. else if (!is_allocated_channel(channel))
  256. {
  257. err_code = NRFX_ERROR_INVALID_STATE;
  258. }
  259. else
  260. {
  261. nrf_ppi_channel_endpoint_setup(channel, eep, tep);
  262. NRFX_LOG_INFO("Assigned channel: %d, event end point: %x, task end point: %x.",
  263. channel,
  264. eep,
  265. tep);
  266. }
  267. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  268. return err_code;
  269. }
  270. nrfx_err_t nrfx_ppi_channel_fork_assign(nrf_ppi_channel_t channel, uint32_t fork_tep)
  271. {
  272. nrfx_err_t err_code = NRFX_SUCCESS;
  273. #ifdef PPI_FEATURE_FORKS_PRESENT
  274. if (!is_allocated_channel(channel))
  275. {
  276. err_code = NRFX_ERROR_INVALID_STATE;
  277. }
  278. else
  279. {
  280. nrf_ppi_fork_endpoint_setup(channel, fork_tep);
  281. NRFX_LOG_INFO("Fork assigned channel: %d, task end point: %d.", channel, fork_tep);
  282. }
  283. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  284. return err_code;
  285. #else
  286. err_code = NRFX_ERROR_NOT_SUPPORTED;
  287. NRFX_LOG_WARNING("Function: %s, error code: %s.",
  288. __func__,
  289. NRFX_LOG_ERROR_STRING_GET(err_code));
  290. return err_code;
  291. #endif
  292. }
  293. nrfx_err_t nrfx_ppi_channel_enable(nrf_ppi_channel_t channel)
  294. {
  295. nrfx_err_t err_code = NRFX_SUCCESS;
  296. if (!is_app_channel(channel))
  297. {
  298. err_code = NRFX_ERROR_INVALID_PARAM;
  299. }
  300. else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel))
  301. {
  302. err_code = NRFX_ERROR_INVALID_STATE;
  303. }
  304. else
  305. {
  306. nrf_ppi_channel_enable(channel);
  307. }
  308. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  309. return err_code;
  310. }
  311. nrfx_err_t nrfx_ppi_channel_disable(nrf_ppi_channel_t channel)
  312. {
  313. nrfx_err_t err_code = NRFX_SUCCESS;
  314. if (!is_app_channel(channel))
  315. {
  316. err_code = NRFX_ERROR_INVALID_PARAM;
  317. }
  318. else if (is_programmable_app_channel(channel) && !is_allocated_channel(channel))
  319. {
  320. err_code = NRFX_ERROR_INVALID_STATE;
  321. }
  322. else
  323. {
  324. nrf_ppi_channel_disable(channel);
  325. err_code = NRFX_SUCCESS;
  326. }
  327. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  328. return err_code;
  329. }
  330. nrfx_err_t nrfx_ppi_group_alloc(nrf_ppi_channel_group_t * p_group)
  331. {
  332. nrfx_err_t err_code;
  333. uint32_t mask = 0;
  334. nrf_ppi_channel_group_t group;
  335. err_code = NRFX_ERROR_NO_MEM;
  336. mask = NRFX_PPI_ALL_APP_GROUPS_MASK;
  337. for (group = NRF_PPI_CHANNEL_GROUP0; mask != 0; mask &= ~group_to_mask(group), group++)
  338. {
  339. NRFX_CRITICAL_SECTION_ENTER();
  340. if ((mask & group_to_mask(group)) && (!is_allocated_group(group)))
  341. {
  342. group_allocated_set(group);
  343. *p_group = group;
  344. err_code = NRFX_SUCCESS;
  345. }
  346. NRFX_CRITICAL_SECTION_EXIT();
  347. if (err_code == NRFX_SUCCESS)
  348. {
  349. NRFX_LOG_INFO("Allocated group: %d.", group);
  350. break;
  351. }
  352. }
  353. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  354. return err_code;
  355. }
  356. nrfx_err_t nrfx_ppi_group_free(nrf_ppi_channel_group_t group)
  357. {
  358. nrfx_err_t err_code = NRFX_SUCCESS;
  359. if (!is_app_group(group))
  360. {
  361. err_code = NRFX_ERROR_INVALID_PARAM;
  362. }
  363. if (!is_allocated_group(group))
  364. {
  365. err_code = NRFX_ERROR_INVALID_STATE;
  366. }
  367. else
  368. {
  369. nrf_ppi_group_disable(group);
  370. NRFX_CRITICAL_SECTION_ENTER();
  371. group_allocated_clr(group);
  372. NRFX_CRITICAL_SECTION_EXIT();
  373. }
  374. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  375. return err_code;
  376. }
  377. nrfx_err_t nrfx_ppi_group_enable(nrf_ppi_channel_group_t group)
  378. {
  379. nrfx_err_t err_code = NRFX_SUCCESS;
  380. if (!is_app_group(group))
  381. {
  382. err_code = NRFX_ERROR_INVALID_PARAM;
  383. }
  384. else if (!is_allocated_group(group))
  385. {
  386. err_code = NRFX_ERROR_INVALID_STATE;
  387. }
  388. else
  389. {
  390. nrf_ppi_group_enable(group);
  391. }
  392. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  393. return err_code;
  394. }
  395. nrfx_err_t nrfx_ppi_group_disable(nrf_ppi_channel_group_t group)
  396. {
  397. nrfx_err_t err_code = NRFX_SUCCESS;
  398. if (!is_app_group(group))
  399. {
  400. err_code = NRFX_ERROR_INVALID_PARAM;
  401. }
  402. else
  403. {
  404. nrf_ppi_group_disable(group);
  405. }
  406. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  407. return err_code;
  408. }
  409. nrfx_err_t nrfx_ppi_channels_remove_from_group(uint32_t channel_mask,
  410. nrf_ppi_channel_group_t group)
  411. {
  412. nrfx_err_t err_code = NRFX_SUCCESS;
  413. if (!is_app_group(group))
  414. {
  415. err_code = NRFX_ERROR_INVALID_PARAM;
  416. }
  417. else if (!is_allocated_group(group))
  418. {
  419. err_code = NRFX_ERROR_INVALID_STATE;
  420. }
  421. else if (!are_app_channels(channel_mask))
  422. {
  423. err_code = NRFX_ERROR_INVALID_PARAM;
  424. }
  425. else
  426. {
  427. NRFX_CRITICAL_SECTION_ENTER();
  428. nrf_ppi_channels_remove_from_group(channel_mask, group);
  429. NRFX_CRITICAL_SECTION_EXIT();
  430. }
  431. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  432. return err_code;
  433. }
  434. nrfx_err_t nrfx_ppi_channels_include_in_group(uint32_t channel_mask,
  435. nrf_ppi_channel_group_t group)
  436. {
  437. nrfx_err_t err_code = NRFX_SUCCESS;
  438. if (!is_app_group(group))
  439. {
  440. err_code = NRFX_ERROR_INVALID_PARAM;
  441. }
  442. else if (!is_allocated_group(group))
  443. {
  444. err_code = NRFX_ERROR_INVALID_STATE;
  445. }
  446. else if (!are_app_channels(channel_mask))
  447. {
  448. err_code = NRFX_ERROR_INVALID_PARAM;
  449. }
  450. else
  451. {
  452. NRFX_CRITICAL_SECTION_ENTER();
  453. nrf_ppi_channels_include_in_group(channel_mask, group);
  454. NRFX_CRITICAL_SECTION_EXIT();
  455. }
  456. NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
  457. return err_code;
  458. }
  459. #endif // NRFX_CHECK(NRFX_PPI_ENABLED)