cmcu为stm32h743IIt6
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

151 lines
4.3 KiB

/*
* 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 <rtthread.h>
#include <rtdevice.h>
#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;
}