12299|4

45

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

基于STM32F429的freeRTOS的低功耗学习 [复制链接]

 最近在研究freeRTOS的低功耗特性,平台是STM32F429控制器,低功耗是现在电子消费类产品的一大要求,尤其是对手机,手环这类便携类产品,大家如果对这方面感兴趣可以交流一下,废话少说,直接上菜一、先从F429的低功耗模式说起
    1、F4的三种模式:
      F4系列的控制器有三种低功耗状态,分别是休眠状态、stop状态以及standby状态
      休眠状态:内核(包括MPU)停止工作,外设(定时器、时钟等)仍然在工作,退出睡眠模式后程序从停止处继续执行,该模式类似于人在睡觉,大脑已经停止思考,但心脏脉搏仍在跳动
      stop状态:内核包括1.2V区域的所有时钟停止运作,PLLs, HSI 和HSE RC oscillators被失能,计数器和寄存器的内容不变,并且在该模式下电压和内部FLASH也可以通过软件事先的配置进入低功耗模式,当内部flash进入低功耗模式时,那么在退出该模式后也会有相应的启动延时,故对实时性要求高的系统对是否试FLASH进入低功耗模式应慎重,退出该模式后程序从停止处开始执行,
    sdandby状态:功耗最低状态,在STOP状态的基础上,电压调节器失能,除backup区域,SRAM以及寄存器的值全部丢失,故退出该状态后,系统类似于复位
   
2、F4如何进入睡眠模式和stop模式以及如何退出
      关于这个问题一张表格就可很清晰的说明,如下:

硬件部分就说这么多吧,想要详细的了解朋友就要去看数据手册了

二、freeRTOS的低功耗原理

    一句话概括就是实时改变滴答时钟的中断频率
     我们知道,操作系统都有一个滴答时钟,以一定的频率产生定时器中断,freeRTOS使用systick时钟产生滴答时钟,在操作系统的运行过程中,大部分时间可能在运行空闲任务,也就是这个时候无事可干,那么如果我们能在无事可干的时间让系统进入睡眠或者停止模式,那么系统的功耗是不是就会降下去呢,答案是肯定的,那么我们每次进入空闲任务之后就让系统休眠,直至产生滴答时钟中断被唤醒,在中断服务函数中查看是不是有需要运行的任务运行,但是我们一般的滴答时钟周期设置为10ms,也就是说不管有没有任务运行,必须10ms醒过来检测一次
   但是freeRTOS不满足于这样,他想到了一个更“省电”的方法:原理如下,当我们开启freeRTOS的低功耗模式后,系统会在空闲模式中计算出下一次某一个应用任务开始运行的时间,那么freeRTOS就设置SYSTICKD的重装值,使之恰好在这个时间点产生滴答时钟中断,然后“睡觉”,直至中断发生推出睡眠,从而进行任务的切换,这样系统就只需要在必须醒来的时候醒来进行任务切换,而不必每10ms就醒过来检测一次,那么是不是可以美美的睡上一觉呢

问题:如果需要睡眠的时间太长,超过了systick所能产生的最大时钟周期怎么办?
答:freeRTOS提出了解决方案,那就是使用普通定时器作为滴答时钟,通过改变其分频数来达到systick不能达到的的时钟周期

三、freertos低功耗具体的实现过程
      1、找到空闲函数static portTASK_FUNCTION( prvIdleTask, pvParameters ),我们截取部分代码,并用红色字体标出重要的点
  1. <font color="#ff0000">                #if ( configUSE_TICKLESS_IDLE != 0 )     //点1</font>
  2.                 {
  3.                 TickType_t xExpectedIdleTime;

  4.                         /* It is not desirable to suspend then resume the scheduler on
  5.                         each iteration of the idle task.  Therefore, a preliminary
  6.                         test of the expected idle time is performed without the
  7.                         scheduler suspended.  The result here is not necessarily
  8.                         valid. */
  9. <font color="#ff0000">                        xExpectedIdleTime = prvGetExpectedIdleTime();     //点2</font>

  10.                         if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
  11.                         {
  12.                                 vTaskSuspendAll();
  13.                                 {
  14.                                         /* Now the scheduler is suspended, the expected idle
  15.                                         time can be sampled again, and this time its value can
  16.                                         be used. */
  17.                                         configASSERT( xNextTaskUnblockTime >= xTickCount );
  18.                                         xExpectedIdleTime = prvGetExpectedIdleTime();

  19.                                         if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
  20.                                         {
  21.                                                 traceLOW_POWER_IDLE_BEGIN();
  22. <font color="#ff0000">                                                portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );      //点3</font>
  23.                                                 traceLOW_POWER_IDLE_END();
  24.                                         }
  25.                                         else
  26.                                         {
  27.                                                 mtCOVERAGE_TEST_MARKER();
  28.                                         }
  29.                                 }
  30.                                 ( void ) xTaskResumeAll();
  31.                         }
  32.                         else
  33.                         {
  34.                                 mtCOVERAGE_TEST_MARKER();
  35.                         }
  36.                 }
