打印
[G32A]

G32A 看门狗的应用介绍

[复制链接]
15|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
guiyan|  楼主 | 2024-9-20 18:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 guiyan 于 2024-9-20 18:18 编辑

前言
本篇节重点介绍G32A1445芯片的看门狗的应用和测试。

一、基本功能介绍

1.1 时钟源
  • BUS_CLOCK(总线时钟)
  • LPO(低功耗振荡器)
  • SYSOSC(系统振荡器时钟)
  • LSICLK(低速内部时钟)
看门狗的时钟源一般选择128 KHz LPO 作为时钟源。
1.2 喂狗
由特定的时序才能完成,0xB480A602写入到CNT寄存器中,或者0xA602,0xB480分2次写入。
1.3 解锁
通过解锁,可以再次配置更新相关的寄存器位域。
用户必须在 16 个总线时钟内输入完整的解锁序列,并在 128 个总线时钟内完成重新配置,否则解锁窗口将被关闭,需要重新输入解锁序列。
由特定的时序才能完成, 0xD928C520写入到CNT寄存器中,或者0xC520,0xD928分2次写入。

1.4 窗口模式
如果使能窗口模式并设置窗口值,那么当计数器值在窗口值范围内没有被刷新,则会产生复位。
刷新机制如下图所示:


1.5 溢出复位
看门狗的计数器CNT如果发生溢出,可以立即引起复位,也可以启用中断服务函数,延时128 bus clocks才引起系统复位;
也可以再延长(通过配置RMU外设,514 LPO cycles )。
系统复位的延迟时间具体情况,如下表所示:

WDT_CSTS
[WDTIEN]
RMU_RSTIEN
[WDTEIN]
RMU_RSTIEN
[GIEN]
中断
延迟与复位
0
0
0
-
看门狗复位
0
0
1
-
看门狗复位
0
1
0
-
无中断, RMU 延迟看门狗复位
0
1
1
RMU IRQ
RMU 中断, RMU 延迟看门狗复位
1
0
0
WDT IRQ
看门狗中断,看门狗延迟看门狗复位
1
0
1
WDT IRQ
看门狗中断,看门狗延迟看门狗复位
1
1
0
WDT IRQ
看门狗中断,看门狗延迟+RMU 延迟看门狗复位
1
1
1
WDT IRQRMU IRQ 被挂起)
看门狗中断,看门狗延迟+RMU 延迟看门狗复位

二、实验测试
本实验是测试系统复位的延时时间。本实验的BUS_CLOCK(总线时钟)是48MHz。
总体思路:
首先配置好看门狗,开启窗口模式,使能WDT中断。
在WDT中断函数中,添加GPIO翻转的代码,观察GPIO翻转波形的时长,即可测试出看门狗计数器溢出,到系统复位的总时长。
然后利用滴答时钟中断函数,进行喂狗。判断按键KEY1按下,则失能滴答时钟中断,停止喂狗,等待触发WDT中断。

2.1 看门狗的配置
const WDT_CONFIG_T wdtConfig =
{
    .clkSrc = WDT_LPO_CLOCK,    //时钟源为128KHz LPO
    .updateEnable = true,
    .intEnable = true,                 //使能WDT中断,延长系统复位时间
    .timeoutValue = 64000U,
    .windowEnable = true,         //开启窗口模式
    .windowValue = 30000U,
    .prescalerEnable = false,     //不分频
    .opMode =
    {
        false,    /* Wait Mode */
        false,    /* Stop Mode */
        false     /* Debug Mode*/
    }
};
2.2 利用滴答时钟中断进行喂狗
void SysTick_Handler(void)
{
    if (WDT_ReadCounter(WDT_INSTANCE) > wdtConfig.windowValue) //判断计数器值在窗口内,就进行喂狗
    {
        /* Reset Watchdog counter */
        INT_SYS_DisableIRQGlobal();
        WDT_HW_Refresh(WDT);  //特定的时序,进行喂狗
        INT_SYS_EnableIRQGlobal();
        printf("Feed WDT \r\n");
    }
}
2.3 WDT中断函数
void WDT_EWDT_IRQHandler(void)
{
    if(WDT->CSTS.reg & 0x4000) //Watchdog Interrupt Flag
    {
        while(1)
        {
            GPIOD->PLLOT.reg = (1U << 16U);//翻转PD16,观察波形的输出时间,即可测试出系统复位延时时间
        }
    }
}
2.4 main函数主体逻辑
if(POWER_SYS_ReadResetSrcStatus(RMU, RMU_BY_WATCH_DOG) == true)//判断复位源是不是看门狗引起的系统复位
{
    printf("******************************** \r\n");
    printf("Reset by WDT, disable WDT now \r\n");
    WDT_DeInit(WDT_INSTANCE);

    LED_On(LED_RED);
}
else
{
    SysTick_Init();
    status = WDT_Init(WDT_INSTANCE, &wdtConfig);
    if(status == STATUS_SUCCESS)
    {
        LED_On(LED_GREEN);
    }
}

while(1)
{
    /* Put down KEY1, disable the systick */
    if (BTN_GetState(BUTTON_KEY1) == 0)
    {
        G32_SysTick->CSR.reg = 0U; //停止喂狗
    }
}
2.5 测试情况

本实验的BUS_CLOCK(总线时钟)是48MHz,128个BUS_CLOCK 就约等于2.6us。
实测符合预期。





2.6 使能RMU中断,再次延长系统复位时间

RMU中断函数
void RMU_IRQHandler(void)
{
    if(WDT->CSTS.reg & 0x4000) //Watchdog Interrupt Flag
    {
        while(1)
        {
            GPIOD->PLLOT.reg = (1U << 16U);
        }
    }
}
main函数主体逻辑代码
if(POWER_SYS_ReadResetSrcStatus(RMU, RMU_BY_WATCH_DOG) == true)
{
    printf("******************************** \r\n");
    printf("Reset by WDT, disable WDT now \r\n");
    WDT_DeInit(WDT_INSTANCE);

    LED_On(LED_RED);
}
else
{
    SysTick_Init();
    status = WDT_Init(WDT_INSTANCE, &wdtConfig);
    if(status == STATUS_SUCCESS)
    {
        LED_On(LED_GREEN);
    }
    INT_SYS_DisableIRQ(WDT_EWDT_IRQn);  //失能WDT中断
    RMU->RSTIEN.reg = 0x00A3;           //配置系统复位延长时间,514 LPO cycles(≈4ms,128kHz)
    INT_SYS_EnableIRQ(RMU_IRQn);        //使能RMU中断
}

while(1)
{
    /* Put down KEY1, disable the systick */
    if (BTN_GetState(BUTTON_KEY1) == 0)
    {
        G32_SysTick->CSR.reg = 0U;
    }
}

测试情况:
系统复位延时时间:514 LPO cycles约等于4ms。
实测符合预期。
















使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

6

主题

23

帖子

0

粉丝