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

nRF9160 UART: Loosing data when RxData is split into 2 buffers (Async API)

Hello everyone,

 

I am currently using the Nordic-Thingy-91 to test the nRF9160. Now I am trying to receive Data from the UART interface using the "UART Async API".

 

I am switching between three 64 bytes buffers to ensure continuous reception of data.

And that is where run into a problem when the receiving data is split into two buffers, due to one buffer running out of space.

 

I am using Putty to send data and I am not sending byte for byte, I am sending multiple bytes at once.

As long as the received data fits into the current buffer, everything is fine.

But if the RX data doesn't fit into to current buffer and the second buffer is used too, I loose data.

 

For example:

RxBuffer1 and RxBuffer2 each have 64 bytes.

 

RxBuffer1 has only 4 bytes left.

I send 10 bytes of data from Putty to the board.

 

Expected behaviour:

  • RX_RDY event for the 4 bytes in RxBuffer1
  • Another RX_RDY event for the remaining 6 bytes in RxBuffer2

 

Actual behaviour:

  • RX_RDY event for the 4 bytes in RxBuffer1
  • Another RX_RDY event, but the event data says there is only 1 byte in RxBuffer2
    --> so I loose 5 bytes of data

 

For RX_BUF_REQUEST events I provide the API with the next buffer, to ensure continuous reception.

 

Here are two Screenshots of exactly this case. I have marked the 3 buffers in the memory window.

The red entries in the memory view is the new data which is split into 2 buffers.

So there are 4 new bytes in the first buffer and 6 new bytes in the second buffer.

 

Here is the first RX_RDY event which gives me 4 bytes in the first buffer. Everythings is fine..

 

 

The second RX_RDY event, which is shown next, says there is only 1 byte new in the second buffer, even though I can see there is actually more data in the memory.

 

 

So all the data is received and correctly stored in the memory, but the second RX_RDY event for the second buffer only gives me 1 byte, even though there are more…

 

Has anyone experienced a similar problem and can help me with this issue? Or is this a known issue?

 

I have also looked into the Zephyr driver test under *\v1.5.0\zephyr\tests\drivers\uart\uart_async_api but this test only sends/receives data which fits perfectly into the buffer.

 

Here is my prj.conf and main.c I use:

prj.conf:

# UART
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y # Enable Async API

# Enable UART console, for printk()
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

main.c

#include <string.h>
#include <zephyr.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/uart.h>
#include <sys/printk.h>

// UART0 device
#define UART_DEV DT_LABEL(DT_NODELABEL(uart0))
//#define UART_DEV  DT_LABEL(DT_ALIAS(serial0)) // also works

// Rx Buffers
static uint8_t rx_buf0[64];
static uint8_t rx_buf1[64];
static uint8_t rx_buf2[64];

// Callback for asynchron UART communication
static void uart_CB(const struct device *dev, struct uart_event *evt, void *user_data)
{
	static uint8_t lineBuffer[64];
	static int lineLength = 0;
	static uint8_t * buffers[3] = { rx_buf0, rx_buf1, rx_buf2 };
	static uint8_t index = 1;

	switch (evt->type)
	{
	case UART_RX_RDY:

		if(evt->data.rx.len > 0)
		{
			//printk("UART RX reading %d bytes from buffer %p with offset %d\n", evt->data.rx.len, evt->data.rx.buf, evt->data.rx.offset);
			memcpy(lineBuffer+lineLength, evt->data.rx.buf + evt->data.rx.offset, evt->data.rx.len);
			lineLength += evt->data.rx.len;

			if(lineBuffer[lineLength-1] == '\n' || lineBuffer[lineLength-1] == '\r')	// echo line
			{
				int ret = uart_tx(dev, lineBuffer, lineLength, SYS_FOREVER_MS);

				if (ret != 0)	
                    printk("uart_tx() failed, returned: %d\n", ret);

				lineLength = 0;
			}
		}
		
		break;

	case UART_RX_BUF_REQUEST:
		printk("Event: UART_RX_BUF_REQUEST\n");
		uart_rx_buf_rsp(dev, buffers[index], 64); // switch between 3 buffers
		index = (index + 1) % 3;
		break;

	case UART_RX_DISABLED:
		printk("Event: UART_RX_DISABLED\n");
		uart_rx_enable(dev, evt->data.rx_buf.buf, 64, 100); // re-enable rx
		break;

	case UART_RX_BUF_RELEASED:
		printk("Event: UART_RX_BUF_RELEASED, buf = %p\n", evt->data.rx_buf.buf);
		break;

	case UART_TX_DONE:
		printk("\nuartCB() callback: TxDone sent %d bytes\n", evt->data.tx.len);
		break;
		
	default:
		printk("Unexpected event type in callback: %d\n", evt->type);
		break;
	}
	
}

void main(void)
{	
	int ret = 0;

	const struct device *uart_dev = device_get_binding(UART_DEV);

	if (uart_dev == NULL) {
		printk("Failed to get UART device\n");
	}

	// register callback function
	ret = uart_callback_set(uart_dev, uart_CB, NULL);

	if (ret != 0) {
		printk("uart_callback_set() failed, returned: %d\n", ret);
	}

	ret = uart_rx_enable(uart_dev, rx_buf0, 64, 10);

	if (ret != 0) {
		printk("uart_rx_enable() failed, returned: %d\n", ret);
	}

	while (1)
	{		

	}
}

Parents Reply Children
Related