Simultaneous communication on 2 sync libUARTe

Hi.

We are using nRF52833 (on BL653 module) where UART0 and UART1 are used for communication purposes (one with STM MUC and the other with quectel modem). Current solution uses SDK 17.0.2, softdevice and freeRTOS, where async libuarte support is used for uart communication. The main problem is that, from time to time (every couple of minutes), we get a HardFault. But only when both are active. If we disable on of them, the code looks to work as expected.

Currently, the UARTs are defined as (using app_timer):

NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 1, 4, NRF_LIBUARTE_PERIPHERAL_NOT_USED, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 1024, 3);

NRF_LIBUARTE_ASYNC_DEFINE(quectel_libuarte, 0, 3, NRF_LIBUARTE_PERIPHERAL_NOT_USED, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 1024, 3);

We found out that using exact TIMER (TIMER2) works worse as before we used:
NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 1, 4, 2, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 1024, 3);
NRF_LIBUARTE_ASYNC_DEFINE(quectel_libuarte, 0, 3, NRF_LIBUARTE_PERIPHERAL_NOT_USED, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 1024, 3);
So, the first question is which TIMER is preferred to be used for UART when softdevice is present?
And while changing to app_timer made things better, HardFault still occurs. In the docs you can find: "If the TXD.PTR and the RXD.PTR are not pointing to the Data RAM region, an EasyDMA transfer may result in a HardFault or RAM corruption.". What is the best scenario to check whether this is the cause in our case?
Also, do both interfaces share any common shared source (besides easyDMA, which should work with both of them)? For example, should UART1 wait for UART0 to finish anything it does (writing and/or reading)? We are aware that UART can not read and write at the same time. Are we missing something else?
Best regards,
Vojko
Parents
  • To elaborate further here is our uarte handler:

    void uarte_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt){
    switch (p_evt->type){
    case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
    {
    NRF_LOG_ERROR("uarte: EVT_RX - data received");
    BaseType_t yield = pdFALSE;
    BaseType_t sent = errQUEUE_FULL;
    uart_queue_data_t data;
    data.length = p_evt->data.rxtx.length;
    data.p_data = p_evt->data.rxtx.p_data;
    sent = xQueueSendFromISR(stm_uart_rx_queue, &data, &yield);
    if(sent != pdTRUE){
    NRF_LOG_ERROR("uarte: queue full");
    }
    portYIELD_FROM_ISR(yield);
    } break;

    case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
    {
    BaseType_t yield = pdFALSE;
    xEventGroupSetBitsFromISR(stm_uart_tx_event_h, 0x01, &yield);
    portYIELD_FROM_ISR(yield);
    } break;
    case NRF_LIBUARTE_ASYNC_EVT_ERROR:
    NRF_LOG_ERROR("uarte: error %d", p_evt->data.errorsrc);
    break;
    case NRF_LIBUARTE_ASYNC_EVT_OVERRUN_ERROR:
    NRF_LOG_ERROR("uarte: overrun: lost %d", p_evt->data.overrun_err.overrun_length);
    break;
    default:
    NRF_LOG_ERROR("uarte: wrong state");
    break;
    }
    }
    nrf_libuarte_async_rx_free is called in the task fetching data from the queue. UART baudrate is 115200 with hardware flow control disabled:
    nrf_libuarte_async_config_t nrf_libuarte_async_config = {
    .tx_pin = UARTE_TX_PIN,
    .rx_pin = UARTE_RX_PIN,
    .baudrate = NRF_UARTE_BAUDRATE_115200,
    .parity = NRF_UARTE_PARITY_INCLUDED,
    .hwfc = NRF_UARTE_HWFC_DISABLED,
    .timeout_us = 100,
    .int_prio = APP_IRQ_PRIORITY_LOW
    };
Reply
  • To elaborate further here is our uarte handler:

    void uarte_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt){
    switch (p_evt->type){
    case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
    {
    NRF_LOG_ERROR("uarte: EVT_RX - data received");
    BaseType_t yield = pdFALSE;
    BaseType_t sent = errQUEUE_FULL;
    uart_queue_data_t data;
    data.length = p_evt->data.rxtx.length;
    data.p_data = p_evt->data.rxtx.p_data;
    sent = xQueueSendFromISR(stm_uart_rx_queue, &data, &yield);
    if(sent != pdTRUE){
    NRF_LOG_ERROR("uarte: queue full");
    }
    portYIELD_FROM_ISR(yield);
    } break;

    case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
    {
    BaseType_t yield = pdFALSE;
    xEventGroupSetBitsFromISR(stm_uart_tx_event_h, 0x01, &yield);
    portYIELD_FROM_ISR(yield);
    } break;
    case NRF_LIBUARTE_ASYNC_EVT_ERROR:
    NRF_LOG_ERROR("uarte: error %d", p_evt->data.errorsrc);
    break;
    case NRF_LIBUARTE_ASYNC_EVT_OVERRUN_ERROR:
    NRF_LOG_ERROR("uarte: overrun: lost %d", p_evt->data.overrun_err.overrun_length);
    break;
    default:
    NRF_LOG_ERROR("uarte: wrong state");
    break;
    }
    }
    nrf_libuarte_async_rx_free is called in the task fetching data from the queue. UART baudrate is 115200 with hardware flow control disabled:
    nrf_libuarte_async_config_t nrf_libuarte_async_config = {
    .tx_pin = UARTE_TX_PIN,
    .rx_pin = UARTE_RX_PIN,
    .baudrate = NRF_UARTE_BAUDRATE_115200,
    .parity = NRF_UARTE_PARITY_INCLUDED,
    .hwfc = NRF_UARTE_HWFC_DISABLED,
    .timeout_us = 100,
    .int_prio = APP_IRQ_PRIORITY_LOW
    };
Children
No Data
Related