1@page page_device_uart UART Device
2
3# UART Introduction
4
5UART (Universal Asynchronous Receiver/Transmitter), as a kind of asynchronous serial communication protocol, the working principle is to transmit each character of the transmitted data one by one. It is the most frequently used data bus during application development.
6
7The UART serial port is characterized by sequentially transmitting data one bit at a time. As long as  two transmission lines can realize two-way communication, one line transmits data while the other receives data . There are several important functions for UART serial communication, namely baud rate, start bit, data bit, stop bit and parity bit. For two ports that use UART serial port communication, these functions must be matched, otherwise the communication can't be carried out normally. The data format of the UART serial port transmission is as shown below:
8
9![Serial Transmission Data Format](figures/uart1.png)
10
11* Start bit: Indicates the start of data transfer and the level logic is "0".
12- Data bits: Possible values are 5, 6, 7, 8, and 9, indicating that these bits are transmitted. The value is generally 8, because an ASCII character value is 8 bits.
13- Parity check bit: It it used by the receiver to verify the received data. The number of bits is used in the check of "1" is even (even parity) or odd (odd parity) ,in order to verify the data transmission. It is also fine by not using this bit .
14- Stop Bit: Indicates the end of one frame of data. The level logic is "1".
15- Baudrate: It is the rate at which a serial port communicates, which expressed in bits per second (bps) of the binary code transmitted in unit time. The common baud rate values are 4800, 9600, 14400, 38400, 115200, etc. The higher the value is, the faster the data transmission will be.
16
17# Access UART Device
18
19The application accesses the serial port hardware through the I/O device management interface provided by RT-Thread. The related interfaces are as follows:
20
21| **Funtion** | **Description**                |
22| --------------------------- | -------------------------- |
23| rt_device_find()  | find device |
24| rt_device_open()     | open device |
25| rt_device_read()   | read device |
26| rt_device_write()  |write device|
27| rt_device_control()  | control device |
28| rt_device_set_rx_indicate()   | set receive callback function |
29| rt_device_set_tx_complete()  | set send complete callback function |
30| rt_device_close()     | close device |
31
32## Find UART Device
33
34The application obtains the device handle according to the uart device name, and then can operate the uart device.The device find function is shown below
35
36```c
37rt_device_t rt_device_find(const char* name);
38```
39
40| **Parameter** | **Description**                                              |
41| ------------- | ------------------------------------------------------------ |
42| name          | device's name                                                |
43| **back**      | ——                                                           |
44| device handle | finding the corresponding device will return to the corresponding device handle |
45| RT_NULL       | corresponding device object was not found                    |
46
47Generally, the name of the uart device registered to the system is uart0, uart1, etc. samples are as follows:
48
49```c
50#define SAMPLE_UART_NAME       "uart2"  /* uart device name */
51static rt_device_t serial;              /* uart device handle */
52/* Find uart device*/
53serial = rt_device_find(SAMPLE_UART_NAME);
54```
55
56## Open UART Device
57
58Through the device handle, the application can open and close the device. When the device is opened, it will detect whether the device has been initialized. If it is not initialized, it will call the initialization interface to initialize the device by default. Open the device through the following functions:
59
60```c
61rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflags);
62```
63
64| **Parameter** | **Description**               |
65| ---------- | ------------------------------- |
66| dev        | device handle            |
67| oflags     | device mode flags   |
68| **back** | ——                             |
69| RT_EOK     | device opened successfully |
70| -RT_EBUSY  | If the standalone parameter RT_DEVICE_FLAG_STANDALONE is included in the functions specified when the device is registered, the device will not be allowed to be opened repeatedly |
71| Other error codes | device failed to open |
72
73oflags parameters support the following values (Use OR logic to support multiple values):
74
75```c
76#define RT_DEVICE_FLAG_STREAM       0x040     /* Stream mode      */
77/* Receive mode function */
78#define RT_DEVICE_FLAG_INT_RX       0x100     /* Interrupt receive mode */
79#define RT_DEVICE_FLAG_DMA_RX       0x200     /* DMA receiving mode */
80/* Receive mode function */
81#define RT_DEVICE_FLAG_INT_TX       0x400     /* Interrupt receive mode*/
82#define RT_DEVICE_FLAG_DMA_TX       0x800     /* DMA receive mode    */
83```
84
85There are three modes of uart data receiving and sending: interrupt mode, polling mode and DMA mode. When used, only one of the three modes can be selected. If the open parameter oflag of the serial port does not specify the use of interrupt mode or DMA mode, the polling mode is used by default.
86
87The DMA (Direct Memory Access) transfer mode does not require the CPU to directly control the transfer, and does not have the process of reserving the scene and restoring the scene as they have in the interrupt processing mode. The DMA controller opens a path for directly transferring data to the RAM and the I/O device, which saves CPU resources to do other things. Using DMA transfer can continuously acquire or send a piece of information without taking up interrupts or delays, which is useful when communication is frequent or when large pieces of information are to be transmitted.
88
89>RT_DEVICE_FLAG_STREAM: Stream mode is used to output a string to the serial terminal: when the output character is `"\n"` (corresponding to the hexadecimal value 0x0A), a ``\r"` is automatically output in front (corresponding to hexadecimal value is 0x0D).
90
91The stream mode `RT_DEVICE_FLAG_STREAM` can be used with the receive and send mode parameter with the "|" logic.
92
93An example of using  a uart device in **interrupt receive mode and polling mode** as follows:
94
95```c
96#define SAMPLE_UART_NAME       "uart2"  /* uart device name */
97static rt_device_t serial;              /* uart device handle */
98/* find uart device */
99serial = rt_device_find(SAMPLE_UART_NAME);
100
101/* Open the uart device in interrupt receive mode and polling mode*/
102rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
103```
104
105If the uart is to use the DMA receive mode, the oflags takes the value RT_DEVICE_FLAG_DMA_RX.  An example of using a uart device in the **DMA receive and polling send mode** is as follows:
106
107```c
108#define SAMPLE_UART_NAME       "uart2"  /* uart device's name */
109static rt_device_t serial;              /* uart device handle */
110/* find uart device */
111serial = rt_device_find(SAMPLE_UART_NAME);
112
113/* Open the uart device in DMA receive and polling send mode*/
114rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX);
115```
116
117## Control UART Device
118
119Through command  control word, the application can configure the uart device by the following function:
120
121```c
122rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg);
123```
124
125| **Parameter**     | **Description**                                              |
126| ----------------- | ------------------------------------------------------------ |
127| dev               | device handle                                                |
128| cmd               | command  control word can be valued as:RT_DEVICE_CTRL_CONFIG |
129| arg               | controlled parameter: struct serial_configure               |
130| **Back**          | ——                                                           |
131| RT_EOK            | function executed successfully                               |
132| -RT_ENOSYS        | execution failed, dev is empty                               |
133| Other error codes | execution failed                                             |
134
135* The prototype of control parameter structure: struct serial_configure is as follows:
136
137```c
138struct serial_configure
139{
140    rt_uint32_t baud_rate;          /* Baudrate */
141    rt_uint32_t data_bits    :4;    /* Data bit */
142    rt_uint32_t stop_bits    :2;    /* Stop bit */
143    rt_uint32_t parity       :2;    /* Parity bit */
144    rt_uint32_t bit_order    :1;    /* Prioritized by order */
145    rt_uint32_t invert       :1;    /* Mode */
146    rt_uint32_t bufsz        :16;   /* Receive data buffer size */
147    rt_uint32_t reserved     :4;    /* Reserved bit */
148};
149```
150
151* The default macro configuration provided by RT-Thread is as follows:
152
153```c
154#define RT_SERIAL_CONFIG_DEFAULT           \
155{                                          \
156    BAUD_RATE_115200, /* 115200 bps */     \
157    DATA_BITS_8,      /* 8 databits */     \
158    STOP_BITS_1,      /* 1 stopbit */      \
159    PARITY_NONE,      /* No parity  */     \
160    BIT_ORDER_LSB,    /* LSB first sent */ \
161    NRZ_NORMAL,       /* Normal mode */    \
162    RT_SERIAL_RB_BUFSZ, /* Buffer size */  \
163    0                                      \
164}
165```
166
167The configuration parameters provided by RT-Thread can be defined as the following macro definitions::
168
169```c
170/* The baudrate can be defined as*/
171#define BAUD_RATE_2400                  2400
172#define BAUD_RATE_4800                  4800
173#define BAUD_RATE_9600                  9600
174#define BAUD_RATE_19200                 19200
175#define BAUD_RATE_38400                 38400
176#define BAUD_RATE_57600                 57600
177#define BAUD_RATE_115200                115200
178#define BAUD_RATE_230400                230400
179#define BAUD_RATE_460800                460800
180#define BAUD_RATE_921600                921600
181#define BAUD_RATE_2000000               2000000
182#define BAUD_RATE_3000000               3000000
183/* Data bits can be defined as*/
184#define DATA_BITS_5                     5
185#define DATA_BITS_6                     6
186#define DATA_BITS_7                     7
187#define DATA_BITS_8                     8
188#define DATA_BITS_9                     9
189/* Stop bits can be defined as */
190#define STOP_BITS_1                     0
191#define STOP_BITS_2                     1
192#define STOP_BITS_3                     2
193#define STOP_BITS_4                     3
194/* Parity bits can be defined as */
195#define PARITY_NONE                     0
196#define PARITY_ODD                      1
197#define PARITY_EVEN                     2
198/* Bit order can be defined as */
199#define BIT_ORDER_LSB                   0
200#define BIT_ORDER_MSB                   1
201/* Mode canbe defined as */
202#define NRZ_NORMAL                      0   /* normal mode */
203#define NRZ_INVERTED                    1   /* inverted mode */
204/* Default size of the receive data buffer */
205#define RT_SERIAL_RB_BUFSZ              64
206```
207
208**Receive Buffer**
209
210When the uart device is opened using interrupt receive mode, the uart driver framework will open a buffer according to the size of RT_SERIAL_RB_BUFSZ to save the received data. When the underlying driver receives a data, it will put the data into the buffer in the interrupt service program.
211
212>The default size of the receive data buffer is 64 bytes.  If the number of received data in one-time is too large and the data is not read in time, the data of the buffer will be overwritten by the newly received data, resulting in data loss. It is recommended to increase the buffer.
213
214A sample for configuring uart hardware parameters such as data bits, check bits, stop bits, and so on are shown below:
215
216```c
217#define SAMPLE_UART_NAME       "uart2"  /* uart device's name */
218static rt_device_t serial;              /* uart device handle */
219struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* Configuration parameters */
220/* Find uart devices */
221serial = rt_device_find(SAMPLE_UART_NAME);
222
223/* Open the uart device in interrupt receive and polling send mode */
224rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
225
226config.baud_rate = BAUD_RATE_115200;
227config.data_bits = DATA_BITS_8;
228config.stop_bits = STOP_BITS_2;
229config.parity = PARITY_NONE;
230/* The serial port configuration parameters can only be modified after opening the device */
231rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);
232```
233
234## Send Data
235
236To write data to the serial port, the following functions can be used:
237
238```c
239rt_size_t rt_device_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size);
240```
241
242| **Parameter** | **Description**                         |
243| ---------- | ------------------------------------------ |
244| dev                | device handle                 |
245| pos                | Write data offset, this parameter is not used in uart device |
246| buffer             | Memory buffer pointer, place the data to be written |
247| size               | The size of the written data |
248| **back**       | ——                                     |
249| The actual size of the written data | If it is a character device, the return size is in bytes; |
250| 0                  | It needs to read the current thread's errno to determine the error status |
251
252Calling this function will write the data in the `buffer` to the `dev` device, the size of the write data is: size.
253
254The sample program for writing data to the serial port is as follows:
255
256```c
257#define SAMPLE_UART_NAME       "uart2"  /* uart device's name */
258static rt_device_t serial;              /* uart device handle */
259char str[] = "hello RT-Thread!\r\n";
260struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* Configuration parameter */
261/*find uart device */
262serial = rt_device_find(SAMPLE_UART_NAME);
263
264/* Open the uart device in interrupt reception and polling mode */
265rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
266/* Send string */
267rt_device_write(serial, 0, str, (sizeof(str) - 1));
268```
269
270## Set The Send completion Callback Function
271
272When the application calls `rt_device_write()` to write data, if the underlying hardware can support automatic transmission, the upper application can set a callback function. This callback function is called after the underlying hardware data has been sent (for example, when the DMA transfer is complete or the FIFO has been written to complete the completion interrupt). You can set the device to send completion instructions by the following function:
273
274```c
275rt_err_t rt_device_set_tx_complete(rt_device_t dev, rt_err_t (*tx_done)(rt_device_t dev,void *buffer));
276```
277
278| **Parameter** | **Description**           |
279| ------------- | ------------------------- |
280| dev           | device handle             |
281| tx_done       | callback function pointer |
282| **back**      | ——                        |
283| RT_EOK        | set up successfully       |
284
285When this function is called, the callback function is provided by the user. When the hardware device sends the data, the device driver calls back this function and passes the sent data block address buffer as a parameter to the upper application. When the application (thread) receives the indication, it will release the buffer memory block or use it as the buffer for the next write data according to the condition of sending the buffer.
286
287## Set The Receive Callback Function
288
289The data receiving instruction can be set by the following function. When the serial port receives the data, it will inform the upper application thread that the data has arrived:
290
291```c
292rt_err_t rt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_t dev,rt_size_t size));
293```
294
295| **Parameter** | **Description** |
296| -------- | ------------ |
297| dev      | device handle |
298| rx_ind   | callback function pointer |
299| dev      | device handle (callback function parameter) |
300| size     | buffer data size (callback function parameter) |
301| **back** | ——           |
302| RT_EOK   | set up successfully |
303
304The callback function for this function is provided by the user. If the uart device is opened in interrupt receive mode, the callback function will be called when the serial port receives a data, and the data size of the buffer will be placed in the `size` parameter, and the uart device handle will be placed in the `dev` parameter.
305
306If the uart is opened in DMA receive mode, the callback function is called when the DMA completes receiving a batch of data.
307
308Normally the receiving callback function can send a semaphore or event to notify the serial port data processing thread that data has arrived. The example is as follows:
309
310```c
311#define SAMPLE_UART_NAME       "uart2"  /* uart device name */
312static rt_device_t serial;              /* uart device handle */
313static struct rt_semaphore rx_sem;      /* The semaphore used to receive the message */
314
315/* Receive data callback function */
316static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
317{
318    /* When the serial port receives the data, it triggers interrupts, calls this callback function, and sends the received semaphore */
319    rt_sem_release(&rx_sem);
320
321    return RT_EOK;
322}
323
324static int uart_sample(int argc, char *argv[])
325{
326    serial = rt_device_find(SAMPLE_UART_NAME);
327
328    /* Open the uart device in interrupting receive mode */
329    rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
330
331    /* Initialization semaphore */
332    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
333
334    /* Set the receive callback function */
335    rt_device_set_rx_indicate(serial, uart_input);
336}
337
338```
339
340## Receive Data
341
342You can call the following function to read the data received by the uart:
343
344```c
345rt_size_t rt_device_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size);
346```
347
348| **Parameter**                    | **Description**                                              |
349| -------------------------------- | ------------------------------------------------------------ |
350| dev                              | device handle                                                |
351| pos                              | Read data offset, uart device dose not use this parameter    |
352| buffer                           | Buffer pointer, the data read will be saved in the buffer    |
353| size                             | Read the size of the data                                    |
354| **back**                         | ——                                                           |
355| Read the actual size of the data | If it is a character device, the return size is in bytes.    |
356| 0                                | It needs to read the current thread's errno to determine the error status |
357
358Read data offset: pos is not valid for character devices. This parameter is mainly used for block devices.
359
360An example of using the interrupt receive mode with the receive callback function is as follows:
361
362```c
363static rt_device_t serial;            /* uart device handle */
364static struct rt_semaphore rx_sem;    /* Semaphore used to receive messages */
365
366/* Thread receiving data */
367static void serial_thread_entry(void *parameter)
368{
369    char ch;
370
371    while (1)
372    {
373        /* Reads a byte of data from the serial port and waits for the receiving semaphore if it is not read */
374        while (rt_device_read(serial, -1, &ch, 1) != 1)
375        {
376            /* Blocking waiting to receive semaphore, waiting for the semaphore to read the data again*/
377            rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
378        }
379        /* Read the data through the serial port dislocation output*/
380        ch = ch + 1;
381        rt_device_write(serial, 0, &ch, 1);
382    }
383}
384```
385
386## Close The UART Device
387
388After the application completes the serial port operation, the uart device can be closed by the following functions:
389
390```c
391rt_err_t rt_device_close(rt_device_t dev);
392```
393
394| **Parameter**     | **Description**                                              |
395| ----------------- | ------------------------------------------------------------ |
396| dev               | device handle                                                |
397| **back**          | ——                                                           |
398| RT_EOK            | device closed successfully                                   |
399| -RT_ERROR         | The device has been completely shut down and cannot be shut down repeatedly |
400| other error codes | fail to close the device                                     |
401
402Use the `rt_device_close()` interface and `rt_device_open()` interface in pair. When you open the device, you need to close the device once, so that the device will be completely shut down, otherwise the device will remain open.
403
404# Examples Of Using UART Device
405
406## Interrupt Receiving And Polling Send
407
408The main steps of the sample code are as follows:
409
4101. First find the uart device to get the device handle.
4112. Initialize the semaphore that the callback function sends, and then open the uart device in read/write and interrupt receive mode.
4123. Set the receive callback function of the uart device, then send the string and create a read data thread.
4134. The read data thread will try to read a character data. If there is no data, it will hang and wait for the semaphore. When the uart device receives a data, it will trigger an interrupt and call the receive callback function. This function will send a semaphore to wake up the thread. At this point, the thread will immediately read the received data.
4145. This sample code is not limited to a specific BSP. According to the uart device registered by BSP, modify the uart device's name corresponding to the sample code's macro definition  SAMPLE_UART_NAME  to run.
415
416The running sequence diagram is shown as follows:
417
418![Serial Port Interrupt Reception and Polling Transmission Sequence Diagram](figures/uart-int.png)
419
420
421```c
422/*
423 * Program list: This is a uart device usage routine
424 * The routine exports the uart_sample command to the control terminal
425 * Format of command: uart_sample uart2
426 * Command explanation: the second parameter of the command is the name of the uart device. If it is null, the default uart device wil be used
427 * Program function: output the string "hello RT-Thread!" through the serial port, and then malposition the input character
428*/
429
430#include <rtthread.h>
431
432#define SAMPLE_UART_NAME       "uart2"
433
434/* Semaphore used to receive messages */
435static struct rt_semaphore rx_sem;
436static rt_device_t serial;
437
438/* Receive data callback function */
439static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
440{
441    /* After the uart device receives the data, it generates an interrupt, calls this callback function, and then sends the received semaphore. */
442    rt_sem_release(&rx_sem);
443
444    return RT_EOK;
445}
446
447static void serial_thread_entry(void *parameter)
448{
449    char ch;
450
451    while (1)
452    {
453        /* Read a byte of data from the serial port and wait for the receiving semaphore if it is not read */
454        while (rt_device_read(serial, -1, &ch, 1) != 1)
455        {
456            /* Being Suspended and waiting for the semaphore */
457            rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
458        }
459        /* Read the data from the serial port and output through dislocation */
460        ch = ch + 1;
461        rt_device_write(serial, 0, &ch, 1);
462    }
463}
464
465static int uart_sample(int argc, char *argv[])
466{
467    rt_err_t ret = RT_EOK;
468    char uart_name[RT_NAME_MAX];
469    char str[] = "hello RT-Thread!\r\n";
470
471    if (argc == 2)
472    {
473        rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
474    }
475    else
476    {
477        rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
478    }
479
480    /* Find uart devices in the system */
481    serial = rt_device_find(uart_name);
482    if (!serial)
483    {
484        rt_kprintf("find %s failed!\n", uart_name);
485        return -RT_ERROR;
486    }
487
488    /* Initialize the semaphore */
489    rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
490    /* Open the uart device in interrupt receive and polling send mode */
491    rt_device_open(serial, RT_DEVICE_FLAG_INT_RX);
492    /* Set the receive callback function */
493    rt_device_set_rx_indicate(serial, uart_input);
494    /* Send string */
495    rt_device_write(serial, 0, str, (sizeof(str) - 1));
496
497    /* Create a serial thread */
498    rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
499    /* Start the thread successfully */
500    if (thread != RT_NULL)
501    {
502        rt_thread_startup(thread);
503    }
504    else
505    {
506        ret = -RT_ERROR;
507    }
508
509    return ret;
510}
511/* Export to the msh command list */
512MSH_CMD_EXPORT(uart_sample, uart device sample);
513```
514
515## DMA Reception And Polling Transmission
516
517When the serial port receives a batch of data, it will call the receive callback function. The receive callback function will send the data size of the buffer at this time to the waiting data processing thread through the message queue. After the thread gets the message, it is activated and reads the data. In general, the DMA receive mode completes data reception in conjunction with the DMA receive completion interrupt and the serial port idle interrupt.
518
519* This sample code is not limited to a specific BSP. According to the uart device registered by BSP, modify the sample code macro to define the uart device name corresponding to SAMPLE_UART_NAME to run.
520
521The running sequence diagram is shown below:
522
523![Serial DMA Receiving and Polling Transmission Sequence Diagram](figures/uart-dma.png)
524
525```c
526/*
527 * Program list: This is a uart device DMA receive usage routine
528 * The routine exports the uart_dma_sample command to the control terminal
529 * Command format: uart_dma_sample uart3
530 * Command explanation: The second parameter of the command is the name of the uart device to be used. If it is empty, the default uart device will be used.
531 * Program function: output the string "hello RT-Thread!" through the serial port, and output the received data through the serial port, and then print the received data.
532*/
533
534#include <rtthread.h>
535
536#define SAMPLE_UART_NAME       "uart3"      /* uart device name */
537
538/* Serial port receiving message structure*/
539struct rx_msg
540{
541    rt_device_t dev;
542    rt_size_t size;
543};
544/* uart device handle */
545static rt_device_t serial;
546/* Message queue control block*/
547static struct rt_messagequeue rx_mq;
548
549/* Receive data callback function */
550static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
551{
552    struct rx_msg msg;
553    rt_err_t result;
554    msg.dev = dev;
555    msg.size = size;
556
557    result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
558    if ( result == -RT_EFULL)
559    {
560        /* message queue full */
561        rt_kprintf("message queue full!\n");
562    }
563    return result;
564}
565
566static void serial_thread_entry(void *parameter)
567{
568    struct rx_msg msg;
569    rt_err_t result;
570    rt_uint32_t rx_length;
571    static char rx_buffer[RT_SERIAL_RB_BUFSZ + 1];
572
573    while (1)
574    {
575        rt_memset(&msg, 0, sizeof(msg));
576        /* Read messages from the message queue*/
577        result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), RT_WAITING_FOREVER);
578        if (result >= 0)
579        {
580            /*Read data from the serial port*/
581            rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
582            rx_buffer[rx_length] = '\0';
583            /* Output the read message through the uart device: serial */
584            rt_device_write(serial, 0, rx_buffer, rx_length);
585            /* Print data */
586            rt_kprintf("%s\n",rx_buffer);
587        }
588    }
589}
590
591static int uart_dma_sample(int argc, char *argv[])
592{
593    rt_err_t ret = RT_EOK;
594    char uart_name[RT_NAME_MAX];
595    static char msg_pool[256];
596    char str[] = "hello RT-Thread!\r\n";
597
598    if (argc == 2)
599    {
600        rt_strncpy(uart_name, argv[1], RT_NAME_MAX);
601    }
602    else
603    {
604        rt_strncpy(uart_name, SAMPLE_UART_NAME, RT_NAME_MAX);
605    }
606
607    /* find uart device */
608    serial = rt_device_find(uart_name);
609    if (!serial)
610    {
611        rt_kprintf("find %s failed!\n", uart_name);
612        return -RT_ERROR;
613    }
614
615    /* Initialize message queue */
616    rt_mq_init(&rx_mq, "rx_mq",
617               msg_pool,                 /* a pool for storing messages */
618               sizeof(struct rx_msg),    /* The maximum length of a message*/
619               sizeof(msg_pool),         /* The size of the message pool */
620               RT_IPC_FLAG_FIFO);        /* If there are multiple threads waiting, assign messages according to the order. */
621
622    /* Open the uart device in DMA receive and polling send mode */
623    rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX);
624    /* Set the receive callback function */
625    rt_device_set_rx_indicate(serial, uart_input);
626    /* Send string */
627    rt_device_write(serial, 0, str, (sizeof(str) - 1));
628
629    /* Create a thread */
630    rt_thread_t thread = rt_thread_create("serial", serial_thread_entry, RT_NULL, 1024, 25, 10);
631    /* Start the thread if it is created successfully*/
632    if (thread != RT_NULL)
633    {
634        rt_thread_startup(thread);
635    }
636    else
637    {
638        ret = -RT_ERROR;
639    }
640
641    return ret;
642}
643/* Export to the msh command list */
644MSH_CMD_EXPORT(uart_dma_sample, uart device dma sample);
645```
646
647