/* * 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 * 2025-11-12 Modified Switch to IDLE interrupt mode (no DMA, no ringbuffer) */ #include #include #include "data_comm.h" #define SAMPLE_UART_NAME "uart1" #define RX_LINE_BUF_SIZE 1024 // 假设 MAX_INPUT_LEN 已定义,如 256 static rt_device_t serial; static struct rt_semaphore rx_sem; // 接收回调:注意 size 实际是事件指针(RT-Thread 特性) static rt_err_t uart_rx_ind(rt_device_t dev, rt_size_t size) { rt_uint32_t event = *(rt_uint32_t *)&size; // 强制解释为事件 // if (event & RT_SERIAL_EVENT_RX_IDLE) { rt_sem_release(&rx_sem); } return RT_EOK; } // 从串口设备读取一行(以 \n 结尾) static int read_line_from_uart(char *buf, int maxlen) { char ch; int len = 0; while (len < maxlen - 1) { // 从串口缓冲区读一个字节(非阻塞,因为由 IDLE 触发说明有数据) if (rt_device_read(serial, 0, &ch, 1) <= 0) { break; // 无数据(理论上不应发生) } buf[len++] = ch; if (ch == '\n') { buf[len] = '\0'; return len; } } // 缓冲区满仍未遇到 \n,强制结束(可选策略) buf[len] = '\0'; return len; } void uart_thread_entry(void *parameter) { char input[RX_LINE_BUF_SIZE]; int len; // 初始化信号量 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; } // 配置串口:设置内部接收缓冲区大小(必须 >= 最大可能的一行) struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; config.bufsz = RX_LINE_BUF_SIZE; // 关键:驱动内部 buffer 要够大 rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config); // 打开串口:使用中断接收(INT_RX),不使用 DMA rt_err_t result = rt_device_open(serial, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX); if (result != RT_EOK) { rt_kprintf("Failed to open %s with INT, error=%d\n", SAMPLE_UART_NAME, result); return; } // 设置接收回调(用于接收 IDLE 事件) rt_device_set_rx_indicate(serial, uart_rx_ind); rt_kprintf("UART thread (IDLE mode) running on %s...\n", SAMPLE_UART_NAME); while (1) { // 等待空闲中断通知 if (rt_sem_take(&rx_sem, RT_WAITING_FOREVER) == RT_EOK) { // 读取完整行 len = read_line_from_uart(input, sizeof(input)); if (len <= 0) continue; // 构造请求 struct proc_request *req = rt_malloc(sizeof(struct proc_request)); if (!req) continue; rt_strncpy(req->input, input, sizeof(req->input) - 1); 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_free(req->sem); rt_free(req); } } } // 启动 UART 线程 int start_uart_thread(void) { rt_thread_t tid = rt_thread_create("data_uart", uart_thread_entry, RT_NULL, 2048, // 栈大小(2KB 足够) 25, // 优先级 10); // 时间片 if (tid != RT_NULL) { rt_thread_startup(tid); } return 0; }