Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
NXP 微控制器
看门狗
【NXP-MCXA153】看门狗驱动移植
发布于 2024-12-17 08:39:38 浏览:20
订阅该版
[tocm] ## 介绍 看门狗,顾名思义就是看家护院的狗,狗子在家里静静呆着定期检查家里有没有异常情况:一旦异常发生,狗子也就会叫起来(系统复位),平时则是周期性管它吃喝拉撒就可以了(喂狗) ## 移植流程 **以WWDT0为例** ① 在board里边添加相应的外设:配置WWDT0外设为复位状态 ② 添加相应的Kconfig开关,用以指示相应的外设开启与关闭(本质是通过宏定义或者条件编译的方式) ③ 根据[SDK_2_14_2_FRDM-MCXA153](https://mcuxpresso.nxp.com/zh/builder?hw=FRDM-MCXA153)提供的WWDT示例工程编写wwdt0驱动,需要实现3个关键的函数 - rt_hw_wdt_init - wdt_control - wdt_init ④ 添加相应的库文件依赖:fsl_wwdt.c ## 驱动文件 ### pin_mux.c 在`BOARD_InitPins`函数里进行时钟复位状态 ```c CLOCK_EnableClock(kCLOCK_GateGPIO3); ``` ### board/Kconfig 加入看门狗相关配置,这里是menuconfig菜单的选项部分 ``` config BSP_USING_WDT bool "Enable WatchDog" select RT_USING_WDT default n ``` ### drv_wdt.c wdt驱动层修改如下,这里跟Linux的内核总线驱动有点像,都是一个适配器层的代码 ```c /* * Copyright (c) 2006-2024, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2024-11-25 hywing The first version for NXP MCXA153 Board */ #include
#include "drv_wdt.h" #include "fsl_wwdt.h" #include "fsl_clock.h" #ifdef RT_USING_WDT #define WDT_CLK_FREQ CLOCK_GetWwdtClkFreq() #define WWDT WWDT0 #define APP_WDT_IRQn WWDT0_IRQn #define APP_WDT_IRQ_HANDLER WWDT0_IRQHandler struct mcx_wdt { rt_watchdog_t watchdog; WWDT_Type *wdt_base; }; static struct mcx_wdt wdt_dev; void APP_WDT_IRQ_HANDLER(void) { uint32_t wdtStatus = WWDT_GetStatusFlags(WWDT); /* The chip will reset before this happens */ if (wdtStatus & kWWDT_TimeoutFlag) { WWDT_ClearStatusFlags(WWDT, kWWDT_TimeoutFlag); } /* Handle warning interrupt */ if (wdtStatus & kWWDT_WarningFlag) { /* A watchdog feed didn't occur prior to warning timeout */ WWDT_ClearStatusFlags(WWDT, kWWDT_WarningFlag); /* User code. User can do urgent case before timeout reset. * IE. user can backup the ram data or ram log to flash. * the period is set by config.warningValue, user need to * check the period between warning interrupt and timeout. */ } SDK_ISR_EXIT_BARRIER; } static rt_err_t wdt_init(rt_watchdog_t *wdt) { wwdt_config_t config; uint32_t wdtFreq; bool timeOutResetEnable; /* Enable the WWDT time out to reset the CPU. */ timeOutResetEnable = true; /* The WDT divides the input frequency into it by 4 */ wdtFreq = WDT_CLK_FREQ / 4; WWDT_GetDefaultConfig(&config); /* * Set watchdog feed time constant to approximately 4s * Set watchdog warning time to 512 ticks after feed time constant * Set watchdog window time to 1s */ config.timeoutValue = wdtFreq * 4; config.warningValue = 512; config.windowValue = wdtFreq * 1; /* Configure WWDT to reset on timeout */ config.enableWatchdogReset = true; /* Setup watchdog clock frequency(Hz). */ config.clockFreq_Hz = WDT_CLK_FREQ; WWDT_Init(WWDT, &config); NVIC_EnableIRQ(APP_WDT_IRQn); return RT_EOK; } void delayWwdtWindow(void) { /* For the TV counter register value will decrease after feed watch dog, * we can use it to as delay. But in user scene, user need feed watch dog * in the time period after enter Window but before warning intterupt. */ while (WWDT->TV > WWDT->WINDOW) { __NOP(); } } static rt_err_t wdt_control(rt_watchdog_t *wdt, int cmd, void *arg) { switch (cmd) { case RT_DEVICE_CTRL_WDT_START: WWDT_Enable(wdt_dev.wdt_base); return RT_EOK; case RT_DEVICE_CTRL_WDT_STOP: WWDT_Disable(wdt_dev.wdt_base); return RT_EOK; case RT_DEVICE_CTRL_WDT_KEEPALIVE: delayWwdtWindow(); WWDT_Refresh(wdt_dev.wdt_base); return RT_EOK; case RT_DEVICE_CTRL_WDT_SET_TIMEOUT: if (arg != RT_NULL) { uint32_t timeout = *((uint32_t *)arg); timeout = timeout * WDT_CLK_FREQ / 4; WWDT_SetTimeoutValue(wdt_dev.wdt_base, timeout); return RT_EOK; } return -RT_ERROR; default: return -RT_ERROR; } } static struct rt_watchdog_ops wdt_ops = { wdt_init, wdt_control, }; int rt_hw_wdt_init(void) { wdt_dev.wdt_base = WWDT; wdt_dev.watchdog.ops = &wdt_ops; if (rt_hw_watchdog_register(&wdt_dev.watchdog, "wdt", RT_DEVICE_FLAG_DEACTIVATE, RT_NULL) != RT_EOK) { rt_kprintf("wdt register failed\n"); return -RT_ERROR; } return RT_EOK; } INIT_BOARD_EXPORT(rt_hw_wdt_init); #endif /* RT_USING_WDT */ ``` ### SConscript 在`Libraries/MCXA153/SConscript`文件里边加上以下代码 ``` src += ['MCXA153/drivers/fsl_wwdt.c'] ``` 在`Libraries/drivers/SConscript`文件里边加上以下代码 ``` if GetDepend('BSP_USING_WDT'): src += ['drv_wdt.c'] ``` ## 测试用例 打开使能WatchDog驱动,保存配置退出menuconfig ![使能看门狗.png](https://oss-club.rt-thread.org/uploads/20241217/b307a44e0ef6d81a51cd8d732d2817bd.png.webp) 导出MDK5工程,最后编译并烧录到开发板上去 ``` scons --target=mdk5 ``` 看门狗测试例程,这里需要模拟系统`正常运行的`情况和`出现异常`的情况,周期喂狗时间为4秒 ```c /* * Copyright (c) 2006-2024, RT-Thread Development Team * Copyright (c) 2019-2020, Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2024-11-25 hywing The WWDT test * */ #include
#include "drv_pin.h" #define LED_PIN ((3*32)+12) #define WDT_DEV "wdt" static rt_device_t wdg_dev; // 在hook函数里边定期喂狗 static void idle_hook(void) { rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL); rt_kprintf("We are feeding the dog!\r\n"); } // 初始化看门狗设备 static int init_wdt(void) { rt_err_t ret = RT_EOK; rt_uint32_t timeout = 4; wdg_dev = rt_device_find(WDT_DEV); if (!wdg_dev) { rt_kprintf("find %s failed!\n", WDT_DEV); return RT_ERROR; } rt_device_init(wdg_dev); ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout); if (ret != RT_EOK) { rt_kprintf("set %s timeout failed!\n", WDT_DEV); return RT_ERROR; } ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL); if (ret != RT_EOK) { rt_kprintf("start %s failed!\n", WDT_DEV); return -RT_ERROR; } rt_thread_idle_sethook(idle_hook); return ret; } MSH_CMD_EXPORT(init_wdt, init wdt); int main(void) { unsigned short i = 0; char *p = NULL; #if defined(__CC_ARM) rt_kprintf("using armcc, version: %d\n", __ARMCC_VERSION); #elif defined(__clang__) rt_kprintf("using armclang, version: %d\n", __ARMCC_VERSION); #elif defined(__ICCARM__) rt_kprintf("using iccarm, version: %d\n", __VER__); #elif defined(__GNUC__) rt_kprintf("using gcc, version: %d.%d\n", __GNUC__, __GNUC_MINOR__); #endif rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); /* Set GPIO as Output */ rt_kprintf("MCXA153 is restarting now\r\n"); init_wdt(); i = 0; while (1) { // 系统正常运行:LED交替亮灭 rt_pin_write(LED_PIN, PIN_HIGH); rt_thread_mdelay(500); rt_pin_write(LED_PIN, PIN_LOW); rt_thread_mdelay(500); #if 1 if(i++ > 10) // 模拟系统出现故障情况,不能正常喂狗,如果没有这段代码系统是正常运行的 { rt_kprintf("We make a crash here : i=%d!\n", i); rt_pin_write(LED_PIN, PIN_HIGH); *p = 1080; } #endif } } ``` 实验现象:可以看到LED交替亮灭十几秒后,LED灭掉系统重新复位 ![看门狗实验现象.png](https://oss-club.rt-thread.org/uploads/20241217/9f768be10013d0de6839f83873f16147.png.webp) ### 总结 - WWDT和IWDT不一样,WWDT则是在要在指定的时间窗口内喂狗,对时间的要求比较高,一般用来定期反馈系统的运行状态 - 这个WWDT例程是可以在Debug模式下跑的 - 开了看门狗偶尔会出现Flash下载异常的情况,长按ISP下载按键再Flash就可以了
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
hywing
嵌入式系统开发工程师,从事物联网、工业自动化、汽车电子开发工作
文章
8
回答
3
被采纳
0
关注TA
发私信
相关文章
1
试贴-消灭0主题
2
LPC M4的一些资料
3
LPC4088的临时分支
4
lpc1788 ad 不稳定
5
1788 LCD控制器缓冲区字节问题
6
一起来学习LPC4088吧
7
上传LPC4088的realtouch主工程
8
RealBoard 4088预定帖 [第一批板子不多,预定提前结束]
9
晒RealBoard LPC4088开箱照啦,速带小板凳前来围观
10
4088主程序需要的SD卡资源
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
freemodbus
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
踩姑娘的小蘑菇
7
个答案
2
次被采纳
a1012112796
15
个答案
1
次被采纳
Ryan_CW
5
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
本月文章贡献
YZRD
3
篇文章
6
次点赞
catcatbing
3
篇文章
6
次点赞
lizimu
2
篇文章
7
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部