打印
[其他ST产品]

STM32通用低功耗组件——PM

[复制链接]
3069|47
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
电源管理组件
嵌入式系统低功耗管理的目的在于满足用户对性能需求的前提下,尽可能降低系统能耗以延长设备待机时间。高性能与有限的电池能量在嵌入式系统中矛盾最为突出,硬件低功耗设计与软件低功耗管理的联合应用成为解决矛盾的有效手段。现在的各种 MCU 都或多或少的在低功耗方面提供了管理接口。比如对主控时钟频率的调整、工作电压的改变、总线频率的调整甚至关闭、外围设备工作时钟的关闭等。有了硬件上的支持,合理的软件设计就成为节能的关键,一般可以把低功耗管理分为三个类别:
  • 处理器电源管理主要实现方式:对 CPU 频率的动态管理,以及系统空闲时对工作模式的调整。


使用特权

评论回复
沙发
欢乐家园|  楼主 | 2022-4-29 12:38 | 只看该作者
设备电源管理主要实现方式:关闭个别闲置设备

系统平台电源管理主要实现方式:针对特定系统平台的非常见设备具体定制。

随着物联网 (IoT) 的兴起,产品对功耗的需求越来越强烈。作为数据采集的传感器节点通常需要在电池供电时长期工作,而作为联网的 SOC 也需要有快速的响应功能和较低的功耗。

在产品开发的起始阶段,首先考虑是尽快完成产品的功能开发。在产品功能逐步完善之后,就需要加入电源管理 (Power Management,以下简称 PM) 功能。为了适应 IoT 的这种需求,RT-Thread 提供了电源管理组件。电源管理组件的理念是尽量透明,使得产品加入低功耗功能更加轻松。

使用特权

评论回复
板凳
欢乐家园|  楼主 | 2022-4-29 13:35 | 只看该作者
PM 组件介绍
RT-Thread 的 PM 组件采用分层设计思想,分离架构和芯片相关的部分,提取公共部分作为核心。在对上层提供通用的接口同时,也让底层驱动对组件的适配变得更加简单。

使用特权

评论回复
地板
欢乐家园|  楼主 | 2022-4-29 13:37 | 只看该作者
主要特点
RT-Thread PM 组件主要特点如下所示:

基于模式来管理功耗,空闲时动态调整工作模式,支持多个等级的休眠。

对应用透明,组件在底层自动完成电源管理。

支持运行模式下动态变频,根据模式自动更新设备的频率配置,确保在不同的运行模式都可以正常工作。

支持设备电源管理,根据模式自动管理设备的挂起和恢复,确保在不同的休眠模式下可以正确的挂起和恢复。

支持可选的休眠时间补偿,让依赖 OS Tick 的应用可以透明使用。

向上层提供设备接口,如果打开了 devfs 组件,那么也可以通过文件系统接口访问。

使用特权

评论回复
5
欢乐家园|  楼主 | 2022-4-29 13:37 | 只看该作者
工作原理
低功耗的本质是系统空闲时 CPU 停止工作,中断或事件唤醒后继续工作。在 RTOS 中,通常包含一个 IDLE 任务,该任务的优先级最低且一直保持就绪状态,当高优先级任务未就绪时,OS 执行 IDLE 任务。一般地,未进行低功耗处理时,CPU 在 IDLE 任务中循环执行空指令。RT-Thread 的电源管理组件在 IDLE 任务中,通过对 CPU 、时钟和设备等进行管理,从而有效降低系统的功耗。

使用特权

评论回复
6
欢乐家园|  楼主 | 2022-4-29 13:38 | 只看该作者

上图所示,当高优先级任务运行结束或被挂起时,系统将进入 IDLE 任务中。在 IDLE 任务执行后,它将判断系统是否可以进入到休眠状态(以节省功耗)。如果可以进入休眠, 将根据芯片情况关闭部分硬件模块,OS Tick 也非常有可能进入暂停状态。此时电源管理框架会根据系统定时器情况,计算出下一个超时时间点,并设置低功耗定时器,让设备能够在这个时刻点唤醒,并进行后续的工作。当系统被(低功耗定时器中断或其他唤醒中断源)唤醒后,系统也需要知道睡眠时间长度是多少,并对OS Tick 进行补偿,让系统的OS tick值调整为一个正确的值。

使用特权

评论回复
7
欢乐家园|  楼主 | 2022-4-29 13:40 | 只看该作者
低功耗状态和模式
RT-Thread PM 组件将系统划分为两种状态:运行状态(RUN)和休眠状态(Sleep)。运行状态控制 CPU 的频率,适用于变频场景;休眠状态根据 SOC 特性实现休眠 CPU,以降低功耗。两种状态分别使用不同的 API 接口,独立控制。

使用特权

评论回复
8
欢乐家园|  楼主 | 2022-4-29 14:02 | 只看该作者
休眠状态休眠状态也就是通常意义上的低功耗状态,通过关闭外设、执行 SOC 电源管理接口,降低系统功耗。休眠状态又分为六个模式,呈现为金字塔的形式。随着模式增加,功耗逐级递减的特点。下面是休眠状态下模式的定义,开发者可根据具体的 SOC 实现相应的模式,但需要遵循功耗逐级降低的特点。

使用特权

评论回复
9
欢乐家园|  楼主 | 2022-4-29 14:02 | 只看该作者

使用特权

评论回复
10
欢乐家园|  楼主 | 2022-4-29 14:03 | 只看该作者
运行状态运行状态通常用于改变 CPU 的运行频率,独立于休眠模式。当前运行状态划分了四个等级:高速、正常、中速、低速,如下:

使用特权

