https://github.com/RT-Thread/rt-thread/blob/ecd29fda6005ef19c625f194f9311259ba907a78/components/drivers/include/drivers/serial.h#L67C1-L67C1 或者有什么规划,说一下 后续完善下
Activity
cc-caixf commentedon Oct 18, 2023
我对SERIAL_V2框架的问题:
假如驱动实现 INT TX 的
RT_SERIAL_TX_BLOCKING_NO_BUFFER, 也就是TX用_serial_fifo_tx_blocking_nbuf(),那么SERIAL_V2框架里都没有初始化
rb, 这里又调用rt_ringbuffer_data_len(), 明显不对.(意思就是 驱动 实现TX 中断模式 下用RT_SERIAL_TX_BLOCKING_NO_BUFFER模式, SERIAL_V2框架会出现错误)
Yunlk commentedon Oct 20, 2026
盘点结论:宏已定义,但框架两条实现都没接线,驱动 emit 了也是空操作
一、框架侧现状
宏定义在
components/drivers/include/drivers/dev_serial.h:168(顺带说明:这个文件原来就是 issue 里链接的serial.h,后来拆分改名,原链接已失效):v1 ——
components/drivers/serial/dev_serial.crt_hw_serial_isr()的 switch(1536-1695 行)只处理 0x01~0x04:没有 0x05 的分支,而且整个 switch 没有 default。所以在 v1 下调用
rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_TIMEOUT)完全不做任何事。v2 ——
components/drivers/serial/dev_serial_v2.crt_hw_serial_isr()(2174-2370 行)同样是那四个 case,末尾是:0x05 落进 default 被直接丢弃。
二、为什么两条线都没实现——超时语义本身不同
这不是「漏写一个 case」,而是这个事件在现有框架里没有落点:
v1 根本没有「超时」这个概念。 中断模式收到数据就发
RX_IND,不存在「半帧」状态。要支持这个事件,得先引入定时器 + 半帧状态机,属于新增功能,不是补一个 case。v1 也没有任何超时相关控制命令——RT_SERIAL_CTRL_SET_RX_TIMEOUT只定义在dev_serial_v2.h(206 行),v1 侧没有。v2 的超时是「读侧 deadline」,不是「事件」。 v2 提供了
RT_SERIAL_CTRL_SET_RX_TIMEOUT/GET_RX_TIMEOUT(dev_serial_v2.c:195、1641、1684),实现在阻塞读路径里:超时表现为
read()到点返回已经收到的部分数据,由读侧自己兜住,不需要 ISR 再发一个事件。所以 v2 是「用另一套机制解决了同一个问题」。三、真正受影响的驱动:2 个,且它们现在都在调空操作
全仓搜索这个宏只有 4 处出现(1 处定义、2 处调用、1 处已注释):
components/drivers/include/drivers/dev_serial.hbsp/wch/arm/ch579m/board/drv_uart.cUART_II_RECV_TOUT中断)bsp/synwit/libraries/SWM341_drivers/drv_uart.cUART_IT_RX_TOUT中断)bsp/wch/risc-v/libraries/ch56x_drivers/ch56x_uart.c两个驱动的用法一致,都是靠芯片自带的接收超时中断来切分数据帧。ch579m 的注释写得很直接:
它们的意图是「超时即一帧收完」。但框架把 0x05 丢掉了,这个「帧结束」信号永远到不了应用层——两个驱动只能靠
RX_IND按 FIFO 水位上报,帧边界实际上丢了。换句话说,这两处调用目前是看起来生效、实际无效。四、建议
要给一个可实现的方案,得先回答:半帧超时之后,通知谁、带什么信息?三个方向:
RX_IND,即serial->parent.rx_indicate(&serial->parent, <当前 FIFO 中可读长度>)。只补一个 case,不动结构体和 ABI,两个现有驱动的原意立刻能兑现。rx_timeout_cb),语义更清晰,但要改rt_serial_device结构,涉及 ABI。我倾向方案 A:改动最小、不破坏兼容性、现有两个驱动直接受益。
如果需要我做方案 A 的 PR(补 case,并在两个 BSP 上验证),或者先补一份 utest 用例,可以告诉我。
Yunlk commentedon Oct 20, 2026
/claim
github-actions commentedon Oct 20, 2026
@Yunlk has claimed this issue.
Yunlk commentedon Oct 20, 2026
更正上一条盘点里的一处说法
上一条我写「v2 的
rt_hw_serial_isr同样只有那四个 case,0x05 落进default: break被丢弃」。这句话是错的,编译验证时才发现:components/drivers/include/drivers/dev_serial_v2.h只定义了 0x01~0x04,根本没有RT_SERIAL_EVENT_RX_TIMEOUT:我在 v2 的 isr 里试着加
case RT_SERIAL_EVENT_RX_TIMEOUT:,直接编译失败:所以准确的说法是:V2 下这个事件不存在,驱动无法引用(会编译不过),不存在"丢进 default"这回事。这个坑只存在于 V1——宏定义了,但
rt_hw_serial_isr没有对应 case,且 switch 没有 default。顺带确认了受影响范围:发出该事件的两个驱动所在的 BSP(
bsp/wch/arm/ch579m、bsp/synwit/swm341-mini)都使用 V1 框架,所以确实会命中这个静默丢弃。已按方案 A 提了草稿 PR:#11909
改动只有 V1 的一行 case(把超时并入
RX_IND分支),V2 不动。附带说明:这个事件由芯片的接收空闲超时中断触发,QEMU 的 pl011 没有该中断,我也没有 ch579m / SWM341 硬件,所以目前只做到编译级验证,没有行为验证。如果认可这个语义方向,我可以补一个不依赖硬件的 utest(直接调rt_hw_serial_isr,用伪 serial 设备校验rx_indicate的次数与长度)。[serial] test: add v1 utest for RT_SERIAL_EVENT_RX_TIMEOUT