<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/104641/nrf52dk-nrf52832-uart-asynchronous-receive</link><description>I am working through the Nordic Developer Academy and got stuck at lesson 4 (UART receive) 
 https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-4-serial-communication-uart/topic/uart-driver/ 
 
 In particular, I am confused</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 18 Mar 2025 12:59:59 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/104641/nrf52dk-nrf52832-uart-asynchronous-receive" /><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/527842?ContentTypeID=1</link><pubDate>Tue, 18 Mar 2025 12:59:59 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:fca9670b-7104-4c57-8441-9f7397e874dd</guid><dc:creator>Sarkar</dc:creator><description>&lt;p&gt;Hi &lt;a href="https://devzone.nordicsemi.com/members/zazas321"&gt;zazas321&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Can I have your code for testing.&lt;br /&gt;&lt;br /&gt;Actually I tried this code only then noticed a my_gpio header file so asking for your help to understand the code.&lt;br /&gt;&lt;br /&gt;I am also trying for the UART part.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/467185?ContentTypeID=1</link><pubDate>Thu, 01 Feb 2024 13:49:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:35ddf048-b7f7-492d-aee1-f81a5864f4c0</guid><dc:creator>Edvin</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;Andreas is currently busy with other tasks, so I will have a look at this ticket.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Please note that there is a lot of information here, but I have tried to get a reasonable overview.&amp;nbsp;&lt;/p&gt;
[quote user="zazas321"]POINT 1[/quote]
&lt;p&gt;Yes. This is a very simplified application. I suspect you are looking for functionality closer to the one found in ncs\nrf\samples\bluetooth\peripheral_uart. Please note that this doesn&amp;#39;t echo the data back on the UART, but it will transmit the UART data over BLE to the connected device. Please see the &lt;a href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/nrf/samples/bluetooth/peripheral_uart/README.html"&gt;sample description&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
[quote user="zazas321"]POINT 2[/quote]
&lt;p&gt;Noted. I agree.&lt;/p&gt;
[quote user="zazas321"]POINT 3[/quote]
&lt;p&gt;This makes sense, actually.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;printf, in your case uses the UART backend, so every time you send a message, or possibly a character, over UART, it will trigger a new callback to the very same uart callback that printed the character in the first place. Therefore, I recommend, if you want to use the log while using the UART, you should use the logging module (LOG_INF()) with RTT backend (and not UART backend). To see how to do this, look at how it is done in the ncs\nrf\samples\bluetooth\peripheral_uart sample.&amp;nbsp;&lt;/p&gt;
[quote user="zazas321"]Is this expected behaviour that a few printf statements in&amp;nbsp;&lt;strong&gt;uart_cb&lt;/strong&gt; causes weird behaviour as have been shown above?[/quote]
&lt;p&gt;I wouldn&amp;#39;t recommend using printf(), which will trigger uart callbacks inside the uart_cb.&lt;/p&gt;
[quote user="zazas321"]&amp;nbsp;If above is true, I am concerned about other high priority tasks or callbacks interrupting the UART&amp;nbsp;reception and causing &lt;span&gt;similar&amp;nbsp;&lt;/span&gt;issues even when all print statements are removed from the callback itself. Is ASYNC UART affected by other Zephyr RTOS threads running or it is independent and not affected at all?[/quote]
&lt;p&gt;I don&amp;#39;t think you will see similar issues with other high priority interrupts, as long as they are not triggered recursively via the UART callback.&amp;nbsp;&lt;/p&gt;
[quote user="zazas321"]During the discussion above it has been mentioned that it is recommended to use larger UART_BUF_SIZE but that did not help in any way. The only thing that does is just simply requires more serial data to be received before it fills up and eventually breaks.[/quote]
&lt;p&gt;I agree. That will just postpone the issue.&amp;nbsp;&lt;/p&gt;
[quote user="zazas321"]I would highly appreciate if someone with good Zephyr and ASYNC UART knowledge could shed some light here and cover the issues that I have encountered and the solutions that I have found.[/quote]
&lt;p&gt;I agree that this seems like a good solution for this need. However, I suggest not using the UART for log messages at all inside the uart callback handler. Either use no log, or use the RTT backend.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Edvin&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/467052?ContentTypeID=1</link><pubDate>Thu, 01 Feb 2024 06:43:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:f51385a1-e908-49f6-af9d-f46fe8d5a740</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;It has been a while but I still believe some things are not fully clear regarding ASYNC UART. Perhaps some things will be clarified at some point:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;POINT 1&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The async UART lesson in the code academy (&lt;a id="" href="https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-4-serial-communication-uart/topic/exercise-1-5/"&gt;https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-4-serial-communication-uart/topic/exercise-1-5/&lt;/a&gt;)&lt;br /&gt; can only be used in cases where the fixed length serial data is being received which is not what most UART use cases are like.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;POINT 2&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In order to use async UART when trying to receive varying length serial data (strings) with terminator, double buffer approach should be used because we need to handle a scenario where the buffer fills up but the full message hasnt been received and we need to stitch 2 buffers together to build a complete message.&lt;/p&gt;
&lt;p&gt;I have created some test code to test this out:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/drivers/gpio.h&amp;gt;
#include &amp;quot;stdio.h&amp;quot;
#include &amp;quot;my_gpio.h&amp;quot;
#include &amp;quot;zephyr/drivers/uart.h&amp;quot;
#include &amp;lt;zephyr/sys/ring_buffer.h&amp;gt;

#define LOG_LEVEL 4
#include &amp;lt;zephyr/logging/log.h&amp;gt;
LOG_MODULE_REGISTER(nrf52_learning);

#define UART_BUF_SIZE 24

#define UART_RX_TIMEOUT_MS 1000
K_SEM_DEFINE(rx_disabled, 0, 1);

// UART RX primary buffers
uint8_t uart_double_buffer[2][UART_BUF_SIZE];

uint8_t *uart_buf_next = uart_double_buffer[1];

uint8_t complete_message[UART_BUF_SIZE];
uint8_t complete_message_counter = 0;
bool currently_active_buffer = 1; // 0 - uart_double_buffer[0] is active, 1 - uart_double_buffer[1] is active

static const struct device *dev_uart;

static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{

	switch (evt-&amp;gt;type)
	{

	case UART_TX_DONE:
		printf(&amp;quot;transmission complete \n&amp;quot;);
		break;

	case UART_TX_ABORTED:
		// do something
		break;

	case UART_RX_RDY:

		printf(&amp;quot;Received %i bytes \n&amp;quot;, evt-&amp;gt;data.rx.len);
		printf(&amp;quot;Offset = %i  \n&amp;quot;, evt-&amp;gt;data.rx.offset);

		printf(&amp;quot;Constructing a complete message \n&amp;quot;);
		if (currently_active_buffer == 0)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[0][i];
				complete_message_counter++;
				if (uart_double_buffer[0][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 0 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		if (currently_active_buffer == 1)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[1][i];
				complete_message_counter++;
				if (uart_double_buffer[1][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 1 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		break;

	case UART_RX_BUF_REQUEST:
		uart_rx_buf_rsp(dev_uart, uart_buf_next, UART_BUF_SIZE);
		currently_active_buffer = !currently_active_buffer;
		if (currently_active_buffer == 0)
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[0] \n&amp;quot;);
		}
		else
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[1] \n&amp;quot;);
		}
		break;

	case UART_RX_BUF_RELEASED:
		printf(&amp;quot;Old buffer has been released \n&amp;quot;);
		uart_buf_next = evt-&amp;gt;data.rx_buf.buf;
		break;

	case UART_RX_DISABLED:
		printf(&amp;quot;rx disabled \n&amp;quot;);
		k_sem_give(&amp;amp;rx_disabled);
		break;

	case UART_RX_STOPPED:
		// do something
		break;

	default:
		break;
	}
}