评论回复
11
欢乐家园|  楼主 | 2022-4-29 14:03 | 只看该作者
PM组件的实现接口
在 RT-Thrad PM 组件中,外设或应用通过投票机制对所需的功耗模式进行投票,当系统空闲时,根据投票数决策出合适的功耗模式,调用抽象接口,控制芯片进入低功耗状态,从而降低系统功耗。当未进行进行任何投票时,会以默认模式进入(通常为空闲模式)。

使用特权

评论回复
12
欢乐家园|  楼主 | 2022-4-29 14:04 | 只看该作者
pm组件的控制块:

static struct rt_pm _pm;

使用特权

评论回复
13
欢乐家园|  楼主 | 2022-4-29 14:05 | 只看该作者
API接口:

请求休眠模式

void rt_pm_request(uint8_t sleep_mode);

使用特权

评论回复
14
欢乐家园|  楼主 | 2022-4-29 14:06 | 只看该作者
sleep_mode 取以下枚举值:
enum
{
   /* sleep modes */
   PM_SLEEP_MODE_NONE = 0,    /* 活跃状态 */
   PM_SLEEP_MODE_IDLE,        /* 空闲模式(默认) */
   PM_SLEEP_MODE_LIGHT,       /* 轻度睡眠模式 */
   PM_SLEEP_MODE_DEEP,        /* 深度睡眠模式 */
   PM_SLEEP_MODE_STANDBY,     /* 待机模式 */
   PM_SLEEP_MODE_SHUTDOWN,    /* 关断模式 */
   PM_SLEEP_MODE_MAX,
};

使用特权

评论回复
15
欢乐家园|  楼主 | 2022-4-29 14:07 | 只看该作者
调用该函数会将对应的模式计数加1,并锁住该模式。此时如果请求更低级别的功耗模式,将无法进入,只有释放(解锁)先前请求的模式后,系统才能进入更低的模式;向更高的功耗模式请求则不受此影响。该函数需要和 rt_pm_release 配合使用,用于对某一阶段或过程进行保护。下面是具体代码实现:

void rt_pm_request(rt_uint8_t mode)
{
    rt_base_t level;
    struct rt_pm *pm;

    if (_pm_init_flag == 0)
        return;

    if (mode > (PM_SLEEP_MODE_MAX - 1))
        return;

    level = rt_hw_interrupt_disable();
    pm = &_pm;
    if (pm->modes[mode] < 255)
        pm->modes[mode] ++;//将对应的模式计数加1
    rt_hw_interrupt_enable(level);
}

使用特权

评论回复
16
欢乐家园|  楼主 | 2022-4-29 14:07 | 只看该作者
释放休眠模式

void rt_pm_release(uint8_t sleep_mode);



调用该函数会将对应的模式计数减1,配合 rt_pm_request 使用,释放先前请求的模式。下面是具体代码实现:

void rt_pm_release(rt_uint8_t mode)
{
    rt_ubase_t level;
    struct rt_pm *pm;

    if (_pm_init_flag == 0)
        return;

    if (mode > (PM_SLEEP_MODE_MAX - 1))
        return;

    level = rt_hw_interrupt_disable();
    pm = &_pm;
    if (pm->modes[mode] > 0)
        pm->modes[mode] --;//将对应的模式计数减1
    rt_hw_interrupt_enable(level);
}

使用特权

评论回复
17
欢乐家园|  楼主 | 2022-4-29 14:08 | 只看该作者
特殊情况下,比如某个阶段并不允许系统进入更低的功耗模式,此时可以通过 rt_pm_request 和 rt_pm_release 对该过程进行保护。如 I2C 读取数据期间,不允许进入深度睡眠模式(可能会导致外设停止工作),因此可以做如下处理:

/* 请求轻度睡眠模式(I2C外设该模式下正常工作) */
rt_pm_request(PM_SLEEP_MODE_LIGHT);

/* 读取数据过程 */

/* 释放该模式 */
rt_pm_release(PM_SLEEP_MODE_LIGHT);

使用特权

评论回复
18
欢乐家园|  楼主 | 2022-4-29 14:09 | 只看该作者
设置运行模式

int rt_pm_run_enter(uint8_t run_mode);

使用特权

评论回复
19
欢乐家园|  楼主 | 2022-4-29 14:09 | 只看该作者
run_mode 可以取以下枚举值:

enum
{
   /* run modes*/
   PM_RUN_MODE_HIGH_SPEED = 0,    /* 高速 */
   PM_RUN_MODE_NORMAL_SPEED,      /* 正常(默认) */
   PM_RUN_MODE_MEDIUM_SPEED,      /* 中速 */
   PM_RUN_MODE_LOW_SPEED,         /* 低速 */
   PM_RUN_MODE_MAX,
};
调用该函数改变 CPU 的运行频率,从而降低运行时的功耗。此函数只提供级别,具体的 CPU 频率应在移植阶段视实际情况而定。

使用特权

评论回复
20
欢乐家园|  楼主 | 2022-4-29 14:10 | 只看该作者
下面是具体代码实现:

int rt_pm_run_enter(rt_uint8_t mode)
{
    rt_base_t level;
    struct rt_pm *pm;

    if (_pm_init_flag == 0)
        return -RT_EIO;

    if (mode > PM_RUN_MODE_MAX)
        return -RT_EINVAL;

    level = rt_hw_interrupt_disable();
    pm = &_pm;
    if (mode < pm->run_mode)
    {
        /* change system runing mode */
        pm->ops->run(pm, mode);
        /* changer device frequency */
        _pm_device_frequency_change(mode);
    }
    else
    {
        pm->flags |= RT_PM_FREQUENCY_PENDING;
    }
    pm->run_mode = mode;
    rt_hw_interrupt_enable(level);

    return RT_EOK;
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

106

主题

941

帖子

1

粉丝