/* * 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 #include #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);