Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
PM组件
RT-Thread
平台适配
RT-Thread PM2.0 应用 -- 平台适配篇
发布于 2021-01-27 09:43:00 浏览:3215
订阅该版
[tocm] [RT-Thread 电源管理与功耗调优系列 - 目录](https://club.rt-thread.org/ask/article/3419.html) [RT-Thread PM组件2.0更新版 -- 使用指南](https://club.rt-thread.org/ask/article/3323.html) [RT-Thread PM组件2.0更新版 -- 【年更】介绍](https://club.rt-thread.org/ask/article/3244.html) [RT-Thread PM框架使用答疑【篇一】](https://club.rt-thread.org/ask/article/3198.html) [RT-Thread PM框架使用答疑【篇二】](https://club.rt-thread.org/ask/article/3201.html) [【PM组件】RT-Thread PM2.0 应用 -- 平台适配篇](https://club.rt-thread.org/ask/article/2517.html) [【PM组件】idle线程栈过小引起的调试异常](https://club.rt-thread.org/ask/article/292.html) [【PM组件】使能RT-Thread PM组件](https://club.rt-thread.org/ask/article/2287.html) [实践:RT-Thread PM管理实战 系列](https://club.rt-thread.org/ask/article/2282.html) [进阶:RT-Thread精通PM功耗调优 系列](https://club.rt-thread.org/ask/article/2296.html) [上手:产品功耗管理与调优经验分享 系列](https://club.rt-thread.org/ask/article/2707.html) ## 开题 * PM2.0 已经合入最新的RT-Thread,以后RT-Thread 组件使用,以2.0版本为基线。 * 目前PM 组件的平台适配,主要在STM32L4系列上得到适配。 * 工程师想在各个平台上使用PM 组件进行功耗的管理。 ## PM组件介绍 ![2021-01-27_094147.png](https://oss-club.rt-thread.org/uploads/20210127/677410672fc6ce80964083f34ebfd2a3.png) * 当我们只开启PM 组件后,发现对功耗没有任何的影响! ![2021-01-27_090429.png](https://oss-club.rt-thread.org/uploads/20210127/f299469425e6811f5a59172ccd4924a0.png) * PM组件大概分为:【PM组件】、【平台适配】、【业务管理】(引脚、电源管理业务逻辑)三个部分。 * 【备注】PM组件不只能用于STM32L4系列,或低功耗L系列MCU上,可以用于RT-Thread的任何MCU平台上,只是平台适配不同而已。 ## 开启组件 ![2021-01-27_085532.png](https://oss-club.rt-thread.org/uploads/20210127/a54fc77d8dbce6f093d6055adf9e69c7.png) ``` RT-Thread Components Device Drivers [*] Using Power Management device drivers ``` ## 平台适配方法 * 新建平台适配文件(或根据现有的STM32L4系列拷贝一份): ``` drv_pm.c 【必要】 drv_lptim.c (可选) ``` * drv_pm 实现的主要函数: ``` rt_system_pm_init /* 初始化pm组件,【必要】 */ /* 主要实现的ops操作: sleep */ static const struct rt_pm_ops _ops = { sleep, /* 【必要】 */ run, /* 可选 */ pm_timer_start, /* 可选 */ pm_timer_stop, /* 可选 */ pm_timer_get_tick /* 可选 */ }; ``` * 必要函数的实现: ``` /** * This function will put apollo3 into sleep mode. * * @param pm pointer to power manage structure */ static void sleep(struct rt_pm *pm, uint8_t mode) { switch (mode) { case PM_SLEEP_MODE_NONE: break; case PM_SLEEP_MODE_IDLE: pm_bsp_enter_idle(); break; case PM_SLEEP_MODE_LIGHT: pm_bsp_enter_light(); break; case PM_SLEEP_MODE_DEEP: pm_bsp_enter_deepsleep(); break; case PM_SLEEP_MODE_STANDBY: /* Enter STANDBY mode */ break; case PM_SLEEP_MODE_SHUTDOWN: /* Enter SHUTDOWNN mode */ pm_bsp_enter_shutdown(); break; default: RT_ASSERT(0); break; } } ``` * 必要的BSP函数实现 ``` void pm_bsp_enter_deepsleep(void) { /* 引脚处理:反初始化,gpio_pins_deinit 【必要】*/ /* 外设处理:反初始化,peripherals_deinit 【可选】*/ /* 进入睡眠 【必要】 */ /* 唤醒处理:系统时钟重新初始化,system_clock_init【按需】 */ /* 外设唤醒处理:初始化,peripherals_init */ /* 唤醒后引脚处理:gpio_pins_init */ } ``` * drv_lptim.c 适配【可选】 * lptimer用于tickless的实现:MCU需要有一个可以在深睡眠情况下,可以唤醒MCU的定时器。 * lptimer用于系统深睡眠下的定时唤醒业务,时钟补偿。 ``` pm_timer_start, //pm_timer_start, pm_timer_stop, //pm_timer_stop, pm_timer_get_tick //pm_timer_get_tick ``` ### 如下为apollo3p 平台的lp_tim.c实现: ``` #include
#include
/** * This function get current count value of LPTIM * * @return the count vlaue */ rt_uint32_t apollo3_lptim_get_current_counter(void) { return am_hal_stimer_counter_get(); } /** * This function get the max value that LPTIM can count * * @return the max count */ rt_uint32_t apollo3_lptim_get_max_counter(void) { return 0xffffffff; } /** * This function start LPTIM with reload value * * @param reload The value that LPTIM count down from * * @return RT_EOK */ rt_err_t apollo3_lptim_start(rt_uint32_t reload) { am_hal_stimer_compare_delta_set(0, reload); return (RT_EOK); } /** * This function stop LPTIM */ void apollo3_lptim_stop(void) { uint32_t lptim_cout = 32768 / RT_TICK_PER_SECOND; am_hal_stimer_compare_delta_set(0, lptim_cout); return; } /** * This function get the count clock of LPTIM * * @return the count clock frequency in Hz */ rt_uint32_t apollo3_get_lptim_freq(void) { return 32768; } ``` ### 对接drv_pm.c的函数实现: ``` /** * This function caculate the PM timer counter from OS tick * * @param tick OS tick * * @return the PM counter */ static rt_tick_t apollo3_pm_counter_from_os_tick(rt_tick_t tick) { rt_uint32_t freq = apollo3_get_lptim_freq(); return (tick * freq / RT_TICK_PER_SECOND); } /** * This function caculate the OS tick from PM counter * * @param tick PM counter * * @return the OS tick */ static rt_tick_t apollo3_os_tick_from_pm_counter(rt_uint32_t counter) { static rt_uint32_t os_tick_remain = 0; rt_uint32_t ret, freq; freq = apollo3_get_lptim_freq(); ret = (counter * RT_TICK_PER_SECOND + os_tick_remain) / freq; os_tick_remain += (counter * RT_TICK_PER_SECOND); os_tick_remain %= freq; return ret; } /** * This function start the timer of pm * * @param pm Pointer to power manage structure * @param timeout How many OS Ticks that MCU can sleep */ static void pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout) { RT_ASSERT(pm != RT_NULL); RT_ASSERT(timeout > 0); if (timeout != RT_TICK_MAX) { /* Convert OS Tick to pmtimer timeout value */ timeout = apollo3_pm_counter_from_os_tick(timeout); if (timeout > apollo3_lptim_get_max_counter()) { timeout = apollo3_lptim_get_max_counter(); } /* Enter PM_TIMER_MODE */ g_os_old_tick = rt_tick_get(); apollo3_lptim_start(timeout); } } /** * This function stop the timer of pm * * @param pm Pointer to power manage structure */ static void pm_timer_stop(struct rt_pm *pm) { RT_ASSERT(pm != RT_NULL); /* Reset pmtimer status */ apollo3_lptim_stop(); } /** * This function calculate how many OS Ticks that MCU have suspended * * @param pm Pointer to power manage structure * * @return OS Ticks */ static rt_tick_t pm_timer_get_tick(struct rt_pm *pm) { rt_uint32_t timer_counter; rt_tick_t os_tick; RT_ASSERT(pm != RT_NULL); timer_counter = apollo3_lptim_get_current_counter(); os_tick = (apollo3_os_tick_from_pm_counter(timer_counter) - g_os_old_tick); g_os_old_tick = 0x00; return os_tick; } ``` ## 运行效果: * idle 线程栈过小编译问题: 【解决方法】增加idle 线程栈大小,如1024或更大。 ![2021-01-27_092628.png](https://oss-club.rt-thread.org/uploads/20210127/3851c6247009fcd500a28326c6d4e87d.png) * 解决上电初始化后,功耗模式为:None,不能自动进入深睡眠的问题: ``` rt_pm_module_release(PM_POWER_ID, RT_PM_DEFAULT_SLEEP_MODE); ``` * 上电后想延时一段时间再进入睡眠,保证驱动初始化: ``` rt_pm_module_delay_sleep(PM_POWER_ID, 5000); /* 5秒后,再进入睡眠 */ ``` * PM组件的控制台命令: ``` pm_release pm_release_all pm_request pm_module_release pm_module_release_all pm_module_request pm_module_delay pm_dump ``` * 功耗相关API接口 ``` void rt_pm_request(rt_uint8_t sleep_mode); /* 请求(不睡眠) */ void rt_pm_release(rt_uint8_t sleep_mode); /* 释放(允许睡眠) */ void rt_pm_release_all(rt_uint8_t sleep_mode); /* 释放此模式的所有请求(清除引用计数) */ void rt_system_pm_init(const struct rt_pm_ops *ops, rt_uint8_t timer_mask, void *user_data); /* 初始化PM组件,注册sleep,lptim的操作函数 */ void rt_pm_module_request(uint8_t module_id, rt_uint8_t sleep_mode); /* 请求(不睡眠),带模块id */ void rt_pm_module_release(uint8_t module_id, rt_uint8_t sleep_mode); /* 释放(允许睡眠),带模块id */ void rt_pm_module_release_all(uint8_t module_id, rt_uint8_t sleep_mode); /* 释放此模式的所有请求(清除引用计数),带模块id */ void rt_pm_module_delay_sleep(rt_uint8_t module_id, rt_tick_t timeout); /* 延时睡眠 */ rt_uint32_t rt_pm_module_get_status(void); /* 获取当前的模块id 请求释放状态(用于功耗日志管理,多线程功耗情况的拆解)*/ rt_uint8_t rt_pm_get_sleep_mode(void); /* 获取当前决策的睡眠状态 */ ``` 以上为PM2.0平台适配需要注意的,多实践验证,可以用于其他的MCU平台。 ## 总结 * 功耗管理牵涉的工作与基础知识点较多,多实践,才能真正的管理好功耗。 * PM组件使用并不复杂,不代表功耗管理也不复杂(需要详细的功耗拆解、业务优化、整体考虑) * 更新rt-thread 源码为最新,以便很好的配合操作系统,完善功耗的管理
5
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
张世争
学以致用
文章
131
回答
802
被采纳
173
关注TA
发私信
相关文章
1
RT-THREAD在STM32H747平台上移植lwip
2
正点原子miniSTM32开发板读写sdcard
3
反馈rtt串口驱动对低功耗串口lpuart1不兼容的问题
4
Keil MDK 移植 RT-Thread Nano
5
RT1061/1052 带 RTT + LWIP和LPSPI,有什么坑要注意吗?
6
RT thread HID 如何收发数据
7
求一份基于RTT系统封装好的STM32F1系列的FLASH操作程序
8
RT-Thread修改项目名称之后不能下载
9
rt-studio编译c++
10
有木有移植rt-thread(nano)到riscv 32位MCU上
推荐文章
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
次点赞
ThinkCode
1
篇文章
1
次点赞
Betrayer
1
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部