nrf_libuarte_async.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. /**
  2. * Copyright (c) 2019 - 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 "sdk_config.h"
  41. #include "nrf_libuarte_async.h"
  42. #include "app_error.h"
  43. #include "nrf_balloc.h"
  44. #include "nrfx_timer.h"
  45. #include "nrfx_rtc.h"
  46. #include "nrfx_ppi.h"
  47. #include "nrf_uart.h"
  48. #include "nrf_queue.h"
  49. #define NRF_LOG_MODULE_NAME libUARTE_async
  50. #if NRF_LIBUARTE_CONFIG_LOG_ENABLED
  51. #define NRF_LOG_LEVEL NRF_LIBUARTE_CONFIG_LOG_LEVEL
  52. #define NRF_LOG_INFO_COLOR NRF_LIBUARTE_CONFIG_INFO_COLOR
  53. #define NRF_LOG_DEBUG_COLOR NRF_LIBUARTE_CONFIG_DEBUG_COLOR
  54. #else // NRF_LIBUARTE_CONFIG_LOG_ENABLED
  55. #define NRF_LOG_LEVEL 0
  56. #endif // NRF_LIBUARTE_CONFIG_LOG_ENABLED
  57. #include "nrf_log.h"
  58. NRF_LOG_MODULE_REGISTER();
  59. #if defined(NRFX_RTC_ENABLED) && NRFX_RTC_ENABLED
  60. #define RTC_IN_USE 1
  61. #else
  62. #define RTC_IN_USE 0
  63. #endif
  64. #if defined(NRFX_TIMER_ENABLED) && NRFX_TIMER_ENABLED
  65. #define TIMER_IN_USE 1
  66. #else
  67. #define TIMER_IN_USE 0
  68. #endif
  69. #define FAULT_IRQ_LEVEL 0xFF
  70. /** Macro is setting up PPI channel set which consist of event, task and optional fork.
  71. *
  72. * @param _ch Channel.
  73. * @param _evt Event.
  74. * @param _tsk Task.
  75. * @param _fork Fork. If NULL fork is not configured.
  76. */
  77. #define PPI_CH_SETUP(_ch, _evt, _tsk, _fork) \
  78. ret = nrfx_ppi_channel_assign(_ch, _evt, _tsk); \
  79. if (ret != NRF_SUCCESS) \
  80. { \
  81. return NRF_ERROR_INTERNAL; \
  82. } \
  83. if (_fork) \
  84. { \
  85. ret = nrfx_ppi_channel_fork_assign(_ch, _fork); \
  86. if (ret != NRF_SUCCESS) \
  87. { \
  88. return NRF_ERROR_INTERNAL; \
  89. } \
  90. }
  91. /* @brief Function returns interrupt level which is the next,lower priority.
  92. *
  93. * If SoftDevice is present then it takes into account which priorities are used
  94. * by the SoftDevice.
  95. *
  96. * @note Caller of this function does not check if error is returned. Error is returned if input
  97. * priority belongs to SoftDevice. In that case SoftDevice will detect attempt to interrupt level
  98. * misuse.
  99. *
  100. * @param prio Interrupt priority.
  101. *
  102. * @return Priority which is one level lower or fault indicator (0xFF).
  103. */
  104. static uint8_t irq_prio_inc(uint8_t prio)
  105. {
  106. #ifdef SOFTDEVICE_PRESENT
  107. static const uint8_t sd_next_irq_lut[] = {
  108. FAULT_IRQ_LEVEL, /* 0 used by softdevice */
  109. FAULT_IRQ_LEVEL, /* 1 used by softdevice */
  110. APP_IRQ_PRIORITY_MID, /* 2 + 1 = 3 */
  111. APP_IRQ_PRIORITY_LOW_MID, /* 3 + 1 = 5 as 4 is used by softdevice */
  112. FAULT_IRQ_LEVEL, /* 4 used by softdevice */
  113. APP_IRQ_PRIORITY_LOW /* 5 + 1 = 6 */,
  114. APP_IRQ_PRIORITY_LOWEST, /* 6 + 1 = 7 */
  115. };
  116. return sd_next_irq_lut[prio];
  117. #else
  118. return prio + 1;
  119. #endif
  120. }
  121. #if NRF_LIBUARTE_ASYNC_WITH_APP_TIMER
  122. static void app_timer_handler(void * p_context);
  123. #define local_app_timer_cnt_get() app_timer_cnt_get()
  124. #define local_app_timer_start(p_timer, ticks, p_context) app_timer_start(p_timer, ticks, p_context)
  125. #define local_app_timer_stop(p_timer) app_timer_stop(p_timer)
  126. #define local_app_timer_create(p_timer) app_timer_create(p_timer, APP_TIMER_MODE_SINGLE_SHOT, app_timer_handler)
  127. #define local_app_timer_cnt_diff_compute(to, from) app_timer_cnt_diff_compute(to, from)
  128. #else
  129. #ifndef APP_TIMER_CONFIG_RTC_FREQUENCY
  130. #define APP_TIMER_CONFIG_RTC_FREQUENCY 0
  131. #endif
  132. #ifndef APP_TIMER_CLOCK_FREQ
  133. #define APP_TIMER_CLOCK_FREQ 1
  134. #endif
  135. #ifndef APP_TIMER_MIN_TIMEOUT_TICKS
  136. #define APP_TIMER_MIN_TIMEOUT_TICKS 0
  137. #endif
  138. #ifndef APP_TIMER_CONFIG_IRQ_PRIORITY
  139. #define APP_TIMER_CONFIG_IRQ_PRIORITY 1
  140. #endif
  141. static void app_timer_handler(void * p_context) __attribute__((unused));
  142. #define local_app_timer_cnt_get() 0
  143. #define local_app_timer_start(p_timer, ticks, p_context) NRF_SUCCESS
  144. #define local_app_timer_stop(p_timer) NRF_SUCCESS
  145. #define local_app_timer_create(p_timer) NRF_SUCCESS
  146. #define local_app_timer_cnt_diff_compute(to, from) 0
  147. #endif
  148. static uint32_t app_timer_ticks_to_us(uint32_t ticks)
  149. {
  150. return (uint32_t)(((uint64_t)ticks * 1000000 * (APP_TIMER_CONFIG_RTC_FREQUENCY + 1)) /
  151. APP_TIMER_CLOCK_FREQ);
  152. }
  153. static uint32_t app_timer_us_to_ticks(uint32_t us)
  154. {
  155. return (uint32_t)((((uint64_t)APP_TIMER_CLOCK_FREQ/(APP_TIMER_CONFIG_RTC_FREQUENCY + 1)) * us) /
  156. 1000000);
  157. }
  158. static bool rx_buffer_schedule(const nrf_libuarte_async_t * p_libuarte)
  159. {
  160. uint8_t * p_data = nrf_balloc_alloc(p_libuarte->p_rx_pool);
  161. if (p_data == NULL)
  162. {
  163. return false;
  164. }
  165. ret_code_t ret = nrf_queue_push(p_libuarte->p_rx_queue, &p_data);
  166. if (ret != NRF_SUCCESS)
  167. {
  168. NRF_LOG_ERROR("RX buffer queue full.");
  169. return false;
  170. }
  171. p_libuarte->p_ctrl_blk->alloc_cnt++;
  172. nrf_libuarte_drv_rx_buf_rsp(p_libuarte->p_libuarte, p_data, p_libuarte->rx_buf_size);
  173. return true;
  174. }
  175. static void uart_evt_handler(void * context, nrf_libuarte_drv_evt_t * p_evt)
  176. {
  177. ret_code_t ret;
  178. const nrf_libuarte_async_t * p_libuarte = (const nrf_libuarte_async_t *)context;
  179. switch (p_evt->type)
  180. {
  181. case NRF_LIBUARTE_DRV_EVT_TX_DONE:
  182. {
  183. NRF_LOG_DEBUG("(evt) TX completed (%d)", p_evt->data.rxtx.length);
  184. nrf_libuarte_async_evt_t evt = {
  185. .type = NRF_LIBUARTE_ASYNC_EVT_TX_DONE,
  186. .data = {
  187. .rxtx = {
  188. .p_data = p_evt->data.rxtx.p_data,
  189. .length = p_evt->data.rxtx.length,
  190. }
  191. }
  192. };
  193. p_libuarte->p_ctrl_blk->evt_handler(p_libuarte->p_ctrl_blk->context, &evt);
  194. break;
  195. }
  196. case NRF_LIBUARTE_DRV_EVT_RX_BUF_REQ:
  197. {
  198. if (p_libuarte->p_ctrl_blk->rx_halted)
  199. {
  200. break;
  201. }
  202. if (rx_buffer_schedule(p_libuarte) == false)
  203. {
  204. if (p_libuarte->p_ctrl_blk->hwfc)
  205. {
  206. p_libuarte->p_ctrl_blk->rx_halted = true;
  207. }
  208. else
  209. {
  210. NRF_LOG_ERROR("(evt) Failed to allocate buffer for RX.");
  211. APP_ERROR_CHECK_BOOL(false);
  212. }
  213. }
  214. break;
  215. }
  216. case NRF_LIBUARTE_DRV_EVT_RX_DATA:
  217. {
  218. uint32_t rx_amount = p_evt->data.rxtx.length - p_libuarte->p_ctrl_blk->sub_rx_count;
  219. if (rx_amount)
  220. {
  221. p_libuarte->p_ctrl_blk->rx_count += rx_amount;
  222. nrf_libuarte_async_evt_t evt = {
  223. .type = NRF_LIBUARTE_ASYNC_EVT_RX_DATA,
  224. .data = {
  225. .rxtx = {
  226. .p_data = &p_evt->data.rxtx.p_data[p_libuarte->p_ctrl_blk->sub_rx_count],
  227. .length = rx_amount,
  228. }
  229. }
  230. };
  231. NRF_LOG_DEBUG("(evt) RX: %d (addr:0x%08X, internal index: %d)",
  232. rx_amount,
  233. p_evt->data.rxtx.p_data,
  234. p_libuarte->p_ctrl_blk->sub_rx_count);
  235. p_libuarte->p_ctrl_blk->sub_rx_count = 0;
  236. if(p_evt->data.rxtx.p_data != p_libuarte->p_ctrl_blk->p_curr_rx_buf)
  237. {
  238. NRF_LOG_ERROR("(evt) RX buffer address mismatch");
  239. }
  240. ret = nrf_queue_pop(p_libuarte->p_rx_queue, &p_libuarte->p_ctrl_blk->p_curr_rx_buf);
  241. if (ret != NRF_SUCCESS)
  242. {
  243. NRF_LOG_ERROR("RX buffer queue empty.");
  244. APP_ERROR_CHECK_BOOL(false);
  245. }
  246. p_libuarte->p_ctrl_blk->evt_handler(p_libuarte->p_ctrl_blk->context, &evt);
  247. }
  248. else
  249. {
  250. NRF_LOG_ERROR("(evt) RX with 0 length: 0x%08X", p_evt->data.rxtx.p_data);
  251. //zero length packet is freed immediately and not forwarded to the application.
  252. APP_ERROR_CHECK_BOOL(false);
  253. }
  254. break;
  255. }
  256. case NRF_LIBUARTE_DRV_EVT_ERROR:
  257. {
  258. nrf_libuarte_async_evt_t evt = {
  259. .type = NRF_LIBUARTE_ASYNC_EVT_ERROR,
  260. .data = {
  261. .errorsrc = p_evt->data.errorsrc
  262. }
  263. };
  264. p_libuarte->p_ctrl_blk->evt_handler(p_libuarte->p_ctrl_blk->context, &evt);
  265. break;
  266. }
  267. case NRF_LIBUARTE_DRV_EVT_OVERRUN_ERROR:
  268. {
  269. NRF_LOG_WARNING("Overrun error - data loss due to UARTE interrupt not handled on time.");
  270. uint32_t rx_amount = p_evt->data.overrun_err.overrun_length - p_libuarte->p_ctrl_blk->sub_rx_count;
  271. p_libuarte->p_ctrl_blk->rx_count += rx_amount;
  272. nrf_libuarte_async_evt_t evt = {
  273. .type = NRF_LIBUARTE_ASYNC_EVT_OVERRUN_ERROR,
  274. .data = {
  275. .overrun_err = { .overrun_length = p_evt->data.overrun_err.overrun_length}
  276. }
  277. };
  278. p_libuarte->p_ctrl_blk->evt_handler(p_libuarte->p_ctrl_blk->context, &evt);
  279. break;
  280. }
  281. default:
  282. APP_ERROR_CHECK_BOOL(false);
  283. break;
  284. }
  285. }
  286. void nrf_libuarte_async_timeout_handler(const nrf_libuarte_async_t * p_libuarte)
  287. {
  288. NRFX_IRQ_DISABLE((IRQn_Type)NRFX_IRQ_NUMBER_GET(p_libuarte->p_libuarte->uarte));
  289. uint32_t capt_rx_count = p_libuarte->p_libuarte->timer.p_reg->CC[3];
  290. if (capt_rx_count > p_libuarte->p_ctrl_blk->rx_count)
  291. {
  292. uint32_t rx_amount = capt_rx_count - p_libuarte->p_ctrl_blk->rx_count;
  293. nrf_libuarte_async_evt_t evt = {
  294. .type = NRF_LIBUARTE_ASYNC_EVT_RX_DATA,
  295. .data = {
  296. .rxtx = {
  297. .p_data = &p_libuarte->p_ctrl_blk->p_curr_rx_buf[p_libuarte->p_ctrl_blk->sub_rx_count],
  298. .length = rx_amount,
  299. }
  300. }
  301. };
  302. NRF_LOG_DEBUG("(tmr evt) RX: %d (addr:0x%08X, internal index: %d)",
  303. rx_amount,
  304. evt.data.rxtx.p_data,
  305. p_libuarte->p_ctrl_blk->sub_rx_count);
  306. p_libuarte->p_ctrl_blk->sub_rx_count += rx_amount;
  307. p_libuarte->p_ctrl_blk->rx_count = capt_rx_count;
  308. p_libuarte->p_ctrl_blk->evt_handler(p_libuarte->p_ctrl_blk->context, &evt);
  309. }
  310. NRFX_IRQ_ENABLE((IRQn_Type)NRFX_IRQ_NUMBER_GET(p_libuarte->p_libuarte->uarte));
  311. }
  312. static void tmr_evt_handler(nrf_timer_event_t event_type, void * p_context)
  313. {
  314. nrf_libuarte_async_timeout_handler((const nrf_libuarte_async_t *)p_context);
  315. }
  316. static void app_timer_handler(void * p_context)
  317. {
  318. const nrf_libuarte_async_t * p_libuarte = p_context;
  319. uint32_t current_rx_count;
  320. uint32_t counter = local_app_timer_cnt_get();
  321. uint32_t ticks = app_timer_us_to_ticks(p_libuarte->p_ctrl_blk->timeout_us)/2;
  322. ticks = MAX(APP_TIMER_MIN_TIMEOUT_TICKS, ticks);
  323. if (p_libuarte->p_ctrl_blk->enabled == false)
  324. {
  325. return;
  326. }
  327. nrf_timer_task_trigger( p_libuarte->p_libuarte->timer.p_reg, NRF_TIMER_TASK_CAPTURE3);
  328. current_rx_count = p_libuarte->p_libuarte->timer.p_reg->CC[3];
  329. UNUSED_RETURN_VALUE(local_app_timer_start(*p_libuarte->p_app_timer, ticks, (void *)p_libuarte));
  330. if (p_libuarte->p_app_timer_ctrl_blk->rx_count != current_rx_count) {
  331. p_libuarte->p_app_timer_ctrl_blk->rx_count = current_rx_count;
  332. /* if number of bytes received changed reset timestamp and activate waiting
  333. * for silent period.
  334. */
  335. p_libuarte->p_app_timer_ctrl_blk->timestamp = counter;
  336. p_libuarte->p_app_timer_ctrl_blk->activate = true;
  337. } else {
  338. uint32_t diff;
  339. /* In case of detected silent period check if its length exceeds configured
  340. * timeout. If yes trigger timeout handler.
  341. */
  342. diff = local_app_timer_cnt_diff_compute(counter,
  343. p_libuarte->p_app_timer_ctrl_blk->timestamp);
  344. if (p_libuarte->p_app_timer_ctrl_blk->activate &&
  345. (app_timer_ticks_to_us(diff) > p_libuarte->p_ctrl_blk->timeout_us)) {
  346. p_libuarte->p_app_timer_ctrl_blk->activate = false;
  347. nrf_libuarte_async_timeout_handler(p_libuarte);
  348. }
  349. }
  350. }
  351. ret_code_t nrf_libuarte_async_init(const nrf_libuarte_async_t * const p_libuarte,
  352. nrf_libuarte_async_config_t const * p_config,
  353. nrf_libuarte_async_evt_handler_t evt_handler,
  354. void * context)
  355. {
  356. ret_code_t ret;
  357. if (p_config->int_prio == APP_IRQ_PRIORITY_LOWEST ||
  358. ((p_libuarte->p_app_timer && NRF_LIBUARTE_ASYNC_WITH_APP_TIMER) &&
  359. (p_config->int_prio >= APP_TIMER_CONFIG_IRQ_PRIORITY))) {
  360. NRF_LOG_ERROR("Too low priority. Lowest possible priority is %d", APP_IRQ_PRIORITY_LOW);
  361. return NRF_ERROR_INVALID_PARAM;
  362. }
  363. if (p_libuarte->p_ctrl_blk->enabled)
  364. {
  365. return NRF_ERROR_INVALID_STATE;
  366. }
  367. p_libuarte->p_ctrl_blk->evt_handler = evt_handler;
  368. p_libuarte->p_ctrl_blk->rx_count = 0;
  369. p_libuarte->p_ctrl_blk->p_curr_rx_buf = NULL;
  370. p_libuarte->p_ctrl_blk->rx_free_cnt = 0;
  371. p_libuarte->p_ctrl_blk->sub_rx_count = 0;
  372. p_libuarte->p_ctrl_blk->alloc_cnt = 0;
  373. p_libuarte->p_ctrl_blk->context = context;
  374. p_libuarte->p_ctrl_blk->timeout_us = p_config->timeout_us;
  375. p_libuarte->p_ctrl_blk->rx_halted = false;
  376. p_libuarte->p_ctrl_blk->hwfc = (p_config->hwfc == NRF_UARTE_HWFC_ENABLED);
  377. uint32_t i;
  378. uint32_t tmr_start_tsk = 0;
  379. uint32_t tmr_clear_tsk = 0;
  380. uint32_t tmr_stop_tsk = 0;
  381. uint32_t tmr_compare_evt = 0;
  382. if (p_libuarte->p_rtc && RTC_IN_USE)
  383. {
  384. nrfx_rtc_config_t rtc_config = NRFX_RTC_DEFAULT_CONFIG;
  385. rtc_config.interrupt_priority = irq_prio_inc(p_config->int_prio);
  386. rtc_config.prescaler = 0;
  387. ret = nrfx_rtc_init(p_libuarte->p_rtc, &rtc_config, p_libuarte->rtc_handler);
  388. if (ret != NRFX_SUCCESS)
  389. {
  390. return NRF_ERROR_INTERNAL;
  391. }
  392. ret = nrfx_rtc_cc_set(p_libuarte->p_rtc, 0, p_config->timeout_us/32, true);
  393. if (ret != NRFX_SUCCESS)
  394. {
  395. return NRF_ERROR_INTERNAL;
  396. }
  397. tmr_start_tsk = nrfx_rtc_task_address_get(p_libuarte->p_rtc, NRF_RTC_TASK_START);
  398. tmr_clear_tsk = nrfx_rtc_task_address_get(p_libuarte->p_rtc, NRF_RTC_TASK_CLEAR);
  399. tmr_stop_tsk = nrfx_rtc_task_address_get(p_libuarte->p_rtc, NRF_RTC_TASK_STOP);
  400. tmr_compare_evt = nrfx_rtc_event_address_get(p_libuarte->p_rtc, NRF_RTC_EVENT_COMPARE_0);
  401. }
  402. else if (p_libuarte->p_timer && TIMER_IN_USE)
  403. {
  404. nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG;
  405. tmr_config.frequency = NRF_TIMER_FREQ_1MHz;
  406. tmr_config.p_context = (void *)p_libuarte;
  407. tmr_config.interrupt_priority = irq_prio_inc(p_config->int_prio);
  408. ret = nrfx_timer_init(p_libuarte->p_timer, &tmr_config, tmr_evt_handler);
  409. if (ret != NRFX_SUCCESS)
  410. {
  411. return NRF_ERROR_INTERNAL;
  412. }
  413. nrfx_timer_compare(p_libuarte->p_timer, NRF_TIMER_CC_CHANNEL0, p_config->timeout_us, true);
  414. tmr_start_tsk = nrfx_timer_task_address_get(p_libuarte->p_timer, NRF_TIMER_TASK_START);
  415. tmr_clear_tsk = nrfx_timer_task_address_get(p_libuarte->p_timer, NRF_TIMER_TASK_CLEAR);
  416. tmr_stop_tsk = nrfx_timer_task_address_get(p_libuarte->p_timer, NRF_TIMER_TASK_SHUTDOWN);
  417. tmr_compare_evt = nrfx_timer_compare_event_address_get(p_libuarte->p_timer, 0);
  418. }
  419. else if (p_libuarte->p_app_timer && NRF_LIBUARTE_ASYNC_WITH_APP_TIMER) {
  420. /* app_timer in use */
  421. if(!p_libuarte->p_ctrl_blk->app_timer_created)
  422. {
  423. ret = local_app_timer_create(p_libuarte->p_app_timer);
  424. if (ret != NRF_SUCCESS)
  425. {
  426. return ret;
  427. }
  428. p_libuarte->p_ctrl_blk->app_timer_created = true;
  429. }
  430. p_libuarte->p_app_timer_ctrl_blk->activate = false;
  431. p_libuarte->p_app_timer_ctrl_blk->rx_count = 0;
  432. p_libuarte->p_app_timer_ctrl_blk->timestamp = 0;
  433. }
  434. else
  435. {
  436. NRF_LOG_ERROR("No timer or rtc defined");
  437. APP_ERROR_CHECK_BOOL(false);
  438. return NRF_ERROR_INTERNAL;
  439. }
  440. /* if RTC or TIMER is used then PPI channels are allocated. */
  441. if (p_libuarte->p_app_timer == NULL || !NRF_LIBUARTE_ASYNC_WITH_APP_TIMER)
  442. {
  443. for (i = 0; i < NRF_LIBUARTE_ASYNC_PPI_CH_MAX; i++)
  444. {
  445. ret = nrfx_ppi_channel_alloc(&p_libuarte->p_ctrl_blk->ppi_channels[i]);
  446. if (ret != NRFX_SUCCESS)
  447. {
  448. //we don't free already allocated channels, system is wrongly configured.
  449. return NRF_ERROR_INTERNAL;
  450. }
  451. }
  452. /*lint -save -e666 */
  453. PPI_CH_SETUP(p_libuarte->p_ctrl_blk->ppi_channels[NRF_LIBUARTE_ASYNC_PPI_CH_RXRDY_CLEAR],
  454. nrf_uarte_event_address_get(p_libuarte->p_libuarte->uarte, NRF_UARTE_EVENT_RXDRDY),
  455. tmr_start_tsk,
  456. tmr_clear_tsk);
  457. PPI_CH_SETUP(p_libuarte->p_ctrl_blk->ppi_channels[NRF_LIBUARTE_ASYNC_PPI_CH_COMPARE_SHUTDOWN],
  458. tmr_compare_evt,
  459. tmr_stop_tsk,
  460. (uint32_t)&p_libuarte->p_libuarte->timer.p_reg->TASKS_CAPTURE[3]);
  461. /*lint -restore */
  462. }
  463. nrf_libuarte_drv_config_t uart_config = {
  464. .tx_pin = p_config->tx_pin,
  465. .rx_pin = p_config->rx_pin,
  466. .cts_pin = p_config->cts_pin,
  467. .rts_pin = p_config->rts_pin,
  468. .startrx_evt = nrf_uarte_event_address_get(p_libuarte->p_libuarte->uarte, NRF_UARTE_EVENT_ENDRX),
  469. .endrx_evt = 0,
  470. .rxstarted_tsk = 0,
  471. .rxdone_tsk = 0,
  472. .hwfc = p_config->hwfc,
  473. .parity = p_config->parity,
  474. .baudrate = p_config->baudrate,
  475. .irq_priority = p_config->int_prio,
  476. .pullup_rx = p_config->pullup_rx,
  477. };
  478. ret = nrf_libuarte_drv_init(p_libuarte->p_libuarte, &uart_config, uart_evt_handler, (void *)p_libuarte);
  479. if (ret != NRF_SUCCESS)
  480. {
  481. return ret;
  482. }
  483. ret = nrf_balloc_init(p_libuarte->p_rx_pool);
  484. if (ret != NRF_SUCCESS)
  485. {
  486. return ret;
  487. }
  488. nrf_queue_reset(p_libuarte->p_rx_queue);
  489. p_libuarte->p_ctrl_blk->enabled = true;
  490. return ret;
  491. }
  492. void nrf_libuarte_async_uninit(const nrf_libuarte_async_t * const p_libuarte)
  493. {
  494. if (p_libuarte->p_ctrl_blk->enabled == false)
  495. {
  496. return;
  497. }
  498. p_libuarte->p_ctrl_blk->enabled = false;
  499. /* if HW timeout was used */
  500. if (p_libuarte->p_app_timer == NULL || !NRF_LIBUARTE_ASYNC_WITH_APP_TIMER)
  501. {
  502. uint32_t i;
  503. ret_code_t ret;
  504. for (i = 0; i < NRF_LIBUARTE_ASYNC_PPI_CH_MAX; i++)
  505. {
  506. ret = nrfx_ppi_channel_disable(p_libuarte->p_ctrl_blk->ppi_channels[i]);
  507. ASSERT(ret == NRF_SUCCESS)
  508. ret = nrfx_ppi_channel_free(p_libuarte->p_ctrl_blk->ppi_channels[i]);
  509. ASSERT(ret == NRF_SUCCESS)
  510. }
  511. }
  512. if (p_libuarte->p_rtc && RTC_IN_USE)
  513. {
  514. nrfx_rtc_disable(p_libuarte->p_rtc);
  515. nrfx_rtc_uninit(p_libuarte->p_rtc);
  516. }
  517. else if (p_libuarte->p_timer && TIMER_IN_USE)
  518. {
  519. nrfx_timer_disable(p_libuarte->p_timer);
  520. nrfx_timer_uninit(p_libuarte->p_timer);
  521. }
  522. else if (p_libuarte->p_app_timer && NRF_LIBUARTE_ASYNC_WITH_APP_TIMER)
  523. {
  524. UNUSED_RETURN_VALUE(local_app_timer_stop(*p_libuarte->p_app_timer));
  525. }
  526. nrf_libuarte_drv_uninit(p_libuarte->p_libuarte);
  527. }
  528. void nrf_libuarte_async_enable(const nrf_libuarte_async_t * const p_libuarte)
  529. {
  530. uint8_t * p_data;
  531. p_data = nrf_balloc_alloc(p_libuarte->p_rx_pool);
  532. p_libuarte->p_ctrl_blk->alloc_cnt++;
  533. if (p_data == NULL)
  534. {
  535. APP_ERROR_CHECK_BOOL(false);
  536. }
  537. if (p_libuarte->p_rtc && RTC_IN_USE)
  538. {
  539. nrfx_rtc_counter_clear(p_libuarte->p_rtc);
  540. }
  541. else if (p_libuarte->p_timer && TIMER_IN_USE)
  542. {
  543. nrfx_timer_clear(p_libuarte->p_timer);
  544. }
  545. if (!(p_libuarte->p_app_timer && NRF_LIBUARTE_ASYNC_WITH_APP_TIMER))
  546. {
  547. nrfx_err_t err;
  548. err = nrfx_ppi_channel_enable(p_libuarte->p_ctrl_blk->ppi_channels[NRF_LIBUARTE_ASYNC_PPI_CH_RXRDY_CLEAR]);
  549. APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
  550. err = nrfx_ppi_channel_enable(p_libuarte->p_ctrl_blk->ppi_channels[NRF_LIBUARTE_ASYNC_PPI_CH_COMPARE_SHUTDOWN]);
  551. APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
  552. }
  553. p_libuarte->p_ctrl_blk->p_curr_rx_buf = p_data;
  554. ret_code_t ret = nrf_libuarte_drv_rx_start(p_libuarte->p_libuarte, p_data, p_libuarte->rx_buf_size, false);
  555. APP_ERROR_CHECK_BOOL(ret == NRF_SUCCESS);
  556. if (p_libuarte->p_app_timer && NRF_LIBUARTE_ASYNC_WITH_APP_TIMER)
  557. {
  558. uint32_t ticks = app_timer_us_to_ticks(p_libuarte->p_ctrl_blk->timeout_us)/2;
  559. ticks = MAX(APP_TIMER_MIN_TIMEOUT_TICKS, ticks);
  560. UNUSED_RETURN_VALUE(local_app_timer_start(*p_libuarte->p_app_timer, ticks, (void *)p_libuarte));
  561. }
  562. }
  563. ret_code_t nrf_libuarte_async_tx(const nrf_libuarte_async_t * const p_libuarte, uint8_t * p_data, size_t length)
  564. {
  565. return nrf_libuarte_drv_tx(p_libuarte->p_libuarte, p_data, length);
  566. }
  567. void nrf_libuarte_async_rx_free(const nrf_libuarte_async_t * const p_libuarte, uint8_t * p_data, size_t length)
  568. {
  569. p_libuarte->p_ctrl_blk->rx_free_cnt += length;
  570. if (p_libuarte->p_ctrl_blk->rx_free_cnt == p_libuarte->rx_buf_size)
  571. {
  572. p_data -= (p_libuarte->p_ctrl_blk->rx_free_cnt - length);
  573. p_libuarte->p_ctrl_blk->rx_free_cnt = 0;
  574. nrf_balloc_free(p_libuarte->p_rx_pool, p_data);
  575. p_libuarte->p_ctrl_blk->alloc_cnt--;
  576. if (p_libuarte->p_ctrl_blk->alloc_cnt<0)
  577. {
  578. NRF_LOG_ERROR("Freeing more RX buffers than allocated.");
  579. APP_ERROR_CHECK_BOOL(false);
  580. }
  581. NRF_LOG_INFO("Freeing full buffer 0x%08X, %d, (currently allocated:%d).",p_data, length, p_libuarte->p_ctrl_blk->alloc_cnt);
  582. if (p_libuarte->p_ctrl_blk->rx_halted)
  583. {
  584. bool ret = rx_buffer_schedule(p_libuarte);
  585. ASSERT(ret);
  586. p_libuarte->p_ctrl_blk->rx_halted = false;
  587. }
  588. }
  589. else if (p_libuarte->p_ctrl_blk->rx_free_cnt > p_libuarte->rx_buf_size)
  590. {
  591. NRF_LOG_ERROR("Unexpected RX free input parameter.");
  592. APP_ERROR_CHECK_BOOL(false);
  593. }
  594. else
  595. {
  596. NRF_LOG_INFO("Freeing partial buffer: 0x%08X, length:%d", p_data, length);
  597. }
  598. }
  599. void nrf_libuarte_async_rts_clear(const nrf_libuarte_async_t * const p_libuarte)
  600. {
  601. nrf_libuarte_drv_rts_clear(p_libuarte->p_libuarte);
  602. }
  603. void nrf_libuarte_async_rts_set(const nrf_libuarte_async_t * const p_libuarte)
  604. {
  605. nrf_libuarte_drv_rts_set(p_libuarte->p_libuarte);
  606. }