×

STM32窗口看门狗(WWDG)开源

消耗积分:5 | 格式:zip | 大小:12.74 MB | 2022-11-14

h1654155273.0656

分享资料个

描述

STM32F401xD/E 有两个看门狗定时器——独立看门狗 (IWDG) 和窗口看门狗 (WWDG)。在这个项目中,我们将看到如何激活并定期抚摸狗,我的意思是刷新看门狗。此外,如果您不在窗口内抚摸您的看门狗,例如太晚或太早抚摸(刷新),我们也会看到会发生什么。

假定读者了解 STM32CubeMX、Keil MDK、GPIO、计数器的一些知识。

理论

顾名思义,看门狗正在监视 MCU 上运行的应用程序。这是一个监控功能。如果程序执行的正常顺序出现任何异常-软件故障,看门狗会检测到它。然后它会启动 MCU 复位,这将有助于重新启动软件。

从功能的角度来看,IWGD 和 WWDG 之间有两个主要区别。

  • IWDG 不提供刷新窗口。[这意味着,IWDG 不在乎,只要在递减计数器之前刷新它(WWDG_CR[6:0],翻转]
  • IWDG 没有像 WWDG 那样提供中断服务程序 (ISR)。[这意味着,就在启动重​​置之前,会生成一个中断,您可以在其中编写例程以安全退出。]

与 IWDG 不同,WWDG 由 APB1 外设时钟提供时钟。下图显示了 STM32CubeMX 的快照形式。

pYYBAGNxJheAd3IjAABJUnczUSI010.png
 

在这个项目中,我们将配置和测试这些案例。

  • 情况 1:激活 WWDG,我们不会刷新 WWDG 并通过倒计时计数器 WWDG_CR[6:0] 来检查是否触发了复位。我们将使用 Digilent-Analog Discovery (Legacy) 仪器监控复位线。
  • 案例 2:包括我们的例程以在窗口中刷新它,并看到 WWDG 没有启动重置。[此时我还没有解释这个窗口是什么。过段时间就会熟悉]
  • 案例 3:我们将过早刷新 WWDG 并检查是否触发了重置。
  • 案例 4:我们将启用 EWI 中断并编写一个程序来切换那里的板载绿色 LED。我们将在示波器上观察到 ISR 在启动 MCU 复位之前执行。这是 WWDG 中的一项高级功能,在 IWDG 中不可用。

启动项目..

1. 通过板选择器在 STM32CubeMX 中创建一个项目。有关详细信息,请参阅附件 - “创建 STM32CubeMX 项目”。

2. 在左侧窗格中,展开 - System Core 并选择 - WWDG。将出现一个显示 WWDG 配置的窗口。那里点击激活。这将使用下图中第 3 部分中显示的默认配置激活 WWDG。

poYBAGNxJh2AGoiMAAHNqqQwXGA131.png
 

让我们了解这些 WWDG 时钟参数。

pYYBAGNxJiCAJmFMAABexVZadKI023.png
 
poYBAGNxJiKAfqEWAACHTJvYDxY647.png
 

WWDG 计数器时钟预分频器:时钟的结果值等于(PCLK1/4096)/预分频器

  • PCKL1为 APB1 时钟(STM32F401RE 为 42MHz)
  • 4096为内分频器

[预分频器只是一个时钟分频器。预分频器越高,计数器的时钟频率就越低。因此计数需要更长的时间。]

让我们选择预分频器为 8: (PCLK1/4096)/ 8

导致递减计数器的 WWDG 时钟为 (42MHz/4096)/8 = 1281.738 Hz。因此时钟周期(1 个时钟周期)约为。780us

tClkWwdg = 780us

窗口:WWDG 中的这个术语是指允许刷新看门狗的时间范围。超出该区域被解释为软件故障,并且 MCU 复位由 WWDG 启动。现在让我们配置这个窗口。请在下面找到图片。

poYBAGNxJiSAONr3AAAvX2IqWR8858.png
STM32F401RE参考手册中的WWDG时序图
 

突出显示的 3 个参数定义了窗口。

T[6:0] 是递减计数器的 WWDG_CR[6:0] 寄存器。最大值为 127。一旦看门狗被激活 WWDG_CR[7] 被设置,倒计时以 tClkWWDG 的速率开始。在这种情况下,它是 780us。

W[6:0] 是 WWDG_CFR[6:0] 寄存器,用于在运行时与递减计数器进行比较的窗口值。

0x3F 是向下计数器计数的最低限制。一旦计数器达到该值,就会触发复位。

当递减计数器值大于 W[6:0] 且小于 0x3F 时,服务(刷新/更新)WWDG 很重要。未能在此窗口中刷新被 WWDG 解释为软件故障并启动复位。

让我们为看门狗窗口选择一些值。

预分频器 = 8;W = 94; T = 127。

pYYBAGNxJieAOYqtAABQ6NhAIKA063.png
 

现在让我们计算时间。

递减计数器从 127 递减到 63 所用时间为 tWWDG = tClkWWDG * (127 - 63) = 49.92ms

从递减计数器 127 开始直到达到 94 都不允许刷新,即 tNoRefr = tClkWWDG * (127-94) = 25.74ms

在 tNoRefr 和 tWWDG 之前允许刷新。

让我们回到 CubeMX,切换到 Project Manager 视角并选择 Keil MDK,保存项目并点击 - 'Generate code'。

请注意,看门狗中断(Early Wakeup Interrupt-EWI)保持禁用状态。我们将在稍后部分讨论它。

poYBAGNxJiqAUjdxAADko0JneZM911.png
STM32CubeMX项目经理视角
 
pYYBAGNxJiyAVrcwAAAvF3LV_f4722.png
 

选择 Open project 并打开 Keil MDK IDE。如下图所示,打开main.c文件。

pYYBAGNxJjGAFAmEAAH3kcbvyz0416.png
Keil MDK-main.c
 

构建项目,看看没有错误。

右键单击看门狗初始化函数并选择转到定义。

static void MX_WWDG_Init(void);

请注意,参数与我们在 CubeMX 中指定的一样。

poYBAGNxJjOASlfUAAB_tuQzCk8580.png
 

也可以随意查看源文件stm32f4xx_it.c,用于 EXTI(外部中断/事件控制器)例程。目前我们还没有配置任何中断。在后面的部分中,我们将更深入地了解它。

poYBAGNxJjWAS2E2AAH7FI6gZFA955.png
 

部署和测试:

无需浪费太多时间,只需构建项目并将其部署到我们的 ST32F401RE Nucleo 板即可。

情况1:

由于我们尚未为 WWDG 提供服务,因此在递减计数器达到 0x3F 后,将触发 MCU 复位。我们将超级有用的 Digilent Analog Discovery 的示波器通道 1 连接到复位线并对其进行监控。

我们的预期是,WWDG 每大约 50 毫秒触发一次复位。

CN4- Pin 5 is NRST

请参阅下面的两张图片以供参考。

pYYBAGNxJjeAbYCxAAA1ovjMUFI308.png
来自 Schematics 的快照
 
pYYBAGNxJjqALhNdAAGJJKr-mxY034.png
 

打开 Digilent 波形。我已经为通道 1 配置了一些测量选项 - x 光标,这将有助于我们查看复位发生的频率。

poYBAGNxJjyAJJyOAAHXnXcyfEI559.png
 

构建项目并点击调试按钮。

让我们从 RCC 外设监控 CRC 寄存器。窗口看门狗复位标志 (WWDGRRSTF) 和删除复位标志 (RMVF) 在 CRC 寄存器中很重要。详情请阅读 STM32 MCU 参考手册。为了方便起见,我刚刚提供了这两个 RCC_CRC 寄存器的图像。

pYYBAGNxJj-AEESUAAFGwN4hEsU548.png
 

 

poYBAGNxJkKAenljAAEBTXTIpmA919.png
 

回到凯尔..

pYYBAGNxJkSAZVejAAF6m6yyGPc927.png
 
poYBAGNxJkaAUZYBAADioIQC2dY569.png
 

代码仍然停止。您会注意到我们设置了一些重置标志。在继续进行干净设置之前清除所有重置。

Click RMVF bit

Hit运行 (F5) 启动程序

poYBAGNxJkiACMRRAACHnHcHza0281.png
 

您将立即看到 WWDGRSTF 设置。

pYYBAGNxJkuAQnhOAABJLPrCujU403.png
 

我们可以看到,正如预期的那样,每 ca 都会切换一次重置线。52 毫秒。

poYBAGNxJk6ATBTgAAIFr6FunU8461.png
 

案例二:

让我们抚摸我们的狗,让它不叫。好的..我的意思是让我们在窗口中刷新我们的 WWDG 看看会发生什么..

转到 main.c。如果您仍处于调试模式,请退出调试透视图。在无限的while循环中包含这段代码。

HAL_Delay(30);
HAL_WWDG_Refresh(&hwwdg);

HAL_Delay(30) 将 MCU 暂停 30 毫秒。我们等待 30ms 并刷新 WWDG。现在可能很清楚,我们无法在 tNoRefr(25.74 毫秒)的持续时间内刷新看门狗。

pYYBAGNxJlGASQBqAAGwNp1d95w914.png
 

结果..应该有由WWDG触发的任何重置。让我们构建项目并检查它..

按照与之前相同的步骤构建项目并在调试模式下打开它。设置 RMVF 位以清除复位标志并运行程序。您应该看到 WWDGRSTF 标志始终是清除的。

poYBAGNxJlOAD9YMAAC-sRRBsJ0526.png
 
pYYBAGNxJlWARPl2AAGhkLBBfvQ050.png
 

没有重置。我们的狗很高兴:)