void app_uart_init()
{
	dev_uart = DEVICE_DT_GET(DT_NODELABEL(uart0));

	if (!device_is_ready(dev_uart))
	{
		return 0;
	}

	int err;
	err = uart_callback_set(dev_uart, uart_cb, NULL);
	if (err)
	{
		return err;
	}
	uart_rx_enable(dev_uart, uart_double_buffer[0], UART_BUF_SIZE, UART_RX_TIMEOUT_MS);
}

int main(void)
{
	app_uart_init();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;and prj.conf&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_LOG=y



&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And I have tested it out on the nRF52840DK NRF52840&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;The problem with the above code is that once the buffer fills up (UART_BUF_SIZE set to 24), the complete message will not be constructed properly out of 2 buffers. This can be easily observed here:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1706767641716v1.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;POINT 3&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;After many hours of debugging the code above, I have figured out what was causing the issues. It turned out to be printf staments. I have removed most of the printf statements and only left the &lt;strong&gt;complete_message&lt;/strong&gt; print. The full code:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/drivers/gpio.h&amp;gt;
#include &amp;quot;stdio.h&amp;quot;
#include &amp;quot;my_gpio.h&amp;quot;
#include &amp;quot;zephyr/drivers/uart.h&amp;quot;
#include &amp;lt;zephyr/sys/ring_buffer.h&amp;gt;

#define LOG_LEVEL 4
#include &amp;lt;zephyr/logging/log.h&amp;gt;
LOG_MODULE_REGISTER(nrf52_learning);

#define UART_BUF_SIZE 24

#define UART_RX_TIMEOUT_MS 1000
K_SEM_DEFINE(rx_disabled, 0, 1);

// UART RX primary buffers
uint8_t uart_double_buffer[2][UART_BUF_SIZE];

uint8_t *uart_buf_next = uart_double_buffer[1];

uint8_t complete_message[UART_BUF_SIZE];
uint8_t complete_message_counter = 0;
bool currently_active_buffer = 1; // 0 - uart_double_buffer[0] is active, 1 - uart_double_buffer[1] is active

static const struct device *dev_uart;

static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{

	switch (evt-&amp;gt;type)
	{

	case UART_TX_DONE:
		//printf(&amp;quot;transmission complete \n&amp;quot;);
		break;

	case UART_TX_ABORTED:
		// do something
		break;

	case UART_RX_RDY:

		//printf(&amp;quot;Received %i bytes \n&amp;quot;, evt-&amp;gt;data.rx.len);
		//printf(&amp;quot;Offset = %i  \n&amp;quot;, evt-&amp;gt;data.rx.offset);

		//printf(&amp;quot;Constructing a complete message \n&amp;quot;);
		if (currently_active_buffer == 0)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[0][i];
				complete_message_counter++;
				if (uart_double_buffer[0][i] == &amp;#39;\n&amp;#39;)
				{
					//printf(&amp;quot;new line found at buffer 0 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		if (currently_active_buffer == 1)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[1][i];
				complete_message_counter++;
				if (uart_double_buffer[1][i] == &amp;#39;\n&amp;#39;)
				{
					//printf(&amp;quot;new line found at buffer 1 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		break;

	case UART_RX_BUF_REQUEST:
		uart_rx_buf_rsp(dev_uart, uart_buf_next, UART_BUF_SIZE);
		currently_active_buffer = !currently_active_buffer;
		if (currently_active_buffer == 0)
		{
			//printf(&amp;quot;currently active buffer is uart_double_buffer[0] \n&amp;quot;);
		}
		else
		{
			//printf(&amp;quot;currently active buffer is uart_double_buffer[1] \n&amp;quot;);
		}
		break;

	case UART_RX_BUF_RELEASED:
		//printf(&amp;quot;Old buffer has been released \n&amp;quot;);
		uart_buf_next = evt-&amp;gt;data.rx_buf.buf;
		break;

	case UART_RX_DISABLED:
		//printf(&amp;quot;rx disabled \n&amp;quot;);
		k_sem_give(&amp;amp;rx_disabled);
		break;

	case UART_RX_STOPPED:
		// do something
		break;

	default:
		break;
	}
}

void app_uart_init()
{
	dev_uart = DEVICE_DT_GET(DT_NODELABEL(uart0));

	if (!device_is_ready(dev_uart))
	{
		return 0;
	}

	int err;
	err = uart_callback_set(dev_uart, uart_cb, NULL);
	if (err)
	{
		return err;
	}
	uart_rx_enable(dev_uart, uart_double_buffer[0], UART_BUF_SIZE, UART_RX_TIMEOUT_MS);
}

int main(void)
{
	app_uart_init();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;and prj.conf:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_LOG=y&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;And when I try to send the exact same sequence of messages using serial terminal, it seems to work fine even after the UART buffer fills up:&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1706768195495v2.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;POINT 4&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;4. Additionally, I have found out that if you add options :&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;CONFIG_UART_0_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2
CONFIG_NRFX_TIMER2=y&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;in the prj.conf, then the complete messages will be received even if I use many printf statements. I do not fully understand why and how which is quite frustrating.&lt;/p&gt;
&lt;p&gt;The full code:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/drivers/gpio.h&amp;gt;
#include &amp;quot;stdio.h&amp;quot;
#include &amp;quot;my_gpio.h&amp;quot;
#include &amp;quot;zephyr/drivers/uart.h&amp;quot;
#include &amp;lt;zephyr/sys/ring_buffer.h&amp;gt;

#define LOG_LEVEL 4
#include &amp;lt;zephyr/logging/log.h&amp;gt;
LOG_MODULE_REGISTER(nrf52_learning);

#define UART_BUF_SIZE 24

#define UART_RX_TIMEOUT_MS 1000
K_SEM_DEFINE(rx_disabled, 0, 1);

// UART RX primary buffers
uint8_t uart_double_buffer[2][UART_BUF_SIZE];

uint8_t *uart_buf_next = uart_double_buffer[1];

uint8_t complete_message[UART_BUF_SIZE];
uint8_t complete_message_counter = 0;
bool currently_active_buffer = 1; // 0 - uart_double_buffer[0] is active, 1 - uart_double_buffer[1] is active

static const struct device *dev_uart;

static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{

	switch (evt-&amp;gt;type)
	{

	case UART_TX_DONE:
		printf(&amp;quot;transmission complete \n&amp;quot;);
		break;

	case UART_TX_ABORTED:
		// do something
		break;

	case UART_RX_RDY:

		printf(&amp;quot;Received %i bytes \n&amp;quot;, evt-&amp;gt;data.rx.len);
		printf(&amp;quot;Offset = %i  \n&amp;quot;, evt-&amp;gt;data.rx.offset);

		printf(&amp;quot;Constructing a complete message \n&amp;quot;);
		if (currently_active_buffer == 0)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[0][i];
				complete_message_counter++;
				if (uart_double_buffer[0][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 0 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		if (currently_active_buffer == 1)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[1][i];
				complete_message_counter++;
				if (uart_double_buffer[1][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 1 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		break;

	case UART_RX_BUF_REQUEST:
		uart_rx_buf_rsp(dev_uart, uart_buf_next, UART_BUF_SIZE);
		currently_active_buffer = !currently_active_buffer;
		if (currently_active_buffer == 0)
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[0] \n&amp;quot;);
		}
		else
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[1] \n&amp;quot;);
		}
		break;

	case UART_RX_BUF_RELEASED:
		printf(&amp;quot;Old buffer has been released \n&amp;quot;);
		uart_buf_next = evt-&amp;gt;data.rx_buf.buf;
		break;

	case UART_RX_DISABLED:
		printf(&amp;quot;rx disabled \n&amp;quot;);
		k_sem_give(&amp;amp;rx_disabled);
		break;

	case UART_RX_STOPPED:
		// do something
		break;

	default:
		break;
	}
}

void app_uart_init()
{
	dev_uart = DEVICE_DT_GET(DT_NODELABEL(uart0));

	if (!device_is_ready(dev_uart))
	{
		return 0;
	}

	int err;
	err = uart_callback_set(dev_uart, uart_cb, NULL);
	if (err)
	{
		return err;
	}
	uart_rx_enable(dev_uart, uart_double_buffer[0], UART_BUF_SIZE, UART_RX_TIMEOUT_MS);
}

int main(void)
{
	app_uart_init();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;and prj.conf:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_LOG=y



CONFIG_UART_0_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2
CONFIG_NRFX_TIMER2=y&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Despite the solution being found, it is still not fully clear to me what is the best way to handle ASYNC UART varying length data reception. I could not find enough information/examples available to fully understand the different methods of handling ASYNC UART reception and I am hoping to get some clarifications regarding this.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is this expected behaviour that a few printf statements in&amp;nbsp;&lt;strong&gt;uart_cb&lt;/strong&gt; causes weird behaviour as have been shown above?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;nbsp;If above is true, I am concerned about other high priority tasks or callbacks interrupting the UART&amp;nbsp;reception and causing &lt;span&gt;similar&amp;nbsp;&lt;/span&gt;issues even when all print statements are removed from the callback itself. Is ASYNC UART affected by other Zephyr RTOS threads running or it is independent and not affected at all?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;During the discussion above it has been mentioned that it is recommended to use larger UART_BUF_SIZE but that did not help in any way. The only thing that does is just simply requires more serial data to be received before it fills up and eventually breaks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Throughout this discussion, other things have been suggested such as using additional config options:&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;CONFIG_UART_0_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2
CONFIG_NRFX_TIMER2=y&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;which seem to help when having multiple print statements in the callback.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I would highly appreciate if someone with good Zephyr and ASYNC UART knowledge could shed some light here and cover the issues that I have encountered and the solutions that I have found. I believe the solutions that I have discovered are not the most optimal and not the best way to handle UART ASYNC data reception. I also believe that this should be relevant for other developers who are working with ASYNC UART.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/454623?ContentTypeID=1</link><pubDate>Wed, 08 Nov 2023 09:57:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:aad87160-9878-41af-9708-16c5df2f2bdf</guid><dc:creator>AHaug</dc:creator><description>&lt;p&gt;&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/members/achimkraus"&gt;Achim Kraus&lt;/a&gt;&amp;nbsp; Thank you for the input, it&amp;#39;s been very valuable to the discussion&lt;/p&gt;
&lt;p&gt;Regarding answering directly to a specific comment, you can use the quote funcitonality.&amp;nbsp;&lt;br /&gt; &amp;nbsp;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1699437437266v1.png" alt=" " /&gt;&lt;/p&gt;
[quote user="zazas321"]&lt;a href="https://devzone.nordicsemi.com/members/ahaug"&gt;AHaug&lt;/a&gt;&amp;nbsp;Hello. It has been a while. Perhaps you had some time to look at our latest discussion with &lt;a href="https://devzone.nordicsemi.com/members/achimkraus"&gt;Achim Kraus&lt;/a&gt;&amp;nbsp;?&lt;br /&gt;&lt;br /&gt;We have discovered some interesting things about ASYNC UART and it would be really nice to get to the bottom of this.[/quote]
&lt;p&gt;@zazas321, I&amp;#39;ve seen the discussion that has been ongoing here and I have nothing more to contribute to it other than the items that has already been discussed.&lt;/p&gt;
&lt;p&gt;I find in my own experiments as well that a larger buffer is required to allow for enough time to pass so that the buffers can fill, send, swap and empty properly&lt;/p&gt;
&lt;p&gt;Kind regards,&lt;br /&gt;Andreas&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/454545?ContentTypeID=1</link><pubDate>Tue, 07 Nov 2023 19:29:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:da0a6f3f-30b4-4db3-b169-0052b0781d43</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;&lt;a href="https://devzone.nordicsemi.com/members/ahaug"&gt;AHaug&lt;/a&gt;&amp;nbsp;Hello. It has been a while. Perhaps you had some time to look at our latest discussion with &lt;a href="https://devzone.nordicsemi.com/members/achimkraus"&gt;Achim Kraus&lt;/a&gt;&amp;nbsp;?&lt;br /&gt;&lt;br /&gt;We have discovered some interesting things about ASYNC UART and it would be really nice to get to the bottom of this.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452870?ContentTypeID=1</link><pubDate>Sat, 28 Oct 2023 12:19:57 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:f53d1853-fe4d-4c69-891a-35e6a6c5d827</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;Hello. Thank you very much for all your insights.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I have played around more with my project (&lt;strong&gt;Async_UART_debug&lt;/strong&gt;) branch and I have found something interesting. &lt;strong&gt;printk&lt;/strong&gt; and &lt;strong&gt;prinf&lt;/strong&gt; statements have huge effect on it.&lt;/p&gt;
&lt;p&gt;Even replacing printk statements with cause the Async UART reception to behave differently.&lt;/p&gt;
&lt;p&gt;The full code (also available in my repository, &lt;strong&gt;UART_async_working&lt;/strong&gt; branch.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/drivers/gpio.h&amp;gt;
#include &amp;quot;stdio.h&amp;quot;
#include &amp;quot;my_gpio.h&amp;quot;
#include &amp;quot;zephyr/drivers/uart.h&amp;quot;
#include &amp;lt;zephyr/sys/ring_buffer.h&amp;gt;

#define LOG_LEVEL 4
#include &amp;lt;zephyr/logging/log.h&amp;gt;
LOG_MODULE_REGISTER(nrf52_learning);

#define UART_BUF_SIZE 20

#define UART_RX_TIMEOUT_MS 1000
K_SEM_DEFINE(rx_disabled, 0, 1);

// UART RX primary buffers
uint8_t uart_double_buffer[2][UART_BUF_SIZE];

uint8_t *uart_buf_next = uart_double_buffer[1];

uint8_t complete_message[UART_BUF_SIZE];
uint8_t complete_message_counter = 0;
bool currently_active_buffer = 1; // 0 - uart_double_buffer[0] is active, 1 - uart_double_buffer[1] is active

static const struct device *dev_uart;

static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{

	switch (evt-&amp;gt;type)
	{

	case UART_TX_DONE:
		break;

	case UART_TX_ABORTED:
		// do something
		break;

	case UART_RX_RDY:

		printk(&amp;quot;Received %i bytes \n&amp;quot;, evt-&amp;gt;data.rx.len);
		printk(&amp;quot;Offset = %i  \n&amp;quot;, evt-&amp;gt;data.rx.offset);

		if (currently_active_buffer == 0)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[0][i];
				complete_message_counter++;
				if (uart_double_buffer[0][i] == &amp;#39;\n&amp;#39;)
				{
					complete_message_counter = 0;
					printk(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		if (currently_active_buffer == 1)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[1][i];
				complete_message_counter++;
				if (uart_double_buffer[1][i] == &amp;#39;\n&amp;#39;)
				{
					complete_message_counter = 0;
					printk(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		break;

	case UART_RX_BUF_REQUEST:
		uart_rx_buf_rsp(dev_uart, uart_buf_next, UART_BUF_SIZE);
		currently_active_buffer = !currently_active_buffer;
		break;

	case UART_RX_BUF_RELEASED:
		uart_buf_next = evt-&amp;gt;data.rx_buf.buf;
		break;

	case UART_RX_DISABLED:
		k_sem_give(&amp;amp;rx_disabled);
		break;

	case UART_RX_STOPPED:
		// do something
		break;

	default:
		break;
	}
}

void app_uart_init()
{
	dev_uart = DEVICE_DT_GET(DT_NODELABEL(uart0));

	if (!device_is_ready(dev_uart))
	{
		return 0;
	}

	int err;
	err = uart_callback_set(dev_uart, uart_cb, NULL);
	if (err)
	{
		return err;
	}
	uart_rx_enable(dev_uart, uart_double_buffer[0], UART_BUF_SIZE, UART_RX_TIMEOUT_MS);
}

int main(void)
{
	app_uart_init();
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;and my prj.conf:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_LOG=y



&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I have removed most debugging printf/prink statements and only left one or two. You can see that it seems to work now. I am able to send/receive messages and &lt;strong&gt;uart_event.rx.len/uart_event.rx.offset&lt;/strong&gt; seems to be correct now.&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1698495460248v1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;It would be very interesting to hear response from nordic about what exactly is happening and also about the additional options that you have suggested:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;CONFIG_UART_0_ASYNC=y&lt;/span&gt;&lt;br /&gt;&lt;span&gt;CONFIG_UART_0_NRF_HW_ASYNC=y&lt;/span&gt;&lt;br /&gt;&lt;span&gt;CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2&lt;/span&gt;&lt;br /&gt;&lt;span&gt;CONFIG_NRFX_TIMER2=y&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-size:150%;"&gt;&lt;strong&gt;UPDATE&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I can confirm that after adding additional prj.conf options that you have suggested, it works much better. I have even managed to get it to work with additional printf/printk statements just by adding these extra options.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I have even tested it out on my &lt;strong&gt;master&lt;/strong&gt; branch (the branch where I had all the issues initially).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;See the full code below:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/drivers/gpio.h&amp;gt;
#include &amp;quot;stdio.h&amp;quot;
#include &amp;quot;my_gpio.h&amp;quot;
#include &amp;quot;zephyr/drivers/uart.h&amp;quot;
#include &amp;lt;zephyr/sys/ring_buffer.h&amp;gt;

#define LOG_LEVEL 4
#include &amp;lt;zephyr/logging/log.h&amp;gt;
LOG_MODULE_REGISTER(nrf52_learning);

#define UART_BUF_SIZE 20

#define UART_RX_TIMEOUT_MS 1000
K_SEM_DEFINE(rx_disabled, 0, 1);

// UART RX primary buffers
uint8_t uart_double_buffer[2][UART_BUF_SIZE];

uint8_t *uart_buf_next = uart_double_buffer[1];

uint8_t complete_message[UART_BUF_SIZE];
uint8_t complete_message_counter = 0;
bool currently_active_buffer = 1; // 0 - uart_double_buffer[0] is active, 1 - uart_double_buffer[1] is active

static const struct device *dev_uart;

static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{

	switch (evt-&amp;gt;type)
	{

	case UART_TX_DONE:
		printf(&amp;quot;transmission complete \n&amp;quot;);
		break;

	case UART_TX_ABORTED:
		// do something
		break;

	case UART_RX_RDY:

		printf(&amp;quot;Received %i bytes \n&amp;quot;, evt-&amp;gt;data.rx.len);
		printf(&amp;quot;Offset = %i  \n&amp;quot;, evt-&amp;gt;data.rx.offset);

		printf(&amp;quot;evt-&amp;gt;data.rx.buf: [&amp;quot;);
		for (int i = 0; i &amp;lt; UART_BUF_SIZE; i++)
		{
			printf(&amp;quot;%u, &amp;quot;, evt-&amp;gt;data.rx.buf[i]);
		}
		printf(&amp;quot;] \n&amp;quot;);

		printf(&amp;quot;uart_double_buffer[0]: [&amp;quot;);
		for (int i = 0; i &amp;lt; UART_BUF_SIZE; i++)
		{
			printf(&amp;quot;%u, &amp;quot;, uart_double_buffer[0][i]);
		}
		printf(&amp;quot;] \n&amp;quot;);

		printf(&amp;quot;uart_double_buffer[1]: [&amp;quot;);
		for (int i = 0; i &amp;lt; UART_BUF_SIZE; i++)
		{
			printf(&amp;quot;%u, &amp;quot;, uart_double_buffer[1][i]);
		}
		printf(&amp;quot;] \n&amp;quot;);

		printf(&amp;quot;Constructing a complete message \n&amp;quot;);
		if (currently_active_buffer == 0)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[0][i];
				complete_message_counter++;
				if (uart_double_buffer[0][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 0 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		if (currently_active_buffer == 1)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[1][i];
				complete_message_counter++;
				if (uart_double_buffer[1][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 1 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		break;

	case UART_RX_BUF_REQUEST:
		uart_rx_buf_rsp(dev_uart, uart_buf_next, UART_BUF_SIZE);
		currently_active_buffer = !currently_active_buffer;
		if (currently_active_buffer == 0)
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[0] \n&amp;quot;);
		}
		else
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[1] \n&amp;quot;);
		}
		break;

	case UART_RX_BUF_RELEASED:
		printf(&amp;quot;Old buffer has been released \n&amp;quot;);
		uart_buf_next = evt-&amp;gt;data.rx_buf.buf;
		break;

	case UART_RX_DISABLED:
		printf(&amp;quot;rx disabled \n&amp;quot;);
		k_sem_give(&amp;amp;rx_disabled);
		break;

	case UART_RX_STOPPED:
		// do something
		break;

	default:
		break;
	}
}

void app_uart_init()
{
	dev_uart = DEVICE_DT_GET(DT_NODELABEL(uart0));

	if (!device_is_ready(dev_uart))
	{
		return 0;
	}

	int err;
	err = uart_callback_set(dev_uart, uart_cb, NULL);
	if (err)
	{
		return err;
	}
	uart_rx_enable(dev_uart, uart_double_buffer[0], UART_BUF_SIZE, UART_RX_TIMEOUT_MS);
}

int main(void)
{
	app_uart_init();
}
&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;and my prj.conf:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;# nothing here
CONFIG_GPIO=y
CONFIG_SERIAL=y


CONFIG_LOG=y

CONFIG_UART_ASYNC_API=y
CONFIG_UART_0_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC=y
CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2
CONFIG_NRFX_TIMER2=y
&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;See the logs below:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img style="max-height:240px;max-width:320px;" alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1698496812382v1.png" /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;As you can see from the logs above, I have bunch of printf statements but that does not have any negative effect on receiving data.&lt;span style="color:#ff0000;"&gt;&amp;nbsp;&lt;strong&gt;And yes, I am aware that using printf statements in callback itself is not a good practise, but that is just for testing purposes!&lt;/strong&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452848?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 17:21:42 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6315c262-a492-45b9-9f36-003c831ec4af</guid><dc:creator>Achim Kraus</dc:creator><description>&lt;p&gt;&amp;gt; At this point, I am not sure how exactly&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;uart_event.rx.len&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;and&lt;/span&gt;&lt;strong&gt;&amp;nbsp;uart_event.rx.offset &lt;/strong&gt;works as it does not seem to show proper values once I change to second dual buffer.&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve tested with your example.&lt;/p&gt;
&lt;p&gt;I understand now the irritation, I would consider it also as bug.&lt;/p&gt;
&lt;p&gt;When the buffers are switched, it seems that only the first received byte is forwarded. And the others then with the next&amp;nbsp;UART_RX_RDY. Looks like the number of available byte is calculated wrong, when the buffers are swapped.&lt;/p&gt;
&lt;p&gt;Edited:&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve checked my &amp;quot;working example&amp;quot; and the difference in the &amp;quot;prj.conf&amp;quot; is&lt;/p&gt;
&lt;p&gt;CONFIG_UART_0_ASYNC=y&lt;br /&gt;CONFIG_UART_0_NRF_HW_ASYNC=y&lt;br /&gt;CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2&lt;br /&gt;CONFIG_NRFX_TIMER2=y&lt;/p&gt;
&lt;p&gt;with that, also your example works as you expect and the irritation is gone. :-).&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452775?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 11:48:18 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c8a29d44-c05c-4de4-bca2-0dad1fba0e35</guid><dc:creator>Achim Kraus</dc:creator><description>&lt;p&gt;After checking the implementation in uart_nrfx_uart.c my understanding is, that the new buffer is already requested, when the first buffer is initially used or the buffers are actually swapped. Anyway, I guess, using something larger will help. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452771?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 11:42:27 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:dcb019ea-4b7c-4c52-bb65-817ec3fdcbe7</guid><dc:creator>Achim Kraus</dc:creator><description>&lt;p&gt;The weird behaviour disappears, if you run my code with larger buffers ;-).&lt;/p&gt;
&lt;p&gt;The point is, if you want a &amp;quot;seamless&amp;quot; DMA transfer in time, you need to request the buffers overlapping. I assume, that e.g. the new buffer is usually requested some bytes&amp;nbsp; ahead (say 32) so that the app provides the new buffer and the DMA still uses the old. When the old is filled, the DMA switches very fast to the already provided new one.&lt;/p&gt;
&lt;p&gt;But with 8 bytes, that&amp;#39;s not working ;-).&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452768?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 11:32:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:09034728-dc00-441b-bf68-b111523f4f3b</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;This issue is quite complex and it might not be obvious if you dont look at it close enough. The weird behaviour becomes very clear if you try to run the code and use debugger to monitor (evt-&amp;gt;data.rx.len, evt-&amp;gt;data.rx.offset and both uart buffers uart_double_buffer[0] and uart_double_buffer[1]&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452766?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 11:29:56 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5147cf99-d802-4716-899c-e40dca9d31f7</guid><dc:creator>Achim Kraus</dc:creator><description>&lt;p&gt;I&amp;#39;m not sure, if the irritation you see is caused by a very short DMA buffer. I would try to use a larger ones. At least in my experience, the async UART works well. I use buffers with 256 bytes.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452765?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 11:22:24 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d1ec6408-b93c-4aa6-87c5-41d166ed3592</guid><dc:creator>Achim Kraus</dc:creator><description>&lt;p&gt;Unfortunately this forum doesn&amp;#39;t really allow to answer to a specific comment. My answer was for the comment 2 days ago with the red lines.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452764?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 11:19:17 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5c060334-19b1-44ae-9a88-e2b6e333d359</guid><dc:creator>Achim Kraus</dc:creator><description>&lt;p&gt;&amp;gt; it does not seem to show proper values once I change to second dual buffer.&lt;/p&gt;
&lt;p&gt;Maybe that&amp;#39;s a misinterpretation of UART_RX_BUF_REQUEST and uart_rx_buf_rsp.&lt;/p&gt;
&lt;p&gt;From the docu:&lt;/p&gt;
&lt;p&gt;Provide pointer to RX buffer, which will be used when current buffer is filled.&lt;/p&gt;
&lt;p&gt;It doesn&amp;#39;t switch immediately after uart_rx_buf_rsp is called, but when the previous buffer is filled.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452763?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 11:16:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ecc8c2f0-1248-4036-9a22-755594054883</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;Hello. What makes you think that my UART_RX_BUF_REQUEST is empty?&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;My UART_RX_BUF_REQUEST is as following:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;	case UART_RX_BUF_REQUEST:
		uart_rx_buf_rsp(dev_uart, uart_buf_next, UART_BUF_SIZE);
		currently_active_buffer = !currently_active_buffer;
		if (currently_active_buffer == 0)
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[0] \n&amp;quot;);
		}
		else
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[1] \n&amp;quot;);
		}
		break;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;And by debugging, I can see that it is switching the buffers as required. But the length and offset is still not correct.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;If you have nrf52DK nRF52832 or nRF52840 NRF25840DK you can easily recreate the issue by using my code in main branch.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452762?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 11:12:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2533f847-84a5-496a-9e39-03dbc5d5a055</guid><dc:creator>Achim Kraus</dc:creator><description>&lt;p&gt;Using empty UART_RX_BUF_REQUEST is causing the irritation. Once you implement the required callback uart_rx_buf_rsp, I guess the behavior will change. &amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452705?ContentTypeID=1</link><pubDate>Fri, 27 Oct 2023 06:22:01 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2b68f7cf-408c-483d-b0f5-98018718492c</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;Thanks again for your insights. I understand what you said. I am determined to get to the bottom of this. Once we are done here, this can then become official Async UART sample project as there is currently no complete Async projects out there to look at. I am sure there are more people like myself who are confused about Async UART and how to get it to behave properly.&lt;br /&gt;&lt;br /&gt;Lets dive a little deeper into this please. I have modified my Async UART program a little bit (removed unnecessary code) and I have added extra printf statements to see what is happening under the hood and I am slighty confused about how&lt;strong&gt; uart_event.rx&lt;/strong&gt; works. In particular&amp;nbsp;&lt;strong&gt;uart_event.rx.len &lt;/strong&gt;and&lt;strong&gt;&amp;nbsp;uart_event.rx.offset&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Full code can be found below:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include &amp;lt;zephyr/kernel.h&amp;gt;
#include &amp;lt;zephyr/drivers/gpio.h&amp;gt;
#include &amp;quot;stdio.h&amp;quot;
#include &amp;quot;my_gpio.h&amp;quot;
#include &amp;quot;zephyr/drivers/uart.h&amp;quot;
#include &amp;lt;zephyr/sys/ring_buffer.h&amp;gt;

#define LOG_LEVEL 4
#include &amp;lt;zephyr/logging/log.h&amp;gt;
LOG_MODULE_REGISTER(nrf52_learning);

#define UART_BUF_SIZE 8

#define UART_RX_TIMEOUT_MS 1000
K_SEM_DEFINE(rx_disabled, 0, 1);



// UART RX primary buffers
uint8_t uart_double_buffer[2][UART_BUF_SIZE];

uint8_t *uart_buf_next = uart_double_buffer[1];

uint8_t complete_message[UART_BUF_SIZE];
uint8_t complete_message_counter = 0;
bool currently_active_buffer = 1; // 0 - uart_double_buffer[0] is active, 1 - uart_double_buffer[1] is active



static const struct device *dev_uart;

static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{

	switch (evt-&amp;gt;type)
	{

	case UART_TX_DONE:
		printf(&amp;quot;transmission complete \n&amp;quot;);
		break;

	case UART_TX_ABORTED:
		// do something
		break;

	case UART_RX_RDY:

		printf(&amp;quot;Received %i bytes \n&amp;quot;, evt-&amp;gt;data.rx.len);
		printf(&amp;quot;Offset = %i  \n&amp;quot;, evt-&amp;gt;data.rx.offset);

		printf(&amp;quot;evt-&amp;gt;data.rx.buf: [&amp;quot;);
		for (int i = 0; i &amp;lt; UART_BUF_SIZE; i++)
		{
			printf(&amp;quot;%u, &amp;quot;, evt-&amp;gt;data.rx.buf[i]);
		}
		printf(&amp;quot;] \n&amp;quot;);

		printf(&amp;quot;uart_double_buffer[0]: [&amp;quot;);
		for (int i = 0; i &amp;lt; UART_BUF_SIZE; i++)
		{
			printf(&amp;quot;%u, &amp;quot;, uart_double_buffer[0][i]);
		}
		printf(&amp;quot;] \n&amp;quot;);

		printf(&amp;quot;uart_double_buffer[1]: [&amp;quot;);
		for (int i = 0; i &amp;lt; UART_BUF_SIZE; i++)
		{
			printf(&amp;quot;%u, &amp;quot;, uart_double_buffer[1][i]);
		}
		printf(&amp;quot;] \n&amp;quot;);

		printf(&amp;quot;Constructing a complete message \n&amp;quot;);
			if (currently_active_buffer == 0)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[0][i];
				complete_message_counter++;
				if (uart_double_buffer[0][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 0 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}

		if (currently_active_buffer == 1)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[1][i];
				complete_message_counter++;
				if (uart_double_buffer[1][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 1 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);
					memset(&amp;amp;complete_message, 0, sizeof(complete_message)); // clear out the buffer to prepare for next read.
					break;
				}
			}
		}



		break;

	case UART_RX_BUF_REQUEST:
		uart_rx_buf_rsp(dev_uart, uart_buf_next, UART_BUF_SIZE);
		currently_active_buffer = !currently_active_buffer;
		if (currently_active_buffer == 0)
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[0] \n&amp;quot;);
		}
		else
		{
			printf(&amp;quot;currently active buffer is uart_double_buffer[1] \n&amp;quot;);
		}
		break;

	case UART_RX_BUF_RELEASED:
		printf(&amp;quot;Old buffer has been released \n&amp;quot;);
		uart_buf_next = evt-&amp;gt;data.rx_buf.buf;
		break;

	case UART_RX_DISABLED:
		printf(&amp;quot;rx disabled \n&amp;quot;);
		k_sem_give(&amp;amp;rx_disabled);
		break;

	case UART_RX_STOPPED:
		// do something
		break;

	default:
		break;
	}
}

void app_uart_init()
{
	dev_uart = DEVICE_DT_GET(DT_NODELABEL(uart0));

	if (!device_is_ready(dev_uart))
	{
		return 0;
	}

	int err;
	err = uart_callback_set(dev_uart, uart_cb, NULL);
	if (err)
	{
		return err;
	}
	uart_rx_enable(dev_uart, uart_double_buffer[0], UART_BUF_SIZE, UART_RX_TIMEOUT_MS);
}

int main(void)
{
	app_uart_init();

}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;and also my git repository (I updated main branch):&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/krupis/nrf52_learning"&gt;github.com/.../nrf52_learning&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;I will briefly explain the logic of my code:&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;I use&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;uart_double_buffering&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;and I have also created a new variable&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;complete_message.&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;I will be using combination of&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;uart_double_buffering[0]&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(first buffer) and&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;uart_double_buffering[1]&lt;/strong&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(second buffer) to keep track of when the received message has rolled over as you have suggested.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I always keep track of currently active buffer by using variable&amp;nbsp;&lt;strong&gt;currently_active_buffer&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;In my &lt;strong&gt;UART_RX_RDY, &lt;/strong&gt;I do the following:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;	case UART_RX_RDY:

		printf(&amp;quot;Received %i bytes \n&amp;quot;, evt-&amp;gt;data.rx.len);
		printf(&amp;quot;Offset = %i  \n&amp;quot;, evt-&amp;gt;data.rx.offset);

		printf(&amp;quot;evt-&amp;gt;data.rx.buf: [&amp;quot;);
		for (int i = 0; i &amp;lt; UART_BUF_SIZE; i++)
		{
			printf(&amp;quot;%u, &amp;quot;, evt-&amp;gt;data.rx.buf[i]);
		}
		printf(&amp;quot;] \n&amp;quot;);

		printf(&amp;quot;uart_double_buffer[0]: [&amp;quot;);
		for (int i = 0; i &amp;lt; UART_BUF_SIZE; i++)
		{
			printf(&amp;quot;%u, &amp;quot;, uart_double_buffer[0][i]);
		}
		printf(&amp;quot;] \n&amp;quot;);

		printf(&amp;quot;uart_double_buffer[1]: [&amp;quot;);
		for (int i = 0; i &amp;lt; UART_BUF_SIZE; i++)
		{
			printf(&amp;quot;%u, &amp;quot;, uart_double_buffer[1][i]);
		}
		printf(&amp;quot;] \n&amp;quot;);

		printf(&amp;quot;Constructing a complete message \n&amp;quot;);
		if (currently_active_buffer == 0)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[0][i];
				complete_message_counter++;
				if (uart_double_buffer[0][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 0 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					break;
				}
			}
		}

		if (currently_active_buffer == 1)
		{
			// read all characters one by one till new line is found
			for (int i = 0 + evt-&amp;gt;data.rx.offset; i &amp;lt; UART_BUF_SIZE; i++)
			{
				complete_message[complete_message_counter] = uart_double_buffer[1][i];
				complete_message_counter++;
				if (uart_double_buffer[1][i] == &amp;#39;\n&amp;#39;)
				{
					printf(&amp;quot;new line found at buffer 1 index = %i \n&amp;quot;, i);
					complete_message_counter = 0;
					break;
				}
			}
		}
		printf(&amp;quot;complete_message = %s \n&amp;quot;, complete_message);

		// memcpy(new_message.bytes, evt-&amp;gt;data.rx.buf + evt-&amp;gt;data.rx.offset, evt-&amp;gt;data.rx.len);
		// new_message.length = evt-&amp;gt;data.rx.len;
		// if (k_msgq_put(&amp;amp;uart_rx_msgq, &amp;amp;new_message, K_NO_WAIT) != 0)
		// {
		// 	printk(&amp;quot;Error: Uart RX message queue full!\n&amp;quot;);
		// }

		break;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;nbsp;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;As you can see from the code above, I looking for an endline termination to determine where is the end of the message. I also use the&amp;nbsp;&lt;strong&gt;evt-&amp;gt;data.rx.offset &lt;/strong&gt;to ensure that I start reading from the last end line detected.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Please look at the logs below:&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1698387547196v1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I think we are slowly but surely moving forwards to finding proper solution for this.&lt;/p&gt;
&lt;p&gt;At this point, I am not sure how exactly&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;strong&gt;uart_event.rx.len&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/strong&gt;&lt;span&gt;and&lt;/span&gt;&lt;strong&gt;&amp;nbsp;uart_event.rx.offset &lt;/strong&gt;works as it does not seem to show proper values once I change to second dual buffer.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I would highly appreciate if you could look at my code and the logs to see if you can make any sense out of it and understand what I am trying to achieve here&amp;nbsp;&lt;span class="emoticon" data-url="https://devzone.nordicsemi.com/cfs-file/__key/system/emoji/1f642.svg" title="Slight smile"&gt;&amp;#x1f642;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452629?ContentTypeID=1</link><pubDate>Thu, 26 Oct 2023 14:13:28 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8f8458bc-161c-4508-8d3f-52bd9c059b9e</guid><dc:creator>AHaug</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
[quote user="zazas321"]will no longer be correct as half of the message can be at the end of the evt-&amp;gt;data.rx.buf and the rest rolled over to the beginning of the buffer. Then pretty much all other messages after the ring buffer has been filled will be trashed (thats exactly what we see from the logs) . Do you see what I mean?&amp;nbsp;[/quote]
&lt;p&gt;Yes, I see what you mean here. But the message is not trashed, you are simply starting to fill the other buffer (in the case of double buffer). What is missing here is some logic to determine if the complete message has been received and to combine the data from the two buffers into one. What you need to determine is among the following (could be other ways to do this as well, but this is at least one way to do it):&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;To determine the message has been completely transmitted (for instance if there is a termination on the final bit)&lt;/li&gt;
&lt;li&gt;To determine if the message has been split, which is what you observe.
&lt;ol&gt;
&lt;li&gt;In this case you will need to combine the messages from both buffers, i.e find where the split message ends in the second buffer to combine the messages into one message&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In Torbjørns &lt;a href="https://github.com/too1/ncs-uart-async-count-rx"&gt;sample&lt;/a&gt;&amp;nbsp;(ncs 1.9.1), the one I linked to earlier, you will still have to do this combining of the message. To do this, it is typically normal to use a messaging protocol such as&amp;nbsp;&lt;a href="https://en.wikipedia.org/wiki/Serial_Line_Internet_Protocol"&gt;SLIP&lt;/a&gt;. SLIP uses what is called an end of frame to determine when this occurs.&amp;nbsp;Instead/in addition to using a start-of-field and/or end-of-field, you can also use a length field in your data making sure that you wait until you&amp;#39;ve received all your data that consists of the complete message and then do the missing logic I&amp;#39;ve described to combine the message.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;a href="https://devzone.nordicsemi.com/f/nordic-q-a/99442/async-uart-coming-in-broken-packets"&gt;async UART coming in broken packets&lt;/a&gt;&amp;nbsp;Is another case that somewhat describes the same thing as you see that briefly mentions what the other developer has done&lt;/p&gt;
[quote user="zazas321"]Please tell me if that makes sense or I am completely misunderstanding how this works or how this supposed to work.[/quote]
&lt;p&gt;So to summarize: you&amp;#39;ve not misunderstood this, but we&amp;#39;re rather missing some steps in the implementation to make the double buffering work properly and to combine the messages that starts in one buffer and ends in the other&lt;/p&gt;
&lt;p&gt;Kind regards,&lt;br /&gt;Andreas&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452406?ContentTypeID=1</link><pubDate>Thu, 26 Oct 2023 05:17:52 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:4471f9a4-b0d9-451c-b27f-554858dc7a09</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;Thanks for your help. It is getting a little bit more clear, but I do not think my issues are related to the timeout. I really appreciate you taking your time to look into this!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;However, I believe it is related to the way ring buffer works in Async UART.&lt;/p&gt;
&lt;p&gt;I have increased&amp;nbsp;UART_BUF_SIZE to 50, see the logs below:&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1698297299718v3.png" /&gt;&lt;/p&gt;
&lt;p&gt;What happens is that when I send messages via serial, the evt-&amp;gt;data.rx.buf is slowly filling up. When it reaches the declared size (UART_BUF_SIZE), the condition:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="text"&gt;memcpy(new_message.bytes, evt-&amp;gt;data.rx.buf + evt-&amp;gt;data.rx.offset, evt-&amp;gt;data.rx.len);&lt;/pre&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;will no longer be correct as half of the message can be at the end of the evt-&amp;gt;data.rx.buf and the rest rolled over to the beginning of the buffer. Then pretty much all other messages after the ring buffer has been filled will be trashed (thats exactly what we see from the logs) . Do you see what I mean?&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;Zephyr states that Async UART is the most efficient way to use UART but I cannot see a single real world application where it could be used since it is not capable of receiving a full message properly (unless there is an issue in my code and below is not correct).&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="text"&gt;	case UART_RX_RDY:
		memcpy(new_message.bytes, evt-&amp;gt;data.rx.buf + evt-&amp;gt;data.rx.offset, evt-&amp;gt;data.rx.len);
		new_message.length = evt-&amp;gt;data.rx.len;
		if (k_msgq_put(&amp;amp;uart_rx_msgq, &amp;amp;new_message, K_NO_WAIT) != 0)
		{
			printk(&amp;quot;Error: Uart RX message queue full!\n&amp;quot;);
		}
		break;&lt;/pre&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;Most UART applications relies on being able to receive and transmit a required size message length at once.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;I was under the impression that the reason why we use double buffer is to avoid this problem and ensure that when the data rolled over, we can still get the full message at once but perhaps that is not the case.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;Please tell me if that makes sense or I am completely misunderstanding how this works or how this supposed to work.&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452280?ContentTypeID=1</link><pubDate>Wed, 25 Oct 2023 13:11:05 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2f5538d9-7fc3-4f4b-ae61-1606d31e3d7d</guid><dc:creator>AHaug</dc:creator><description>&lt;p&gt;Thank you,&lt;/p&gt;
&lt;p&gt;I finally had the time to look at your code. Apologies for why it took so long and to the frustration you must&amp;#39;ve felt. Response times gets a bit longer when we&amp;#39;re nearing release of a new major version of the SDK (v2.5.0).&lt;br /&gt;&lt;br /&gt;Your code works as expected when you&amp;#39;re using asynch UART with static buffers (the central and peripheral_uart samples uses dynamically allocated buffers)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why, you ask?&amp;nbsp;&lt;br /&gt;&lt;/strong&gt;This is the quick and dirty explanation: The uart-cb triggers either when the timeout you&amp;#39;ve set runs out (100ms) or when the buffer you&amp;#39;ve declared (16 bit) is filled. When you enter new messages and you the timeout expires before you&amp;#39;re finished writing the message, you will be left with a message that is separated. In theory if the timeout is sufficiently small and you match your writing speed with the timeout, the callback can trigger 16 times and separate the message into 16 characters instead of 1.&lt;br /&gt;&lt;br /&gt;Hello (6) + ping (5) + message1 (expected to be 9)&amp;nbsp; &amp;gt; 16: You see the callback trigger when both the timeout expires and the buffer length limit is reached&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;For further observation&lt;br /&gt;&lt;/strong&gt;Increase the timeout so you have time to write the new messages, and or play around with the buffer length (which is currently set to 16)&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Please feel free to ask follow up questions if anything is unclear!&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Kind regards,&lt;br /&gt;Andreas&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452179?ContentTypeID=1</link><pubDate>Wed, 25 Oct 2023 08:52:19 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:dc7c6e41-c138-4384-87c3-5aba6af259c1</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;You were right. It was private, my bad!&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I have made it public now.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452157?ContentTypeID=1</link><pubDate>Wed, 25 Oct 2023 07:46:24 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6a94b58a-549e-421a-82c7-26388da5223a</guid><dc:creator>AHaug</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;It looks like the repo you&amp;#39;ve provided is private as the link takes me to a 404 and the nrf52_learning is not listed in your repositories. Could you make it public/share a public version of it?&lt;/p&gt;
&lt;p&gt;Kind regards,&lt;br /&gt;Andreas&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/452129?ContentTypeID=1</link><pubDate>Wed, 25 Oct 2023 05:43:17 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:95f31eb0-e822-4467-8716-d6fc35759d11</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;I have looked at the sample project you have provided. I have removed all the TX related code since I am not interested in TX (I only want to learn about RX first).&amp;nbsp;The latest&amp;nbsp; source code is available here:&lt;/p&gt;
&lt;p&gt;&lt;a id="" href="https://github.com/krupis/nrf52_learning"&gt;https://github.com/krupis/nrf52_learning&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I can confirm that it also does not work. Please look at the logs below:&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" alt=" " src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1698212494609v1.png" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I have underlined response in &lt;span style="color:#00ff00;"&gt;green&lt;/span&gt; where the response is correct and in &lt;span style="color:#ff0000;"&gt;red&lt;/span&gt; where the response is not as expected.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Could you please ask someone else from embedded software team from your side to look at this as this is getting a little frustrating?&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Thanks for keeping this going!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/451940?ContentTypeID=1</link><pubDate>Tue, 24 Oct 2023 10:57:33 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8cead3d7-b2ce-4c8d-b2ee-265b3cd03f15</guid><dc:creator>AHaug</dc:creator><description>&lt;p&gt;Hi,&lt;br /&gt;&lt;br /&gt;I did some more digging and found an older, unofficial sample created by someone in tech support showcasing how to use the Asynchronous UART Driver. Here&amp;#39;s a version of the sample that&amp;nbsp;&lt;em&gt;should&lt;/em&gt; work in NCS v2.4.2&lt;/p&gt;
&lt;p&gt;&lt;a href="https://devzone.nordicsemi.com/cfs-file/__key/communityserver-discussions-components-files/4/ncs_2D00_uart_2D00_async_2D00_count_2D00_rx.zip"&gt;devzone.nordicsemi.com/.../ncs_2D00_uart_2D00_async_2D00_count_2D00_rx.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Kind regards,&lt;br /&gt;Andreas&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/451885?ContentTypeID=1</link><pubDate>Tue, 24 Oct 2023 06:46:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7d48c21c-9823-4f24-9f47-5577e0eb7621</guid><dc:creator>zazas321</dc:creator><description>&lt;p&gt;I have tried to merge the echo_bot to the async uart sample but that is not as straight forward as it may look as it is using completely different functions.. I dont think it can be done this way.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I have posted on Zephyr Git as well as the Zephyr discord that you have recommended but there is no solution yet.. I am still waiting. If you have any more ideas let me know.&lt;/p&gt;
&lt;p&gt;I will be sure to post back here the answer if someone replies on git or discord :)&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52DK nRF52832 UART asynchronous receive</title><link>https://devzone.nordicsemi.com/thread/451312?ContentTypeID=1</link><pubDate>Thu, 19 Oct 2023 12:47:33 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:12c0d4d1-3acf-4a55-beb8-d69e1642dd37</guid><dc:creator>AHaug</dc:creator><description>&lt;p&gt;Of course the echo_bot sample is what I should&amp;#39;ve suggested immediately &lt;span class="emoticon" data-url="https://devzone.nordicsemi.com/cfs-file/__key/system/emoji/1f606.svg" title="Laughing"&gt;&amp;#x1f606;&lt;/span&gt; That sample was not on my mind at all this morning!&amp;nbsp;&lt;/p&gt;
&lt;p&gt;But as you state there is a difference in using polling and the async method, and the lesson you started with from the academy course uses Async. Have you attempted to merge the lesson you started with, i.e &lt;a href="https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-4-serial-communication-uart/topic/uart-driver/"&gt;https://academy.nordicsemi.com/courses/nrf-connect-sdk-fundamentals/lessons/lesson-4-serial-communication-uart/topic/uart-driver/&lt;/a&gt;, into the echo_bot?&lt;/p&gt;
&lt;p&gt;PS: Unless you&amp;#39;ve already been recommended by users on the discord to create a ticket on the github, you can also find Zephyrs discord at &lt;a href="https://www.zephyrproject.org/"&gt;zephyrproject.org&lt;/a&gt;, which might be an even easier way to communicate with other developers using Zephyr&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1697719460213v1.png" alt=" " /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Kind regards,&lt;br /&gt;Andreas&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>