nRF5 SDK is not maintained anymore
More Info: Consider nRF Connect SDK for new designs

LIBUARTE - no NRF_LIBUARTE_ASYNC_EVT_RX_DATA event

Hi

I have combined the ble_app_uart and libuarte example. The combination works "nearly" well.Transmit is ok, but when receiving characters over UARTE, no NRF_LIBUARTE_ASYNC_EVT_RX_DATA event is generated until a buffer is full. Hence, I don't get any timeout! When printing the buffer, I can see that all RX characters are received correctly, but for small packages, I would like to have timeouts.

I'm using nRF5 SDK version17.2 on a custom board. 

this is the definition:

NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 1, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 5);

..and the rest of the essential code:

typedef struct {
    uint8_t * p_data;
    uint32_t length;
} buffer_t;

NRF_QUEUE_DEF(buffer_t, m_buf_queue, 10, NRF_QUEUE_MODE_NO_OVERFLOW);

void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
{
    nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
    ret_code_t ret;

    switch (p_evt->type)
    {
        case NRF_LIBUARTE_ASYNC_EVT_ERROR:
            break;
        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
            NRF_LOG_HEXDUMP_INFO(p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            // Done processing buffer, release buffer back to libUARTE
            nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            break;
        case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
            if (!nrf_queue_is_empty(&m_buf_queue))
            {
                buffer_t buf;
                ret = nrf_queue_pop(&m_buf_queue, &buf);
                APP_ERROR_CHECK(ret);
                UNUSED_RETURN_VALUE(nrf_libuarte_async_tx(p_libuarte, buf.p_data, buf.length));
            }
            else 
            {
                // done transmitting....start listening
                rs485_duplex_mode(RS485_RX);
            }
            break;
        default:
            break;
    }
}

void 
msgSend (uint8_t* data, uint8_t len)
{
    // turn on rs485 Tx --- TODO: turn off in callback
    rs485_duplex_mode(RS485_TX);

//    NRF_LOG_HEXDUMP_INFO(data,len);

    ret_code_t ret = nrf_libuarte_async_tx(&libuarte, data, len);
    if (ret == NRF_ERROR_BUSY)
    {
        buffer_t buf = {
            .p_data = data,
            .length = len,
        };

        ret = nrf_queue_push(&m_buf_queue, &buf);
        APP_ERROR_CHECK(ret);
    }
    else
    {
        APP_ERROR_CHECK(ret);
    }
}

void libuarte_init(void){
    ret_code_t ret = nrf_drv_clock_init();
    APP_ERROR_CHECK(ret);
  
    nrf_drv_clock_lfclk_request(NULL);

    nrf_libuarte_async_config_t nrf_libuarte_async_config = {
            .tx_pin     = TX_PIN_NUMBER,
            .rx_pin     = RX_PIN_NUMBER,
            .baudrate   = NRF_UARTE_BAUDRATE_115200,
            .parity     = NRF_UARTE_PARITY_EXCLUDED,
            .hwfc       = NRF_UARTE_HWFC_DISABLED,
            .timeout_us = 100,
            .int_prio   = APP_IRQ_PRIORITY_MID
    };

    ret_code_t err_code = nrf_libuarte_async_init(&libuarte, &nrf_libuarte_async_config, uart_event_handler, (void *)&libuarte);

    APP_ERROR_CHECK(err_code);

    nrf_libuarte_async_enable(&libuarte);
}

Note: The msgSend() is used since I have placed libuarte definitions outside main(), and msgSend() is called from main() since libuarte is not defined in main()

Note: Communication is over half duplex RS485. Hence, rs485_duplex_mode().

Parents
  • Hi Torbjørn

    I do have a 32 kHz crystal. A quick test setting  CLOCK_CONFIG_LF_SRC  to 0 (RC) did non change anything. I even tried these settings (one at a time):

    NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 1, NRF_LIBUARTE_PERIPHERAL_NOT_USED, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 16, 5);
    NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 1, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 1, 16, 5);
    NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 1, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 2, 16, 5);
    

    1. The first one did no change
    2. The second one gave fatal error. Maybe because timer 1 is used for softdevice?
    3. The third option did work after I enabled timer 2 in sdk_config.h

    But why doesn't RTC work? Any settings to change or tests to perform to find out?

    Best Regards

    Bård

  • Hi Bård

    1. In this case you don't assign any RTC or TIMER to handle the RX timeout, and the driver will revert to using the app_timer instead. If you initialize the app_timer library before you initialize libuarte this should work. 

    2. In this case both of the libuarte TIMER modules are set to 1, which means you get a conflict. The third and fifth parameter needs to point to different timers. 

    bh said:
    But why doesn't RTC work? Any settings to change or tests to perform to find out?

    I forgot to check if you use SoftDevice. The SoftDevice uses RTC0, which is probably why your original configuration didn't work. 

    If you only use RTC modules for the SoftDevice (RTC0) and app_timer (RTC1), then RTC2 should be available for libuarte. 

    Alternatively we can look into why the app_timer option doesn't seem to work, which is a good option if you are planning to use app_timer anyway. 

    Best regards
    Torbjørn

  • Hello , can you specify please what we have to change exactly ?

    I m using the libuarte in that way and i'm facing the same problem 

    NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 0, 2, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);

    i can transmit data .but i can not receive it because i noticed that there wasn't any event happening when i m supposed to receive DATA

  • Hi 

    Did you remember to start RX?

    I would recommend you open a new ticket on this, and share the code you use to initialize the libuarte driver. Then we can have a look at it, and see if we can spot any issues in the code. 

    Best regards
    Torbjørn

Reply Children
No Data
Related