RT-Thread Version
master
Affected area
RT-Smart
Hardware/BSP vendor
Loongson
Architecture
Not applicable / Other
Board and hardware details
LS2K0300
Develop Toolchain
GCC
Describe the bug
问题现象
LoongArch/LS2K300 启用 RT-Thread Smart 模式后,启动过程在 tty 注册期间挂死——没有任何输出,CPU 卡死。
机理:时序倒挂
问题出在 RT-Thread 的初始化阶段分级与 tty 注册时机的错位。完整链条:
// dev_serial.c —— 公共代码,任何开 Smart 的架构都走这里
rt_err_t rt_hw_serial_register(...)
{
...
#if defined(RT_USING_SMART)
rt_hw_serial_register_tty(serial); // ← 注册 tty,依赖 workqueue
#endif
return ret;
}
| 步骤 |
阶段 |
说明 |
rt_hw_uart_init() → rt_hw_serial_register() → rt_hw_serial_register_tty() |
board 阶段(rt_hw_board_init 内) |
LS2K300 在 main.c 的 rt_hw_board_init 里注册 |
_tty_workqueue_init(创建 _ttyworkq) |
INIT_PREV_EXPORT |
由 rt_components_board_init() 触发,晚于 uart 注册 |
_tty_pending_flush(修复新增) |
INIT_COMPONENT_EXPORT |
保证在 workqueue 建好之后 flush |
LS2K300 的 rt_hw_board_init() 里 uart 注册在 rt_components_board_init() 之前:
// bsp/loongarch/ls2k300_dev/applications/main.c
void rt_hw_board_init(void)
{
...
rt_hw_uart_init(); // ← board 阶段注册串口 → 调 tty 注册
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
...
rt_components_board_init(); // ← 之后才跑 INIT_PREV(建 workqueue)
}
而 lwp_tty_create() 内部调用 cv_init() / rt_wqueue_init() / rt_mutex_init(),需要调度器/定时器/workqueue 就绪。board 阶段直接调用时 _ttyworkq 还是 NULL → 挂死。
修复方案
在公共 serial_tty.c 里加延迟注册机制:
rt_err_t rt_hw_serial_register_tty(struct rt_serial_device *serial)
{
/* workqueue 未建时挂 pending 链表,延后到 COMPONENT 阶段再注册 */
if (_ttyworkq == RT_NULL)
{
rt_hw_serial_register_tty_defer(serial);
return RT_EOK;
}
...
}
static int _tty_pending_flush(void)
{
/* COMPONENT 阶段 workqueue 已就绪,flush pending 链表 */
while ((node = rt_slist_first(&_tty_pending)))
{
...
rt_hw_serial_register_tty(pn->serial);
...
}
return RT_EOK;
}
INIT_COMPONENT_EXPORT(_tty_pending_flush);
关键设计:
_ttyworkq == RT_NULL 守卫:只对"workqueue 未建时注册"的架构走延迟路径;晚注册的架构 _ttyworkq != NULL,直接走原路径,行为完全不变——对其他架构 no-op。
- pending 链表 +
INIT_COMPONENT_EXPORT flush:COMPONENT 阶段保证在 PREV 阶段(workqueue 创建)之后执行,时序正确。
- 补丁改的是公共层
serial_tty.c,不是 LoongArch 私有代码——所有开 Smart 的架构一旦暴露此问题,直接受益。
跨架构影响:这是公共缺陷,不是 LoongArch 独有
逐一核对各架构后的结论:
1. 非 Smart BSP(raspi4-64、qemu-vexpress-a9 等)—— 真不需要
它们的 .config 里 RT_USING_SMART 未开,#if defined(RT_USING_SMART) 那段根本不编译,从不调用 rt_hw_serial_register_tty,自然没有 workqueue 依赖。这是"不需要"的唯一正确情形。
2. 开了 Smart 的 BSP(k230 等)—— 同样会踩,只是没暴露
k230 的配置和时序与 LS2K300 完全相同:
// bsp/k230/.config:122
CONFIG_RT_USING_SMART=y
// bsp/k230/board/board.c:113
rt_hw_uart_init(); // board 阶段
#ifdef RT_USING_COMPONENTS_INIT
rt_components_board_init(); // 之后才建 workqueue
#endif
k230 完全相同的时序:board 阶段注册串口 → 开 Smart → 调 rt_hw_serial_register_tty → workqueue 未建。如果它真正走通 tty 注册路径(lwp_tty_create 真执行),会踩一模一样的挂死。d1、d1s、bl808、cv18xx 同理——它们没爆是因为还没走到那条路径,不是不需要。
3. 补丁修的是公共缺陷,对所有 Smart 架构生效
复现环境
- BSP:
bsp/loongarch/ls2k300_dev
- 配置:
CONFIG_RT_USING_SMART=y
- 现象: 启动过程在 tty 注册期间挂死,无任何输出
参考
- 修复 commit:
908b3702d serial/tty: 延迟 tty 注册,避免 board 阶段 workqueue 未就绪
- 关键代码位置:
components/drivers/serial/dev_serial.c:1408(#if RT_USING_SMART 调 rt_hw_serial_register_tty)
components/drivers/serial/serial_tty.c(_tty_workqueue_init = INIT_PREV_EXPORT;_tty_pending_flush = INIT_COMPONENT_EXPORT)
bsp/k230/board/board.c:113(k230 相同时序,潜在踩坑)
Other additional context
No response
RT-Thread Version
master
Affected area
RT-Smart
Hardware/BSP vendor
Loongson
Architecture
Not applicable / Other
Board and hardware details
LS2K0300
Develop Toolchain
GCC
Describe the bug
问题现象
LoongArch/LS2K300 启用 RT-Thread Smart 模式后,启动过程在 tty 注册期间挂死——没有任何输出,CPU 卡死。
机理:时序倒挂
问题出在 RT-Thread 的初始化阶段分级与 tty 注册时机的错位。完整链条:
rt_hw_uart_init()→rt_hw_serial_register()→rt_hw_serial_register_tty()rt_hw_board_init内)main.c的rt_hw_board_init里注册_tty_workqueue_init(创建_ttyworkq)INIT_PREV_EXPORTrt_components_board_init()触发,晚于 uart 注册_tty_pending_flush(修复新增)INIT_COMPONENT_EXPORTLS2K300 的
rt_hw_board_init()里 uart 注册在rt_components_board_init()之前:而
lwp_tty_create()内部调用cv_init()/rt_wqueue_init()/rt_mutex_init(),需要调度器/定时器/workqueue 就绪。board 阶段直接调用时_ttyworkq还是NULL→ 挂死。修复方案
在公共
serial_tty.c里加延迟注册机制:关键设计:
_ttyworkq == RT_NULL守卫:只对"workqueue 未建时注册"的架构走延迟路径;晚注册的架构_ttyworkq != NULL,直接走原路径,行为完全不变——对其他架构 no-op。INIT_COMPONENT_EXPORTflush:COMPONENT 阶段保证在 PREV 阶段(workqueue 创建)之后执行,时序正确。serial_tty.c,不是 LoongArch 私有代码——所有开 Smart 的架构一旦暴露此问题,直接受益。跨架构影响:这是公共缺陷,不是 LoongArch 独有
逐一核对各架构后的结论:
1. 非 Smart BSP(raspi4-64、qemu-vexpress-a9 等)—— 真不需要
它们的
.config里RT_USING_SMART未开,#if defined(RT_USING_SMART)那段根本不编译,从不调用rt_hw_serial_register_tty,自然没有 workqueue 依赖。这是"不需要"的唯一正确情形。2. 开了 Smart 的 BSP(k230 等)—— 同样会踩,只是没暴露
k230 的配置和时序与 LS2K300 完全相同:
k230 完全相同的时序:board 阶段注册串口 → 开 Smart → 调
rt_hw_serial_register_tty→ workqueue 未建。如果它真正走通 tty 注册路径(lwp_tty_create真执行),会踩一模一样的挂死。d1、d1s、bl808、cv18xx 同理——它们没爆是因为还没走到那条路径,不是不需要。3. 补丁修的是公共缺陷,对所有 Smart 架构生效
复现环境
bsp/loongarch/ls2k300_devCONFIG_RT_USING_SMART=y参考
908b3702dserial/tty: 延迟 tty 注册,避免 board 阶段 workqueue 未就绪components/drivers/serial/dev_serial.c:1408(#if RT_USING_SMART调rt_hw_serial_register_tty)components/drivers/serial/serial_tty.c(_tty_workqueue_init= INIT_PREV_EXPORT;_tty_pending_flush= INIT_COMPONENT_EXPORT)bsp/k230/board/board.c:113(k230 相同时序,潜在踩坑)Other additional context
No response