正点原子第52章。
基础知识
正点原子教程


fmql-dts


代码
APP代码(不需要编写驱动代码)
cpp
static int dw_wdt_drv_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct watchdog_device *wdd;
struct dw_wdt *dw_wdt; /* 描述SDWT设备 */
struct resource *mem;
struct dw_wdt_of_data *of_data = NULL;
int ret;
/* 实例化wdt对象 */
dw_wdt = devm_kzalloc(dev, sizeof(*dw_wdt), GFP_KERNEL);
if (!dw_wdt)
return -ENOMEM;
/* 获取SWDT的寄存器基地址(物理地址)
* 并将其转换为内核当中操作使用的虚拟地址
* 将其存放在dw_wdt->regs中
*/
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dw_wdt->regs = devm_ioremap_resource(dev, mem);
if (IS_ERR(dw_wdt->regs))
return PTR_ERR(dw_wdt->regs);
/* 获取输入时钟 */
dw_wdt->clk = devm_clk_get(dev, NULL);
if (IS_ERR(dw_wdt->clk))
return PTR_ERR(dw_wdt->clk);
/* 使能时钟 */
ret = clk_prepare_enable(dw_wdt->clk);
if (ret)
return ret;
/* 获取时钟频率 */
dw_wdt->rate = clk_get_rate(dw_wdt->clk);
if (dw_wdt->rate == 0) {
ret = -EINVAL;
goto out_disable_clk;
}
dw_wdt->rst = devm_reset_control_get_optional_shared(&pdev->dev, NULL);
if (IS_ERR(dw_wdt->rst)) {
ret = PTR_ERR(dw_wdt->rst);
goto out_disable_clk;
}
reset_control_deassert(dw_wdt->rst);
/* 对 struct watchdog_device 对象成员变量进行了初始化 */
wdd = &dw_wdt->wdd;
wdd->info = &dw_wdt_ident;
wdd->ops = &dw_wdt_ops;
wdd->min_timeout = 1;
wdd->max_hw_heartbeat_ms =
dw_wdt_top_in_seconds(dw_wdt, DW_WDT_MAX_TOP) * 1000;
wdd->parent = dev;
/* 调用函数:
* 初始化WDT
*/
watchdog_set_drvdata(wdd, dw_wdt);
watchdog_set_nowayout(wdd, nowayout); // 设置WDT status为WDOG_NO_WAY_OUT
watchdog_init_timeout(wdd, 0, dev); // 超时时间值
/*
* If the watchdog is already running, use its already configured
* timeout. Otherwise use the default or the value provided through
* devicetree.
*/
if (dw_wdt_is_enabled(dw_wdt)) {
wdd->timeout = dw_wdt_get_top(dw_wdt);
set_bit(WDOG_HW_RUNNING, &wdd->status);
} else {
wdd->timeout = DW_WDT_DEFAULT_SECONDS;
watchdog_init_timeout(wdd, 0, dev);
}
platform_set_drvdata(pdev, dw_wdt);
watchdog_set_restart_priority(wdd, 128);
/* 向看门狗核心层注册一个WDT设备 */
ret = watchdog_register_device(wdd);
if (ret)
goto out_disable_clk;
of_data = dev_to_ofdata(&pdev->dev);
if (of_data && of_data->init) {
ret = of_data->init(&pdev->dev);
if (ret)
goto out_disable_clk;
}
return 0;
out_disable_clk:
clk_disable_unprepare(dw_wdt->clk);
return ret;
}
cpp
static const struct watchdog_info dw_wdt_ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE,
.identity = "Synopsys DesignWare Watchdog",
};
/* options:
* WDIOF_KEEPALIVEPING 支持喂狗
* WDIOF_SETTIMEOUT 设置超时时间
* WDIOF_MAGICCLOSE 当应用层关闭设备时,WDT不会停止运行
*/
static const struct watchdog_ops dw_wdt_ops = {
.owner = THIS_MODULE,
.start = dw_wdt_start,
.stop = dw_wdt_stop,
.ping = dw_wdt_ping,
.set_timeout = dw_wdt_set_timeout,
.get_timeleft = dw_wdt_get_timeleft,
.restart = dw_wdt_restart,
};
运行测试

过一会就重启了(应该是WDT没喂狗)

- fmql的WDT时间要比设置的长一些,比如这里我设置的"set 10",理论上是10s,但是我大概计算了一下,需要30s+才会复位。
- 需要查看wdt使用的clk。
开启&定时:

重启:

重启时卡在这里。
发现sd卡的第二个分区未能成功搭载。(当时不知道为什么创建了三个分区:sdb1放启动文件,sdb3放ubuntu系统,sdb2空的)(所以只需要创建2个分区即可★★★)



WDT重启系统后
linux内核启动报错Kernel panic - not syncing: No working init found. 问题分析-CSDN博客
显示SD卡的某个分区未成功加载。

不可行:

之前设置好了:

尝试其他解决办法
法一:
不使用wdt,使用shell命令(如reboot)让ubuntu重启。
理论可行。
法二:修改SD卡分区,只创建2个分区。
并且修改u-boot环境变量,设置为从mmcplk0p2启动
wdt没有喂狗后成功重启ubuntu。
- 备份ubuntu系统:(要先取消sdb3的挂载)
sudo dd if=/dev/sdb3 of=/home/sdcard_backup.img bs=4M status=progress
- 拷贝到SD卡新的分区:
sudo dd if=/home/sdcard_backup.img of=/dev/sdb2 bs=4M status=progress
setenv bootargs 'console=ttyPS0,115200 noinitrd root=/dev/mmcblk0p2 rootfstype=ext4 rootwait rw'
重启后
MobaXterm(windows)无法通过SSH连接ubuntu:

尝试中。。。
其他学习内容
kill杀掉进程

https://download.csdn.net/blog/column/11438800/137284052
buildroot配置目录
【Buildroot】学习记录(2)配置注释_buildroot配置-CSDN博客
17. Buildroot根文件系统的构建 --- [野火]嵌入式Linux镜像构建与部署------基于LubanCat-i.MX6ULL开发板 文档