Meaning of UART_ERROR_FRAMING in UART_RX_STOPPED event on nRF9161DK Asynch UART

Hello, I'm developing on an application which requires to catch high speed, variable size and bursty (~0.5 Mbit/s) data from a sensor connected to a nRF9161DK trough a UART without flow control.

This is the code of the very simple application making use of Async UART API ...

/*
 * Copyright (c) 2019 Tavish Naruka <[email protected]>
 * Copyright (c) 2023 Nordic Semiconductor ASA
 * Copyright (c) 2023 Antmicro <www.antmicro.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/* Sample which uses the filesystem API and SDHC driver */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/logging/log.h>
#include <stdlib.h>
#include <zephyr/drivers/uart.h>

LOG_MODULE_REGISTER(main);

#define UART_BUF_SIZE 512
#define UART_RX_TIMEOUT_MS 10000

// 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->type)
	{

	case UART_TX_DONE:
		LOG_DBG("UART_TX_DONE");
		break;

	case UART_TX_ABORTED:
		LOG_DBG("UART_TX_ABORTED");
		break;

	case UART_RX_RDY:
		LOG_DBG("UART_RX_RDY:  received %i bytes, Offset = %i ", evt->data.rx.len,evt->data.rx.offset);
	
		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)
		{
			LOG_DBG("UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[0] ");
		}
		else
		{
			LOG_DBG("UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[1] ");
		}
		break;

	case UART_RX_BUF_RELEASED:
		LOG_DBG("UART_RX_BUF_RELEASED");
		uart_buf_next = evt->data.rx_buf.buf;
		break;

	case UART_RX_DISABLED:
		LOG_DBG("UART_RX_DISABLED");
		k_sem_give(&rx_disabled);
		break;

	case UART_RX_STOPPED:
		switch (evt->data.rx_stop.reason)
		{
		case UART_ERROR_OVERRUN:
		{
			LOG_DBG("UART_RX_STOPPED UART_ERROR_OVERRUN");
			break;
		}
		case UART_ERROR_PARITY:
		{
			LOG_DBG("UART_RX_STOPPED UART_ERROR_PARITY");
			break;
		}
		case UART_ERROR_FRAMING:
		{
			LOG_DBG("UART_RX_STOPPED UART_ERROR_FRAMING");
			break;
		}
		case UART_BREAK:
		{
			LOG_DBG("UART_RX_STOPPED UART_BREAK");
			break;
		}
		case UART_ERROR_COLLISION:
		{
			LOG_DBG("UART_RX_STOPPED UART_ERROR_COLLISION");
			break;
		}
		case UART_ERROR_NOISE:
		{
			LOG_DBG("UART_RX_STOPPED UART_ERROR_NOISE");
			break;
		}
		}

		break;

	default:
		break;
	}
}


TStationConfig StationConfig;


