概述
分享一个实现虚拟串口功能的代码,它将多个虚拟串口设备的数据转发到一个目标串口设备。使用虚拟串口替代rtt的控制台终端设备,使用串口利用率更高,也可将串口复用为调试串口和协议串口是在不同线程中分别解析。
代码链接: uart_spooling_task.c
代码结构
结构体定义:
typedef struct
{
rt_device_t dest_dev;
uint32_t destBaudRate;
struct rt_ringbuffer dest_tx_rb;
rt_event_t ev;
size_t src_number;
rt_device_t src_dev;
struct rt_ringbuffer * src_tx_rb;
}uart_spooling_t;
定义了一个 uart_spooling_t 结构体,用于存储转发任务的相关信息,包括目标设备、波特率、发送缓冲区、事件、源设备数量、源设备数组、源设备发送缓冲区数组等。
回调函数:
rt_err_t dst_rx_ok(rt_device_t dev,rt_size_t size)
{
uart_spooling_t * p_usp = dev->user_data;
rt_event_send(p_usp->ev, EVENT_FLAG0);
return 0;
}
rt_err_t dst_tx_ok(rt_device_t dev, void *buffer)
{
uart_spooling_t * p_usp = dev->user_data;
rt_event_send(p_usp->ev, EVENT_FLAG1);
return 0;
}
定义了 dst_rx_ok 和 dst_tx_ok 两个回调函数,用于处理目标设备接收数据完成和发送数据完成事件。
设备操作函数:
定义了 rt_serial1_init、rt_serial1_open、rt_serial1_close、rt_serial1_read、rt_serial1_write 和 rt_serial1_control 等函数,用于模拟串口设备的操作。
虚拟串口设备初始化函数:
定义了 rt_virtual_uart_dev_init 函数,用于创建并注册虚拟串口设备。
转发任务线程函数:
定义了 rt_uart_spooling_thread_entry 函数,用于执行转发任务,详见下文的线程代码功能。
转发任务初始化函数:
定义了 uart_spooling_task_init 函数,用于创建一个与目标串口同名的线程并启动rt_uart_spooling_thread_entry 任务,线程的栈大小基于虚拟设备的个数自动计算。
线程代码功能
创建虚拟串口设备:
为每个源设备创建一个虚拟串口设备,并将其注册到 RT-Thread 系统中。
打开目标设备:
打开目标串口设备,并设置其波特率和接收/发送完成回调函数。
数据转发:
从目标设备读取数据,并将其写入到所有源设备的发送缓冲区中;从源设备的发送缓冲区读取数据,并将其写入到目标设备的发送缓冲区中。
事件处理:
使用事件机制来同步数据转发过程,确保数据能够及时被处理。
最终测试效果
#define RT_CONSOLE_DEVICE_NAME "uart4"
int uart_spooling_init(void)
{
void uart_spooling_task_init(const char *name,size_t number,rt_uint8_t priority);
uart_spooling_task_init(RT_CONSOLE_DEVICE_NAME,2,30);
rt_thread_mdelay(1);
rt_console_set_device("v0_"RT_CONSOLE_DEVICE_NAME);
return 0;
}
INIT_PREV_EXPORT(uart_spooling_init);
将原本的RT_CONSOLE_DEVICE_NAME虚拟为两个串口设备,并设置优先级30,等待1ms让线程运行起来,将控制台设备与v0_uart4绑定(原本与uart4绑定)。
线程uart4正确创建
虚拟设备v0_uart4 v1_uart4 正确创建