看门狗 (Watchdog),又叫看门狗定时器(Watchdog Timer),是一种硬件的计时设备,当系统的主程序发生某些错误时,导致未及时清除看门狗计时器的计时值,这时看门狗计时器就会对系统发出复位信号,使系统从悬停状态恢复到正常运作状态。
本文将详细介绍如何使用Ai-WB2的看门狗定时器模块。
一:看门狗定时器(WDG)介绍
BL602芯片内有一组看门狗计数器,不可预知的软件或硬件行为有可能导致应用程序工作失常,看门狗定时器可以帮助系统从中恢复,如果当前阶段超过预定时间,但没有喂狗或关闭看门狗定时器,可依设定触发中断或系统复位。其功能框图如下:
Watchdog定时器时钟有3种选择:
· Fclk-系统主时钟
· 32K-32K时钟
· Xtal-外部晶振
每个计数器有各自的8-bit分频器,可通过APB将选择到的时钟进行1-256的分频, 具体来说设定为0时表示不分频,设定为1时进行2分频以此类推, 最大分频系数为256,计数器将以分频后的时钟作为计数周期单位,每经过一个计数周期进行上数一的动作。
看门狗定时器工作原理
Watchdoa定时器包含一个计数器和一个比较器,计数器从0开始累加计数,如果计数器被复位(喂狗),则从0再次开始向上计数,当计数器的值与比较器相等的时候, 可以产生一个比较中断信号或者系统复位信号,用户可以根据需要选择使用其中一个,看门狗计数器会在每个计数周期单位上加1,软件可以在任何时间点通过APB将看门狗计数器归零。下面以比较器的值为6,Watchdog的工作时序如下图所示:
看门狗定时器报警流程
每个计数器可设定一组比较值,当软件因为系统错误,来不及将看门狗计数器归零,导致看门狗计数器超过比较值时,便会触发看门狗报警,报警方式有两种,第一种是通过中断通知软件进行必要的处置,第二种是进入系统看门狗复位, 看门狗复位被触发时,会通知系统复位控制器,并做好系统复位前准备,当一切就绪后进入系统勘门狗复位,值得注意的是,软件可通过APB读取WSR 寄存器得知是否曾经发生看门狗系统复位。
二:看门狗定时器驱动API介绍
WDG的HOSAL层驱动API在文件 components/platform/hosal/include/hosal_wdg.h。常用API函数如下:
· int hosal_wdg_init(hosal_wdg_dev_t*wdg):初始化看门狗定时器。参数说明如下:
· wdg:看门狗定时器设备对象。其定义如下:
- typedef struct {
- uint8_t port; /**< wdg 端口 */
- hosal_wdg_config_t config; /**< wdg 配置 */
- void *priv; /**< 用户自定义数据 */
- } hosal_wdg_dev_t;
复制代码 hosal_wdg_config_t的定义如下:
- typedef struct {
- uint32_t timeout; /*!<看门狗定时器超时,以毫秒为单位*/
- } hosal_wdg_config_t;
复制代码 · 返回值:成功时返回0;否则返回非零值
· void hosal_wdg_reload(hosal_wdg_dev_t *wdg):看门狗定时器重载,即喂狗。参数说明如下:
· wdg:看门狗定时器设备对象
· 返回值:无
· int hosal_wdg_finalize(hosal_wdg_dev_t *wdg):看门狗定时器销毁,释放相关资源。参数说明如下:
· wdg:看门狗定时器设备对象
· 返回值:成功时返回0;否则返回非零值
三:看门狗定时器使用实例
示例代码如下:
- #include <stdio.h>
- #include <string.h>
- #include <FreeRTOS.h>
- #include <task.h>
- #include <stdio.h>
- #include <stdbool.h>
- #include <hosal_wdg.h>
- #include <blog.h>
- #include "bl602_dma.h"
- #define TAG "wdg_demo"
- hosal_wdg_dev_t wdg;
- void wdg_init(void){
- /* wdg 端口设置 */
- wdg.port = 0;
- /* 最大超时时间 65532/16 ms */
- wdg.config.timeout = 3000;
- /* 初始化WDG */
- hosal_wdg_init(&wdg);
- }
- void wdg_task(void){
- printf("wdg task start...\r\n");
- while(true){
- // 喂狗
- hosal_wdg_reload(&wdg);
- printf("feed wdg\r\n");
- vTaskDelay(2000);
- }
- }
- void counter_task(void){
- size_t counter = 0;
- printf("counter task start...\r\n");
- while(true){
- printf("counter task:counter = %d\r\n",counter++);
- vTaskDelay(500);
- }
- }
- void main(void) {
- wdg_init();
- xTaskCreate(counter_task, "counter_task", 1024, NULL, 15, NULL);
- xTaskCreate(wdg_task, "wdg_task", 1024, NULL, 15, NULL);
- }
复制代码 |
-
|