复制代码



点1:这是一个条件编译选择项,configUSE_TICKLESS_IDLE 为低功耗的宏开关,设为1时开启低功耗模式
点2: prvGetExpectedIdleTime()用于计算从现在到下一个任务运行的时间,也就是可以睡大觉的时间
点3:portSUPPRESS_TICKS_AND_SLEEP()通过xExpectedIdleTime参数调整systick的重装值然后开始“睡大觉”等待下一次唤醒,这个函数可以认真研读一下,比较巧妙
四:freeRTOS的省电效果
    在F429开发板上面,我验证了一下freeRTOS低功耗的省电效果,我的工程是建立两个任务,一个任务是让led1灯以500ms亮灭,另一个任务是让led2灯以1000ms亮灭
     首先是关闭低功耗特性,使程序运行,发现电流在125mA~134mA,注意,单纯的看这个数据没有意义,我们需要和低功耗模式系下进行比较,因为开发板上面还有其他的芯片,功耗也是不可忽略的
    接下来通过相关配置开启freeRTOS睡眠模式,发现电流在99mA~111mA之间,比正常工作模式减少了25mA左右
    置位SLEEPDEEP位,使freeRTOS进入stop模式,发现电流在88mA~96mA之间  比正常工作模式减少了40mA左右


从上面的3组数据看出,freeRTOS的低功耗模式效果相当明显,减少的40mA对某些电子产品来说是非常重要的,当然我们这只是粗略的进行验证,freeRTOS还提供了接口函数configPRE_SLEEP_PROCESSING( xModifiableIdleTime );和configPOST_SLEEP_PROCESSING( xExpectedIdleTime );,这两个函数的位置分别位于_wfi指令前面和后面,用户可以在进入睡眠之前通过configPRE_SLEEP_PROCESSING( xModifiableIdleTime )函数对控制器的外设进行配置,以达到最优的省电效果,退出睡眠模式后通过configPOST_SLEEP_PROCESSING(xModifiableIdleTime )对之前配置的外设进行还原


低功耗这个东西是一个很灵活的东西,在硬件层面和软件层面都可以不断地优化从而使功耗不断降低。
挂一漏万,期待各位的什么纠正








最新回复

分析的很到位,真的。  详情 回复 发表于 2016-6-28 19:00
点赞 关注(2)
 

回复
举报

750

帖子

3

TA的资源

版主

沙发
 
我们的事件驱动也是这么玩的

https://bbs.eeworld.com.cn/thread-458017-1-1.html

点评

对软件定时器一直很陌生,  详情 回复 发表于 2015-10-2 10:34
 
个人签名

要666

 
 

回复

45

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
le062 发表于 2015-10-1 22:34
我们的事件驱动也是这么玩的

https://bbs.eeworld.com.cn/thread-458017-1-1.html

对软件定时器一直很陌生,

点评

其实STM32系列的寄存器设置非常不适合新手 新手学单片机,应该拿新唐的片子玩  详情 回复 发表于 2015-10-2 11:45
 
 
 

回复

750

帖子

3

TA的资源

版主

4
 
zhoulei88 发表于 2015-10-2 10:34
对软件定时器一直很陌生,

其实STM32系列的寄存器设置非常不适合新手

新手学单片机,应该拿新唐的片子玩
 
个人签名

要666

 
 

回复

172

帖子

0

TA的资源

一粒金砂(中级)

5
 
分析的很到位,真的。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表