电子说
模块介绍
N32L40XCL 内置独立看门狗(IWDG)和窗口看门狗(WWDG)定时器,解决软件错误导致的问题。看门狗定时器使用非常灵活,提高了系统的安全性和定时控制的准确性。
独立看门狗(IWDG)由运行在 40KHz 的低速内部时钟(LSI 时钟)驱动,在死循环事件或 MCU 卡死发生时,它仍然可以运行。这可以提供更高的安全级别、定时精度和看门狗的灵活性。它可以通过重置来解决由于软件故障引起的系统故障。IWDG 最适合需要看门狗在主应用程序之外作为完全独立进程运行但时序精度限制较低的应用程序。
窗口看门狗(WWDG)的时钟是由 APB1 时钟频率除以 4096 得到的,通过时间窗口的配置来检测程序运行是否异常。因此,WWDG 适用于精确定时,常用于监控因外部干扰或无法预见的逻辑条件导致应用程序偏离其正常操作顺序的软件故障。当 WWDG 递减计数器在达到窗口寄存器值之前或 WWDG_CTRL.T6 位变为 0 之后刷新时,系统复位发生。
官方WDT驱动实现的是独立看门狗(IWDG)。
开发软件
开发环境:
RT-Thread Studio 2.2.6
RT-Thread版本:4.0.2
下载工具:pyocd
步骤说明
新建工程
打开RT-Thread settings,使能Watchdog Timer,如下图所示。
添加保存后,进行编译,若无问题,则进行下一步。
编写测试程序
编写测试程序如下:
#include
#include
#include
/* defined the LED3 pin: PB5 /
#define LED3_PIN GET_PIN(B, 5)
#define WDT_DEVICE_NAME "wdt" / 看门狗设备名称 /
static rt_device_t wdg_dev; / 看门狗设备句柄 /
static void idle_hook(void)
{
/ 在空闲线程的回调函数里喂狗 /
rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
//rt_kprintf("feed the dog!n ");
}
int main(void)
{
/ set LED3 pin mode to output /
rt_pin_mode(LED3_PIN, PIN_MODE_OUTPUT);
rt_err_t ret = RT_EOK;
rt_uint32_t timeout = 3000; / 溢出时间,单位:毫秒 /
char device_name[RT_NAME_MAX];
rt_strncpy(device_name, WDT_DEVICE_NAME, RT_NAME_MAX);
/ 根据设备名称查找看门狗设备,获取设备句柄 /
wdg_dev = rt_device_find(device_name);
if (!wdg_dev)
{
rt_kprintf("find %s failed!n", device_name);
return RT_ERROR;
}
/ 设置看门狗溢出时间 /
ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);
if (ret != RT_EOK)
{
rt_kprintf("set %s timeout failed!n", device_name);
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", device_name);
return -RT_ERROR;
}
/ 根据设备名称查找看门狗设备,获取设备句柄 /
wdg_dev = rt_device_find(device_name);
if (!wdg_dev)
{
rt_kprintf("find %s failed!n", device_name);
return RT_ERROR;
}
/ 设置空闲线程回调函数 */
rt_thread_idle_sethook(idle_hook);
while (1)
{
rt_pin_write(LED3_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED3_PIN, PIN_LOW);
rt_thread_mdelay(500);
}
}
代码验证
程序很简单,初始化看门狗后,在空闲线程回调函数中不断喂狗即可。在正式使用看门狗时,取消回调函数中的打印。
下载程序后运行。
如果终端打印提示“warning: tidle0 stack is close to end of stack address.”,请在rtconfig.h文件中搜索IDLE_THREAD_STACK_SIZE,并扩大该栈空间。默认值是256,可以扩大到512。
程序中使用RT_DEVICE_CTRL_WDT_SET_TIM命令设置超时时间,需要注意对于N32L40XCL开发板的驱动程序而言,这个超时时间的单位是毫秒,而有些RT-Thread的驱动程序这个超时时间的单位是秒。
此外,这个超时时间不能设置过长,因为过长会超过N32L40XCL寄存器的范围。对于默认配置,这个超时时间不能超过376ms。否则程序会打印如下错误信息:
[W/DBG] wdg set timeout parameter too large, please less than 3276 ms
set wdt timeout failed!
具体的工作原理可以参考下面这段drv_wdt.c的代码:
case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
{
RT_ASSERT(*(uint16_t *)args != 0);
reload_value = *(uint16_t *)args;
if(reload_value > 0xFFF * 32 *1000 / LsiFreq)
{
LOG_W("wdg set timeout parameter too large, please less than %d msn", 0xFFF * 32 *1000 / LsiFreq);
return -RT_EINVAL;
}
/* Enable write access to IWDG_PR and IWDG_RLR registers */
IWDG_WriteConfig(IWDG_WRITE_ENABLE);
/* IWDG counter clock: LSI/32 */
IWDG_SetPrescalerDiv(IWDG_PRESCALER_DIV32);
reload_value = ((uint32_t)reload_value * LsiFreq / 1000) / 32;
IWDG_CntReload(reload_value);
IWDG_WriteConfig(IWDG_WRITE_DISABLE);
}
如果注释掉上面idle_hook中的喂狗语句,则可以看到程序每3秒重启一次。
章节总结
通过测试,可以验证N32L40XCL芯片的WDT驱动程序可以正常运行。
全部0条评论
快来发表一下你的评论吧 !