Losing uart characters - activating UART in place of UARTE in nRF52840

I am receiving characters on the UART of nRF52840. In my application I receive characters at 115 kbaud. As I must inspect each character I set the the receive buffer size to 1 so I receive an interrupt for each character received. I then set a flag of "interrupt pending" and put the work into the scheduler for a task to process the data. I do not need to flag every interrupt, as the task will read all the characters that have arrived in the fifo and processes.

However I am missing interrupts for some characters that arrive and I receive a uart error, and sometimes  miss characters altogther, so my program fails when expecting specific data.

I am assuming that when using easy_dma, there is no fifo for the uart, rather characters are transferred to a memory buffer by dma, an interrupt is generated, and the data is moved from the memory buffer to the fifo buffer; the memory buffer is then set for the next character. This works if all interrupts occur as data is moved to the fifo. and my task will read.

What I really need is to set a memory buffer that is sufficiently large not to miss characters, and will generate an interrupt when data has arrived into the memory buffer and I can read all arrived characters.

This would be the behaviour of the UART, which has 6 deep hardware fifo, and would capture all the incoming characters and release them each time RX is read.

My question: Does the UARTE also use the hardware fifo to capture incoming characters that can be transferred to memory by DMA and interrupt generated for each character?

How do I use UART in place of UARTE, as all the code forces UARTE even if NRF_SERIAL_MODE_IRQ is selected,

#if defined(UARTE_PRESENT) && defined(UART_PRESENT)
    drv_config.use_easy_dma = (p_config->mode == NRF_SERIAL_MODE_DMA);
#endif

Here is my configuration code. I increase IRQ to try to ensure I capture interrupts. I am assuming interrupts are disabled somewhere, but not sure where,

#define SERIAL1_FIFO_TX_SIZE 64

#define SERIAL1_FIFO_RX_SIZE 64

NRF_SERIAL_QUEUES_DEF(serial1_queues, SERIAL1_FIFO_TX_SIZE, SERIAL1_FIFO_RX_SIZE);

#define SERIAL1_BUFF_TX_SIZE 16
#define SERIAL1_BUFF_RX_SIZE 1

NRF_SERIAL_BUFFERS_DEF(serial1_buffs, SERIAL1_BUFF_TX_SIZE, SERIAL1_BUFF_RX_SIZE);

NRF_SERIAL_CONFIG_DEF(serial1_config, NRF_SERIAL_MODE_DMA,
                      &serial1_queues, &serial1_buffs, gprsUartEventHandler, NULL);

NRF_SERIAL_UART_DEF(serial1_uarte, 1);

#define GPRS_UART_CONFIG_IRQ_PRIORITY 2

I have some oscilloscope traces to show enter/exit of the interrupt routine and the task is this helps to understand the issue

Parents
  • Hi,

    This would be the behaviour of the UART, which has 6 deep hardware fifo, and would capture all the incoming characters and release them each time RX is read.

    You are rigth that the UART RX FIFO is 6 bytes. The UARTE use DMA however, so the data is written directly to a buffer that is as large as needed, offloading the CPU. This means that for most real applications (where the application is not only handlig UART), the UARTE is better, and I struggle to see why you want to use the deprecated UART peripheral instead?

    My question: Does the UARTE also use the hardware fifo to capture incoming characters that can be transferred to memory by DMA and interrupt generated for each character?

    The FIFO is still there, but you cannot get an interrupt for each received byte. That is a limitation in UARTE, and if you need to know the number of received bytes before the Rx buffer is full, you may want to have a look at libuarte, which use a TIEMR in counter mode and PPI to count received bytes.

    How do I use UART in place of UARTE, as all the code forces UARTE even if NRF_SERIAL_MODE_IRQ is selected

    I do not immediately recognize these code snippets. Where does it come from? That said, I can think of few applications where it would make sense to use the legacy UART peripheral.

  • I have set SERIAL1_BUFF_RX_SIZE to 1, so this generates an interrupt for each character. However I do not get an interrupt for some characters, and instead I get uart error (no stop bit). I have scope trace to demonstrate the issue.

  • Hi Malcolm,

    Ah, I see. That is why I did not find this. The Serial port library has some issues and was removed from SDK 17.x.x. I would recommend that you use libuarte instead, which is it's replacement. This is also present in SDK 16 (though I would consider migrating to 17.1.0).

    Einar

  • Hi Einor

    Whilst there may be isues in V16 I have not encountered, and we are close to release of software for a pjoect so I do not want to do a complete migration to a new version unless absolutely essential as I have hacked some of the code.

    The issue that remains appears to be that characters are not being buffered in a FIFO and are lost or corrupted by missing parts. I can send an image of a capture from a scope that best illustrates. I cannot upload the image as it pdf file and not allowed.

    I think the main issue for me is that code somewhere disables interrupts for an extended period, and I must find and solve that problem.

  • I see. I am not able to say what the issue is based on what I know, but an important limitation of the serial port library you are using is that it does not do EasyDMA double buffering. So when the buffer is full, you get a NRF_SERIAL_EVENT_RX_DATA event, and only after that has been handled the library start Rx again (using the same old Rx buffer). You can see this from the implementation of uart_event_handler() in nrf_serial.c. So if you spend too long time handling the received bytes, or something else prevents the library from starting Rx again, you can loose incoming data. (This is one of the things that has improved in libuarte).

  • I appear to have encountered a second problem with missing interrupts and characters. I am sure there is not hardware FIFO for the uarte, rather it relies on direct DMA transfer to a buffer. In my case I must process every incoming character. Therefore I will need to ensure that DMA double buffering is configured. I will try libuart to determine if it is a fix.

Reply Children
Related