int app_uart_init()
{
	dev_uart = DEVICE_DT_GET(DT_NODELABEL(uart1));

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

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

int main(void)
{
	while (1) {
		k_sleep(K_MSEC(10000));
	}
	return 0;
}

  As long as there is data coming from the external sensor things seems to work as expected:

*** Booting nRF Connect SDK v3.0.2-89ba1294ac9b ***
*** Using Zephyr OS v4.0.99-f791c49f492c ***
[00:00:00.252,868] <dbg> os: k_sched_unlock: scheduler unlocked (0x20000960:0)
[00:00:00.252,899] <dbg> main: app_uart_init: UART1 RX enabled
[00:00:00.252,929] <dbg> main: uart_cb: UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[0] 
[00:00:00.252,929] <dbg> os: z_tick_sleep: thread 0x20000960 for 327680 ticks
[00:00:01.240,051] <dbg> main: uart_cb: UART_RX_RDY:  received 512 bytes, Offset = 0 
[00:00:01.240,081] <dbg> main: uart_cb: UART_RX_BUF_RELEASED
[00:00:01.240,112] <dbg> main: uart_cb: UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[1] 
[00:00:01.250,396] <dbg> main: uart_cb: UART_RX_RDY:  received 88 bytes, Offset = 0 
[00:00:01.250,396] <dbg> main: uart_cb: UART_RX_BUF_RELEASED
[00:00:01.250,427] <dbg> main: uart_cb: UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[0] 
[00:00:02.239,685] <dbg> main: uart_cb: UART_RX_RDY:  received 512 bytes, Offset = 0 
[00:00:02.239,715] <dbg> main: uart_cb: UART_RX_BUF_RELEASED
[00:00:02.239,715] <dbg> main: uart_cb: UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[1] 
[00:00:02.252,014] <dbg> main: uart_cb: UART_RX_RDY:  received 185 bytes, Offset = 0 
[00:00:02.252,044] <dbg> main: uart_cb: UART_RX_BUF_RELEASED
[00:00:02.252,075] <dbg> main: uart_cb: UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[0] 
[00:00:03.241,882] <dbg> main: uart_cb: UART_RX_RDY:  received 512 bytes, Offset = 0 
[00:00:03.241,912] <dbg> main: uart_cb: UART_RX_BUF_RELEASED
[00:00:03.241,943] <dbg> main: uart_cb: UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[1] 
[00:00:03.256,225] <dbg> main: uart_cb: UART_RX_RDY:  received 201 bytes, Offset = 0 
[00:00:03.256,225] <dbg> main: uart_cb: UART_RX_BUF_RELEASED
[00:00:03.256,256] <dbg> main: uart_cb: UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[0]

Instead, when I power off the external sensor and e reboot the nRF9161DK board I get the following sequence:

*** Booting nRF Connect SDK v3.0.2-89ba1294ac9b ***
*** Using Zephyr OS v4.0.99-f791c49f492c ***
[00:00:00.353,332] <dbg> os: k_sched_unlock: scheduler unlocked (0x20000960:0)
[00:00:00.353,363] <dbg> main: app_uart_init: UART1 RX enabled
[00:00:00.353,393] <dbg> main: uart_cb: UART_RX_BUF_REQUEST: current active buffer uart_double_buffer[0] 
[00:00:00.353,424] <dbg> main: uart_cb: UART_RX_STOPPED UART_ERROR_FRAMING
[00:00:00.353,424] <dbg> os: z_tick_sleep: thread 0x20000960 for 327680 ticks
[00:00:00.353,454] <dbg> main: uart_cb: UART_RX_STOPPED UART_ERROR_FRAMING
[00:00:00.353,485] <dbg> main: uart_cb: UART_RX_STOPPED UART_ERROR_FRAMING
[00:00:00.353,515] <dbg> main: uart_cb: UART_RX_STOPPED UART_ERROR_FRAMING
[00:00:00.353,546] <dbg> main: uart_cb: UART_RX_STOPPED UART_ERROR_FRAMING
[00:00:00.353,576] <dbg> main: uart_cb: UART_RX_BUF_RELEASED
[00:00:00.353,607] <dbg> main: uart_cb: UART_RX_BUF_RELEASED
[00:00:00.353,607] <dbg> main: uart_cb: UART_RX_DISABLED
[00:00:00.353,637] <dbg> main: uart_cb: UART_RX_STOPPED UART_ERROR_FRAMING

What is the meaning of UART_ERROR_FRAMING (I was expecting a timeout instead)?

What is causing UART_RX_DISABLED ? 

Joel

Parents
  • Instead, when I power off the external sensor and e reboot the nRF9161DK board I get the following sequence:

    Can you explain how to achieve this? I don't have your sensor, but I assume the behavior is the same if the sensor is powered off. I don't run into any error. 

    This is the code of the very simple application making use of Async UART API ...

    You are not doing anything other than sleeping in main(). But even running app_uart_init() I don't get any errors.

Reply
  • Instead, when I power off the external sensor and e reboot the nRF9161DK board I get the following sequence:

    Can you explain how to achieve this? I don't have your sensor, but I assume the behavior is the same if the sensor is powered off. I don't run into any error. 

    This is the code of the very simple application making use of Async UART API ...

    You are not doing anything other than sleeping in main(). But even running app_uart_init() I don't get any errors.

Children
  • Since you do not have my sensor you should always get UART_ERROR_FRAMING and then after 4 of those events the UART gets halted.

    Reading form a UART which do not has inbound data triggers UART_ERROR_FRAMING.

    Just sleep on the main and UART calback. It seems to me that instead of triggering UART_RX_RDY with a zero length which indicates a timeout the system generates UART_ERROR_FRAMING events... which is unexpected according to my understanding of the documentation.

    Joel 

Related