案例3:

我们将过早刷新 WWDG 并检查是否触发了重置。

将延迟值从 30ms 修改为小于 tNoRefr (25.74ms) 的任何值。

我选择 15 毫秒。

结果:

pYYBAGNxJliASPSWAAIedGntqSM669.png
 

由于我们很快就会刷新 WWDG,因此每 18 毫秒触发一次重置。

案例4:

最有趣的部分。我们不应该忘记 WWDG 有一个漂亮的特性——它会在触发休息之前产生一个中断。这将帮助我们以安全状态退出,比如说拍摄系统快照并存储到 EEPROM 中。

让我们通过启用 EWI 中断并编写一个例程来切换板载绿色 LED 来检查此功能。我们将在示波器上观察到 ISR 在启动 MCU 复位之前执行。这是 WWDG 中的一项高级功能,在 IWDG 中不可用。

可以使用 CubeMX 以图形方式启用 EWI,如下所示。

poYBAGNxJlqAGRvWAACN9WmKzKQ575.png
 

这还不够。我们需要在 NVIC 设置中启用看门狗中断。如果不启用全局看门狗中断,仅启用 EWI 不起作用,因为中断将无法通过中断控制器-NVIC。我强烈建议您阅读参考手册中的 EXTI 部分以了解更多详细信息,因为这超出了本文的范围。

