samples: drivers: add UART serial sample

This sample demonstrates the use of the UART driver. The data is
received using an ISR callback and a message queue. For sending data,
the polling API is used.

Signed-off-by: Martin Jäger <martin@libre.solar>
This commit is contained in:
Martin Jäger
2022-01-04 18:58:35 +01:00
committed by Maureen Helm
parent be9779753f
commit 0bd3d46cfb
5 changed files with 152 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(uart_sample)
target_sources(app PRIVATE src/main.c)

View File

@@ -0,0 +1,40 @@
.. _uart_sample:
UART Driver Sample
##################
Overview
********
This sample demonstrates how to use the UART serial driver with a simple
echo bot. It reads data from the console and echoes the characters back after
an end of line (return key) is received.
The polling API is used for sending data and the interrupt-driven API
for receiving, so that in theory the thread could do something else
while waiting for incoming data.
By default, the UART peripheral that is normally used for the Zephyr shell
is used, so that almost every board should be supported.
Building and Running
********************
Build and flash the sample as follows, changing ``nrf52840dk_nrf52840`` for
your board:
.. zephyr-app-commands::
:zephyr-app: samples/drivers/uart
:board: nrf52840dk_nrf52840
:goals: build flash
:compact:
Sample Output
=============
.. code-block:: console
Hello! I\'m your echo bot.
Tell me something and press enter:
# Type e.g. "Hi there!" and hit enter!
Echo: Hi there!

View File

@@ -0,0 +1,2 @@
CONFIG_SERIAL=y
CONFIG_UART_INTERRUPT_DRIVEN=y

View File

@@ -0,0 +1,9 @@
sample:
name: UART driver sample
tests:
sample.drivers.uart:
tags: serial uart
filter: CONFIG_SERIAL and
CONFIG_UART_INTERRUPT_DRIVEN and
dt_chosen_enabled("zephyr,shell-uart")
harness: keyboard

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2022 Libre Solar Technologies GmbH
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <device.h>
#include <drivers/uart.h>
#include <string.h>
/* change this to any other UART peripheral if desired */
#define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart)
#define MSG_SIZE 32
/* queue to store up to 10 messages (aligned to 4-byte boundary) */
K_MSGQ_DEFINE(uart_msgq, MSG_SIZE, 10, 4);
static const struct device *uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);
/* receive buffer used in UART ISR callback */
static char rx_buf[MSG_SIZE];
static int rx_buf_pos;
/*
* Read characters from UART until line end is detected. Afterwards push the
* data to the message queue.
*/
void serial_cb(const struct device *dev, void *user_data)
{
uint8_t c;
if (!uart_irq_update(uart_dev)) {
return;
}
while (uart_irq_rx_ready(uart_dev)) {
uart_fifo_read(uart_dev, &c, 1);
if ((c == '\n' || c == '\r') && rx_buf_pos > 0) {
/* terminate string */
rx_buf[rx_buf_pos] = '\0';
/* if queue is full, message is silently dropped */
k_msgq_put(&uart_msgq, &rx_buf, K_NO_WAIT);
/* reset the buffer (it was copied to the msgq) */
rx_buf_pos = 0;
} else if (rx_buf_pos < (sizeof(rx_buf) - 1)) {
rx_buf[rx_buf_pos++] = c;
}
/* else: characters beyond buffer size are dropped */
}
}
/*
* Print a null-terminated string character by character to the UART interface
*/
void print_uart(char *buf)
{
int msg_len = strlen(buf);
for (int i = 0; i < msg_len; i++) {
uart_poll_out(uart_dev, buf[i]);
}
}
void main(void)
{
char tx_buf[MSG_SIZE];
if (!device_is_ready(uart_dev)) {
printk("UART device not found!");
return;
}
/* configure interrupt and callback to receive data */
uart_irq_callback_user_data_set(uart_dev, serial_cb, NULL);
uart_irq_rx_enable(uart_dev);
print_uart("Hello! I'm your echo bot.\r\n");
print_uart("Tell me something and press enter:\r\n");
/* indefinitely wait for input from the user */
while (k_msgq_get(&uart_msgq, &tx_buf, K_FOREVER) == 0) {
print_uart("Echo: ");
print_uart(tx_buf);
print_uart("\r\n");
}
}