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

Reply
  • 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

Children
Related