STM32无法进入STOP模式的解决方法

最近在使用RT-Thread的PM组件时遇到了一奇怪的现象,发现居然进不去,调用HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI)函数会直接跳过里面的__WFI函数,以下是出问题的代码段。

static void _drv_pm_enter(struct rt_pm *pm)
{
    rt_uint32_t mode;

    mode = pm->current_mode;

    switch (mode)
    {
    case PM_RUN_MODE_NORMAL:
        break;

    case PM_SLEEP_MODE_SLEEP:
        HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
        break;

    case PM_SLEEP_MODE_TIMER:
        rt_kprintf("enter stop mode,tick = %d\n",rt_tick_get());
        HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
        rt_update_system_clock();
        rt_kprintf("exit stop mode,tick = %d\n",rt_tick_get());
        break;

    case PM_SLEEP_MODE_SHUTDOWN:
        HAL_PWREx_EnterSHUTDOWNMode();
        break;

    default:
        RT_ASSERT(0);
        break;
    }
}

在进入STOP模式前希望打印一些提示信息,然而就是这行打印导致了进不去STOP模式。因为_drv_pm_enter是个回调函数,在调用这个回调函数前,pm组件调用了rt_hw_interrupt_disable关闭了中断,而这行打印已经超过RTOS的1个tick(我设置的是1000Hz),导致systick中断已经pending了但因为中断被关闭所以无法处理,而__WFI函数的前提是系统没有中断在pending,所以造成了进不去STOP模式的现象。

简单来说,以上现象可以抽象成以下代码。

__disable_irq();                                /* 关闭全局中断 */
printf("enter stop mode\r\n");                  /* 打印提示,因耗时导致systick中断pending */
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);    /* 进入STOP模式 */

根本原因在于进入STOP模式前系统有中断在pending。所以解决方法就是在HAL_PWREx_EnterSTOP2Mode函数前打个断点,查看此时系统中在pending的中断。具体的查看方法可以参考我的这篇博客:https://blog.csdn.net/qq_27575841/article/details/106973644

下图是我截取的NVIC信息,可以看到在进入STOP模式前,systick中断在pending,所以无法进入。

猜你喜欢

转载自blog.csdn.net/qq_27575841/article/details/106974379