Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
PM电源管理
功耗调优
基于RT-Thread功耗调优与PM管理实战经验分享 - 系统篇
发布于 2020-10-18 08:45:25 浏览:3189
订阅该版
[tocm] [RT-Thread 电源管理与功耗调优系列 - 目录](https://club.rt-thread.org/ask/article/3419.html) [基础篇 概念,基础,理解什么是功耗](https://club.rt-thread.org/ask/article/2282.html) [调试篇 开始搭环境,动手调起来](https://club.rt-thread.org/ask/article/2283.html) [驱动篇 想要调功耗,代码也要有](https://club.rt-thread.org/ask/article/2284.html) [系统篇 如何利用rtos或PM框架,配合PMS线程,管理功耗](https://club.rt-thread.org/ask/article/2285.html) [实战篇 具体问题的实战思考与解决思路](https://club.rt-thread.org/ask/article/2286.html) [日志篇 功耗日志文件输出与解析](https://club.rt-thread.org/ask/article/2288.html) [收尾篇 高调做好功耗,低调掌握知识的回顾](https://club.rt-thread.org/ask/article/2289.html) [进阶:RT-Thread精通PM功耗调优 系列](https://club.rt-thread.org/ask/article/2296.html) [上手:产品功耗管理与调优经验分享 系列](https://club.rt-thread.org/ask/article/2707.html) [应用:PM组件应用与经验分享 系列](https://club.rt-thread.org/ask/article/292.html) ## 背景 * 本篇为系统篇,偏OS层,HAL、PM框架相关 * 涉及到与功耗相关的驱动接口的调用,基于RT-Thread多任务操作系统的调试,PM框架的使用,PMS线程配合调试功耗。 * 手头上有apollo3的与stm32l4的板子,目前都已经跑起来RT-Thread PM框架,功耗也都有优化。 * 调试平台:pandora stm32l4 系列的硬件开发板,其他平台的,可以参考,主要讲解PM框架的运行与平台适配时的问题。 ## 前期准备 * 使用的IDE:keil MDK, RT-Thread ENV工具 * 设备:配置直流电源,高精度万用表(精度低些也无所谓),主要是为了看下电流的变化(功耗情况)。 * 硬件:pandora stm32l475 开发板, USB线(供电、板载ST-Link下载) * 这里的PM框架,已经优化了一版,兼容PM上一版本的情况下,丰富了接口、使用文档,增加了目前的教程文章。 * 基于pandora stm32l4,可以git clone PM 测试代码: * 测试demo 代码地址: ```c git clone https://gitee.com/zhangsz0516/rtt_pm2.git ``` * 代码拉下来,没有帮助文档,或许刚接触RT-Thread PM 电源管理框架的同学,不太会用。 * 本篇文章,主要讲解如何使用PM框架,达到功耗调优的目标。 ## 动手操作 * 代码拉下来,进入工程目录: ``` rtt_pm2\demo\bsp\stm32\stm32l475-atk-pandora ``` * 鼠标右键打开:ENV ``` scons --target=mdk5 ``` * 目的:构建好Keil MDK5的工程。 ![2020-10-18_115303.png](/uploads/20201018/c20fb8194840078ec0063e1a4cb5673f.png) * 接着打开:project.uvprojx,Kei MDK版本我用的 5.27的,若打开有问题,先解决MDK版本问题。 * 编译与下载: 点击Keil MDK【全编译】,没错误,就可以点击下载(st-link swd下载) * 硬件与软件环境已经配置好了。 ## 导入PM框架 (1)首先需要开启PM框架(demo里已经开启),这里使用 ENV menuconfig配置。配置方法,我之前有篇文章,可以参考。 [RT-Thread PM组件移植与使用-使能PM组件](https://club.rt-thread.org/ask/article/2287.html) (2)默认开启后,会增加:pm.c, drv_pm.c,drv_lptim.c 加入工程里。 * 其中pm.c 为 pm 框架实现文件(不算复杂,没使用太复杂的算法) * drv_pm.c:平台适配实现,不同的单片机MCU,理论上不同的适配。 * drv_lptim.c:平台适配实现,低功耗定时器时钟驱动,用于深睡眠时系统tick补偿,补偿的作用后面讲解。 (3)若是新平台,如apollo3,上述的 平台适配文件是不存在的。需要copy过来改或自己创建,如果感觉文件取名不好,也可以改到自己满意为止。 (4)工程运行起来了?看看串口的打印吧。别人的msh 大把的命令,我的没有?手动添加到丰富为止。 我这里配置了按键的驱动(含中断),lpuart驱动,led驱动。 (5)pm 电源模式的执行,在idle线程里实现,新PM组件要求改大idle线程的栈大小,默认256,改个2048试下。因为idle里,要干点活。 ## 加入自己的代码 (1)PM新框架,不推荐使用pm_device,不推荐变频(变频牵涉过多的业务外设,用户根据情况自行实现)。接下来,核心的api接口就几个: ``` rt_pm_module_request(PM_BOARD_ID, PM_SLEEP_MODE_IDLE); //请求不睡眠,可以工作在 NONE、IDLE模式 rt_pm_module_release(PM_BOARD_ID, PM_SLEEP_MODE_IDLE); //操作完,允许睡眠,释放请求 rt_pm_module_release_all(PM_BOARD_ID, PM_SLEEP_MODE_IDLE); //释放指定睡眠模式的所有的请求. rt_pm_module_delay_sleep(PM_BOARD_ID, 1000); //如等待外设初始化完成,延时1S再睡眠 ``` (2)我想定义更多的模式ID或模块ID呢?自己建个文件,取名:pm_cfg.h,为何取这个名字,查看pm.h件。 ![2020-10-18_121924.png](/uploads/20201018/23b3bb1b5eb902d9fc13e8e311a00831.png) 定义:PM_HAS_CUSTOM_CONFIG,然后建个 pm_cfg.h文件,然后,加入自己的电源模式id,模块id等。 (3)打开:drv_pm.c,核心的代码:sleep函数的实现。 ![2020-10-18_122124.png](/uploads/20201018/389ff2ed6733d10fa3d0e0c58cf0f177.png) ## 说明 * 感觉很简单,这样是否可以优化了整机功耗? 答:不太可能! * 注意,这是平台适配的文件,板子不同,这里要做很多的事情,不只是简单的进入MCU的各个电源模式。 * 每个case 模式下,都可以实现一些处理,如模式前的引脚处理,退出模式的引脚处理。 * 这里的原则是:不要加太多耗时的开关,耗时的开关,需要拿到外部去。如关闭LCD屏,先关闭,再允许进入睡眠。不要在睡眠函数里,执行LCD的打开与关闭。 * 外部咋实现外设的开关?自己写个事件或消息机制处理,就可以了。属于设备管理的,就不要加入pm管理。 (4)我是要做事情的,你这里随便的睡眠,让我业务怎么正常跑? * 首先,睡眠不是随便的!!是用户自己设置的。 * 如你想干活,你请求不睡眠(可以认为是一把锁)。你干完活,忘记释放,导致系统无法睡眠。 * 你只需要pm_dump,看看当前的电源模式,那些模块id在干活,然后,找到干完活合适的位置,释放掉请求的,即可。 (5) 用户想deepsleep时,不进入stop2,进入stop0,咋办? 答:改下drv_pm.c 里,进入deepsleep的适配代码即可。 (6)按键后,我想干活,不能睡,咋办? 答:按键中断里, rt_pm_module_request,注意,request与release最后成对出现。 (7)灭屏了,没重要事情了,我想进入睡眠,其他的事情干完与否,不重要,咋办? > 答:(1)rt_pm_release_all(不关心module id),把deepsleep 前的各个模式,释放掉即可。 > (2)pm新框架,无任何模式请求,默认进入深睡眠(与老框架的区别之一)。 (8)手动创建一个pm管理相关的线程,实现一些业务通信方面的工作。 ``` /* pms event emq test */ static void pms_thread(void* param) { LOG_D("pms start!\n"); while (1) { led_red_on(); rt_thread_mdelay(2000); led_red_off(); rt_thread_mdelay(2000); LOG_D("%s:tick=%d\n", __func__, rt_tick_get()); } } int pms_task_init(void) { rt_thread_t tid; tid = rt_thread_create("emq_pms", pms_thread, RT_NULL, 2048, 28, 50); rt_thread_startup(tid); return 1; } ``` (9)低功耗定时器的作用: * 用于在deepsleep下(mcu 进入stop模式,无法轻易唤醒,一般不频繁唤醒),干活,系统tick补偿, 干活好理解,进入stop模式,如STM32 STOP2模式,系统的大部分时钟全部关闭,RT-Thread 系统也不跑了,你之前的定时任务,不能工作了,因为软件定时器不工作了。 * 你若不想醒来,深睡眠时,不做事情,不配置drv_lptim即可。 * 你如想定时醒来,干完活接着睡,配置drv_lptim。若不能接着睡,pm_dump,查看问题所在。 (10)总线如i2c uart spi,进入睡眠时推出睡眠时,代码咋写? * 这里给个测试代码吧,不同的硬件,可能不一样。轻睡眠模式下,如WFI,系统会被systick唤醒,频繁,所以,不建议处理一些外设。 * 只有深睡眠模式,不频繁切换时,加入引脚处理的代码,保证待机睡眠时,电流达到超低。 ``` /* BT_UART1:PG9--TX PG10--RX */ void UART1_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = { 0 }; /* Enable GPIO TX/RX clock */ __HAL_RCC_GPIOG_CLK_ENABLE(); /* Enable USARTx clock */ __HAL_RCC_USART1_CLK_ENABLE(); /* UART TX GPIO pin configuration */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); /* UART RX GPIO pin configuration */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); } void UART1_GPIO_DeInit(void) { GPIO_InitTypeDef GPIO_InitStruct = { 0 }; __HAL_RCC_GPIOG_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); __HAL_RCC_USART1_CLK_DISABLE(); } ``` ### uart口的睡眠处理 * 进入睡眠前,调用:UART1_GPIO_DeInit, * 进入深睡眠 * 唤醒后(原地),调用:UART1_GPIO_Init ### 【睡在哪里,唤醒时,就在哪里。】 中唤唤醒,一般先去中断处理,所以按键中断唤醒,中断处理是 pm request一下,不做过多的处理。因为此时MCU,可能时钟、引脚还没有恢复正常!(牢记) (11)开机后,我的pm 咋为none模式,无法睡眠 问:新PM组件,开机后,默认设置为none模式(与上版组件的区别之二)。为什么? 答:不为什么,如果上来,没有任何的request,系统又不睡眠,那才是问题! * 我们干活时请求【不睡眠】,干完活释放。 如果都释放了,咋办?进入深睡眠? 开机就进入深睡眠,你不觉得死机了? * 开机时,默认none模式,你系统跑起来,就release掉 none,就OK了。 ``` rt_pm_module_release(PM_POWER_ID, RT_PM_DEFAULT_SLEEP_MODE); ``` 问:为何是 PM_POWER_ID? 答:因为组件里,初始化时,默认为这个ID。 问:测试代码里,没加,为什么? 答:因为要测试,否则,开机后立即睡眠,你会觉得代码有问题!! (12)延时睡眠,啥意思? ``` rt_pm_module_delay_sleep(PM_POWER_ID, 2000); ``` * 如果你不使用requesst, release,只是想过会在睡,这个不睡的时间间隔,你怎么请求呢? * 调用新PM组件:rt_pm_module_delay_sleep。 * 这是与上版组件区别之三。 OK,写了这些,已经介绍了RT-Thread PM组件的使用方法,期待大家用起来,不要做【嘴上王者】。 ## 使用PM框架的想法 我当前对RT-Thread PM 组件的认识如下: (1)PM是个管理框架,不是枷锁,可以根据实际情况选用。 (2)PM框架实现要用户适配,根据业务作出大量的尝试与修改,不能苛求框架包括一切。 (3)PM框架,不只是用于RT-Thread,其他的rtos,也可以用上去(当然,有的rtos,也有自己的PM框架)。 (4)调功耗,需要与硬件、驱动、项目管理(PM project manager)、业务等多沟通,找到一个合适的点,满足需求,降低功耗,多方考量。
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
张世争
学以致用
文章
131
回答
802
被采纳
173
关注TA
发私信
相关文章
1
STM32F103的低功耗
2
最近用rtthread系统下AD采样并低功耗,中断响应不及时
3
rt-thread低功耗休眠应用问题请教
4
关于RTT对低功耗的支持
5
RT-Thread怎么休眠实现低功耗。
6
RT-Thread V3.0支持的低功耗,OS会自行进入吗?
7
关于RTThread3.0低功耗休眠模式
8
RTT3.0的bsp包中哪些MCU自带低功耗定时器?
9
关于低功耗上次说针对L4出个BSP的,怎么迟迟不见呀
10
低功耗问题。
推荐文章
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
编译报错
msh
SFUD
keil_MDK
rt_mq_消息队列_msg_queue
ulog
C++_cpp
at_device
本月问答贡献
踩姑娘的小蘑菇
7
个答案
3
次被采纳
a1012112796
13
个答案
2
次被采纳
张世争
9
个答案
2
次被采纳
rv666
5
个答案
2
次被采纳
用户名由3_15位
11
个答案
1
次被采纳
本月文章贡献
程序员阿伟
9
篇文章
2
次点赞
hhart
3
篇文章
4
次点赞
大龄码农
1
篇文章
5
次点赞
RTT_逍遥
1
篇文章
2
次点赞
ThinkCode
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部