poYBAGNxJlyAKi9aAADZX38gOvs857.png
 

保存项目并构建。这次当您切换回 Keil 时,它应该会询问您文件是否已更新以及是否要加载它们。说,是的。

pYYBAGNxJl-ADfopAAG6o6_Onrc056.png
 

现在你应该在你的 Keil 项目中拥有最新的文件。转到文件 stm32f4xx_it.c。您将在最后看到添加了这段额外的代码(在红色框中)。它是 WWDG 中断处理程序。

poYBAGNxJmGALCAvAAGfGXuFRMM630.png
 

转到 HAL_WWDG_IRQHandler(&hwwdg); 蓝色框中指示的定义。

pYYBAGNxJmSAPRinAAIF4sG6ekA013.png
 

我们可以看到启用了早期唤醒回调并为我们创建了 __weak 函数。复制该函数并将其粘贴到 main.c 并删除 __weak。这就是我们将编写例程以切换板载绿色 LED 以查看 ISR 是否在启动复位之前执行的地方。请参阅下图,指示它必须在 main.c 中复制的位置。在所有外设初始化功能完成后以及在用户代码开始和结束之间执行此操作。

pYYBAGNxJmaAXaK7AAIg0E5alpg823.png
 

让我们从函数体中删除所有内容并切换我们的板载 LED。

另外,注释掉写在 while(1) 无限循环中的代码。这次我们将让递减计数器过去,并期望 WWDG 重置 MCU。但在此之前,我们希望它服务于我们的中断。我们将通过每 20 毫秒切换一次 LED 来监控这一点。

请按照与之前相同的步骤构建项目并在调试模式下打开它。设置 RMVF 位以清除复位标志并运行程序。

结果:

请参阅显示切换板载绿色 LED 的视频-

 

 

示波器:

Ch1:NRST

通道 2:LED

poYBAGNxJmmAMikBAAIlUAYFcik989.png
 
poYBAGNxJmyAaYfpAAHUmvjpYdQ638.png
 

我们可以看到中断是在大约生成的。复位前 780us,正好是之前的一个 WWDG 时钟周期。但是每 52ms 触发一次复位,即只有在递减计数器倒数到 0x3F(十进制:63)之后。

注意:如果您需要有关 STM32F4 的 HAL 库以及如何使用它们的完整信息,请参阅手册 UM1725。STM32F4 HAL 和底层驱动说明

结论

我们已经在各种场景下对STM32F401RE的Window看门狗进行了配置和测试。在案例 4 中,我们看到了一些非常有趣的东西。板载 LED 不是每 20 毫秒切换一次。复位迫使 LED 关闭,因为 WWDG 只给 MCU 1 个时钟周期来做任何重要的事情。由于每 52ms 发生一次复位,我们可能会将 LED 切换误解为我们的 ISR 例程。事实上,HAL_GPIO_TogglePin()甚至没有完全执行。它被重置破坏了。尝试注释掉HAL_Delay(),尝试替换HAL_GPIO_TogglePin()to HAL_GPO_WritePin(),看看会发生什么。

同样在启用 EWI 的情况下,尝试过早刷新 WWDG 并查看是否执行了 ISR。如果您有任何问题,请告诉我。我很高兴听到您的反馈。感谢您的阅读!


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

