Skip to content

Commit 9936356

Browse files
committed
samples: boards: st: uart: add sample for uart circular mode
This code example will demonstrate how to use uart circular mode on STM32 boards. Signed-off-by: Fabrice DJIATSA <[email protected]>
1 parent f16ddc2 commit 9936356

File tree

8 files changed

+252
-0
lines changed

8 files changed

+252
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(circular_dma)
7+
8+
target_sources(app PRIVATE src/main.c)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
.. zephyr:code-sample:: uart
2+
:name: UART circular mode
3+
:relevant-api: uart_interface
4+
5+
Read data from the console and echo it back using a circular dma configuration.
6+
7+
Overview
8+
********
9+
10+
This sample demonstrates how to use STM32 UART serial driver with DMA in circular mode.
11+
It reads data from the console and echoes it back.
12+
13+
By default, the UART peripheral that is normally assigned to the Zephyr shell
14+
is used, hence the majority of boards should be able to run this sample.
15+
16+
Building and Running
17+
********************
18+
19+
Build and flash the sample as follows, changing ``nucleo_g071rb`` for
20+
your board:
21+
22+
.. zephyr-app-commands::
23+
:zephyr-app: samples/boards/st/uart/circular_dma
24+
:board: nucleo_g071rb
25+
:goals: build flash
26+
:compact:
27+
28+
Sample Output
29+
=============
30+
31+
.. code-block:: console
32+
33+
Enter message to fill RX buffer size and press enter :
34+
# Type e.g. :
35+
# "Lorem Ipsum is simply dummy text of the printing and typesetting industry.
36+
# Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
37+
# when an unknown printer took a galley of type and scrambled it to make a type specimen book.
38+
# It has survived not only five centuries, but also the leap into electronic typesetting,
39+
# remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset
40+
# sheets containing Lorem Ipsum passages, and more recently with desktop publishing software
41+
# like Aldus PageMaker including versions of Lorem Ipsum."
42+
43+
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
44+
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
45+
when an unknown printer took a galley of type and scrambled it to make a type specimen book.
46+
It has survived not only five centuries, but also the leap into electronic typesetting,
47+
remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset
48+
sheets containing Lorem Ipsum passages, and more recently with desktop publishing software
49+
like Aldus PageMaker including versions of Lorem Ipsum.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2024 STMicroelectronics
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&usart2 {
8+
dmas = <&dmamux1 0 53 (STM32_DMA_PERIPH_TX)>,
9+
<&dmamux1 3 52 (STM32_DMA_PERIPH_RX | STM32_DMA_MEM_8BITS | STM32_DMA_MODE_CYCLIC)>;
10+
dma-names = "tx", "rx";
11+
fifo-enable;
12+
};
13+
14+
&dma1 {
15+
status = "okay";
16+
};
17+
18+
&dmamux1 {
19+
status = "okay";
20+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright (c) 2024 STMicroelectronics
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&usart2 {
8+
dmas = <&dma1 4 (STM32_DMA_PERIPH_TX)>,
9+
<&dma1 5 (STM32_DMA_PERIPH_RX | STM32_DMA_MEM_8BITS | STM32_DMA_MODE_CYCLIC)>;
10+
dma-names = "tx", "rx";
11+
fifo-enable;
12+
};
13+
14+
&dma1 {
15+
status = "okay";
16+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Copyright (c) 2024 STMicroelectronics
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&usart2 {
8+
dmas = <&dmamux1 0 53 (STM32_DMA_PERIPH_TX)>,
9+
<&dmamux1 3 52 (STM32_DMA_PERIPH_RX | STM32_DMA_MEM_8BITS | STM32_DMA_MODE_CYCLIC)>;
10+
dma-names = "tx", "rx";
11+
fifo-enable;
12+
};
13+
14+
&dma1 {
15+
status = "okay";
16+
};
17+
18+
&dmamux1 {
19+
status = "okay";
20+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CONFIG_SERIAL=y
2+
CONFIG_UART_ASYNC_API=y
3+
CONFIG_RING_BUFFER=y
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
sample:
2+
name: UART driver sample
3+
tests:
4+
sample.boards.stm32.uart.circular_dma:
5+
integration_platforms:
6+
- nucleo_g071rb
7+
tags:
8+
- serial
9+
- uart
10+
filter: dt_chosen_enabled("zephyr,shell-uart")
11+
harness: keyboard
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/*
2+
* Copyright (c) 2024 STMicroelectronics
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/device.h>
9+
#include <zephyr/devicetree.h>
10+
#include <zephyr/drivers/uart.h>
11+
#include <zephyr/sys/ring_buffer.h>
12+
#include <zephyr/sys/printk.h>
13+
#include <string.h>
14+
15+
#define RING_BUF_SIZE 1000
16+
#define RX_BUF_SIZE 10
17+
18+
#define RECEIVE_TIMEOUT 0
19+
20+
#define STACK_SIZE 1024
21+
22+
#define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart)
23+
24+
static const struct device *const uart_dev = DEVICE_DT_GET(UART_DEVICE_NODE);
25+
26+
/* uart configuration structure */
27+
const struct uart_config uart_cfg = {.baudrate = 115200,
28+
.parity = UART_CFG_PARITY_NONE,
29+
.stop_bits = UART_CFG_STOP_BITS_1,
30+
.data_bits = UART_CFG_DATA_BITS_8,
31+
.flow_ctrl = UART_CFG_FLOW_CTRL_NONE};
32+
33+
/* define a ring buffer to get raw bytes*/
34+
RING_BUF_DECLARE(ring_buf, RING_BUF_SIZE);
35+
36+
/* define uart rx buffer */
37+
static uint8_t rx_buffer[RX_BUF_SIZE];
38+
39+
/* define thread stack size */
40+
static K_THREAD_STACK_DEFINE(uart_rx_stack, STACK_SIZE);
41+
42+
/* struct uart_event async_evt */
43+
static struct k_thread uart_rx_thread_data = {0};
44+
45+
void print_uart(char *buf, int len)
46+
{
47+
for (int i = 0; i < len; i++) {
48+
49+
if ((buf[i] == '\n' || buf[i] == '\r')) {
50+
uart_poll_out(uart_dev, '\n');
51+
} else {
52+
uart_poll_out(uart_dev, buf[i]);
53+
}
54+
}
55+
}
56+
57+
/* Data processing thread */
58+
static void uart_rx_thread(void *p1, void *p2, void *p3)
59+
{
60+
uint8_t rx_data[RX_BUF_SIZE];
61+
size_t len;
62+
63+
while (1) {
64+
65+
/* Check if there's data in the ring buffer */
66+
len = ring_buf_get(&ring_buf, rx_data, sizeof(rx_data));
67+
68+
if (len > 0) {
69+
70+
/* Process `len` bytes of data */
71+
print_uart(rx_data, len);
72+
}
73+
}
74+
}
75+
76+
void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
77+
{
78+
switch (evt->type) {
79+
case UART_RX_RDY:
80+
/* Data received; place into ring buffer */
81+
ring_buf_put(&ring_buf, evt->data.rx.buf + evt->data.rx.offset, evt->data.rx.len);
82+
83+
break;
84+
85+
case UART_RX_DISABLED:
86+
/* Re-enable RX */
87+
uart_rx_enable(uart_dev, rx_buffer, sizeof(rx_buffer), RECEIVE_TIMEOUT);
88+
89+
break;
90+
91+
default:
92+
break;
93+
}
94+
}
95+
96+
int main(void)
97+
{
98+
if (!uart_dev) {
99+
printk("Failed to get UART device");
100+
return 1;
101+
}
102+
103+
/* uart configuration parameters */
104+
int err = uart_configure(uart_dev, &uart_cfg);
105+
106+
if (err == -ENOSYS) {
107+
printk("Configuration is not supported by device or driver,"
108+
" check the UART settings configuration\n");
109+
return -ENOSYS;
110+
}
111+
112+
/* Configure uart callback */
113+
uart_callback_set(uart_dev, uart_cb, NULL);
114+
115+
/* enable uart reception */
116+
uart_rx_enable(uart_dev, rx_buffer, sizeof(rx_buffer), RECEIVE_TIMEOUT);
117+
118+
printk("\n Enter message to fill RX buffer size :\n");
119+
120+
/* start uart data processing thread */
121+
k_tid_t tid = k_thread_create(&uart_rx_thread_data, uart_rx_stack,
122+
K_THREAD_STACK_SIZEOF(uart_rx_stack), uart_rx_thread, NULL,
123+
NULL, NULL, 5, 0, K_NO_WAIT);
124+
k_thread_name_set(tid, "RX_thread");
125+
}

0 commit comments

Comments
 (0)