Initial commit for echo_bot
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# editors
|
||||
*.swp
|
||||
*~
|
||||
|
||||
# build
|
||||
/build*/
|
||||
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal 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(echo_bot)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
41
README.rst
Normal file
41
README.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
.. zephyr:code-sample:: uart
|
||||
:name: UART echo
|
||||
:relevant-api: uart_interface
|
||||
|
||||
Read data from the console and echo it back.
|
||||
|
||||
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/echo_bot
|
||||
: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!
|
||||
13
sample.yaml
Normal file
13
sample.yaml
Normal file
@@ -0,0 +1,13 @@
|
||||
sample:
|
||||
name: UART driver sample
|
||||
tests:
|
||||
sample.drivers.uart:
|
||||
integration_platforms:
|
||||
- qemu_x86
|
||||
tags:
|
||||
- serial
|
||||
- uart
|
||||
filter: CONFIG_SERIAL and
|
||||
CONFIG_UART_INTERRUPT_DRIVEN and
|
||||
dt_chosen_enabled("zephyr,shell-uart")
|
||||
harness: keyboard
|
||||
107
src/main.c
Normal file
107
src/main.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Libre Solar Technologies GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/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 *const 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;
|
||||
}
|
||||
|
||||
if (!uart_irq_rx_ready(uart_dev)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* read until FIFO empty */
|
||||
while (uart_fifo_read(uart_dev, &c, 1) == 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]);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char tx_buf[MSG_SIZE];
|
||||
|
||||
if (!device_is_ready(uart_dev)) {
|
||||
printk("UART device not found!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* configure interrupt and callback to receive data */
|
||||
int ret = uart_irq_callback_user_data_set(uart_dev, serial_cb, NULL);
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOTSUP) {
|
||||
printk("Interrupt-driven UART API support not enabled\n");
|
||||
} else if (ret == -ENOSYS) {
|
||||
printk("UART device does not support interrupt-driven API\n");
|
||||
} else {
|
||||
printk("Error setting UART callback: %d\n", ret);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
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");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user