评论(0)
发评论

下载排行榜

全部0条评论

快来发表一下你的评论吧 !

'+ '

'+ '

'+ ''+ '
'+ ''+ ''+ '
'+ ''+ '' ); $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code ==5){ $(pop_this).attr('href',"/login/index.html"); return false } if(data.code == 2){ //跳转到VIP升级页面 window.location.href="//m.obk20.com/vip/index?aid=" + webid return false } //是会员 if (data.code > 0) { $('body').append(htmlSetNormalDownload); var getWidth=$("#poplayer").width(); $("#poplayer").css("margin-left","-"+getWidth/2+"px"); $('#tips').html(data.msg) $('.download_confirm').click(function(){ $('#dialog').remove(); }) } else { var down_url = $('#vipdownload').attr('data-url'); isBindAnalysisForm(pop_this, down_url, 1) } }); }); //是否开通VIP $.get('/article/vipdownload/aid/'+webid,function(data){ if(data.code == 2 || data.code ==5){ //跳转到VIP升级页面 $('#vipdownload>span').text("开通VIP 免费下载") return false }else{ // 待续费 if(data.code == 3) { vipExpiredInfo.ifVipExpired = true vipExpiredInfo.vipExpiredDate = data.data.endoftime } $('#vipdownload .icon-vip-tips').remove() $('#vipdownload>span').text("VIP免积分下载") } }); }).on("click",".download_cancel",function(){ $('#dialog').remove(); }) var setWeixinShare={};//定义默认的微信分享信息,页面如果要自定义分享,直接更改此变量即可 if(window.navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){ var d={ title:'STM32窗口看门狗(WWDG)开源',//标题 desc:$('[name=description]').attr("content"), //描述 imgUrl:'https://'+location.host+'/static/images/ele-logo.png',// 分享图标,默认是logo link:'',//链接 type:'',// 分享类型,music、video或link,不填默认为link dataUrl:'',//如果type是music或video,则要提供数据链接,默认为空 success:'', // 用户确认分享后执行的回调函数 cancel:''// 用户取消分享后执行的回调函数 } setWeixinShare=$.extend(d,setWeixinShare); $.ajax({ url:"//www.obk20.com/app/wechat/index.php?s=Home/ShareConfig/index", data:"share_url="+encodeURIComponent(location.href)+"&format=jsonp&domain=m", type:'get', dataType:'jsonp', success:function(res){ if(res.status!="successed"){ return false; } $.getScript('https://res.wx.qq.com/open/js/jweixin-1.0.0.js',function(result,status){ if(status!="success"){ return false; } var getWxCfg=res.data; wx.config({ //debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:getWxCfg.appId, // 必填,公众号的唯一标识 timestamp:getWxCfg.timestamp, // 必填,生成签名的时间戳 nonceStr:getWxCfg.nonceStr, // 必填,生成签名的随机串 signature:getWxCfg.signature,// 必填,签名,见附录1 jsApiList:['onMenuShareTimeline','onMenuShareAppMessage','onMenuShareQQ','onMenuShareWeibo','onMenuShareQZone'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 }); wx.ready(function(){ //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 wx.onMenuShareTimeline({ title: setWeixinShare.title, // 分享标题 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享给朋友”按钮点击状态及自定义分享内容接口 wx.onMenuShareAppMessage({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 type: setWeixinShare.type, // 分享类型,music、video或link,不填默认为link dataUrl: setWeixinShare.dataUrl, // 如果type是music或video,则要提供数据链接,默认为空 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ”按钮点击状态及自定义分享内容接口 wx.onMenuShareQQ({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到腾讯微博”按钮点击状态及自定义分享内容接口 wx.onMenuShareWeibo({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); //获取“分享到QQ空间”按钮点击状态及自定义分享内容接口 wx.onMenuShareQZone({ title: setWeixinShare.title, // 分享标题 desc: setWeixinShare.desc, // 分享描述 link: setWeixinShare.link, // 分享链接 imgUrl: setWeixinShare.imgUrl, // 分享图标 success: function () { setWeixinShare.success; // 用户确认分享后执行的回调函数 }, cancel: function () { setWeixinShare.cancel; // 用户取消分享后执行的回调函数 } }); }); }); } }); } function openX_ad(posterid, htmlid, width, height) { if ($(htmlid).length > 0) { var randomnumber = Math.random(); var now_url = encodeURIComponent(window.location.href); var ga = document.createElement('iframe'); ga.src = 'https://www1.elecfans.com/www/delivery/myafr.php?target=_blank&cb=' + randomnumber + '&zoneid=' + posterid+'&prefer='+now_url; ga.width = width; ga.height = height; ga.frameBorder = 0; ga.scrolling = 'no'; var s = $(htmlid).append(ga); } } openX_ad(828, '#berry-300', 300, 250);