|
|
|
/*
|
|
|
|
* Copyright (c) 2006-2021, RT-Thread Development Team
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*
|
|
|
|
* Change Logs:
|
|
|
|
* Date Author Notes
|
|
|
|
* 2025-10-20 Administrator the first version
|
|
|
|
*/
|
|
|
|
/* DATA_uart.c */
|
|
|
|
#include <rtthread.h>
|
|
|
|
#include <rtdevice.h>
|
|
|
|
#include "data_comm.h"
|
|
|
|
|
|
|
|
#define SAMPLE_UART_NAME "uart2"
|
|
|
|
#define DMA_RX_BUF_SIZE 512
|
|
|
|
#define RINGBUF_SIZE 4096
|
|
|
|
|
|
|
|
static rt_device_t serial;
|
|
|
|
|
|
|
|
// DMA 接收缓冲区
|
|
|
|
//static rt_uint8_t dma_rx_buffer[DMA_RX_BUF_SIZE];
|
|
|
|
|
|
|
|
// 环形缓冲区(暂存未完整报文)
|
|
|
|
static struct rt_ringbuffer rx_rb;
|
|
|
|
static rt_uint8_t rb_pool[RINGBUF_SIZE];
|
|
|
|
|
|
|
|
// 接收回调信号量
|
|
|
|
static struct rt_semaphore rx_sem;
|
|
|
|
|
|
|
|
// 函数声明
|
|
|
|
static rt_err_t uart_rx_ind(rt_device_t dev, rt_size_t size);
|
|
|
|
static int get_line(char *buf, int maxlen);
|
|
|
|
|
|
|
|
void uart_thread_entry(void *parameter)
|
|
|
|
{
|
|
|
|
char input[MAX_INPUT_LEN];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
// 初始化环形缓冲区和信号量
|
|
|
|
rt_ringbuffer_init(&rx_rb, rb_pool, sizeof(rb_pool));
|
|
|
|
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
|
|
|
|
|
|
|
|
// 查找串口设备
|
|
|
|
serial = rt_device_find(SAMPLE_UART_NAME);
|
|
|
|
if (!serial) {
|
|
|
|
rt_kprintf("Cannot find %s\n", SAMPLE_UART_NAME);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 配置串口参数(只设置 bufsz,去掉 dma_rx)
|
|
|
|
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
|
|
|
config.bufsz = DMA_RX_BUF_SIZE; // 设置接收缓冲区大小
|
|
|
|
|
|
|
|
rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);
|
|
|
|
|
|
|
|
// 打开设备:关键!使用 RT_DEVICE_FLAG_DMA_RX 启用 DMA 接收
|
|
|
|
rt_err_t result = rt_device_open(serial, RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX);
|
|
|
|
if (result != RT_EOK)
|
|
|
|
{
|
|
|
|
rt_kprintf("Failed to open %s with DMA, error=%d\n", SAMPLE_UART_NAME, result);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 设置接收指示回调(DMA 完成或中断后调用)
|
|
|
|
rt_device_set_rx_indicate(serial, uart_rx_ind);
|
|
|
|
|
|
|
|
rt_kprintf("UART DMA thread running...\n");
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
// 等待数据就绪
|
|
|
|
if (rt_sem_take(&rx_sem, RT_WAITING_FOREVER) == RT_EOK)
|
|
|
|
{
|
|
|
|
// 处理接收到的数据(提取完整行)
|
|
|
|
while ((len = get_line(input, sizeof(input))) > 0)
|
|
|
|
{ // 调试:打印每个字节
|
|
|
|
/* rt_kprintf("Len=%d, Data: ", len);
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
rt_kprintf("[%02X '%c'] ", input[i],
|
|
|
|
(input[i] >= 32 && input[i] < 127) ? input[i] : '.');
|
|
|
|
}
|
|
|
|
rt_kprintf("\n");
|
|
|
|
|
|
|
|
rt_kprintf("Received: [%.*s]\n", len, input);*/
|
|
|
|
// 动态分配请求结构体(见之前完整代码)
|
|
|
|
struct proc_request *req = rt_malloc(sizeof(struct proc_request));
|
|
|
|
if (!req) continue;
|
|
|
|
|
|
|
|
rt_strncpy(req->input, input, sizeof(req->input));
|
|
|
|
req->input_len = len;
|
|
|
|
|
|
|
|
req->sem = rt_malloc(sizeof(struct rt_semaphore));
|
|
|
|
if (!req->sem) {
|
|
|
|
rt_free(req);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
rt_sem_init(req->sem, "uart_resp", 0, RT_IPC_FLAG_FIFO);
|
|
|
|
|
|
|
|
// 发送到处理线程
|
|
|
|
if (rt_mq_send(proc_mq, &req, sizeof(req)) == RT_EOK)
|
|
|
|
{
|
|
|
|
// 等待处理完成
|
|
|
|
if (rt_sem_take(req->sem, RT_WAITING_FOREVER) == RT_EOK)
|
|
|
|
{
|
|
|
|
rt_device_write(serial, 0, req->output, req->output_len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 清理
|
|
|
|
rt_sem_detach(req->sem); // 或 rt_sem_delete
|
|
|
|
rt_free(req->sem);
|
|
|
|
rt_free(req);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// DMA 接收回调
|
|
|
|
static rt_err_t uart_rx_ind(rt_device_t dev, rt_size_t size)
|
|
|
|
{
|
|
|
|
rt_uint8_t temp[64];
|
|
|
|
rt_size_t read_size;
|
|
|
|
|
|
|
|
// 从设备读取数据(驱动内部有 DMA buffer)
|
|
|
|
while (size > 0)
|
|
|
|
{
|
|
|
|
read_size = rt_device_read(dev, 0, temp, (size > 64) ? 64 : size);
|
|
|
|
if (read_size > 0) {
|
|
|
|
rt_ringbuffer_put(&rx_rb, temp, read_size);
|
|
|
|
// 调试:打印实际读到的数据
|
|
|
|
/* for (int i = 0; i < read_size; i++) {
|
|
|
|
rt_kprintf("RX: 0x%02X '%c'\n", temp[i],
|
|
|
|
(temp[i] >= 32 && temp[i] < 127) ? temp[i] : '.');
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
size -= read_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
rt_sem_release(&rx_sem);
|
|
|
|
return RT_EOK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 从环形缓冲区提取一行
|
|
|
|
static int get_line(char *buf, int maxlen)
|
|
|
|
{
|
|
|
|
int len = rt_ringbuffer_get(&rx_rb, (rt_uint8_t*)buf, maxlen - 1);
|
|
|
|
if (len > 0) {
|
|
|
|
buf[len] = '\0';
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 启动 UART 线程
|
|
|
|
int start_uart_thread(void)
|
|
|
|
{
|
|
|
|
rt_thread_t tid = rt_thread_create("data_uart", uart_thread_entry, RT_NULL,
|
|
|
|
4096, // 栈大小:4KB
|
|
|
|
25, // 优先级
|
|
|
|
10); // 时间片
|
|
|
|
if (tid != RT_NULL)
|
|
|
|
{
|
|
|
|
rt_thread_startup(tid);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
//INIT_COMPONENT_EXPORT(start_uart_thread);
|