nrf_libuarte_async.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /**
  2. * Copyright (c) 2018 - 2019, 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 "sdk_config.h"
  41. #include "nrf_libuarte_async.h"
  42. #include "nrf_libuarte.h"
  43. #include "app_error.h"
  44. #include "nrf_balloc.h"
  45. #include "nrfx_timer.h"
  46. #include "nrfx_rtc.h"
  47. #include "nrfx_clock.h"
  48. #include "nrfx_ppi.h"
  49. #include "nrf_uart.h"
  50. #include "nrf_queue.h"
  51. #define NRF_LOG_MODULE_NAME libUARTE_async
  52. #if NRF_LIBUARTE_CONFIG_LOG_ENABLED
  53. #define NRF_LOG_LEVEL NRF_LIBUARTE_CONFIG_LOG_LEVEL
  54. #define NRF_LOG_INFO_COLOR NRF_LIBUARTE_CONFIG_INFO_COLOR
  55. #define NRF_LOG_DEBUG_COLOR NRF_LIBUARTE_CONFIG_DEBUG_COLOR
  56. #else // NRF_LIBUARTE_CONFIG_LOG_ENABLED
  57. #define NRF_LOG_LEVEL 0
  58. #endif // NRF_LIBUARTE_CONFIG_LOG_ENABLED
  59. #include "nrf_log.h"
  60. NRF_LOG_MODULE_REGISTER();
  61. #if defined(NRFX_RTC_ENABLED) && NRFX_RTC_ENABLED
  62. #define RTC_IN_USE 1
  63. #else
  64. #define RTC_IN_USE 0
  65. #endif
  66. #if defined(NRFX_TIMER_ENABLED) && NRFX_TIMER_ENABLED
  67. #define TIMER_IN_USE 1
  68. #else
  69. #define TIMER_IN_USE 0
  70. #endif
  71. /** Macro is setting up PPI channel set which consist of event, task and optional fork.
  72. *
  73. * @param _ch Channel.
  74. * @param _evt Event.
  75. * @param _tsk Task.
  76. * @param _fork Fork. If NULL fork is not configured.
  77. */
  78. #define PPI_CH_SETUP(_ch, _evt, _tsk, _fork) \
  79. ret = nrfx_ppi_channel_assign(_ch, _evt, _tsk); \
  80. if (ret != NRF_SUCCESS) \
  81. { \
  82. return NRF_ERROR_INTERNAL; \
  83. } \
  84. if (_fork) \
  85. { \
  86. ret = nrfx_ppi_channel_fork_assign(_ch, _fork); \
  87. if (ret != NRF_SUCCESS) \
  88. { \
  89. return NRF_ERROR_INTERNAL; \
  90. } \
  91. }
  92. static void uart_evt_handler(void * context, nrf_libuarte_evt_t * p_evt)
  93. {
  94. ret_code_t ret;
  95. const nrf_libuarte_async_t * p_libuarte = (const nrf_libuarte_async_t *)context;
  96. switch (p_evt->type)
  97. {
  98. case NRF_LIBUARTE_EVT_TX_DONE:
  99. {
  100. NRF_LOG_DEBUG("(evt) TX completed (%d)", p_evt->data.rxtx.length);
  101. nrf_libuarte_async_evt_t evt = {
  102. .type = NRF_LIBUARTE_ASYNC_EVT_TX_DONE,
  103. .data.rxtx.p_data = p_evt->data.rxtx.p_data,
  104. .data.rxtx.length = p_evt->data.rxtx.length,
  105. };
  106. p_libuarte->p_ctrl_blk->evt_handler(p_libuarte->p_ctrl_blk->context, &evt);
  107. break;
  108. }
  109. case NRF_LIBUARTE_EVT_RX_BUF_REQ:
  110. {
  111. uint8_t * p_data = nrf_balloc_alloc(p_libuarte->p_rx_pool);
  112. if (p_data)
  113. {
  114. ret = nrf_queue_push(p_libuarte->p_rx_queue, &p_data);
  115. if (ret != NRF_SUCCESS)
  116. {
  117. NRF_LOG_ERROR("(evt) RX buffer queue full.");
  118. APP_ERROR_CHECK_BOOL(false);
  119. }
  120. p_libuarte->p_ctrl_blk->alloc_cnt++;
  121. nrf_libuarte_rx_buf_rsp(p_libuarte->p_libuarte, p_data, p_libuarte->p_ctrl_blk->rx_chunk_size);
  122. }
  123. else
  124. {
  125. NRF_LOG_ERROR("(evt) Failed to allocate buffer for RX.");
  126. APP_ERROR_CHECK_BOOL(false);
  127. }
  128. break;
  129. }
  130. case NRF_LIBUARTE_EVT_RX_DATA:
  131. {
  132. uint32_t rx_amount = p_evt->data.rxtx.length - p_libuarte->p_ctrl_blk->sub_rx_count;
  133. if (rx_amount)
  134. {
  135. p_libuarte->p_ctrl_blk->rx_count += rx_amount;
  136. nrf_libuarte_async_evt_t evt = {
  137. .type = NRF_LIBUARTE_ASYNC_EVT_RX_DATA,
  138. .data.rxtx.p_data = &p_evt->data.rxtx.p_data[p_libuarte->p_ctrl_blk->sub_rx_count],
  139. .data.rxtx.length = rx_amount,
  140. };
  141. NRF_LOG_DEBUG("(evt) RX: %d (addr:0x%08X, internal index: %d)",
  142. rx_amount,
  143. p_evt->data.rxtx.p_data,
  144. p_libuarte->p_ctrl_blk->sub_rx_count);
  145. p_libuarte->p_ctrl_blk->sub_rx_count = 0;
  146. if(p_evt->data.rxtx.p_data != p_libuarte->p_ctrl_blk->p_curr_rx_buf)
  147. {
  148. NRF_LOG_ERROR("(evt) RX buffer address mismatch");
  149. }
  150. ret = nrf_queue_pop(p_libuarte->p_rx_queue, &p_libuarte->p_ctrl_blk->p_curr_rx_buf);
  151. if (ret != NRF_SUCCESS)
  152. {
  153. NRF_LOG_ERROR("RX buffer queue empty.");
  154. APP_ERROR_CHECK_BOOL(false);
  155. }
  156. p_libuarte->p_ctrl_blk->evt_handler(p_libuarte->p_ctrl_blk->context, &evt);
  157. }
  158. else
  159. {
  160. NRF_LOG_ERROR("(evt) RX with 0 length: 0x%08X", p_evt->data.rxtx.p_data);
  161. //zero length packet is freed immediately and not forwarded to the application.
  162. APP_ERROR_CHECK_BOOL(false);
  163. }
  164. break;
  165. }
  166. default:
  167. APP_ERROR_CHECK_BOOL(false);
  168. break;
  169. }
  170. }
  171. void nrf_libuarte_async_timeout_handler(const nrf_libuarte_async_t * p_libuarte)
  172. {
  173. uint32_t capt_rx_count = p_libuarte->p_libuarte->timer.p_reg->CC[2];
  174. if (capt_rx_count > p_libuarte->p_ctrl_blk->rx_count)
  175. {
  176. uint32_t rx_amount = capt_rx_count - p_libuarte->p_ctrl_blk->rx_count;
  177. nrf_libuarte_async_evt_t evt = {
  178. .type = NRF_LIBUARTE_ASYNC_EVT_RX_DATA,
  179. .data.rxtx.p_data = &p_libuarte->p_ctrl_blk->p_curr_rx_buf[p_libuarte->p_ctrl_blk->sub_rx_count],
  180. .data.rxtx.length = rx_amount,
  181. };
  182. NRF_LOG_DEBUG("(tmr evt) RX: %d (addr:0x%08X, internal index: %d)",
  183. rx_amount,
  184. evt.data.rxtx.p_data,
  185. p_libuarte->p_ctrl_blk->sub_rx_count);
  186. p_libuarte->p_ctrl_blk->sub_rx_count += rx_amount;
  187. p_libuarte->p_ctrl_blk->rx_count = capt_rx_count;
  188. p_libuarte->p_ctrl_blk->evt_handler(p_libuarte->p_ctrl_blk->context, &evt);
  189. }
  190. }
  191. static void tmr_evt_handler(nrf_timer_event_t event_type, void * p_context)
  192. {
  193. nrf_libuarte_async_timeout_handler((const nrf_libuarte_async_t *)p_context);
  194. }
  195. ret_code_t nrf_libuarte_async_init(const nrf_libuarte_async_t * const p_libuarte,
  196. nrf_libuarte_async_config_t const * p_config,
  197. nrf_libuarte_async_evt_handler_t evt_handler,
  198. void * context)
  199. {
  200. ret_code_t ret;
  201. p_libuarte->p_ctrl_blk->evt_handler = evt_handler;
  202. p_libuarte->p_ctrl_blk->rx_count = 0;
  203. p_libuarte->p_ctrl_blk->p_curr_rx_buf = NULL;
  204. p_libuarte->p_ctrl_blk->rx_free_cnt = 0;
  205. p_libuarte->p_ctrl_blk->sub_rx_count = 0;
  206. p_libuarte->p_ctrl_blk->alloc_cnt = 0;
  207. p_libuarte->p_ctrl_blk->context = context;
  208. p_libuarte->p_ctrl_blk->timeout_us = p_config->timeout_us;
  209. uint32_t i;
  210. for (i = 0; i < NRF_LIBUARTE_ASYNC_PPI_CH_MAX; i++)
  211. {
  212. ret = nrfx_ppi_channel_alloc(&p_libuarte->p_ctrl_blk->ppi_channels[i]);
  213. if (ret != NRFX_SUCCESS)
  214. {
  215. //we don't free already allocated channels, system is wrongly configured.
  216. return NRF_ERROR_INTERNAL;
  217. }
  218. }
  219. uint32_t tmr_start_tsk = 0;
  220. uint32_t tmr_clear_tsk = 0;
  221. uint32_t tmr_stop_tsk = 0;
  222. uint32_t tmr_compare_evt = 0;
  223. if (p_libuarte->p_rtc && RTC_IN_USE)
  224. {
  225. nrfx_rtc_config_t rtc_config = NRFX_RTC_DEFAULT_CONFIG;
  226. nrfx_clock_lfclk_start();
  227. rtc_config.prescaler = 0;
  228. ret = nrfx_rtc_init(p_libuarte->p_rtc, &rtc_config, p_libuarte->rtc_handler);
  229. if (ret != NRFX_SUCCESS)
  230. {
  231. return NRF_ERROR_INTERNAL;
  232. }
  233. ret = nrfx_rtc_cc_set(p_libuarte->p_rtc, 0, p_config->timeout_us/32, true);
  234. if (ret != NRFX_SUCCESS)
  235. {
  236. return NRF_ERROR_INTERNAL;
  237. }
  238. tmr_start_tsk = nrfx_rtc_task_address_get(p_libuarte->p_rtc, NRF_RTC_TASK_START);
  239. tmr_clear_tsk = nrfx_rtc_task_address_get(p_libuarte->p_rtc, NRF_RTC_TASK_CLEAR);
  240. tmr_stop_tsk = nrfx_rtc_task_address_get(p_libuarte->p_rtc, NRF_RTC_TASK_STOP);
  241. tmr_compare_evt = nrfx_rtc_event_address_get(p_libuarte->p_rtc, NRF_RTC_EVENT_COMPARE_0);
  242. }
  243. else if (p_libuarte->p_timer && TIMER_IN_USE)
  244. {
  245. nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG;
  246. tmr_config.frequency = NRF_TIMER_FREQ_1MHz;
  247. tmr_config.p_context = (void *)p_libuarte;
  248. ret = nrfx_timer_init(p_libuarte->p_timer, &tmr_config, tmr_evt_handler);
  249. if (ret != NRFX_SUCCESS)
  250. {
  251. return NRF_ERROR_INTERNAL;
  252. }
  253. nrfx_timer_compare(p_libuarte->p_timer, NRF_TIMER_CC_CHANNEL0, p_config->timeout_us, true);
  254. tmr_start_tsk = nrfx_timer_task_address_get(p_libuarte->p_timer, NRF_TIMER_TASK_START);
  255. tmr_clear_tsk = nrfx_timer_task_address_get(p_libuarte->p_timer, NRF_TIMER_TASK_CLEAR);
  256. tmr_stop_tsk = nrfx_timer_task_address_get(p_libuarte->p_timer, NRF_TIMER_TASK_SHUTDOWN);
  257. tmr_compare_evt = nrfx_timer_compare_event_address_get(p_libuarte->p_timer, 0);
  258. }
  259. else
  260. {
  261. NRF_LOG_ERROR("No timer or rtc defined");
  262. APP_ERROR_CHECK_BOOL(false);
  263. }
  264. /*lint -save -e666 */
  265. PPI_CH_SETUP(p_libuarte->p_ctrl_blk->ppi_channels[NRF_LIBUARTE_ASYNC_PPI_CH_RXRDY_CLEAR],
  266. nrf_uarte_event_address_get(p_libuarte->p_libuarte->uarte, NRF_UARTE_EVENT_RXDRDY),
  267. tmr_start_tsk,
  268. tmr_clear_tsk);
  269. PPI_CH_SETUP(p_libuarte->p_ctrl_blk->ppi_channels[NRF_LIBUARTE_ASYNC_PPI_CH_COMPARE_SHUTDOWN],
  270. tmr_compare_evt,
  271. tmr_stop_tsk,
  272. (uint32_t)&p_libuarte->p_libuarte->timer.p_reg->TASKS_CAPTURE[2]);
  273. /*lint -restore */
  274. nrf_libuarte_config_t uart_config = {
  275. .tx_pin = p_config->tx_pin,
  276. .rx_pin = p_config->rx_pin,
  277. .cts_pin = p_config->cts_pin,
  278. .rts_pin = p_config->rts_pin,
  279. .startrx_evt = nrf_uarte_event_address_get(p_libuarte->p_libuarte->uarte, NRF_UARTE_EVENT_ENDRX),
  280. .endrx_evt = 0,
  281. .rxstarted_tsk = 0,
  282. .rxdone_tsk = 0,
  283. .hwfc = p_config->hwfc,
  284. .parity = p_config->parity,
  285. .baudrate = p_config->baudrate,
  286. .irq_priority = 7,
  287. };
  288. ret = nrf_libuarte_init(p_libuarte->p_libuarte, &uart_config, uart_evt_handler, (void *)p_libuarte);
  289. if (ret != NRF_SUCCESS)
  290. {
  291. return ret;
  292. }
  293. ret = nrf_balloc_init(p_libuarte->p_rx_pool);
  294. if (ret != NRF_SUCCESS)
  295. {
  296. return ret;
  297. }
  298. nrf_queue_reset(p_libuarte->p_rx_queue);
  299. return ret;
  300. }
  301. void nrf_libuarte_async_uninit(const nrf_libuarte_async_t * const p_libuarte)
  302. {
  303. nrfx_err_t err = nrfx_ppi_channel_disable(p_libuarte->p_ctrl_blk->ppi_channels[NRF_LIBUARTE_ASYNC_PPI_CH_RXRDY_CLEAR]);
  304. APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
  305. nrf_libuarte_uninit(p_libuarte->p_libuarte);
  306. if (p_libuarte->p_rtc && NRFX_RTC_ENABLED)
  307. {
  308. nrfx_rtc_disable(p_libuarte->p_rtc);
  309. nrfx_rtc_uninit(p_libuarte->p_rtc);
  310. }
  311. else if (p_libuarte->p_timer)
  312. {
  313. nrfx_timer_disable(p_libuarte->p_timer);
  314. nrfx_timer_uninit(p_libuarte->p_timer);
  315. }
  316. uint32_t i;
  317. ret_code_t ret;
  318. for (i = 0; i < NRF_LIBUARTE_ASYNC_PPI_CH_MAX; i++)
  319. {
  320. ret = nrfx_ppi_channel_disable(p_libuarte->p_ctrl_blk->ppi_channels[i]);
  321. ASSERT(ret == NRF_SUCCESS)
  322. ret = nrfx_ppi_channel_free(p_libuarte->p_ctrl_blk->ppi_channels[i]);
  323. ASSERT(ret == NRF_SUCCESS)
  324. }
  325. }
  326. void nrf_libuarte_async_enable(const nrf_libuarte_async_t * const p_libuarte)
  327. {
  328. size_t chunk_size = NRF_BALLOC_ELEMENT_SIZE(p_libuarte->p_rx_pool);
  329. uint8_t * p_data;
  330. p_data = nrf_balloc_alloc(p_libuarte->p_rx_pool);
  331. p_libuarte->p_ctrl_blk->alloc_cnt++;
  332. if (p_data == NULL)
  333. {
  334. APP_ERROR_CHECK_BOOL(false);
  335. }
  336. if (p_libuarte->p_rtc && NRFX_RTC_ENABLED)
  337. {
  338. nrfx_rtc_counter_clear(p_libuarte->p_rtc);
  339. }
  340. else if (p_libuarte->p_timer)
  341. {
  342. nrfx_timer_clear(p_libuarte->p_timer);
  343. }
  344. nrfx_err_t err = nrfx_ppi_channel_enable(p_libuarte->p_ctrl_blk->ppi_channels[NRF_LIBUARTE_ASYNC_PPI_CH_RXRDY_CLEAR]);
  345. APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
  346. err = nrfx_ppi_channel_enable(p_libuarte->p_ctrl_blk->ppi_channels[NRF_LIBUARTE_ASYNC_PPI_CH_COMPARE_SHUTDOWN]);
  347. APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
  348. p_libuarte->p_ctrl_blk->p_curr_rx_buf = p_data;
  349. p_libuarte->p_ctrl_blk->rx_chunk_size = chunk_size;
  350. ret_code_t ret = nrf_libuarte_rx_start(p_libuarte->p_libuarte, p_data, chunk_size, false);
  351. APP_ERROR_CHECK_BOOL(ret == NRF_SUCCESS);
  352. }
  353. ret_code_t nrf_libuarte_async_tx(const nrf_libuarte_async_t * const p_libuarte, uint8_t * p_data, size_t length)
  354. {
  355. return nrf_libuarte_tx(p_libuarte->p_libuarte, p_data, length);
  356. }
  357. void nrf_libuarte_async_rx_free(const nrf_libuarte_async_t * const p_libuarte, uint8_t * p_data, size_t length)
  358. {
  359. p_libuarte->p_ctrl_blk->rx_free_cnt += length;
  360. if (p_libuarte->p_ctrl_blk->rx_free_cnt == p_libuarte->p_ctrl_blk->rx_chunk_size)
  361. {
  362. p_data -= (p_libuarte->p_ctrl_blk->rx_free_cnt - length);
  363. p_libuarte->p_ctrl_blk->rx_free_cnt = 0;
  364. nrf_balloc_free(p_libuarte->p_rx_pool, p_data);
  365. p_libuarte->p_ctrl_blk->alloc_cnt--;
  366. if (p_libuarte->p_ctrl_blk->alloc_cnt<0)
  367. {
  368. NRF_LOG_ERROR("Freeing more RX buffers than allocated.");
  369. APP_ERROR_CHECK_BOOL(false);
  370. }
  371. NRF_LOG_INFO("Freeing full buffer 0x%08X, %d, (currently allocated:%d).",p_data, length, p_libuarte->p_ctrl_blk->alloc_cnt);
  372. }
  373. else if (p_libuarte->p_ctrl_blk->rx_free_cnt > p_libuarte->p_ctrl_blk->rx_chunk_size)
  374. {
  375. NRF_LOG_ERROR("Unexpected RX free input parameter.")
  376. APP_ERROR_CHECK_BOOL(false);
  377. }
  378. else
  379. {
  380. NRF_LOG_INFO("Freeing partial buffer: 0x%08X, length:%d", p_data, length)
  381. }
  382. }