[drivers] Fix OFW bus conflict and prevent duplicate device creation#11090
[drivers] Fix OFW bus conflict and prevent duplicate device creation#11090Rbb666 merged 1 commit intoRT-Thread:masterfrom
Conversation
|
👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread! 为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。 🛠 操作步骤 | Steps
完成后,提交将自动更新至 如有问题欢迎联系我们,再次感谢您的贡献!💐 |
📌 Code Review Assignment🏷️ Tag: componentsReviewers: Maihuanyi Changed Files (Click to expand)
🏷️ Tag: components_driver_i2cReviewers: wdfk-prog Changed Files (Click to expand)
🏷️ Tag: components_driver_spiReviewers: Liang1795 wdfk-prog Changed Files (Click to expand)
📊 Current Review Status (Last Updated: 2025-12-25 18:48 CST)
📝 Review Instructions
|
e3e10fd to
ff03e9c
Compare
Problem: When enumerating device tree nodes, platform bus and native buses (I2C/SPI) may create duplicate devices for the same OFW node, causing cross-bus conflicts. This triggers assertion failure '(dev->bus != new_bus)' in rt_bus_reload_driver_device() during boot on minimal DM-enabled systems. Root Cause: 1. Platform bus tries to reload devices that already belong to other buses by calling rt_bus_reload_driver_device(dev->bus, dev), which violates the API contract (requires dev->bus != new_bus). 2. Native buses (I2C/SPI) do not mark OFW nodes as occupied, so platform bus creates duplicate platform devices for I2C/SPI client nodes. Solution: 1. components/drivers/core/platform_ofw.c: Return RT_EOK when np->dev exists, letting the native bus handle device lifecycle instead of cross-bus reload. 2. components/drivers/i2c/dev_i2c_bus.c: Mark i2c_client_np->dev during scan to prevent platform bus from duplicating I2C client devices. 3. components/drivers/spi/dev_spi_bus.c: Mark spi_dev_np->dev during scan to prevent platform bus from duplicating SPI devices. Tested on Spacemit K1 RISC-V platform with minimal DM configuration. Signed-off-by: lhxj <2743257167@qq.com>
ff03e9c to
5b18fe8
Compare
|
@GuEe-GUI 帮忙看看 |
| } | ||
| else | ||
| { | ||
| err = rt_bus_reload_driver_device(dev->bus, dev); |
There was a problem hiding this comment.
这里的目的是为了舍弃之前匹配上的驱动,重新根据设备状态进行驱动匹配,看上去并没有影响 I2C/SPI 呀,如果会发生错误,那应该是调用方的方法不对。
There was a problem hiding this comment.
查阅 rt_bus_reload_driver_device 的底层实现,发现内核断言严格禁止了这种操作。说明这个函数本身是为了“跨总线迁移”设计的,不支持“同总线重载”。

- API 的限制:在 rt_bus_reload_driver_device 函数内部,存在如下断言: RT_ASSERT(dev->bus != new_bus); 当前代码执行 rt_bus_reload_driver_device(dev->bus, dev) 时,将当前总线作为新总线传入。这会直接触发断言失败,程序根本没机会执行后续的匹配逻辑。
- 之前的初始化时序可能使得 pinctrl 驱动在被请求前就已经加载完成了。此时 dev->drv 不为空,代码走了 if 分支,从而避开了这个有 Bug 的 else 分支。
- 而当在任何时序稍有变动的场景中,若pinctrl 被请求时驱动尚未加载 (drv == NULL)。代码则会掉入 else 分支并触发崩溃。
|
好的,那这个修改就 OK 了,具体后续解决具体问题再提交就行,@Rbb666 可以合并了 |
拉取/合并请求描述:(PR description)
[
为什么提交这份PR (why to submit this PR)
Context: 此问题是在 Spacemit K1 BSP 精简版上发现的。由于在该版本中存在更频繁或特定的设备树(OFW)节点枚举逻辑,触发了跨总线冲突。
Problem:
在枚举设备树节点时,平台总线(platform bus)和原生总线(I2C/SPI)可能会为同一个 OFW 节点创建重复的设备。这会导致在 rt_bus_reload_driver_device() 中触发断言失败 (dev->bus != new_bus)。
Root Cause:
平台总线尝试通过调用 rt_bus_reload_driver_device(dev->bus, dev) 来重新加载已经属于其他总线的设备,这违反了 API 约束。
你的解决方案是什么 (what is your solution)
Solution:
本次修改的核心在于 rt_platform_ofw_request。现在,当检测到节点已经绑定了设备(np->dev 已存在)时,直接返回 RT_EOK。这一改动直接从路径上阻断了平台总线对已占用节点的再次注册尝试,从而杜绝了跨总线重复创建设备的问题。仅凭此项平台侧的改动即可消除断言失败。
请提供验证的bsp和config (provide the config and bsp)
https://github.com/lhxj/rt-thread/tree/spacemit-k1
Path: rt-thread/bsp/spacemit/k1
修改前运行结果:


修改后运行结果:
根据对两个 .config 文件的对比,k1pr(精简版)相比 k1(完整版)的主要改动如下:
]
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up