NRFX UART RX CONTINUOUS RECEIVE where RX LEN is unknown

Hello,

  I am using nrfx library for nrf5340 because I wanted to change UART pins dynamically at run time by disabling, changing pins and renabling the UART.  This part is working fine,

Now I neewd to know how to receive data continuously and fill to an OS fifo. 

Right now I am having a handler as below

static void uarte_handler(nrfx_uarte_event_t const * p_event, void * p_context)
{
    nrfx_uarte_t * p_inst = p_context;
    if (p_event->type == NRFX_UARTE_EVT_TX_DONE)
    {
        // NRFX_LOG_INFO("--> UARTE event: TX done");
        // NRFX_LOG_INFO("Content of TX buffer: %s", m_tx_buffer);
        // NRFX_LOG_INFO("Content of RX buffer: %s", m_rx_buffer);
    }
    else
    {
        //NRFX_LOG_INFO("UARTE event: %d", p_event->type);
    }
    //nrfx_uarte_uninit(p_inst);
}
And the method of initializing RX is to do something like below
   status = nrfx_uarte_rx(&uarte_inst, m_rx_buffer, sizeof(m_rx_buffer));
   NRFX_ASSERT(status == NRFX_SUCCESS);
But how can I continuously receive data where I don't know the length of data because that depends on payload type and this is totally asynchronous and at any time I should be able to receive data. In this scenereo how to achieve it?
  • Thanks for this information.

    I implemented the method I mentioned and I faced sometime some data missing while aboarting and re-starting. I will look into the EVENTS_RXDRDY and will update you. 

    Update after implementing RXDRDY:

    1)By the way, I am not able to find the libuarte source code, could you please show where I can find it?

    2)RXRDY is showing as event 1 or 0, but how can I know how many bytes are received in the RAM if timeout happens? I checked many registers under UARTE0 but  couldn't find anything holding the current number of received bytes over dma (partial).

    3)Out of curiosity, asking, how to collect partially received data in RAM without aborting the uart_rx?

    Attaching my current working code, implemented RXRDY to detect if something is received after timeout or not, if something is received, then Iam aborting at present to collect the data RX. This is working at present without any error after several minutes of testing, but still I am looking for somehing without aborting the rx at all.

    #include <stdio.h>
    #include <zephyr/kernel.h>
    #include <zephyr/sys/ring_buffer.h>
    #include <nrfx_uarte.h>
    #include <zephyr/sys/printk.h>
    #include <nrfx_log.h>
     
    #define UARTE_INST_IDX 0
    #define UARTE_TX_PIN 31
    #define UARTE_RX_PIN 5
    #define DOUBLE_BUFF_SIZE 200
    #define UART_RX_TIMEOUT 200 // 100ms
    #define MY_RING_BUF_BYTES 1024
     
    K_SEM_DEFINE(rx_timeout_sem, 0, 1);
    RING_BUF_DECLARE(uart_rx_ring_buf, MY_RING_BUF_BYTES);
    nrfx_uarte_t uarte_inst = NRFX_UARTE_INSTANCE(UARTE_INST_IDX);
     
    static volatile uint8_t uart_rx_timeout_triggered;
    static uint8_t rx_doublebuffer[2][DOUBLE_BUFF_SIZE];
     
     
    volatile static int skipcnt;
     
     
     static void uart_rx_timeout_work_handler(struct k_work *work);
     
    static K_WORK_DELAYABLE_DEFINE(uart_rx_timeout_work, uart_rx_timeout_work_handler);
     
     static void uart_rx_timeout_work_handler(struct k_work *work)
    {
        ARG_UNUSED(work);
        uart_rx_timeout_triggered = 1;
        if((uarte_inst.p_reg)->EVENTS_RXDRDY) {
            nrfx_uarte_rx_abort(&uarte_inst);
        }else {
            skipcnt++;
            k_work_reschedule(&uart_rx_timeout_work, K_MSEC(UART_RX_TIMEOUT)); // RX TIMEOUT RESCHEDULE
        }
    }
     
    static void uarte_handler(nrfx_uarte_event_t const *p_event, void *p_context)
    {
        nrfx_uarte_t *p_inst = p_context;
     
        if (p_event->type == NRFX_UARTE_EVT_TX_DONE)
        {
            ;
        }
        else if (p_event->type == NRFX_UARTE_EVT_RX_DONE)
        {
            uint8_t *buffer = p_event->data.rxtx.p_data; // alternate double buffer
     
            if (p_event->data.rxtx.bytes)
                ring_buf_put(&uart_rx_ring_buf, buffer, p_event->data.rxtx.bytes);
            nrfx_uarte_rx(p_inst, buffer, DOUBLE_BUFF_SIZE);
            if (uart_rx_timeout_triggered)
            {
                uart_rx_timeout_triggered = 0;
                if (ring_buf_size_get(&uart_rx_ring_buf))
                    k_sem_give(&rx_timeout_sem);
            }
            else if (ring_buf_size_get(&uart_rx_ring_buf) >= (MY_RING_BUF_BYTES / 2))
            {
                k_sem_give(&rx_timeout_sem);
            }
     
            k_work_reschedule(&uart_rx_timeout_work, K_MSEC(UART_RX_TIMEOUT)); // RX TIMEOUT RESCHEDULE
        }
        else if (p_event->type == NRFX_UARTE_EVT_ERROR)
        {
            nrfx_uarte_rx(&uarte_inst, rx_doublebuffer[0], DOUBLE_BUFF_SIZE);
            nrfx_uarte_rx(&uarte_inst, rx_doublebuffer[1], DOUBLE_BUFF_SIZE);
            ; // todo
        }
    }
     
    int nrfx_uart1_main(void)
    {
        nrfx_err_t status;
        (void)status;
     
        nrfx_uarte_config_t uarte_config1 = NRFX_UARTE_DEFAULT_CONFIG(31, 5); // UARTE_RX_PIN);
        nrfx_uarte_config_t uarte_config2 = NRFX_UARTE_DEFAULT_CONFIG(5, UARTE_RX_PIN);
        nrfx_uarte_config_t uarte_config3 = NRFX_UARTE_DEFAULT_CONFIG((1 << 5) | 10, UARTE_RX_PIN);
        uarte_config1.p_context = &uarte_inst;
        uarte_config2.p_context = &uarte_inst;
        uarte_config3.p_context = &uarte_inst;
        status = nrfx_uarte_init(&uarte_inst, &uarte_config1, uarte_handler);
        NRFX_ASSERT(status == NRFX_SUCCESS);
     
    #if defined(__ZEPHYR__)
        IRQ_DIRECT_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_UARTE_INST_GET(UARTE_INST_IDX)), IRQ_PRIO_LOWEST,
                           NRFX_UARTE_INST_HANDLER_GET(UARTE_INST_IDX), 0);
    #endif
     
        status = nrfx_uarte_rx(&uarte_inst, rx_doublebuffer[0], DOUBLE_BUFF_SIZE);
        NRFX_ASSERT(status == NRFX_SUCCESS);
        status = nrfx_uarte_rx(&uarte_inst, rx_doublebuffer[1], DOUBLE_BUFF_SIZE);
        NRFX_ASSERT(status == NRFX_SUCCESS);
        k_work_reschedule(&uart_rx_timeout_work, K_MSEC(UART_RX_TIMEOUT)); // debounce
        // status = nrfx_uarte_tx(&uarte_inst, m_tx_buffer, sizeof(m_tx_buffer));
        // NRFX_ASSERT(status == NRFX_SUCCESS);
     
        int cnt = 0;
        while (1)
        {
     
            k_sem_take(&rx_timeout_sem, K_FOREVER);
            while (1)
            {
                char c;
                if (ring_buf_get(&uart_rx_ring_buf, &c, 1) == 1)
                {
                    printk("%c", c);
                }
                else
                    break;
            }
     
            // SWITCHING UART PORT
            //  char txb[100];
            //  sprintf(txb, "HELLO WORLD %d\n", cnt++);
            //  char r[101];
            //  r[101] = 0;
            //  k_msgq_get(&q_name, r, K_FOREVER);
            //  printk("%s", r);
            //  nrfx_uarte_uninit(&uarte_inst);
            //  nrfx_uarte_init(&uarte_inst, &uarte_config1, uarte_handler);
            //  sprintf(txb, "HELLO WORLD %d\n", cnt++);
            //  nrfx_uarte_tx(&uarte_inst, txb, strlen(txb));
            //  k_msleep(1000);
     
            // nrfx_uarte_uninit(&uarte_inst);
            // nrfx_uarte_init(&uarte_inst, &uarte_config2, uarte_handler);
            // sprintf(txb, "HELLO WORLD %d\n", cnt++);
            // nrfx_uarte_tx(&uarte_inst, txb, strlen(txb));
            // k_msleep(1000);
     
            // nrfx_uarte_uninit(&uarte_inst);
            // nrfx_uarte_init(&uarte_inst, &uarte_config3, uarte_handler);
            // sprintf(txb, "HELLO WORLD %d\n", cnt++);
            // nrfx_uarte_tx(&uarte_inst, txb, strlen(txb));
            // k_msleep(1000);
            // NRFX_EXAMPLE_LOG_PROCESS();
        }
    }
     
    /** @} */

  • vinodsdw said:
    1)By the way, I am not able to find the libuarte source code, could you please show where I can find it?

    /nRF5_SDK_17.1.0_ddde560/components/libraries/libuarte

    vinodsdw said:
    2)RXRDY is showing as event 1 or 0, but how can I know how many bytes are received in the RAM if timeout happens? I checked many registers under UARTE0 but  couldn't find anything holding the current number of received bytes over dma (partial).

    You need to connect the event to a TIMER in counter mode to count the number of events triggered.

Related