RT-Thread 的复位控制器框架为嵌入式系统中的硬件复位信号管理提供了标准化接口。复位控制器对于正确初始化、恢复和管理硬件外设及子系统的状态至关重要。
复位信号对硬件管理至关重要:
常见的复位控制器类型包括:
RT-Thread 复位控制器框架位于 components/drivers/reset/,提供:
menuconfig RT_USING_RESET
bool "Using Reset Controller support"
depends on RT_USING_DM
depends on RT_USING_OFW
default n
在 menuconfig 中的位置:
RT-Thread Components → Device Drivers → Using Reset Controller support
依赖项:
RT_USING_DM:必须首先启用RT_USING_OFW:需要设备树支持默认值:禁用(选择加入功能)
config RT_RESET_SCMI
bool "Reset driver controlled via ARM SCMI interface"
depends on RT_USING_RESET
depends on RT_FIRMWARE_ARM_SCMI
default n
支持通过 ARM 系统控制和管理接口(SCMI)控制的复位控制器。
config RT_RESET_SIMPLE
bool "Simple Reset Controller Driver"
depends on RT_USING_RESET
default n
支持基本的基于寄存器的复位控制器,具有简单的位操作。
复位控制器使用以下方式导出复位:
#reset-cells = <n>; /* 复位说明符中的单元数 */
单元数通常表示标识特定复位线所需的值数量(通常为 1)。
设备使用以下方式引用复位线:
resets = <&rstc idx>; /* 复位控制器 phandle 和索引 */
reset-names = "name"; /* 复位线名称 */
soc {
/* 复位控制器节点 */
rstc: reset-controller@1c20000 {
compatible = "vendor,reset-controller", "reset-simple";
reg = <0x1c20000 0x100>;
#reset-cells = <1>;
};
};
/* 单复位消费者 */
uart0: serial@1c28000 {
compatible = "vendor,uart";
reg = <0x1c28000 0x400>;
interrupts = <0 0 4>;
clocks = <&ccu 64>;
resets = <&rstc 32>; /* 复位索引 32 */
reset-names = "uart";
status = "okay";
};
/* 多复位消费者 */
usb0: usb@1c19000 {
compatible = "vendor,usb-otg";
reg = <0x1c19000 0x1000>;
interrupts = <0 32 4>;
clocks = <&ccu 24>, <&ccu 25>;
clock-names = "ahb", "otg";
resets = <&rstc 11>, <&rstc 12>;
reset-names = "ahb", "phy";
status = "okay";
};
消费者 API 为设备驱动程序提供简单的函数来控制复位线。复位操作通常在设备初始化和错误恢复期间执行。
struct rt_reset_control *rt_reset_control_get_by_name(struct rt_device *dev,
const char *name);
通过名称获取复位控制。
参数:
dev:设备结构指针name:复位线名称(匹配设备树中的 reset-names)返回值:
示例:
struct rt_reset_control *rst;
/* 获取 "phy" 复位线 */
rst = rt_reset_control_get_by_name(dev, "phy");
if (!rst) {
LOG_W("没有 phy 复位线");
/* 不致命 - 某些板可能没有 */
}
struct rt_reset_control *rt_reset_control_get_by_index(struct rt_device *dev,
int index);
通过索引获取复位控制。
参数:
dev:设备结构指针index:resets 属性中的复位索引(从 0 开始)返回值:
struct rt_reset_control *rt_reset_control_get_array(struct rt_device *dev);
获取设备的所有复位控制作为数组。
参数:
dev:设备结构指针返回值:
void rt_reset_control_put(struct rt_reset_control *rstc);
释放复位控制。
参数:
rstc:复位控制指针rt_err_t rt_reset_control_reset(struct rt_reset_control *rstc);
执行复位脉冲:断言然后解除断言。
参数:
rstc:复位控制指针返回值:
RT_EOK注意:
示例:
/* 在初始化期间复位外设 */
ret = rt_reset_control_reset(rst);
if (ret != RT_EOK) {
LOG_E("复位外设失败: %d", ret);
return ret;
}
/* 等待硬件稳定 */
rt_thread_mdelay(10);
rt_err_t rt_reset_control_assert(struct rt_reset_control *rstc);
断言(激活)复位信号。
参数:
rstc:复位控制指针返回值:
RT_EOK注意:
示例:
/* 在断电前将设备置于复位状态 */
rt_reset_control_assert(rst);
rt_err_t rt_reset_control_deassert(struct rt_reset_control *rstc);
解除断言(停用)复位信号。
参数:
rstc:复位控制指针返回值:
RT_EOK注意:
示例:
/* 将设备从复位中取出 */
rt_reset_control_deassert(rst);
/* 等待硬件准备好 */
rt_thread_mdelay(1);
int rt_reset_control_status(struct rt_reset_control *rstc);
获取复位线的当前状态。
参数:
rstc:复位控制指针返回值:
#include <rtthread.h>
#include <drivers/platform.h>
#include <drivers/clk.h>
#include <drivers/reset.h>
struct usb_device {
void *base;
int irq;
struct rt_clk *ahb_clk;
struct rt_clk *otg_clk;
struct rt_reset_control *ahb_rst;
struct rt_reset_control *phy_rst;
};
static rt_err_t usb_hw_init(struct usb_device *usb)
{
rt_err_t ret;
/* 首先启用时钟 */
ret = rt_clk_prepare_enable(usb->ahb_clk);
if (ret != RT_EOK) {
LOG_E("启用 AHB 时钟失败: %d", ret);
return ret;
}
ret = rt_clk_prepare_enable(usb->otg_clk);
if (ret != RT_EOK) {
LOG_E("启用 OTG 时钟失败: %d", ret);
goto err_disable_ahb;
}
/* 启用时钟后解除断言复位 */
ret = rt_reset_control_deassert(usb->ahb_rst);
if (ret != RT_EOK) {
LOG_E("解除断言 AHB 复位失败: %d", ret);
goto err_disable_otg;
}
ret = rt_reset_control_deassert(usb->phy_rst);
if (ret != RT_EOK) {
LOG_E("解除断言 PHY 复位失败: %d", ret);
goto err_assert_ahb;
}
/* 等待硬件稳定 */
rt_thread_mdelay(10);
return RT_EOK;
err_assert_ahb:
rt_reset_control_assert(usb->ahb_rst);
err_disable_otg:
rt_clk_disable_unprepare(usb->otg_clk);
err_disable_ahb:
rt_clk_disable_unprepare(usb->ahb_clk);
return ret;
}
static void usb_hw_deinit(struct usb_device *usb)
{
/* 在禁用时钟之前断言复位 */
rt_reset_control_assert(usb->phy_rst);
rt_reset_control_assert(usb->ahb_rst);
/* 禁用时钟 */
rt_clk_disable_unprepare(usb->otg_clk);
rt_clk_disable_unprepare(usb->ahb_clk);
}
static rt_err_t usb_probe(struct rt_platform_device *pdev)
{
rt_err_t ret;
struct rt_device *dev = &pdev->parent;
struct usb_device *usb;
/* 分配设备结构 */
usb = rt_calloc(1, sizeof(*usb));
if (!usb)
return -RT_ENOMEM;
/* 映射 MMIO 区域 */
usb->base = rt_dm_dev_iomap(dev, 0);
if (!usb->base) {
ret = -RT_ERROR;
goto err_free;
}
/* 获取 IRQ */
usb->irq = rt_dm_dev_get_irq(dev, 0);
/* 获取时钟 */
usb->ahb_clk = rt_clk_get_by_name(dev, "ahb");
if (!usb->ahb_clk) {
LOG_E("获取 AHB 时钟失败");
ret = -RT_ERROR;
goto err_unmap;
}
usb->otg_clk = rt_clk_get_by_name(dev, "otg");
if (!usb->otg_clk) {
LOG_E("获取 OTG 时钟失败");
ret = -RT_ERROR;
goto err_put_ahb_clk;
}
/* 获取复位 */
usb->ahb_rst = rt_reset_control_get_by_name(dev, "ahb");
if (!usb->ahb_rst) {
LOG_W("没有 AHB 复位线");
/* 不致命 - 某些平台可能没有 */
}
usb->phy_rst = rt_reset_control_get_by_name(dev, "phy");
if (!usb->phy_rst) {
LOG_W("没有 PHY 复位线");
/* 不致命 */
}
/* 初始化硬件 */
ret = usb_hw_init(usb);
if (ret != RT_EOK) {
goto err_put_resets;
}
pdev->priv = usb;
LOG_I("USB 设备已初始化");
return RT_EOK;
err_put_resets:
if (usb->phy_rst)
rt_reset_control_put(usb->phy_rst);
if (usb->ahb_rst)
rt_reset_control_put(usb->ahb_rst);
rt_clk_put(usb->otg_clk);
err_put_ahb_clk:
rt_clk_put(usb->ahb_clk);
err_unmap:
rt_iounmap(usb->base);
err_free:
rt_free(usb);
return ret;
}
struct rt_reset_control_ops {
/* 解析设备树参数 */
rt_err_t (*ofw_parse)(struct rt_reset_control *rstc,
struct rt_ofw_cell_args *args);
/* 复位操作 */
rt_err_t (*reset)(struct rt_reset_control *rstc);
rt_err_t (*assert)(struct rt_reset_control *rstc);
rt_err_t (*deassert)(struct rt_reset_control *rstc);
int (*status)(struct rt_reset_control *rstc);
};
#include <rtthread.h>
#include <drivers/platform.h>
#include <drivers/reset.h>
#define RESET_ASSERT 0x0
#define RESET_DEASSERT 0x4
#define RESET_STATUS 0x8
struct simple_reset {
struct rt_reset_controller rstcer;
void *base;
rt_uint32_t nr_resets;
};
static rt_err_t simple_reset_ofw_parse(struct rt_reset_control *rstc,
struct rt_ofw_cell_args *args)
{
/* args->args[0] 包含复位索引 */
if (args->args_count != 1) {
return -RT_EINVAL;
}
rstc->id = args->args[0];
return RT_EOK;
}
static rt_err_t simple_reset_assert(struct rt_reset_control *rstc)
{
struct simple_reset *sr = rstc->rstcer->priv;
rt_uint32_t mask = RT_BIT(rstc->id);
/* 设置位以断言复位 */
writel(readl(sr->base + RESET_ASSERT) | mask,
sr->base + RESET_ASSERT);
return RT_EOK;
}
static rt_err_t simple_reset_deassert(struct rt_reset_control *rstc)
{
struct simple_reset *sr = rstc->rstcer->priv;
rt_uint32_t mask = RT_BIT(rstc->id);
/* 设置位以解除断言复位 */
writel(readl(sr->base + RESET_DEASSERT) | mask,
sr->base + RESET_DEASSERT);
return RT_EOK;
}
static int simple_reset_status(struct rt_reset_control *rstc)
{
struct simple_reset *sr = rstc->rstcer->priv;
rt_uint32_t status = readl(sr->base + RESET_STATUS);
/* 如果处于复位状态返回 1,否则返回 0 */
return !!(status & RT_BIT(rstc->id));
}
static const struct rt_reset_control_ops simple_reset_ops = {
.ofw_parse = simple_reset_ofw_parse,
.assert = simple_reset_assert,
.deassert = simple_reset_deassert,
.status = simple_reset_status,
};
static rt_err_t simple_reset_probe(struct rt_platform_device *pdev)
{
rt_err_t ret;
rt_uint32_t nr_resets;
struct rt_device *dev = &pdev->parent;
struct simple_reset *sr;
/* 分配驱动结构 */
sr = rt_calloc(1, sizeof(*sr));
if (!sr)
return -RT_ENOMEM;
/* 映射复位控制器寄存器 */
sr->base = rt_dm_dev_iomap(dev, 0);
if (!sr->base) {
ret = -RT_ERROR;
goto err_free;
}
/* 获取复位线数量 */
if (rt_dm_dev_prop_read_u32(dev, "reset-count", &nr_resets)) {
nr_resets = 32; /* 默认值 */
}
sr->nr_resets = nr_resets;
/* 初始化复位控制器 */
sr->rstcer.ops = &simple_reset_ops;
sr->rstcer.ofw_node = dev->ofw_node;
sr->rstcer.priv = sr;
/* 向框架注册 */
ret = rt_reset_controller_register(&sr->rstcer);
if (ret != RT_EOK) {
LOG_E("注册复位控制器失败: %d", ret);
goto err_unmap;
}
pdev->priv = sr;
LOG_I("简单复位控制器已注册: %u 线", nr_resets);
return RT_EOK;
err_unmap:
rt_iounmap(sr->base);
err_free:
rt_free(sr);
return ret;
}
static const struct rt_ofw_node_id simple_reset_ofw_ids[] = {
{ .compatible = "simple-reset" },
{ /* sentinel */ }
};
static struct rt_platform_driver simple_reset_driver = {
.name = "simple-reset",
.ids = simple_reset_ofw_ids,
.probe = simple_reset_probe,
};
static int simple_reset_drv_register(void)
{
rt_platform_driver_register(&simple_reset_driver);
return 0;
}
INIT_SUBSYS_EXPORT(simple_reset_drv_register);
/* 正确的初始化顺序 */
rt_clk_prepare_enable(clk); /* 1. 启用时钟 */
rt_reset_control_deassert(rst); /* 2. 从复位中取出 */
rt_thread_mdelay(10); /* 3. 等待稳定 */
/* 初始化硬件寄存器 */
/* 正确的清理顺序(初始化的相反顺序)*/
/* 禁用硬件 */
rt_reset_control_assert(rst); /* 1. 置于复位状态 */
rt_clk_disable_unprepare(clk); /* 2. 禁用时钟 */
/* 发生错误时复位设备 */
if (device_error_detected()) {
rt_reset_control_reset(rst); /* 脉冲复位 */
rt_thread_mdelay(10);
reinitialize_device();
}
找不到复位
resets 和 reset-names 属性存在复位后设备不工作
复位期间系统挂起
components/drivers/reset/components/drivers/include/drivers/reset.h