nrf_libuarte_async.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /**
  2. * Copyright (c) 2018, 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_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. static nrf_libuarte_async_evt_handler m_evt_handler;
  60. #define POOL_SZ 3UL
  61. #define MAX_CHUNK_SZ 255UL
  62. NRF_BALLOC_DEF(m_rx_pool, MAX_CHUNK_SZ, POOL_SZ);
  63. NRF_QUEUE_DEF(uint8_t *, m_rxdata_queue, 3, NRF_QUEUE_MODE_NO_OVERFLOW);
  64. #define UART_DRV_TIMER CONCAT_2(NRF_TIMER, NRF_LIBUARTE_CONFIG_TIMER_USED)
  65. #define UART_DRV_UARTE CONCAT_2(NRF_UARTE, NRF_LIBUARTE_CONFIG_UARTE_USED)
  66. static nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(NRF_LIBUARTE_ASYNC_CONFIG_TIMER_USED);
  67. #if CONCAT_3(NRFX_TIMER, NRF_LIBUARTE_ASYNC_CONFIG_TIMER_USED,_ENABLED) == 0
  68. #error "Timer instance not enabled"
  69. #endif
  70. typedef enum
  71. {
  72. PPI_CH_RXRDY_CLEAR,
  73. PPI_CH_COMPARE_SHUTDOWN,
  74. PPI_CH_MAX
  75. } nrf_libuarte_async_ppi_channel_t;
  76. static nrf_ppi_channel_t m_ppi_channels[PPI_CH_MAX];
  77. static int32_t m_alloc_cnt;
  78. static uint32_t m_rx_count;
  79. static uint32_t m_sub_rx_count;
  80. static uint8_t * mp_curr_rx_buf;
  81. static uint32_t m_rx_free_cnt;
  82. static size_t m_rx_chunk_size;
  83. #define PPI_CH_SETUP(_ch, _evt, _tsk, _fork) \
  84. ret = nrfx_ppi_channel_assign(m_ppi_channels[_ch], _evt, _tsk); \
  85. if (ret != NRF_SUCCESS) \
  86. { \
  87. return NRF_ERROR_INTERNAL; \
  88. } \
  89. if (_fork) \
  90. { \
  91. ret = nrfx_ppi_channel_fork_assign(m_ppi_channels[_ch], _fork); \
  92. if (ret != NRF_SUCCESS) \
  93. { \
  94. return NRF_ERROR_INTERNAL; \
  95. } \
  96. }
  97. static void uart_evt_handler(nrf_libuarte_evt_t * p_evt)
  98. {
  99. ret_code_t ret;
  100. switch (p_evt->type)
  101. {
  102. case NRF_LIBUARTE_EVT_TX_DONE:
  103. {
  104. NRF_LOG_DEBUG("(evt) TX completed (%d)", p_evt->data.rxtx.length);
  105. nrf_libuarte_async_evt_t evt = {
  106. .type = NRF_LIBUARTE_ASYNC_EVT_TX_DONE,
  107. .data.rxtx.p_data = p_evt->data.rxtx.p_data,
  108. .data.rxtx.length = p_evt->data.rxtx.length,
  109. };
  110. m_evt_handler(&evt);
  111. break;
  112. }
  113. case NRF_LIBUARTE_EVT_RX_BUF_REQ:
  114. {
  115. uint8_t * p_data = nrf_balloc_alloc(&m_rx_pool);
  116. if (p_data)
  117. {
  118. ret = nrf_queue_push(&m_rxdata_queue, &p_data);
  119. if (ret != NRF_SUCCESS)
  120. {
  121. NRF_LOG_ERROR("(evt) RX buffer queue full.");
  122. APP_ERROR_CHECK_BOOL(false);
  123. }
  124. m_alloc_cnt++;
  125. nrf_libuarte_rx_buf_rsp(p_data, m_rx_chunk_size);
  126. }
  127. else
  128. {
  129. NRF_LOG_ERROR("(evt) Failed to allocate buffer for RX.");
  130. APP_ERROR_CHECK_BOOL(false);
  131. }
  132. break;
  133. }
  134. case NRF_LIBUARTE_EVT_RX_DATA:
  135. {
  136. uint32_t rx_amount = p_evt->data.rxtx.length - m_sub_rx_count;
  137. if (rx_amount)
  138. {
  139. m_rx_count += rx_amount;
  140. nrf_libuarte_async_evt_t evt = {
  141. .type = NRF_LIBUARTE_ASYNC_EVT_RX_DATA,
  142. .data.rxtx.p_data = &p_evt->data.rxtx.p_data[m_sub_rx_count],
  143. .data.rxtx.length = rx_amount,
  144. };
  145. NRF_LOG_DEBUG("(evt) RX: %d (addr:0x%08X, internal index: %d)",
  146. rx_amount,
  147. p_evt->data.rxtx.p_data,
  148. m_sub_rx_count);
  149. m_sub_rx_count = 0;
  150. if(p_evt->data.rxtx.p_data != mp_curr_rx_buf)
  151. {
  152. NRF_LOG_ERROR("(evt) RX buffer address mismatch");
  153. }
  154. ret = nrf_queue_pop(&m_rxdata_queue, &mp_curr_rx_buf);
  155. if (ret != NRF_SUCCESS)
  156. {
  157. NRF_LOG_ERROR("RX buffer queue empty.");
  158. APP_ERROR_CHECK_BOOL(false);
  159. }
  160. m_evt_handler(&evt);
  161. }
  162. else
  163. {
  164. NRF_LOG_ERROR("(evt) RX with 0 length: 0x%08X", p_evt->data.rxtx.p_data);
  165. //zero length packet is freed immediately and not forwarded to the application.
  166. APP_ERROR_CHECK_BOOL(false);
  167. }
  168. break;
  169. }
  170. default:
  171. APP_ERROR_CHECK_BOOL(false);
  172. break;
  173. }
  174. }
  175. static void tmr_evt_handler(nrf_timer_event_t event_type, void * p_context)
  176. {
  177. uint32_t capt_rx_count = UART_DRV_TIMER->CC[2];
  178. if (capt_rx_count > m_rx_count)
  179. {
  180. uint32_t rx_amount = capt_rx_count - m_rx_count;
  181. nrf_libuarte_async_evt_t evt = {
  182. .type = NRF_LIBUARTE_ASYNC_EVT_RX_DATA,
  183. .data.rxtx.p_data = &mp_curr_rx_buf[m_sub_rx_count],
  184. .data.rxtx.length = rx_amount,
  185. };
  186. NRF_LOG_DEBUG("(tmr evt) RX: %d (addr:0x%08X, internal index: %d)",
  187. rx_amount,
  188. evt.data.rxtx.p_data,
  189. m_sub_rx_count);
  190. m_sub_rx_count += rx_amount;
  191. m_rx_count = capt_rx_count;
  192. m_evt_handler(&evt);
  193. }
  194. }
  195. ret_code_t nrf_libuarte_async_init(nrf_libuarte_async_config_t const * p_config, nrf_libuarte_async_evt_handler evt_handler)
  196. {
  197. ret_code_t ret;
  198. m_evt_handler = evt_handler;
  199. m_rx_count = 0;
  200. mp_curr_rx_buf = NULL;
  201. m_rx_free_cnt = 0;
  202. m_sub_rx_count = 0;
  203. m_alloc_cnt = 0;
  204. nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG;
  205. tmr_config.frequency = NRF_TIMER_FREQ_1MHz;
  206. ret = nrfx_timer_init(&m_timer, &tmr_config, tmr_evt_handler);
  207. if (ret != NRFX_SUCCESS)
  208. {
  209. return NRF_ERROR_INTERNAL;
  210. }
  211. nrfx_timer_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, p_config->timeout_us, true);
  212. uint32_t i;
  213. for (i = 0; i < PPI_CH_MAX; i++)
  214. {
  215. ret = nrfx_ppi_channel_alloc(&m_ppi_channels[i]);
  216. if (ret != NRFX_SUCCESS)
  217. {
  218. //we don't free already allocated channels, system is wrongly configured.
  219. return NRF_ERROR_INTERNAL;
  220. }
  221. }
  222. /*lint -save -e666 */
  223. PPI_CH_SETUP(m_ppi_channels[PPI_CH_RXRDY_CLEAR],
  224. nrf_uarte_event_address_get(UART_DRV_UARTE, NRF_UARTE_EVENT_RXDRDY),
  225. nrfx_timer_task_address_get(&m_timer, NRF_TIMER_TASK_START),
  226. nrfx_timer_task_address_get(&m_timer, NRF_TIMER_TASK_CLEAR));
  227. PPI_CH_SETUP(m_ppi_channels[PPI_CH_COMPARE_SHUTDOWN],
  228. nrfx_timer_compare_event_address_get(&m_timer, 0),
  229. nrfx_timer_task_address_get(&m_timer, NRF_TIMER_TASK_SHUTDOWN),
  230. (uint32_t)&UART_DRV_TIMER->TASKS_CAPTURE[2]);
  231. /*lint -restore */
  232. nrf_libuarte_config_t uart_config = {
  233. .tx_pin = p_config->tx_pin,
  234. .rx_pin = p_config->rx_pin,
  235. .cts_pin = p_config->cts_pin,
  236. .rts_pin = p_config->rts_pin,
  237. .startrx_evt = nrf_uarte_event_address_get(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDRX),
  238. .endrx_evt = 0,
  239. .rxstarted_tsk = 0,
  240. .rxdone_tsk = 0,
  241. .hwfc = p_config->hwfc,
  242. .parity = p_config->parity,
  243. .baudrate = p_config->baudrate,
  244. .irq_priority = 7,
  245. };
  246. ret = nrf_libuarte_init(&uart_config, uart_evt_handler);
  247. if (ret != NRF_SUCCESS)
  248. {
  249. return ret;
  250. }
  251. ret = nrf_balloc_init(&m_rx_pool);
  252. if (ret != NRF_SUCCESS)
  253. {
  254. return ret;
  255. }
  256. nrf_queue_reset(&m_rxdata_queue);
  257. return ret;
  258. }
  259. void nrf_libuarte_async_uninit(void)
  260. {
  261. nrfx_err_t err = nrfx_ppi_channel_disable(m_ppi_channels[PPI_CH_RXRDY_CLEAR]);
  262. APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
  263. nrf_libuarte_uninit();
  264. nrfx_timer_disable(&m_timer);
  265. nrfx_timer_uninit(&m_timer);
  266. uint32_t i;
  267. ret_code_t ret;
  268. for (i = 0; i < PPI_CH_MAX; i++)
  269. {
  270. ret = nrfx_ppi_channel_disable(m_ppi_channels[i]);
  271. ASSERT(ret == NRF_SUCCESS)
  272. ret = nrfx_ppi_channel_free(m_ppi_channels[i]);
  273. ASSERT(ret == NRF_SUCCESS)
  274. }
  275. }
  276. void nrf_libuarte_async_enable(size_t chunk_size)
  277. {
  278. ASSERT(chunk_size <= MAX_CHUNK_SZ);
  279. uint8_t * p_data;
  280. p_data = nrf_balloc_alloc(&m_rx_pool);
  281. m_alloc_cnt++;
  282. if (p_data == NULL)
  283. {
  284. APP_ERROR_CHECK_BOOL(false);
  285. }
  286. nrfx_timer_clear(&m_timer);
  287. nrfx_err_t err = nrfx_ppi_channel_enable(m_ppi_channels[PPI_CH_RXRDY_CLEAR]);
  288. APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
  289. err = nrfx_ppi_channel_enable(m_ppi_channels[PPI_CH_COMPARE_SHUTDOWN]);
  290. APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
  291. mp_curr_rx_buf = p_data;
  292. m_rx_chunk_size = chunk_size;
  293. ret_code_t ret = nrf_libuarte_rx_start(p_data, chunk_size, false);
  294. APP_ERROR_CHECK_BOOL(ret == NRF_SUCCESS);
  295. }
  296. ret_code_t nrf_libuarte_async_tx(uint8_t * p_data, size_t length)
  297. {
  298. return nrf_libuarte_tx(p_data, length);
  299. }
  300. void nrf_libuarte_async_rx_free(uint8_t * p_data, size_t length)
  301. {
  302. m_rx_free_cnt += length;
  303. if (m_rx_free_cnt == m_rx_chunk_size)
  304. {
  305. p_data -= (m_rx_free_cnt - length);
  306. m_rx_free_cnt = 0;
  307. nrf_balloc_free(&m_rx_pool, p_data);
  308. m_alloc_cnt--;
  309. if (m_alloc_cnt<0)
  310. {
  311. NRF_LOG_ERROR("Freeing more RX buffers than allocated.");
  312. APP_ERROR_CHECK_BOOL(false);
  313. }
  314. NRF_LOG_INFO("Freeing full buffer 0x%08X, %d, (currently allocated:%d).",p_data, length, m_alloc_cnt);
  315. }
  316. else if (m_rx_free_cnt > m_rx_chunk_size)
  317. {
  318. NRF_LOG_ERROR("Unexpected RX free input parameter.")
  319. APP_ERROR_CHECK_BOOL(false);
  320. }
  321. else
  322. {
  323. NRF_LOG_INFO("Freeing partial buffer: 0x%08X, length:%d", p_data, length)
  324. }
  325. }