发新帖本帖赏金 60.00元(功能说明)我要提问
返回列表
打印
[MM32生态]

喂狗?为什么IWDG和WWDG里起这么奇怪的名字?开发过程在这里

[复制链接]
1152|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 春娇霹雳娃 于 2023-8-16 17:35 编辑

#申请原创# @21小跑堂
本实验基于MM32F0040实现IWDG和WWDG工程开发工作。

1.开发板简介
MM32F0040使用高性能的 Arm® Cortex-M0 为内核的 32 位微控制器,最高工作频率可达 72MHz,内置高速存储器,其硬件外观如下图所示:

电路图如下:


2.功能描述
2.1 IWDG

IWDG(Independent Watch Dog),为检测和解决由软件错误所引起的故障而设计。独立看门狗(IWDG)适用于需要看门狗作为一个处于主程序之外,能够完全独立工作,适用于对时间精度要求低的需求场景中。IWDG分为两种工作模式:
  • 硬件独立看门狗
  • 软件独立看门狗(默认为软件独立看门狗模式)

功能框图如下:


本质:可理解为一个12位递减计数器,当计数器的值从装载的值一直递减到零时,向系统触发复位信号,即IWDG_RESET。在计数器递减到零之前,重新装置计数器内的值,则不会产生复位信号,重置计数器值的操作即为“喂狗”。
“喂狗” 分为两种方式:
  • 直接重载初始化设定值
  • 重新设定重载值

2.2 WWDG
WWDG(Window Watchdog Timer)窗口看门狗,一种七位向下计数的timer,计数范围0x7F~0x3F(计数到0x3F将发出复位请求)。喂狗操作:通过更新计数器WWDG_CR[T]计数值,避免计数器向下计数到0x3F,实现“喂狗”操作。
有上下限的喂狗(IWDG只有下限)
  • 上限:寄存器WWDG_CFGR[W]配置值,如果计数值大于此配置值时“喂狗”,则WWDG向CPU发出复位请求(提前“喂狗”)
  • 下限:0x3F(不可修改),如果计数值计数到0x3F,则WWDG向CPU发出复位请求(没有“喂狗”)

作用:
  • 当程序运行偏离了正常的程序路径,能够及时发出复位请求
  • 程序运行偏离了正常的程序路径,提前执行了“喂狗”操作,也能及时发出复位请求

WWDG功能框图如下:

WWDG使用范围:
1.用于程序执行时间精度要求较高的场景
  • 通过APB时钟分频作为计数器时钟来源,计数时钟可精确计算
  • 具有上下限的喂狗窗口范围,避免过早喂狗使喂狗失效
2.喂狗时间范围极小
  • 当APB1时钟频率为60MHz时,最晚30毫秒内就需要喂狗一次
3.能否在低功耗状态下使用
  • WWDG的计数时钟来源于APB时钟的分频
  • 如果APB时钟关闭,WWDG则无法继续计数,因此WWDG无法在低功耗状态下使用。


3.寄存器配置
3.1 IWDG
iwdg 受访问保护的寄存器有:
  • IWDG_PR
  • IWDG_CR
  • IWDG_IGEN
  • IWDG_RLR

上述四个寄存器受访问保护。若要修改其中任一寄存器,须先对 IWDG_KR寄存器写入解锁值( 0x5555),写入后四个寄存器将同时被解除访问保护。当IWDG_KR被写入除0x5555外的值时,上述四个寄存器将同时都被锁定。如重装载操作(即“喂狗”)也会对上述四个寄存器启动访问保护功能。

预分频系数设置:


IWDG 实现思路:
  • 初始化IWDG
  • 开启LSI时钟
  • 设置IWDG预分频系数
  • 设置IWDG重载值
  • IWDG溢出配置
  • 更新IWDG重载值
  • 使能IWDG
  2. 更新重载值
  • 方法一:通过IWDG_KG直接重载初定值
  • 方法二: 重新设定重载值
  3. 中断配置
  • 使能IWDG中断
  • 失能IWDG中断(仅能在初始化阶段使用)
  • 配置IWDG中断触发值
  • 获取IWDG中断状态
  • 清除IWDG中断


