Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
PM2.0
RT-Thread PM 功耗调优经验总结 - 功耗管理的方法
发布于 2023-12-17 12:11:20 浏览:860
订阅该版
[tocm] [电源管理与功耗调优系列 - 目录](https://club.rt-thread.org/ask/article/a875f009b6e99e64.html) ## 【郑重声明】 - 本系列文章为【个人】的功耗管理及经验总结,只代表【个人】的立场,不牵涉【具体】的项目、产品、公司,请不要【断章取义】,如有疑问与不同的见解,可与我【个人】取得联系。 - 本篇文章只是讲解自己过往的一些功耗调试经验,目的仅仅是:希望对刚接触功耗管理的同学有所启发。 ## 开门见山 - 对于低功耗管理之前写了几篇文章,估计很多人看了也看不懂,也理解不了功耗在代码层面上如何去管理,对于这一点我其实深有体会。 - 因为很多项目,功耗管理五花八门,并没有什么准则,很多项目,功耗管理者都会自己修改或者设计自己的功耗管理框架。 - 很多 RTOS,包括 Linux,都有自己的功耗管理(电源管理)的方法,这里只谈一下基于 RT-Thread 的功耗管理 - 苦口婆心的讲解,反而营造了一种【王婆卖瓜】的感觉,算是仁者见仁、智者见智吧,功耗管理确实牵涉到很多专业与非专业的知识点,部分知识点只有在实际的操作中才能深入体会 ## 电源模式 - 抛开 RT-Thread PM 管理框架,抛开 RT-Thread,裸机情况下,想一想,我们如何去开展功耗管理? - 首先要去了解 MCU 本身支持的各个电源模式,电源模式的进入与退出流程,电源模式的特点,这部分可以从 MCU 的 datasheet 中获取。 - MCU 进入睡眠需要调用 MCU 厂家提供的 API,一般 MCU 都会有个类似于 HAL 库的东西。比如 STM32,进入 Deepsleep STOP2 的函数为:`HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);`,不同的平台,这些接口是不一样的。 - MCU 电源模式的退出,一般是 中断,这个是 MCU 的硬件行为。举个例子,让当前 MCU 处于 STOP 模式,此时整个 MCU 不工作了,处于冻结状态,此时来了一个按键中断,MCU 就唤醒了,唤醒后,需要做一些【恢复】操作,然后系统就正常工作起来。 这个按键(GPIO 外部中断)就是唤醒源。 - RT-Thread 功耗管理用到的睡眠模式,一般只需要适配 空闲模式 `PM_SLEEP_MODE_IDLE` 与 深睡眠模式 `PM_SLEEP_MODE_DEEP`。 - 电源模式的划分,与实际的功耗模式有关 ![2023-12-17_110239.png](https://oss-club.rt-thread.org/uploads/20231217/6d184dbba5e5c685321dd0b15e7439c4.png) ## 睡眠管理思路 - 刚刚接触 RT-Thread 功耗管理时,多线程一直在脑中回旋,由于每个线程都是各自为政,对于功耗管理,是不是需要使用线程的 IPC 通信机制,通知每个线程,系统要睡眠了(比如灭屏了),再就是通知系统唤醒了,大家醒醒开始工作?想想就头大。 - 我也想过管理各个注册过的设备,比如注册过的每个 rt_device,管理各个线程 rt_thread,但是当我要代码层面实现时,发现困难重重。 - 比如线程本身虽然是无限循环函数,但是大部分情况下,线程之间都会有 IPC 通信或者同步的,此时 PM 管理如果想插上一脚,代码没有地方安排,【不能】设计成如下的线程操作: ```c /* 失败的功耗管理方法:线程里面直接开关外设 */ while (1) { 【开启外设】 【线程工作】 【关闭外设】 } ``` - 这样是比较失败的设计,不仅影响了线程的实时性,更导致功耗变高(我们目的是降低功耗),外设频繁的开关,会导致耗时、功耗变高,影响实时性,并且多个线程有交互,影响【功能性】。比如 多个线程都使用同一个外设,一个线程关闭了外设,导致其他的线程工作异常。 - 这就说明,在多线程下,进入睡眠不再是随时随地,需要有引用计数的概念,一个设备多次打开,第二次打开时,设备处于打开状态,就会增加引用计数。设备关闭,如果引用计数不为1,则引用计数仅仅减一操作。同理,整个系统的电源模式,可以引入引用计数的管理方法 ## 睡眠通知机制 - 系统进入睡眠是否需要通知其他的线程?RT-Thread PM 框架是支持通知机制的,比如 notify,现在的问题就是是否需要通知?发什么通知?通知后做什么操作? - 有的同学使用了通知 notify,并且还使用了 信号量等 IPC 通信机制,本意应该是想控制进程操作的每一步。先不谈通知的实现是否靠谱,是否影响线程工作,如果线程有几十个甚至上百个,能通知的过来吗? - 使用通知的初衷应该是:担心各个线程个子为政,无法控制,系统无法进入睡眠! - 这就是典型的【主动睡眠策略】,也可以认为是功耗管理的一种主动式的方法。有一个【领导级】的线程,其他线程是【员工级】的,领导确定是否进入睡眠,如果要睡眠,各个员工需要立即处理好手头工作,进入睡眠。领导说要醒来工作,员工立即恢复好,进入工作。这个【领导级】,可以认为是一个 【定时闹钟】,也可以认为是一个设计良好的线程,或者有【全局掌控力】的用户应用。 - 在功耗层面上分析,主动式的睡眠管理方法,默认系统是不睡眠的,如果想要睡眠,比如某个进程手头工作暂时做完,就请求休息一会【请求深睡眠】,【释放浅睡眠模式】,当各个线程都空闲了,【领导级】决定进入睡眠。问题点:此时还需要通知?通知给谁? - 在主动睡眠下,如果采用以上的主动式策略,通知不是必须的。也就是等大家都空闲了,就可以真正进入深睡眠。 ## 被动睡眠机制 - 被动睡眠机制的核心思想是 系统默认是睡眠的,比如深睡眠。这就导致系统上来就是【深睡眠】,什么都不干,为了干活,【员工级】线程需要请求工作,比如请求【不睡眠或者轻度睡眠】,【员工级】开始工作,工作一段时间后,想休息一下,就【释放请求的不睡眠或者轻度睡眠】。 - 那么被动睡眠机制下系统何时睡眠,何时唤醒呢?当所有【员工级】线程都没有请求【不睡眠】时,也就是所有线程都空闲了,此时没有请求,系统默认就进入睡眠。 - 这样比较一下,主动睡眠与被动睡眠,都是需要等到 所有线程空闲后,才能进入真正的睡眠。当前主动睡眠也可以不用等,强制其他线程进入睡眠或者唤醒退出睡眠,但被动睡眠只等等待 ## 睡眠模式的策略 - 多个线程请求不同的睡眠模式,需要有一个策略,比如一个线程请求了 IDLE,一个请求了 LIGHT,一个线程请求了 NONE,那么系统到底处于哪个睡眠模式呢? - RT-Thread PM 框架的电源模式决策:选择请求中功耗最高的电源模式,如下 ![2023-12-17_112158.png](https://oss-club.rt-thread.org/uploads/20231217/01119dde4354ef00c308bc08613759b6.png) ![2023-12-17_110739.png](https://oss-club.rt-thread.org/uploads/20231217/952d9e37958e14b4322543542adb67ec.png) ## 何时真正进入睡眠? - RT-Thread PM 框架,电源模式真正切换在 `idle` 线程中执行的,`idle` 线程是优先级最低的线程,所以电源模式的切换,不会影响其他线程的正常工作,其他线程可以对功耗模式切换【无感知】 ## 几个疑问的解答 > 是否需要 通过 `rt_pm_device_register` 注册 pm 相关的device? 【答】:这里【推荐】不注册,因为没有什么用 > 采用主动睡眠还是被动睡眠? 【答】:采用被动睡眠,这样功耗控制的粒度更细,更简单 > 是否需要 通知机制 notify 【答】:不建议使用,被动睡眠,各个线程只需要管理好自己的工作即可,无须通知其他线程 ```c /* 开启 PM 框架后 线程处理函数的效果 */ while (1) { /* 请求与释放 是根据实际情况按需加入,大部分情况下线程不会收到睡眠影响,也就是不需要请求与释放操作 */ rt_pm_sleep_idle_request(PM_KEY0_ID); 线程处理() rt_pm_sleep_idle_release(PM_KEY0_ID); } ``` - 由于是【被动睡眠】+【idle 线程执行电源模式切换】,所以不是所有的线程都必须 【请求不睡眠】,前期线程可以不做任何的操作,如果遇到因为【系统睡眠】影响了线程工作,再增加【请求释放不睡眠】操作 > 释放需要实现变频的功能? 【答】出于简化功耗管理,建议刚接触 功耗管理,不需要考虑变频的问题,也就是变频的操作可以注释掉或者不实现。 睡眠管理中的电源模式切换,其实MCU 也做了频率的切换,比如从正确工作到停止。这里的变频管理,需要考虑更多的因素,是否对功耗有利。 `功耗 = 功率 * 时间`, 如果降低 功率,增加执行时间,`还能节省功耗`,待熟悉了功耗管理流程,可以尝试开启变频功能。如果不熟悉功耗管理流程,直接开启变频功能,可能效果适得其反,引入系统不稳定的额外问题。 > 无法进入睡眠怎么分析? 【答】:首先需要确认是否有【不睡眠】的模式请求了没有释放, PM 框架提供了几个 模式打印功能,可以查看一下,确认哪个模式请求了没有释放,通过 模式的id 可以找到具体的驱动或者线程 > 无法唤醒怎么分析? 【答】:进入睡眠与唤醒,其实是 MCU 的硬件行为,如果无法唤醒,确认是否有深睡眠下唤醒的中断可用,有些中断,比如串口中断,在深睡眠下是没有唤醒功能的,有些 MCU,只有指定的几个唤醒引脚中断才能唤醒 MCU,这个需要查看 MCU 的 datasheet > 睡眠进入与退出切换时间过长怎么分析? 【答】:确认时间耗在了哪里,是否有有优化的空间,退出睡眠,尤其在 【深睡眠】模式下,需要恢复很多的时钟,甚至MCU 的核电压域等,如果有其他的时钟,比如 USB 等,可以不需要在唤醒时初始化,而是在 USB 需要开启时再初始化,这样只初始化必须的时钟,缩短系统唤醒时间。 由于 tick 补偿,会造成唤醒后,一些定时器超时,进入超时函数,这部分需要根据应用业务需求,调整与优化定时器 ## 小结 - 总之功耗管理会遇到各种问题,需要保持平常心态,耐心分析与解决,甚至优化或者重写 电源管理框架来完成自己的功耗管理工作 - 如果遇到不清楚如何使用 PM 电源管理框架时,可以先关闭 PM 电源管理框架,自己想一想,是否有更好的功耗管理思路,毕竟框架只是一种工具,框架很多,不能根据框架去了解功耗管理,而是反过来,先明白如何管理功耗,管理的思路,然后再借助框架实现
4
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
张世争
学以致用
文章
131
回答
805
被采纳
174
关注TA
发私信
相关文章
1
【PM2.0组件优化】优化建议集思广益交流
2
RT-Thread PM2.0 新框架已经上线,欢迎大家使用,提建议
3
PM2.0 组件调试请教
4
RT-Thread :PM不能休眠
5
STM32L4下PM组件测试无法进入STOP2
6
关于STM32L4 PM组件使用的疑问
7
PM2.0组件函数 rt_pm_notify_set 后 notify 回调影响进入休眠
8
硬件版本stm32l412kbu6,使用对应bsp搭建pm框架时,在drv_pm.c改变主频的的函数为找到,是需要自己处理吗?
9
STM32L4进入低功耗的外设初始化
10
【PM】在深睡唤醒的中断中使用会发生调度的API可能会导致未提升频率就执行其他线程
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部