UART Interrupt mode RX

I have been working with different UART modes (Polling, Interrupt, Async). I have had a lot of troubles using Async mode, I have even created a seperate issue regarding this which has not yet been solved:

 nRF52DK nRF52832 UART asynchronous receive 

I have decided to try UART interrupt and have managed to create something that seems to work. My main.c:

/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include "stdio.h"
#include "zephyr/drivers/uart.h"

static const struct device *dev_uart;
static void uart_irq_handler(const struct device *dev, void *context);

#define RX_BUF_SIZE 64

void app_uart_init()
{
	dev_uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
	if (!device_is_ready(dev_uart))
	{
		return 0;
	}
	uart_irq_callback_set(dev_uart, uart_irq_handler);
	uart_irq_rx_enable(dev_uart);
}

static void uart_irq_handler(const struct device *dev, void *context)
{
	uint8_t char_received;
	static uint8_t command_line[RX_BUF_SIZE];
	static int char_counter = 0;

	if (uart_irq_rx_ready(dev))
	{
		int len = uart_fifo_read(dev, &char_received, 1);
		if (len)
		{
			command_line[char_counter] = char_received;
			char_counter++;
			if (char_received == '\n' || char_received == '\r')
			{
				command_line[char_counter] = '\0'; // put null at the end of the string to indicate end of message or end of string
				char_counter = 0;				   // reset the char counter
				printk("command_line = %s \n", command_line);
				memset(&command_line, 0, sizeof(command_line));
			}
		}
	}
}

int main(void)
{
	app_uart_init();
}

As you can see from the code above, I am reading one byte at a time using:

int len = uart_fifo_read(dev, &char_received, 1);
I then append each byte to command_line untill end line is detected. When end line (\n or \r) is detected, I then assume that full message has been received and then I can print out the message (command_line) and do whatever I want with it.
My code assumes that when communicating with other UART devices, message will always be terminated with either (\n or \r).
I want to understand whether I am using UART Interrupt as supposed to? I would appreciate any ideas to make it more efficient and correct. Thanks in advance.
  • Hi again!

    First of all, it's great that you've created another case for this question and linked to your other case so we can handle them separately since the topic is different! Keep doing that in the future as well

    My code assumes that when communicating with other UART devices, message will always be terminated with either (\n or \r).
    I want to understand whether I am using UART Interrupt as supposed to? I would appreciate any ideas to make it more efficient and correct. Thanks in advance.

    Regarding if you're using it correct: Mainly 'yes' and a tiny bit 'no'. You are using interrupt based UART correct, but it is not "has to be \n or \r" termination (although that is typically the default ones used together with zero-termination)

    There are no "standard" way to terminate the message. Typically, depending on the type of device and/or implementation and use case, UART messages can be terminated with different means. Either through \n or \r as you list, but zero-termination or termination through 'ff', 'aaa', or other means are equally valid. This means that you will have to either define and/or look up what termination the devices you intend to communicate will be using as their method of termination

    Regarding if this is the most efficient implementation I will have to leave to other developers on the forum (either here on Zephyr forums) that has their own preferences and experiences. If the interrupt based UART works with your implementation, which it seems to do based on looking through your code, you should be golden.

    Kind regards,
    Andreas

Related