3.2 WWDG
WWDG实现思路:
1.启动WWDG
  • 开启WWDG的RCC时钟
  • 初始化WWDG,包括配置时基和重装载窗口值
  • 使能WWDG,计数器开始计数
  • 使能WWDG_INT_EW中断(可选)
2.喂狗
  • 在规定时间内重装载计数值“喂狗”,提前或超时重装载计数值将产生复位请求
3.中断
  • 使能WWDG_INT_EW中断后,计数器计数到0x40产生中断
4.复位
  • WWDG产生复位请求后,CPU响应复位请求产生复位,复位后RCC_CSR[WWDGRSTF]置位
  • MCU复位后,可通过查看RCC_CSR[WWDGRSTF]标志位确定是否为窗口看门狗复位

4.软件实现
4.1 IWDG
启动检测,若为独立看门口复位,则通过UART输出本次启动为独立看门口复位,若非独立看门狗复位,则通过UART输出本次启动为正常启动或其他复位。开启时钟LSI , 配置IWDG的预分频系数为 32,重载值为 0x1F,初始化独立看门狗功能。在主函数中循环喂狗10次后停止喂狗。停止喂狗,则等待计数器溢出,独立看门狗触发复位信号。
主函数:
int main(void){
    uint32_t i = 0;

    BOARD_Init();
    printf("iwdg_basic example.\r\n");

    app_iwdg_init();

    for(i = 0; i < 10; i++){
        /* Reload the IWDG counter. */
        IWDG_DoReload(BOARD_IWDG_PORT);
        printf("Feed dog count: %u\r\n", (unsigned)(i+1) );
        app_soft_delay(200);}

    /* Waiting for MCU reset. */
    while(1){}}
配置IWDG
/* IWDG. */
#define BOARD_IWDG_PORT              IWDG
#define BOARD_IWDG_RELOAD            0x7ff //0x3ff
#define BOARD_IWDG_PRESCALER         IWDG_Prescaler_32
初始化:
void IWDG_Init(IWDG_Type * IWDGx, IWDG_Init_Type * init)
{   
    if ( NULL != init )
    {
        IWDGx->KR = IWDG_KEY_UNLOCK;   
        IWDGx->PR = init->Prescaler;
        
        IWDGx->KR = IWDG_KEY_UNLOCK;
        IWDGx->RLR = init->Relaod;

        IWDG_DoReload(IWDGx);
    }
}
使能IWDG
void IWDG_Start(IWDG_Type * IWDGx)
{
    IWDGx->KR = IWDG_KEY_ENABLE;
}
重载IWDG
void IWDG_DoReload(IWDG_Type * IWDGx)
{
    IWDGx->KR = IWDG_KEY_RELOAD;
}
开启中断
void IWDG_EnableInterrupts(IWDG_Type * IWDGx, uint32_t interrupts, bool enable)
{
    if( (true == enable ) && (IWDG_INT_ALMOST_TIMEOUT == interrupts) )
    {
        IWDGx->CR |= IWDG_CR_IRQSEL_MASK;
    }
    else
    {
        /* if IWDG_EnableInterrupts interrupt was enabled, only MCU reset can close it. */
    }
}

4.2 WWDG
1.初始化WWDG_Init():
  • 配置计数器的计数时基(分频系数)TimeBase
  • 配置“喂狗”重装载窗口值(喂狗上限)ReloadWindow
2.使能WWDG_Enable():
  • 使能WWDG,使计数器开始计数
  • 使能WWDG后,只有复位才能关闭WWDG。
3.重装载计数值WWDG_Reload():
  • 重装载计数值,实现“喂狗”操作
  • 重装载计数值后,计数器从新的计数值开始向下计数
