aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte.c578
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte.h153
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte_async.c365
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte_async.h135
4 files changed, 1231 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte.c
new file mode 100644
index 0000000..6f44d0b
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte.c
@@ -0,0 +1,578 @@
+/**
+ * Copyright (c) 2018 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "sdk_config.h"
+#include "nrf_libuarte.h"
+#include "nrfx_ppi.h"
+#include "nrf_uarte.h"
+#include "nrf_gpio.h"
+#include "nrfx_timer.h"
+
+
+
+#define NRF_LOG_MODULE_NAME libUARTE
+#if NRF_LIBUARTE_CONFIG_LOG_ENABLED
+#define NRF_LOG_LEVEL NRF_LIBUARTE_CONFIG_LOG_LEVEL
+#define NRF_LOG_INFO_COLOR NRF_LIBUARTE_CONFIG_INFO_COLOR
+#define NRF_LOG_DEBUG_COLOR NRF_LIBUARTE_CONFIG_DEBUG_COLOR
+#else // NRF_LIBUARTE_CONFIG_LOG_ENABLED
+#define NRF_LOG_LEVEL 0
+#endif // NRF_LIBUARTE_CONFIG_LOG_ENABLED
+#include "nrf_log.h"
+NRF_LOG_MODULE_REGISTER();
+
+
+#define INTERRUPTS_MASK \
+ (NRF_UARTE_INT_ENDRX_MASK | NRF_UARTE_INT_RXSTARTED_MASK | NRF_UARTE_INT_ERROR_MASK | \
+ NRF_UARTE_INT_ENDTX_MASK | NRF_UARTE_INT_TXSTOPPED_MASK)
+
+#define UART_DRV_UARTE CONCAT_2(NRF_UARTE, NRF_LIBUARTE_CONFIG_UARTE_USED)
+
+#if NRF_LIBUARTE_CONFIG_UARTE_USED == 0
+#define UART_DRV_IRQn UARTE0_UART0_IRQn
+#define UART_DRV_IRQHandler UARTE0_UART0_IRQHandler
+#define MAX_DMA_XFER_LEN (1<<UARTE0_EASYDMA_MAXCNT_SIZE)
+#elif NRF_LIBUARTE_CONFIG_UARTE_USED == 1
+#define UART_DRV_IRQn UARTE1_UART1_IRQn
+#define UART_DRV_IRQHandler UARTE1_IRQHandler
+#define MAX_DMA_XFER_LEN (1<<UARTE1_EASYDMA_MAXCNT_SIZE)
+#endif
+
+typedef enum
+{
+ PPI_CH_EXT_TRIGGER_STARTRX_EN_ENDRX_STARTX,
+ PPI_CH_RXSTARTED_EXT_TSK,
+ PPI_CH_EXT_STOP_STOPRX,
+ PPI_CH_EXT_STOP_GROUPS_EN,
+ PPI_CH_RXRDY_TIMER_COUNT,
+
+ PPI_CH_RX_MAX,
+ PPI_CH_ENDRX_STARTRX = PPI_CH_RX_MAX,
+ PPI_CH_ENDRX_EXT_TSK,
+
+ PPI_CH_RX_GROUP_MAX,
+
+ PPI_CH_ENDTX_STARTTX = PPI_CH_RX_GROUP_MAX,
+
+ PPI_CH_MAX
+} nrf_libuarte_ppi_channel_t;
+
+typedef enum
+{
+ PPI_GROUP_ENDRX_STARTRX,
+ PPI_GROUP_ENDRX_EXT_RXDONE_TSK,
+ PPI_GROUP_MAX
+} nrf_libuarte_ppi_group_t;
+
+static nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(NRF_LIBUARTE_CONFIG_TIMER_USED);
+
+#if CONCAT_3(NRFX_TIMER, NRF_LIBUARTE_CONFIG_TIMER_USED,_ENABLED) == 0
+#error "Timer instance not enabled"
+#endif
+
+static nrf_ppi_channel_t m_ppi_channels[PPI_CH_MAX];
+static nrf_ppi_channel_group_t m_ppi_groups[PPI_GROUP_MAX];
+
+static uint8_t * mp_tx;
+static size_t m_tx_len;
+static size_t m_tx_cur_idx;
+
+static uint8_t * mp_cur_rx;
+static uint8_t * mp_next_rx;
+static uint8_t * mp_next_next_rx;
+static nrf_libuarte_evt_handler_t m_evt_handler;
+static uint32_t m_last_rx_byte_cnt;
+static uint32_t m_last_pin_rx_byte_cnt;
+static uint8_t m_tx_chunk8;
+static uint32_t m_chunk_size;
+
+#define PPI_CH_SETUP(_ch, _evt, _tsk, _fork) \
+ ret = nrfx_ppi_channel_assign(m_ppi_channels[_ch], _evt, _tsk); \
+ if (ret != NRF_SUCCESS) \
+ { \
+ return NRF_ERROR_INTERNAL; \
+ } \
+ if (_fork) \
+ { \
+ ret = nrfx_ppi_channel_fork_assign(m_ppi_channels[_ch], _fork); \
+ if (ret != NRF_SUCCESS) \
+ { \
+ return NRF_ERROR_INTERNAL; \
+ } \
+ }
+
+#define PPI_GROUP_SETUP(_ch, _group, _en_tsk, _dis_tsk) \
+ ret = nrfx_ppi_channel_include_in_group(m_ppi_channels[_ch], \
+ m_ppi_groups[_group]); \
+ if (ret != NRF_SUCCESS) \
+ { \
+ return NRF_ERROR_INTERNAL; \
+ } \
+ _en_tsk = nrfx_ppi_task_addr_group_enable_get(m_ppi_groups[_group]); \
+ _dis_tsk = nrfx_ppi_task_addr_group_disable_get(m_ppi_groups[_group]);
+
+
+static ret_code_t ppi_configure(nrf_libuarte_config_t * p_config)
+{
+ ret_code_t ret;
+
+/*lint -save -e666 */
+
+ ///////////////////////////////////////////////////////////////////////////////
+ uint32_t group1_en_tsk;
+ uint32_t group1_dis_tsk;
+
+ PPI_GROUP_SETUP(PPI_CH_ENDRX_STARTRX, PPI_GROUP_ENDRX_STARTRX, group1_en_tsk, group1_dis_tsk);
+
+ PPI_CH_SETUP(PPI_CH_ENDRX_STARTRX,
+ nrf_uarte_event_address_get(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDRX),
+ nrf_uarte_task_address_get(UART_DRV_UARTE, NRF_UARTE_TASK_STARTRX),
+ nrfx_timer_capture_task_address_get(&m_timer, 0));
+
+
+ ///////////////////////////////////////////////////////////////////////////////
+ uint32_t group2_en_tsk;
+ uint32_t group2_dis_tsk;
+
+ PPI_GROUP_SETUP(PPI_CH_ENDRX_EXT_TSK, PPI_GROUP_ENDRX_EXT_RXDONE_TSK, group2_en_tsk, group2_dis_tsk);
+
+ PPI_CH_SETUP(PPI_CH_ENDRX_EXT_TSK,
+ nrf_uarte_event_address_get(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDRX),
+ nrfx_timer_capture_task_address_get(&m_timer, 0),
+ p_config->rxdone_tsk);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ PPI_CH_SETUP(PPI_CH_EXT_TRIGGER_STARTRX_EN_ENDRX_STARTX,
+ p_config->startrx_evt,
+ group1_en_tsk,
+ nrf_uarte_task_address_get(UART_DRV_UARTE, NRF_UARTE_TASK_STARTRX));
+
+ ///////////////////////////////////////////////////////////////////////////////
+ PPI_CH_SETUP(PPI_CH_RXSTARTED_EXT_TSK,
+ nrf_uarte_event_address_get(UART_DRV_UARTE, NRF_UARTE_EVENT_RXSTARTED),
+ group2_dis_tsk,
+ p_config->rxstarted_tsk);
+
+ if (p_config->endrx_evt)
+ {
+ ///////////////////////////////////////////////////////////////////////////////
+ PPI_CH_SETUP(PPI_CH_EXT_STOP_STOPRX,
+ p_config->endrx_evt,
+ nrf_uarte_task_address_get(UART_DRV_UARTE, NRF_UARTE_TASK_STOPRX),
+ group2_en_tsk);
+
+ ///////////////////////////////////////////////////////////////////////////////
+ PPI_CH_SETUP(PPI_CH_EXT_STOP_GROUPS_EN,
+ p_config->endrx_evt,
+ group1_dis_tsk,
+ nrfx_timer_capture_task_address_get(&m_timer, 1));
+ }
+
+ ////////////////////////////////TX///////////////////////////////////////////////
+ PPI_CH_SETUP(PPI_CH_ENDTX_STARTTX,
+ nrf_uarte_event_address_get(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDTX),
+ nrf_uarte_task_address_get(UART_DRV_UARTE, NRF_UARTE_TASK_STARTTX),
+ 0);
+
+ ////////////////////////////////TX///////////////////////////////////////////////
+ PPI_CH_SETUP(PPI_CH_RXRDY_TIMER_COUNT,
+ nrf_uarte_event_address_get(UART_DRV_UARTE, NRF_UARTE_EVENT_RXDRDY),
+ nrfx_timer_task_address_get(&m_timer, NRF_TIMER_TASK_COUNT),
+ 0);
+
+ if (ret != NRFX_SUCCESS)
+ {
+ return NRF_ERROR_INTERNAL;
+ }
+ return NRF_SUCCESS;
+/*lint -restore */
+}
+
+void tmr_evt_handler(nrf_timer_event_t event_type, void * p_context)
+{
+ UNUSED_PARAMETER(event_type);
+ UNUSED_PARAMETER(p_context);
+}
+
+ret_code_t nrf_libuarte_init(nrf_libuarte_config_t * p_config, nrf_libuarte_evt_handler_t evt_handler)
+{
+ ret_code_t ret;
+ m_evt_handler = evt_handler;
+ mp_cur_rx = NULL;
+ mp_next_rx = NULL;
+ mp_next_next_rx = NULL;
+ mp_tx = NULL;
+
+ //UART init
+ nrf_gpio_pin_set(p_config->tx_pin);
+ nrf_gpio_cfg_output(p_config->tx_pin);
+ nrf_gpio_cfg_input(p_config->rx_pin, NRF_GPIO_PIN_NOPULL);
+ nrf_uarte_baudrate_set(UART_DRV_UARTE, p_config->baudrate);
+ nrf_uarte_configure(UART_DRV_UARTE, p_config->parity, p_config->hwfc);
+ nrf_uarte_txrx_pins_set(UART_DRV_UARTE, p_config->tx_pin, p_config->rx_pin);
+
+ if (p_config->hwfc == NRF_UARTE_HWFC_ENABLED)
+ {
+ if (p_config->cts_pin != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_cfg_input(p_config->cts_pin, NRF_GPIO_PIN_NOPULL);
+ }
+ if (p_config->rts_pin != NRF_UARTE_PSEL_DISCONNECTED)
+ {
+ nrf_gpio_pin_set(p_config->rts_pin);
+ nrf_gpio_cfg_output(p_config->rts_pin);
+ }
+ nrf_uarte_hwfc_pins_set(UART_DRV_UARTE, p_config->rts_pin, p_config->cts_pin);
+ }
+
+ nrf_uarte_int_enable(UART_DRV_UARTE, INTERRUPTS_MASK);
+
+ NVIC_SetPriority(UART_DRV_IRQn, p_config->irq_priority);
+ NVIC_ClearPendingIRQ(UART_DRV_IRQn);
+ NVIC_EnableIRQ(UART_DRV_IRQn);
+
+ nrf_uarte_enable(UART_DRV_UARTE);
+
+ nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG;
+ tmr_config.mode = NRF_TIMER_MODE_COUNTER;
+ tmr_config.bit_width = NRF_TIMER_BIT_WIDTH_32;
+ ret = nrfx_timer_init(&m_timer, &tmr_config, tmr_evt_handler);
+ if (ret != NRFX_SUCCESS)
+ {
+ return NRF_ERROR_INTERNAL;
+ }
+ nrfx_timer_enable(&m_timer);
+ nrfx_timer_clear(&m_timer);
+ m_last_rx_byte_cnt = 0;
+ m_last_pin_rx_byte_cnt = 0;
+
+ uint32_t i;
+ for (i = 0; i < PPI_CH_MAX; i++)
+ {
+ ret = nrfx_ppi_channel_alloc(&m_ppi_channels[i]);
+ if (ret != NRFX_SUCCESS)
+ {
+ //we don't free already allocated channels, system is wrongly configured.
+ return NRF_ERROR_INTERNAL;
+ }
+ }
+
+ for (i = 0; i < PPI_GROUP_MAX; i++)
+ {
+ ret = nrfx_ppi_group_alloc(&m_ppi_groups[i]);
+ if (ret != NRFX_SUCCESS)
+ {
+ //we don't free already allocated channels, system is wrongly configured.
+ return NRF_ERROR_INTERNAL;
+ }
+ }
+
+ return ppi_configure(p_config);
+}
+
+void nrf_libuarte_uninit(void)
+{
+ NVIC_DisableIRQ(UART_DRV_IRQn);
+ nrf_uarte_int_disable(UART_DRV_UARTE, 0xFFFFFFFF);
+ nrf_uarte_disable(UART_DRV_UARTE);
+
+ nrfx_timer_disable(&m_timer);
+ nrfx_timer_uninit(&m_timer);
+
+ uint32_t i;
+ ret_code_t ret;
+ for (i = 0; i < PPI_CH_MAX; i++)
+ {
+ ret = nrfx_ppi_channel_disable(m_ppi_channels[i]);
+ ASSERT(ret == NRFX_SUCCESS)
+ ret = nrfx_ppi_channel_free(m_ppi_channels[i]);
+ ASSERT(ret == NRFX_SUCCESS)
+ }
+
+ for (i = 0; i < PPI_GROUP_MAX; i++)
+ {
+ ret = nrfx_ppi_group_free(m_ppi_groups[i]);
+ ASSERT(ret == NRFX_SUCCESS)
+ }
+
+}
+
+ret_code_t nrf_libuarte_tx(uint8_t * p_data, size_t len)
+{
+ if (mp_tx)
+ {
+ return NRF_ERROR_BUSY;
+ }
+ mp_tx = p_data;
+ m_tx_len = len;
+ m_tx_cur_idx = 0;
+ uint8_t first_chunk;
+
+ if (len <= MAX_DMA_XFER_LEN)
+ {
+ first_chunk = len;
+ m_tx_chunk8 = 0;
+ }
+ else
+ {
+ uint32_t num_of_chunks = CEIL_DIV(len, MAX_DMA_XFER_LEN);
+ m_tx_chunk8 = len/num_of_chunks;
+ first_chunk = m_tx_chunk8 + len%m_tx_chunk8;
+ }
+
+ NRF_LOG_DEBUG("Started TX total length:%d, first chunk:%d", len, first_chunk);
+ nrf_uarte_tx_buffer_set(UART_DRV_UARTE, p_data, first_chunk);
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_TXSTARTED);
+ nrf_uarte_task_trigger(UART_DRV_UARTE, NRF_UARTE_TASK_STARTTX);
+
+ if (len > MAX_DMA_XFER_LEN)
+ {
+ while(nrf_uarte_event_check(UART_DRV_UARTE, NRF_UARTE_EVENT_TXSTARTED) == 0)
+ {
+ }
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_TXSTARTED);
+ nrfx_err_t err = nrfx_ppi_channel_enable(m_ppi_channels[PPI_CH_ENDTX_STARTTX]);
+ if (err != NRFX_SUCCESS)
+ {
+ return NRF_ERROR_INTERNAL;
+ }
+
+ nrf_uarte_tx_buffer_set(UART_DRV_UARTE, &p_data[first_chunk], m_tx_chunk8);
+ }
+ return NRF_SUCCESS;
+}
+
+ret_code_t nrf_libuarte_rx_start(uint8_t * p_data, size_t len, bool ext_trigger_en)
+{
+
+ m_chunk_size = len;
+
+ uint32_t i;
+ for (i = 0; i < PPI_CH_RX_MAX; i++)
+ {
+ nrfx_err_t err = nrfx_ppi_channel_enable(m_ppi_channels[i]);
+ if (err != NRFX_SUCCESS)
+ {
+ return NRF_ERROR_INTERNAL;
+ }
+ }
+
+ ASSERT(len <= MAX_DMA_XFER_LEN);
+
+ if (p_data)
+ {
+ mp_cur_rx = p_data;
+ nrf_uarte_rx_buffer_set(UART_DRV_UARTE, p_data, len);
+ }
+
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDRX);
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_RXSTARTED);
+ if (ext_trigger_en)
+ {
+ }
+ else
+ {
+
+ *(uint32_t *)nrfx_ppi_task_addr_group_enable_get(m_ppi_groups[PPI_GROUP_ENDRX_STARTRX]) = 1;
+ nrf_uarte_task_trigger(UART_DRV_UARTE, NRF_UARTE_TASK_STARTRX);
+ }
+ NRF_LOG_DEBUG("Start continues RX. Provided buffer:0x%08X", p_data);
+ return NRF_SUCCESS;
+}
+
+void nrf_libuarte_rx_buf_rsp(uint8_t * p_data, size_t len)
+{
+ if (mp_next_rx == NULL)
+ {
+ mp_next_rx = p_data;
+ NRF_LOG_DEBUG("RX buf response (next). Provided buffer:0x%08X", p_data);
+ nrf_uarte_rx_buffer_set(UART_DRV_UARTE, p_data, len);
+ }
+ else
+ {
+ NRF_LOG_DEBUG("RX buf response (mp_next_rx not NULL:0x%08X), Provided buffer:0x%08X",
+ mp_next_rx,
+ p_data);
+ mp_next_next_rx = p_data;
+ }
+}
+
+void nrf_libuarte_rx_stop(void)
+{
+ uint32_t i;
+ for (i = 0; i < PPI_CH_RX_MAX; i++)
+ {
+ nrfx_err_t err = nrfx_ppi_channel_disable(m_ppi_channels[i]);
+ ASSERT(err == NRFX_SUCCESS);
+ }
+
+ NRF_LOG_DEBUG("RX stopped.");
+ nrf_uarte_task_trigger(UART_DRV_UARTE, NRF_UARTE_TASK_STOPRX);
+}
+
+void UART_DRV_IRQHandler(void)
+{
+ if (nrf_uarte_event_check(UART_DRV_UARTE, NRF_UARTE_EVENT_ERROR))
+ {
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_ERROR);
+ nrf_libuarte_evt_t evt = {
+ .type = NRF_LIBUARTE_EVT_ERROR
+ };
+ m_evt_handler(&evt);
+ }
+
+ if (nrf_uarte_event_check(UART_DRV_UARTE, NRF_UARTE_EVENT_RXSTARTED))
+ {
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_RXSTARTED);
+
+ nrf_libuarte_evt_t evt = {
+ .type = NRF_LIBUARTE_EVT_RX_BUF_REQ,
+ };
+ m_evt_handler(&evt);
+ }
+
+ if (nrf_uarte_event_check(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDRX))
+ {
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDRX);
+
+ uint32_t endrx_byte_cnt = nrfx_timer_capture_get(&m_timer, NRF_TIMER_CC_CHANNEL0);
+ uint32_t stop_byte_cnt = nrfx_timer_capture_get(&m_timer, NRF_TIMER_CC_CHANNEL1);
+
+ uint32_t dma_amount = endrx_byte_cnt - m_last_rx_byte_cnt;
+ uint32_t pin_amount = stop_byte_cnt - m_last_pin_rx_byte_cnt;
+ NRF_LOG_DEBUG("(evt) RX dma_cnt:%d, endrx_cnt:%d, stop_cnt:%d",
+ dma_amount,
+ endrx_byte_cnt,
+ stop_byte_cnt);
+ m_last_rx_byte_cnt = endrx_byte_cnt;
+ m_last_pin_rx_byte_cnt = stop_byte_cnt;
+
+ if (dma_amount || pin_amount)
+ {
+ uint32_t chunk0 = (dma_amount > m_chunk_size) ? m_chunk_size : dma_amount;
+ uint32_t chunk1 = dma_amount - chunk0;
+
+ NRF_LOG_DEBUG("RX END chunk0:%d, chunk1:%d, data[0]=%d %d",
+ chunk0,
+ chunk1,
+ mp_cur_rx[0],
+ mp_cur_rx[1]);
+ nrf_libuarte_evt_t evt = {
+ .type = NRF_LIBUARTE_EVT_RX_DATA,
+ .data = {
+ .rxtx = {
+ .p_data = mp_cur_rx,
+ .length = chunk0
+ }
+ }
+ };
+ mp_cur_rx = mp_next_rx;
+ mp_next_rx = NULL;
+ if (mp_next_next_rx)
+ {
+ mp_next_rx = mp_next_next_rx;
+ mp_next_next_rx = NULL;
+ nrf_uarte_rx_buffer_set(UART_DRV_UARTE, mp_next_rx, m_chunk_size);
+ }
+ m_evt_handler(&evt);
+
+ if ( chunk1 ||
+ ((dma_amount == m_chunk_size) && (endrx_byte_cnt == stop_byte_cnt)))
+ {
+ NRF_LOG_WARNING("RX END Chunk1:%d", chunk1);
+
+ evt.data.rxtx.length = chunk1;
+ evt.data.rxtx.p_data = mp_cur_rx;
+
+ mp_cur_rx = mp_next_rx;
+ mp_next_rx = NULL;
+ m_evt_handler(&evt);
+ }
+ }
+ }
+
+ if (nrf_uarte_event_check(UART_DRV_UARTE, NRF_UARTE_EVENT_TXSTOPPED))
+ {
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_TXSTOPPED);
+ nrf_libuarte_evt_t evt = {
+ .type = NRF_LIBUARTE_EVT_TX_DONE,
+ .data = {
+ .rxtx = {
+ .p_data = mp_tx,
+ .length = m_tx_len
+ }
+ }
+ };
+ mp_tx = NULL;
+ m_evt_handler(&evt);
+ }
+
+ if (nrf_uarte_event_check(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDTX))
+ {
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDTX);
+ uint8_t amount = nrf_uarte_tx_amount_get(UART_DRV_UARTE);
+ NRF_LOG_DEBUG("(evt) TX completed (%d)", amount);
+ m_tx_cur_idx += amount;
+ if (m_tx_cur_idx == m_tx_len)
+ {
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_TXSTOPPED);
+ nrf_uarte_task_trigger(UART_DRV_UARTE, NRF_UARTE_TASK_STOPTX);
+ }
+ else
+ {
+ size_t rem_len = (m_tx_len - m_tx_cur_idx);
+ if ( rem_len <= MAX_DMA_XFER_LEN)
+ {
+ nrfx_err_t err = nrfx_ppi_channel_disable(m_ppi_channels[PPI_CH_ENDTX_STARTTX]);
+ ASSERT(err == NRFX_SUCCESS);
+ }
+ else
+ {
+ if (nrf_uarte_event_check(UART_DRV_UARTE, NRF_UARTE_EVENT_TXSTARTED) == 0)
+ {
+ NRF_LOG_ERROR("Tx not started yet!");
+ ASSERT(false);
+ }
+ nrf_uarte_event_clear(UART_DRV_UARTE, NRF_UARTE_EVENT_TXSTARTED);
+ nrf_uarte_tx_buffer_set(UART_DRV_UARTE, &mp_tx[m_tx_cur_idx + m_tx_chunk8], m_tx_chunk8);
+ }
+ }
+
+ }
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte.h
new file mode 100644
index 0000000..0c9d97b
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte.h
@@ -0,0 +1,153 @@
+/**
+ * Copyright (c) 2018 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef NRF_LIBUARTE_H
+#define NRF_LIBUARTE_H
+
+#include "sdk_errors.h"
+#include "nrf_uarte.h"
+#include <stdint.h>
+#include <stdbool.h>
+
+/**
+ * @defgroup nrf_libuarte libUARTE
+ * @ingroup app_common
+ *
+ * @brief Module for reliable communication over UARTE.
+ *
+ * @{
+ */
+
+typedef enum
+{
+ NRF_LIBUARTE_EVT_RX_DATA, ///< Data received.
+ NRF_LIBUARTE_EVT_RX_BUF_REQ, ///< Requesting new buffer for receiving data.
+ NRF_LIBUARTE_EVT_TX_DONE, ///< Requested TX transfer completed.
+ NRF_LIBUARTE_EVT_ERROR ///< Error reported by the UARTE peripheral.
+} nrf_libuarte_evt_type_t;
+
+typedef struct
+{
+ uint8_t * p_data; ///< Pointer to the data to be sent or received.
+ size_t length; ///< Length of the data.
+} nrf_libuarte_data_t;
+
+typedef struct
+{
+ nrf_libuarte_evt_type_t type; ///< Event type.
+ union {
+ nrf_libuarte_data_t rxtx; ///< Data provided for transfer completion events.
+ } data;
+} nrf_libuarte_evt_t;
+
+typedef struct {
+ uint32_t tx_pin; ///< TXD pin number.
+ uint32_t rx_pin; ///< RXD pin number.
+ uint32_t cts_pin; ///< CTS pin number.
+ uint32_t rts_pin; ///< RTS pin number.
+ uint32_t startrx_evt; ///< Event to trigger STARTRX task in UARTE.
+ uint32_t endrx_evt; ///< Event to trigger STOPRX task in UARTE.
+ uint32_t rxstarted_tsk; ///< Task to be triggered when RXSTARTED UARTE event occurs.
+ uint32_t rxdone_tsk; ///< Task to be triggered when ENDRX UARTE event occurs.
+ nrf_uarte_hwfc_t hwfc; ///< Flow control configuration.
+ nrf_uarte_parity_t parity; ///< Parity configuration.
+ nrf_uarte_baudrate_t baudrate; ///< Baud rate.
+ uint8_t irq_priority; ///< Interrupt priority.
+} nrf_libuarte_config_t;
+
+typedef void (*nrf_libuarte_evt_handler_t)(nrf_libuarte_evt_t * p_evt);
+
+/**
+ * @brief Function for initializing the libUARTE library.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] evt_handler Event handler provided by the user. Must not be NULL.
+ *
+ * @return NRF_SUCCESS when properly initialized. NRF_ERROR_INTERNAL otherwise.
+ */
+ret_code_t nrf_libuarte_init(nrf_libuarte_config_t * p_config, nrf_libuarte_evt_handler_t evt_handler);
+
+/** @brief Function for uninitializing the libUARTE library. */
+void nrf_libuarte_uninit(void);
+
+/**
+ * @brief Function for sending data over UARTE using EasyDMA.
+ *
+ * @param[in] p_data Pointer to data.
+ * @param[in] len Number of bytes to send.
+ *
+ * @retval NRF_ERROR_BUSY Data is transferring.
+ * @retval NRF_ERROR_INTERNAL Error during PPI channel configuration.
+ * @retval NRF_SUCCESS Buffer set for sending.
+ */
+ret_code_t nrf_libuarte_tx(uint8_t * p_data, size_t len);
+
+/**
+ * @brief Function for starting receiving data with additional configuration of external
+ * trigger to start receiving.
+ *
+ * @param p_data Pointer to data.
+ * @param len Number of bytes to receive. Maximum possible length is
+ * dependent on the used SoC (see the MAXCNT register
+ * description in the Product Specification). The library
+ * checks it with an assertion.
+ * @param ext_trigger_en True to disable immediate start.
+ *
+ * @retval NRF_ERROR_INTERNAL Error during PPI channel configuration.
+ * @retval NRF_SUCCESS Buffer set for receiving.
+ */
+ret_code_t nrf_libuarte_rx_start(uint8_t * p_data, size_t len, bool ext_trigger_en);
+
+/**
+ * @brief Function for setting a buffer for data that will be later received in UARTE.
+ *
+ * @param p_data Pointer to data.
+ * @param len Number of bytes to receive. Maximum possible length is
+ * dependent on the used SoC (see the MAXCNT register
+ * description in the Product Specification). The library
+ * checks it with an assertion.
+ */
+void nrf_libuarte_rx_buf_rsp(uint8_t * p_data, size_t len);
+
+/** @brief Function for stopping receiving data over UARTE. */
+void nrf_libuarte_rx_stop(void);
+
+/** @} */
+
+#endif //NRF_libuarte_H
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte_async.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte_async.c
new file mode 100644
index 0000000..5c5a639
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte_async.c
@@ -0,0 +1,365 @@
+/**
+ * Copyright (c) 2018 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "sdk_config.h"
+#include "nrf_libuarte_async.h"
+#include "nrf_libuarte.h"
+#include "app_error.h"
+#include "nrf_balloc.h"
+#include "nrfx_timer.h"
+#include "nrfx_ppi.h"
+#include "nrf_uart.h"
+#include "nrf_queue.h"
+
+#define NRF_LOG_MODULE_NAME libUARTE_async
+#if NRF_LIBUARTE_CONFIG_LOG_ENABLED
+#define NRF_LOG_LEVEL NRF_LIBUARTE_CONFIG_LOG_LEVEL
+#define NRF_LOG_INFO_COLOR NRF_LIBUARTE_CONFIG_INFO_COLOR
+#define NRF_LOG_DEBUG_COLOR NRF_LIBUARTE_CONFIG_DEBUG_COLOR
+#else // NRF_LIBUARTE_CONFIG_LOG_ENABLED
+#define NRF_LOG_LEVEL 0
+#endif // NRF_LIBUARTE_CONFIG_LOG_ENABLED
+#include "nrf_log.h"
+NRF_LOG_MODULE_REGISTER();
+
+static nrf_libuarte_async_evt_handler m_evt_handler;
+#define POOL_SZ 3UL
+#define MAX_CHUNK_SZ 255UL
+
+NRF_BALLOC_DEF(m_rx_pool, MAX_CHUNK_SZ, POOL_SZ);
+
+NRF_QUEUE_DEF(uint8_t *, m_rxdata_queue, 3, NRF_QUEUE_MODE_NO_OVERFLOW);
+
+#define UART_DRV_TIMER CONCAT_2(NRF_TIMER, NRF_LIBUARTE_CONFIG_TIMER_USED)
+#define UART_DRV_UARTE CONCAT_2(NRF_UARTE, NRF_LIBUARTE_CONFIG_UARTE_USED)
+
+static nrfx_timer_t m_timer = NRFX_TIMER_INSTANCE(NRF_LIBUARTE_ASYNC_CONFIG_TIMER_USED);
+
+#if CONCAT_3(NRFX_TIMER, NRF_LIBUARTE_ASYNC_CONFIG_TIMER_USED,_ENABLED) == 0
+#error "Timer instance not enabled"
+#endif
+
+typedef enum
+{
+ PPI_CH_RXRDY_CLEAR,
+ PPI_CH_COMPARE_SHUTDOWN,
+ PPI_CH_MAX
+} nrf_libuarte_async_ppi_channel_t;
+
+static nrf_ppi_channel_t m_ppi_channels[PPI_CH_MAX];
+static int32_t m_alloc_cnt;
+static uint32_t m_rx_count;
+static uint32_t m_sub_rx_count;
+static uint8_t * mp_curr_rx_buf;
+static uint32_t m_rx_free_cnt;
+static size_t m_rx_chunk_size;
+
+#define PPI_CH_SETUP(_ch, _evt, _tsk, _fork) \
+ ret = nrfx_ppi_channel_assign(m_ppi_channels[_ch], _evt, _tsk); \
+ if (ret != NRF_SUCCESS) \
+ { \
+ return NRF_ERROR_INTERNAL; \
+ } \
+ if (_fork) \
+ { \
+ ret = nrfx_ppi_channel_fork_assign(m_ppi_channels[_ch], _fork); \
+ if (ret != NRF_SUCCESS) \
+ { \
+ return NRF_ERROR_INTERNAL; \
+ } \
+ }
+
+static void uart_evt_handler(nrf_libuarte_evt_t * p_evt)
+{
+ ret_code_t ret;
+ switch (p_evt->type)
+ {
+ case NRF_LIBUARTE_EVT_TX_DONE:
+ {
+ NRF_LOG_DEBUG("(evt) TX completed (%d)", p_evt->data.rxtx.length);
+ nrf_libuarte_async_evt_t evt = {
+ .type = NRF_LIBUARTE_ASYNC_EVT_TX_DONE,
+ .data.rxtx.p_data = p_evt->data.rxtx.p_data,
+ .data.rxtx.length = p_evt->data.rxtx.length,
+ };
+ m_evt_handler(&evt);
+ break;
+ }
+ case NRF_LIBUARTE_EVT_RX_BUF_REQ:
+ {
+ uint8_t * p_data = nrf_balloc_alloc(&m_rx_pool);
+ if (p_data)
+ {
+ ret = nrf_queue_push(&m_rxdata_queue, &p_data);
+ if (ret != NRF_SUCCESS)
+ {
+ NRF_LOG_ERROR("(evt) RX buffer queue full.");
+ APP_ERROR_CHECK_BOOL(false);
+ }
+
+ m_alloc_cnt++;
+ nrf_libuarte_rx_buf_rsp(p_data, m_rx_chunk_size);
+ }
+ else
+ {
+ NRF_LOG_ERROR("(evt) Failed to allocate buffer for RX.");
+ APP_ERROR_CHECK_BOOL(false);
+ }
+ break;
+ }
+ case NRF_LIBUARTE_EVT_RX_DATA:
+ {
+
+ uint32_t rx_amount = p_evt->data.rxtx.length - m_sub_rx_count;
+ if (rx_amount)
+ {
+ m_rx_count += rx_amount;
+ nrf_libuarte_async_evt_t evt = {
+ .type = NRF_LIBUARTE_ASYNC_EVT_RX_DATA,
+ .data.rxtx.p_data = &p_evt->data.rxtx.p_data[m_sub_rx_count],
+ .data.rxtx.length = rx_amount,
+ };
+ NRF_LOG_DEBUG("(evt) RX: %d (addr:0x%08X, internal index: %d)",
+ rx_amount,
+ p_evt->data.rxtx.p_data,
+ m_sub_rx_count);
+
+ m_sub_rx_count = 0;
+
+ if(p_evt->data.rxtx.p_data != mp_curr_rx_buf)
+ {
+ NRF_LOG_ERROR("(evt) RX buffer address mismatch");
+ }
+
+ ret = nrf_queue_pop(&m_rxdata_queue, &mp_curr_rx_buf);
+ if (ret != NRF_SUCCESS)
+ {
+ NRF_LOG_ERROR("RX buffer queue empty.");
+ APP_ERROR_CHECK_BOOL(false);
+ }
+
+ m_evt_handler(&evt);
+ }
+ else
+ {
+ NRF_LOG_ERROR("(evt) RX with 0 length: 0x%08X", p_evt->data.rxtx.p_data);
+ //zero length packet is freed immediately and not forwarded to the application.
+ APP_ERROR_CHECK_BOOL(false);
+ }
+ break;
+ }
+ default:
+ APP_ERROR_CHECK_BOOL(false);
+ break;
+ }
+}
+
+static void tmr_evt_handler(nrf_timer_event_t event_type, void * p_context)
+{
+ uint32_t capt_rx_count = UART_DRV_TIMER->CC[2];
+
+ if (capt_rx_count > m_rx_count)
+ {
+ uint32_t rx_amount = capt_rx_count - m_rx_count;
+ nrf_libuarte_async_evt_t evt = {
+ .type = NRF_LIBUARTE_ASYNC_EVT_RX_DATA,
+ .data.rxtx.p_data = &mp_curr_rx_buf[m_sub_rx_count],
+ .data.rxtx.length = rx_amount,
+ };
+ NRF_LOG_DEBUG("(tmr evt) RX: %d (addr:0x%08X, internal index: %d)",
+ rx_amount,
+ evt.data.rxtx.p_data,
+ m_sub_rx_count);
+
+ m_sub_rx_count += rx_amount;
+ m_rx_count = capt_rx_count;
+ m_evt_handler(&evt);
+ }
+}
+
+ret_code_t nrf_libuarte_async_init(nrf_libuarte_async_config_t const * p_config, nrf_libuarte_async_evt_handler evt_handler)
+{
+ ret_code_t ret;
+
+ m_evt_handler = evt_handler;
+ m_rx_count = 0;
+ mp_curr_rx_buf = NULL;
+ m_rx_free_cnt = 0;
+ m_sub_rx_count = 0;
+ m_alloc_cnt = 0;
+
+ nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG;
+ tmr_config.frequency = NRF_TIMER_FREQ_1MHz;
+ ret = nrfx_timer_init(&m_timer, &tmr_config, tmr_evt_handler);
+ if (ret != NRFX_SUCCESS)
+ {
+ return NRF_ERROR_INTERNAL;
+ }
+ nrfx_timer_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, p_config->timeout_us, true);
+
+ uint32_t i;
+ for (i = 0; i < PPI_CH_MAX; i++)
+ {
+ ret = nrfx_ppi_channel_alloc(&m_ppi_channels[i]);
+ if (ret != NRFX_SUCCESS)
+ {
+ //we don't free already allocated channels, system is wrongly configured.
+ return NRF_ERROR_INTERNAL;
+ }
+ }
+
+/*lint -save -e666 */
+ PPI_CH_SETUP(m_ppi_channels[PPI_CH_RXRDY_CLEAR],
+ nrf_uarte_event_address_get(UART_DRV_UARTE, NRF_UARTE_EVENT_RXDRDY),
+ nrfx_timer_task_address_get(&m_timer, NRF_TIMER_TASK_START),
+ nrfx_timer_task_address_get(&m_timer, NRF_TIMER_TASK_CLEAR));
+
+ PPI_CH_SETUP(m_ppi_channels[PPI_CH_COMPARE_SHUTDOWN],
+ nrfx_timer_compare_event_address_get(&m_timer, 0),
+ nrfx_timer_task_address_get(&m_timer, NRF_TIMER_TASK_SHUTDOWN),
+ (uint32_t)&UART_DRV_TIMER->TASKS_CAPTURE[2]);
+
+/*lint -restore */
+
+ nrf_libuarte_config_t uart_config = {
+ .tx_pin = p_config->tx_pin,
+ .rx_pin = p_config->rx_pin,
+ .cts_pin = p_config->cts_pin,
+ .rts_pin = p_config->rts_pin,
+ .startrx_evt = nrf_uarte_event_address_get(UART_DRV_UARTE, NRF_UARTE_EVENT_ENDRX),
+ .endrx_evt = 0,
+ .rxstarted_tsk = 0,
+ .rxdone_tsk = 0,
+ .hwfc = p_config->hwfc,
+ .parity = p_config->parity,
+ .baudrate = p_config->baudrate,
+ .irq_priority = 7,
+ };
+
+ ret = nrf_libuarte_init(&uart_config, uart_evt_handler);
+ if (ret != NRF_SUCCESS)
+ {
+ return ret;
+ }
+
+ ret = nrf_balloc_init(&m_rx_pool);
+ if (ret != NRF_SUCCESS)
+ {
+ return ret;
+ }
+
+ nrf_queue_reset(&m_rxdata_queue);
+
+ return ret;
+}
+
+void nrf_libuarte_async_uninit(void)
+{
+ nrfx_err_t err = nrfx_ppi_channel_disable(m_ppi_channels[PPI_CH_RXRDY_CLEAR]);
+ APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
+ nrf_libuarte_uninit();
+ nrfx_timer_disable(&m_timer);
+ nrfx_timer_uninit(&m_timer);
+
+ uint32_t i;
+ ret_code_t ret;
+ for (i = 0; i < PPI_CH_MAX; i++)
+ {
+ ret = nrfx_ppi_channel_disable(m_ppi_channels[i]);
+ ASSERT(ret == NRF_SUCCESS)
+ ret = nrfx_ppi_channel_free(m_ppi_channels[i]);
+ ASSERT(ret == NRF_SUCCESS)
+ }
+}
+
+void nrf_libuarte_async_enable(size_t chunk_size)
+{
+ ASSERT(chunk_size <= MAX_CHUNK_SZ);
+ uint8_t * p_data;
+ p_data = nrf_balloc_alloc(&m_rx_pool);
+ m_alloc_cnt++;
+ if (p_data == NULL)
+ {
+ APP_ERROR_CHECK_BOOL(false);
+ }
+ nrfx_timer_clear(&m_timer);
+ nrfx_err_t err = nrfx_ppi_channel_enable(m_ppi_channels[PPI_CH_RXRDY_CLEAR]);
+ APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
+ err = nrfx_ppi_channel_enable(m_ppi_channels[PPI_CH_COMPARE_SHUTDOWN]);
+ APP_ERROR_CHECK_BOOL(err == NRFX_SUCCESS);
+
+ mp_curr_rx_buf = p_data;
+ m_rx_chunk_size = chunk_size;
+ ret_code_t ret = nrf_libuarte_rx_start(p_data, chunk_size, false);
+ APP_ERROR_CHECK_BOOL(ret == NRF_SUCCESS);
+}
+
+ret_code_t nrf_libuarte_async_tx(uint8_t * p_data, size_t length)
+{
+ return nrf_libuarte_tx(p_data, length);
+}
+
+void nrf_libuarte_async_rx_free(uint8_t * p_data, size_t length)
+{
+ m_rx_free_cnt += length;
+ if (m_rx_free_cnt == m_rx_chunk_size)
+ {
+ p_data -= (m_rx_free_cnt - length);
+ m_rx_free_cnt = 0;
+ nrf_balloc_free(&m_rx_pool, p_data);
+
+ m_alloc_cnt--;
+ if (m_alloc_cnt<0)
+ {
+ NRF_LOG_ERROR("Freeing more RX buffers than allocated.");
+ APP_ERROR_CHECK_BOOL(false);
+ }
+ NRF_LOG_INFO("Freeing full buffer 0x%08X, %d, (currently allocated:%d).",p_data, length, m_alloc_cnt);
+ }
+ else if (m_rx_free_cnt > m_rx_chunk_size)
+ {
+ NRF_LOG_ERROR("Unexpected RX free input parameter.")
+ APP_ERROR_CHECK_BOOL(false);
+ }
+ else
+ {
+ NRF_LOG_INFO("Freeing partial buffer: 0x%08X, length:%d", p_data, length)
+ }
+
+}
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte_async.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte_async.h
new file mode 100644
index 0000000..9930a81
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_libuarte/nrf_libuarte_async.h
@@ -0,0 +1,135 @@
+/**
+ * Copyright (c) 2018 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#ifndef UART_ASYNC_H
+#define UART_ASYNC_H
+#include <stdint.h>
+#include "sdk_errors.h"
+#include <hal/nrf_uarte.h>
+
+/** @brief Types of libuarte driver events. */
+typedef enum
+{
+ NRF_LIBUARTE_ASYNC_EVT_RX_DATA, ///< Requested TX transfer completed.
+ NRF_LIBUARTE_ASYNC_EVT_TX_DONE, ///< Requested RX transfer completed.
+ NRF_LIBUARTE_ASYNC_EVT_ERROR ///< Error reported by UARTE peripheral.
+} nrf_libuarte_async_evt_type_t;
+
+/** @brief Structure for libuarte async transfer completion event. */
+typedef struct
+{
+ uint8_t * p_data; ///< Pointer to memory used for transfer.
+ size_t length; ///< Number of bytes transfered.
+} nrf_libuarte_async_data_t;
+
+/** @brief Structure for libuarte async configuration. */
+typedef struct
+{
+ uint32_t rx_pin; ///< RXD pin number.
+ uint32_t tx_pin; ///< TXD pin number.
+ uint32_t cts_pin; ///< CTS pin number.
+ uint32_t rts_pin; ///< RTS pin number.
+ uint32_t timeout_us; ///< Receiver timeout in us unit.
+ nrf_uarte_hwfc_t hwfc; ///< Flow control configuration.
+ nrf_uarte_parity_t parity; ///< Parity configuration.
+ nrf_uarte_baudrate_t baudrate; ///< Baudrate.
+} nrf_libuarte_async_config_t;
+
+/** @brief Structure for libuarte error event. */
+typedef struct
+{
+ nrf_libuarte_async_evt_type_t type; ///< Event type.
+ union {
+ nrf_libuarte_async_data_t rxtx; ///< RXD/TXD data.
+ } data; ///< Union with data.
+} nrf_libuarte_async_evt_t;
+
+/**
+ * @brief Interrupt event handler.
+ *
+ * @param[in] p_evt Pointer to event structure. Event is allocated on the stack so it is available
+ * only within the context of the event handler.
+ */
+typedef void (*nrf_libuarte_async_evt_handler)(nrf_libuarte_async_evt_t * p_evt);
+
+/**
+ * @brief Function for initializing the libuarte async library.
+ *
+ * @param[in] p_config Pointer to the structure with initial configuration.
+ * @param[in] evt_handler Event handler provided by the user. Must not be NULL.
+ *
+ * @return NRF_SUCCESS when properly initialized. NRF_ERROR_INTERNAL otherwise.
+ */
+ret_code_t nrf_libuarte_async_init(nrf_libuarte_async_config_t const * p_config,
+ nrf_libuarte_async_evt_handler evt_handler);
+
+/** @brief Function for uninitializing the libuarte async library */
+void nrf_libuarte_async_uninit(void);
+
+/**
+ * @brief Funtrion for setting buffer and its size for received data.
+ *
+ * @param chunk_size Number of bytes in chunk of data
+ */
+void nrf_libuarte_async_enable(size_t chunk_size);
+
+/**
+ * @brief Function for sending data asynchronously over UARTE.
+ *
+ * @param[in] p_data Pointer to data.
+ * @param[in] length Number of bytes to send. Maximum possible length is
+ * dependent on the used SoC (see the MAXCNT register
+ * description in the Product Specification). The library
+ * checks it with assertion.
+ *
+ * @retval NRF_ERROR_BUSY Data is transferring.
+ * @retval NRF_ERROR_INTERNAL Error during configuration.
+ * @retval NRF_SUCCESS Buffer set for sending.
+ */
+ret_code_t nrf_libuarte_async_tx(uint8_t * p_data, size_t length);
+
+/**
+ * @brief Function for deallocating received buffer data.
+ *
+ * @param[in] p_data Pointer to data.
+ * @param[in] length Number of bytes to free.
+ */
+void nrf_libuarte_async_rx_free(uint8_t * p_data, size_t length);
+
+#endif //UART_ASYNC_H