This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Libuarte stops working after a certain amount of bytes have been recieved/transmitted

Hi,

I am running into some problems with libuarte. I have two nRF52840-DKs talking to each other over UART. My setup is not ordinary however. The hardware configuration looks like this:

I am basically trying to communicate over a 1-wire bus using libuarte. The way I'm doing it is by having the TX pin configured as an input when in "RX mode" and have the TX pin configured as an output pin when in "TX mode". One problem that is faced with such a configuration is that the transmitted data will also be received by the transmitter. But this data can be discarded by comparing each incoming packet with the latest transmitted packet.

My code looks like this:

#define UNUSED_DEV_PIN NRF_GPIO_PIN_MAP(1, 15)

NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 3, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 7000, 3);

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

    switch (p_evt->type)
    {
        int txCmp;
        case NRF_LIBUARTE_ASYNC_EVT_ERROR:
            NRF_LOG_ERROR("NRF_LIBUARTE_ASYNC_EVT_ERROR\r\n");
            break;
        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
            txCmp = memcmp((uint8_t *)libuarte.p_libuarte->uarte->TXD.PTR ,p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            if (0 == txCmp)
            {
                // This message was a message we transmitted, ignore!
                nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
                break;
            }

            // handle_received_data(p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            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:
            enable_uart_rx();
            break;
        default:
            break;
    }
}

uint32_t pot_serial_init()
{
    ret_code_t err_code;

    nrf_libuarte_async_config_t nrf_libuarte_async_config = {
            .tx_pin     = UART_TX_PIN_NUMBER,
            .rx_pin     = UART_RX_PIN_NUMBER,
            .baudrate   = NRF_UARTE_BAUDRATE_460800,
            .parity     = NRF_UARTE_PARITY_EXCLUDED,
            .hwfc       = NRF_UARTE_HWFC_DISABLED,
            .timeout_us = 100,
            .int_prio   = APP_IRQ_PRIORITY_LOW
    };

    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);
;
    enable_uart_rx();

    return 0;
}

uint32_t serial_tx(uint16_t conn_key, uint8_t *p_data, uint16_t length)
{
    enable_uart_tx();
    ret_code_t err_code = nrf_libuarte_async_tx(&libuarte, p_data, length);

    return err_code;
}

static void enable_uart_tx()
{

    nrf_gpio_pin_set(UART_TX_PIN_NUMBER);
    nrf_gpio_cfg_output(UART_TX_PIN_NUMBER);
    nrf_uarte_txrx_pins_set(libuarte.p_libuarte->uarte, UART_TX_PIN_NUMBER, UART_RX_PIN_NUMBER);
}

static void enable_uart_rx()
{
    nrf_gpio_cfg_input(UART_TX_PIN_NUMBER, NRF_GPIO_PIN_NOPULL);
    nrf_uarte_txrx_pins_set(libuarte.p_libuarte->uarte, UNUSED_DEV_PIN, UART_RX_PIN_NUMBER);
}

This implementation works fine up until a certain point. The problem I am facing is that after a while, the communication stops working...The problem can be remedied by increasing the rx_buf_size in the NRF_LIBUARTE_ASYNC_DEFINE macro call. I don't understand why this could be happening, I am calling nrf_libuarte_async_rx_free in every instance the libuarte event handler is called with event type NRF_LIBUARTE_ASYNC_EVT_RX_DATA. It's worth noting that both sides (both nRF52840-DKs) experience this issue.

Am I missing something?


I am using arm-gcc 9.2.1 on MacOS with nRF5SDK v.17.0.2.


Best regards,

Tofik

Parents
  • Hi 

    Are you sure reconfiguring the pins back and forth is necessary? 

    When the UARTE interface is assigned to a pin it should override the GPIO settings, and it might be possible to simply assign both TX and RX to the same pin all the time. 

    In either case please note that this is not a use case that is tested or officially supported, so use it at your own risk. 

    Does it matter how fast you send data, or is it just the number of bytes that triggers the error?

    Does it happen consistently after a certain number of bytes?

    Do you get any errors or asserts in the code when the issue happens?

    Best regards
    Torbjørn

Reply
  • Hi 

    Are you sure reconfiguring the pins back and forth is necessary? 

    When the UARTE interface is assigned to a pin it should override the GPIO settings, and it might be possible to simply assign both TX and RX to the same pin all the time. 

    In either case please note that this is not a use case that is tested or officially supported, so use it at your own risk. 

    Does it matter how fast you send data, or is it just the number of bytes that triggers the error?

    Does it happen consistently after a certain number of bytes?

    Do you get any errors or asserts in the code when the issue happens?

    Best regards
    Torbjørn

Children
  • Hi Torbjörn,

    The reason I am reconfiguring the pins is that I don't want the receiving party's TX pin to transmit a high signal (default UART behavior when a TX pin is not transmitting any data) while it's receiving data. This is because that would make the data in the one-wire interface transmitted from the transmitting party erroneous.

    The speed does not seem to affect this. It seems to happen when the number of bytes specified for rx_buf_size in NRF_LIBUARTE_ASYNC_DEFINE has been received. I get no errors during the code execution. I have also enabled logging for the libuarte module and I don't see any errors there.


    Regards,
    Tofik

  • You might find this link uarte-in-semi-duplex-mode useful; it discusses your intention in some detail.

  • Hi hmoleswort,

    I checked the ticket you referred to. I am not sure the same problem is experienced since I'm not getting any frame errors or overruns. My problem seems to be linked to the rx buffer libuarte uses. I might however try to use app_uart instead of libuarte if there is a chance that I won't experience this problem with that library.

    / Tofik

  • Ok so I tried to do the same thing using app_uart instead of libuarte. I was using the same approach in regards to switching the TX pin to an input pin when receiving data (while setting uart tx pin select to an unused pin). But now I opted to also set the RX uart pin select to an unused pin when transmitting data (therefore, I don't receive the data I transmit). This approach worked with app_uart and I don't experience the communication not working after a certain number of bytes have been received.

    However, I still don't understand why the code I posted initially did not work. I would prefer to use libuarte and there must be something wrong in how the rx buffer was handled with the way I was using libuarte.

  • I also measured the performance of app_uart is not up to par with libuarte in terms of retrieving the received bytes, which makes us more interested in using libuarte instead...

Related