4.中断
  • 提前唤醒中断WWDG_INT_EW,当计数器计数到0x40时发出,通知CPU即将发出复位请求。
  • 同使能WWDG一样,使能提前唤醒中断WWDG_INT_EW后只有复位才能关闭此中断。
初始化:
void WWDG_Init(WWDG_Type * WWDGx, WWDG_Init_Type * init)
{
    if (NULL != init)
    {
        WWDGx->CFGR = WWDG_CFGR_WDGTB(init->Prescaler)
                    | WWDG_CFGR_W(init->UpperLimit);
    }
}
使能WWDG
void WWDG_Start(WWDG_Type * WWDGx)
{
    WWDGx->CR |=  WWDG_CR_WDGA_MASK;
}
重载WWDG
void WWDG_Reload(WWDG_Type * WWDGx, uint32_t value)
{
    if (value > WWDG_LOWER_LIMIT)
    {
        WWDGx->CR = (WWDGx->CR & ~WWDG_CR_T_MASK) | WWDG_CR_T(value);
    }
}
中断唤醒
void WWDG_EnableInterrupts(WWDG_Type * WWDGx, uint32_t interrupts, bool enable)
{
    if ( (true == enable) && (WWDG_INT_ALMOST_TIMEOUT == interrupts) )
    {
        WWDGx->CFGR |= WWDG_CFGR_EWI_MASK;
    }
    else
    {
        /* if WWDG_INT_ALMOST_TIMEOUT interrupt is enabled, only MCU reset can close it. */
    }
}
配置中断
/* WWDG */
#define BOARD_WWDG_PORT              WWDG
#define BOARD_WWDG_IRQn              WWDG_IWDG_IRQn
#define BOARD_WWDG_IRQHandler        WWDG_IWDG_IRQHandler
#define BOARD_WWDG_UPPER_LIMIT       0x7fu
#define BOARD_WWDG_RELOAD_TIMES      100u
#define BOARD_WWDG_RELOAD_VALUE      0x7fu
#define BOARD_WWDG_PRESCALER         WWDG_Prescaler_8
开启时钟
/* WWDG. */
    RCC_EnableAPB1Periphs(RCC_APB1_PERIPH_WWDG, true);
    RCC_ResetAPB1Periphs(RCC_APB1_PERIPH_WWDG);
主函数:
int main(void)
{
    BOARD_Init();
    printf("\r\nwwdg_basic example.\r\n");

    /* Setup WWDG. */
    app_wwdg_init();

    while (1)
    {
        putchar('.');
        app_soft_delay(100);
    }
}

5.实验现象
iwdg_basic


wwdg_basic


6.附件
原理图: Mini-F0040_SCH.pdf (314.04 KB)
工程文件: mini-f0040_iwdg_basic_mdk.zip (510.03 KB) mini-f0040_wwdg_basic_mdk.zip (510.23 KB)



使用特权

评论回复

打赏榜单

21小跑堂 打赏了 60.00 元 2023-08-09
理由:恭喜通过原创审核!期待您更多的原创作品~

评论
21小跑堂 2023-8-9 15:44 回复TA
对比介绍IWDG和WWDG两种单片机外设,原理介绍清晰,实现过程较好,值得借鉴 
沙发
春娇霹雳娃|  楼主 | 2023-7-31 17:43 | 只看该作者

使用特权

评论回复
板凳
春娇霹雳娃|  楼主 | 2023-8-10 11:13 | 只看该作者

使用特权

评论回复
地板
zwll| | 2023-8-10 20:56 | 只看该作者
密码帖?

使用特权

评论回复
5
春娇霹雳娃|  楼主 | 2023-8-15 09:32 | 只看该作者

使用特权

评论回复
6
单片小菜| | 2023-8-16 16:45 | 只看该作者
密码贴是啥意思?

使用特权

评论回复
7
春娇霹雳娃|  楼主 | 2023-8-16 17:31 | 只看该作者

使用特权

评论回复
发新帖 本帖赏金 60.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:灵动系统开发工程师
简介:none........

19

主题

154

帖子

3

粉丝