STM32低功耗和FreeRTOS低功耗模式tickless

STM32的低功耗模式有3种

  1. 睡眠模式:CM3内核停止,外设仍然运行。
  2. 停止模式:所有时钟都停止,SRAM 和寄存器内容保留。最低2uA左右的电流,一般不用。
  3. 待机模式:1.8V内核电源关闭,只有备份的寄存器和待机电路各维持供电。最低2uA左右的电流,一般不用。
模式说明进入语句唤醒方式

对1.8V区域时钟影响

对VDD区域时钟影响

调压器
睡眠内核及其外设停止工作,系统时钟(SysTick)等仍在工作_WFI()任一中断

内核时钟关,对其他时钟无影响

_WFE()唤醒事件
停止所有时钟都停止PWR_EnterSTOPMode()任一外部中断关闭所有1.8V区域的时钟HSI和HSE时钟关闭开启或处于低功耗模式
待机1.8V电源关闭PWR_EnterSTANDBMode()WKUP引脚的上升沿、RTC闹钟事件、复位按键、IWDG复位

WFI和WFE区别:

1. WFI需要中断才能唤醒,WFE是不经过中断的。

2. WFE还会受控于一个1BIT Event Register,此寄存器软件不可访问。此功能时为多核而准备的。

    WFE在 Event Register 为0,或为1时,其功能是不一样的。WFE的E就是指这个事件寄存器。

           进一步描述:假设两个核,分别为core1和core2,

           A、core1可以执行SEV指令更改Event Register,同时它可以

                通过TXEV硬连接到core2的RXEV更改core2的Event Register。

          B、core1在执行WFE时,如果发现Event Register=1,它是不会进低功耗的,这里就是区别。

                基于以上描述WFE是多核低功耗用的,举个例子:当core1和core2抢同一个资源A时,

                core1占据A,那core2就WFE进低功耗,等待core1的SEV发过来。

       3. WFE因为可以等待事件,因此在某些不能WFI的场合可以采用WFE。比如唤醒后,

           系统需要做一些恢复操作才能响应中断,那采用WFE先唤醒系统,完成芯片所需的恢复操作。

FREERTOS中的低功耗:tickless模式

开启自带的低功耗模式(睡眠模式):将宏定义 configUSE_TICKLESS_IDLE 配置为 1

系统自动调用低功耗模式满足以下2个条件:

  1. 当前只有空闲任务正在运行,所有其他的任务处在挂起状态或者阻塞状态。

  2. 当系统运行于低功耗模式 的时钟节拍数大于宏定义 configEXPECTED_IDLE_TIME_BEFORE_SLEEP (系统默认是2个系统时钟节拍,用户定义必须大于2)。

函数 portSUPPRESS_TICKS_AND_SLEEP 是实现tickless的关键,此函数被空闲任务调用,在portmacro.h中。

在自带的tickless模式基础上实现停机模式,步骤如下:

在FreeRTOSConfig.h定义如下两个函数:

#define configPRE_SLEEP_PROCESSING(x)    OS_PreSleepProcessing(x)

#define configPOST_SLEEP_PROCESSING(x)    OS_PostSleepProcessing(x)

在port.c里面的函数vPortSuppressTicksAndSleep调用了上面两个函数。

void OS_PreSleepProcessing(uint32_t vParameter)
{
    (void)vParameter;

    /*用户可以考虑在此处加入关闭外设时钟来进一步降低功耗*/

    vParameter = 0;
    PWR_EnterSTOPMode(PWR_Regulator_LowPower,PWR_STOPEntry_WFE);
}

void OS_PostSleepProcessing(uint32_t vParameter)
{
    /*当上面关闭了外设,在这里恢复*/
    
    /*恢复外部时钟配置*/
    RCC_HSEConfig(RCC_HSE_ON);
    while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET){}

    RCC_PLLCmd(ENABLE);
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET){}
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        
    while (RCC_GetSYSCLKSource() != 0x08){}

}

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值