RTT 电源管理(一)

本文讨论了嵌入式系统中的低功耗管理,强调了硬件和软件的联合应用在满足性能需求和延长电池寿命方面的关键作用。RTT的电源管理组件通过分层设计和模式管理实现低功耗,包括处理器电源管理、设备电源管理和系统平台电源管理。文章还介绍了如何在物联网设备中优化功耗,特别是在RTOS环境下的休眠状态管理和外设控制。

嵌入式系统低功耗管理的目的在于满足用户对性能需求的前提下,尽可能降低系统能耗以延长设备待机时间。
高性能与有限的电池能量在嵌入式系统中矛盾最为突出,硬件低功耗设计与软件低功耗管理的联合应用称为解决矛盾的有效手段。
现在的各种MCU都或多或少的在低功耗管理方面提供了管理接口。比如对主控时钟频率的调整、工作电压的改变、总线频率的调整甚至关闭、外围设备工作时钟的关闭等。

有了硬件上的支持,合理的软件设计就成为节能的关键,一般可以把低功耗管理分为三个类别:

  • 处理器电源管理主要实现方式:对CPU频率的动态管理,以及系统空闲时对工作模式的调整。
  • 设备电源管理主要实现方式:关闭个别闲置设备。
  • 系统平台电源管理主要实现方式:针对特定系统平台的非常见设备具体定制。

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

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

PM组件介绍

RTT的PM组件采用分层设计思想,分离架构和芯片相关的部分,提取公共部分作为核心。在对上层提供通用的接口同时,也让底层驱动对组件的适配变得更加简单。

  • 基于模式来管理功耗,空闲时动态调整工作模式,支持多个等级的休眠。
  • 对应用透明,组件在底层自动完成电源管理。
  • 支持运行模式下动态变频,根据模式自动更新设备的频率配置,确保在不同的运行模式都可以正常工作。
  • 支持设备电源管理,根据模式自动管理设备的挂起和恢复,确保在不同的休眠模式下可以正确的挂起和恢复。
  • 支持可选的休眠时间补偿,让依赖OS Tick的应用可以透明使用。

工作原理

低功耗的本质是系统空闲时CPU停止工作,中断或事件唤醒后继续工作。
在RTOS中,通常包含一个IDLE任务,该任务的优先级最低且一直保持就绪状态,当高优先级任务未就绪时,OS执行IDLE任务。
一般地,未进行低功耗处理器,CPU在IDLE任务中循环执行空指令。
RTT的电源管理组件在IDLE任务中,通过对CPU、时钟和设备等进行管理,从而有效降低系统功耗。

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

设计架构

在RTT PM组件中,外设或应用通过投票机制对所需的功耗模式进行投票,当系统空闲时,根据投票数决策出合适的功耗模式,调用抽象接口,控制芯片进入低功耗状态,从而降低系统功耗。
当未进行任何投票时,会以默认模式进入(通常为空闲模式)。
与应用不同,某些外设可能在进入低功耗状态时执行特定操作,退出低功耗时采取措施恢复,此时可以通过注册PM设备来实现。
通过注册PM设备,在进入低功耗状态之前,会触发注册设备的suspend回调,开发者可在回调里执行自己的操作;类似地,从低功耗状态退出时,也会触发resume回调。

在这里插入图片描述

低功耗状态和模式

RTT PM组件将系统划分为两种状态:运行状态(RUN)和休眠状态(SLEEP)。
运行状态控制CPU的频率,适用于变频场景;休眠状态根据SOC特性实现休眠CPU,以降低功耗。
两种状态分别使用不同的API接口,独立控制。

休眠状态

休眠状态也就是通常意义上的低功耗状态,通过关闭外设,执行SOC电源管理接口,降低系统功耗。
休眠状态又分为六个模式,呈现为金字塔的形式。随着模式增加,功耗逐级递减的特点。

  1. PM_SLEEP_MODE_NONE:系统处于活跃状态,未采取任何的措施降低功耗状态。
  2. PM_SLEEP_MODE_IDLE:空闲模式,该模式在系统空闲时停止CPU和部分时钟,任何事件或中断均可以唤醒。
  3. PM_SLEEP_MODE_LIGHT:轻度睡眠模式,CPU停止,多数时钟和外设停止,唤醒后需要进行时间补偿
  4. PM_SLEEP_MODE_DEEP:深度睡眠模式,CPU停止,仅少数低功耗外设工作,可被特殊中断唤醒。
  5. PM_SLEEP_MODE_STANDBY:待机模式,CPU停止,设备上下文丢失(可保存至特殊外设),唤醒后通常复位。
  6. PM_SLEEP_MODE_SHUTDOWN:关断模式,比Standby模式功耗更低,上下文通常不可恢复,唤醒后复位。

因各家芯片差异,功耗管理的实现也不尽相同,上述的描述仅给出一些推荐的场景,并非一定需要实现所有。开发者可根据自身情况选择其中的几种进行实现,但是需要遵循级别越高,功耗越低的原则!

运行状态

因各家芯片差异,功耗管理的实现也不尽相同,上述的描述仅给出一些推荐的场景,并非一定需要实现所有。开发者可根据自身情况选择其中的几种进行实现,但是需要遵循级别越高,功耗越低的原则!

在这里插入图片描述

模式的请求和释放

在PM组件里,上层应用可以通过请求和释放休眠模式主动参与功耗管理。
应用可以根据场景请求不同的休眠模式,并在处理完毕后释放,只要有任意一个应用或设备请求高等级的功耗模式,就不会切换到比它更低的模式。

因此,休眠模式的请求和释放的操作通常成对出现,可用于对某个阶段进行保护,如外设的DMA传输过程。

对模式变化敏感的设备

在PM组件里,切换到新的运行模式可能会导致CPU频率发生变化,如果外设和CPU共用一部分时钟,那么外设的时钟就会受到影响;
在进入新的休眠模式,大部分时钟源会被停止,大部分时钟源会被停止,如果外设不支持休眠的冻结功能,那么从休眠唤醒的时候,外设的时钟就需要重新配置外设。所以PM组件里支持了PM模式敏感的PM设备。使得设备在切换到新的运行模式或者新的休眠模式都能正常的工作。
该功能需要底层驱动实现相关的接口并注册为对模式变化敏感的设备

在这里插入图片描述
首先应用设置进出休眠状态的回调函数,然后调用rt_pm_request请求休眠模式,触发休眠操作;
PM组件在系统空闲时检查休眠模式计数,根据投票数给出推荐的模式;
接着PM组件调用notify通知应用,告知即将进入休眠模式;
然后对注册的PM设备执行挂起操作,返回OK后执行SOC实现的休眠模式,系统进入休眠状态(如果使能时间补偿,休眠之前会先启动低功耗定时器)。
此时CPU停止工作,等待事件或者中断唤醒。
当系统被唤醒后,由于全局中断为关闭状态,系统继续从该处执行,获取睡眠时间补偿系统的心跳,依次唤醒设备,通知应用从休眠模式退出。
如此一个周期执行完毕,退出,等待系统下次空闲。

请求休眠模式

void rt_pm_request(uint8_t sleep_mode);

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,
}

调用该函数会将对应的模式计数加1,并锁住该模式。
此时如果请求更低级别的功耗模式,将无法进入,只要释放先前请求的模式后,才能进入更低的模式。向更高的功耗模式请求则不受影响。

该函数需要和rt_pm_release配合使用,用于对某一阶段或过程进行保护。

void rt_pm_release(uint8_t sleep_mode);

调用该函数会将对应的模式计数减1。

设置进入/退出休眠模式的回调通知

void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), void *data);

event为以下两个枚举值,分别标识进入/退出休眠模式。

enum
{
    RT_PM_ENTER_SLEEP = 0,    /* 进入休眠模式 */
    RT_PM_EXIT_SLEEP,         /* 退出休眠模式 */
};

使用说明

设置低功耗等级
如果系统需要进入指定等级的低功耗,可通过调用rt_pm_request实现。
如果进入深度睡眠模式:

rt_pm_request(PM_SLEEP_MODE_DEEP);

如果程序的其它地方请求了更高的功耗模式,如Light Mode或者Idle Mode,则需要释放相应的模式后,深度睡眠模式才能被进入。

保护某个阶段或者过程
特殊情况下,比如某个阶段并不允许系统进入更低的功耗模式,此时可以通过rt_pm_request和release对该过程进行保护。
如I2C读取数据期间,不允许进入深度睡眠模式(可能会导致外设停止工作),因此可以做如下处理:

rt_pm_request(PM_SLEEP_MODE_LIGHT);

/*读取数据*/

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

移植说明

低功耗管理是一项十分细致的任务,开发者在移植时,不仅需要充分了解芯片本身的功耗管理,还需熟悉板卡的外围电路,进入低功耗状态时逐一处理,避免出现外围电路漏电拉升整体功耗的情况。
RTT PM组件对各部分进行抽象,提供不同的ops接口供开发者适配。

struct rt_pm_ops
{
	void (*sleep)(struct rt_pm *pm, uint8_t mode);
	void (*run)(struct rt_pm *pm, uint8_t mode);
	/*以下三个接口用于心跳停止后启动低功耗定时器以补偿心跳*/
	void (*timer_start)(struct rt_pm *pm, rt_uint32_t timeout);
	void (*timer_stop)(struct rt_pm *pm);
	rt_tick_t (*timer_get_tick)(struct rt_pm *pm);	
};


/*该ops用于管理外设的功耗*/
struct rt_device_pm_ops
{
	int (*suspend)(const struct rt_device *device, uint8_t mode);
	void (*resume)(const struct rt_device *device, uint8_t mode);
	int (*frequency_change)(const struct rt_device *device, uint8_t mode);
}

/*注册一个PM设备*/
void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops);

在某些休眠模式下(Light Sleep或Deep Sleep),内核心跳定时器可能会被停止,此时需要对启动一个定时器对休眠的时间进行计量,唤醒后对心跳补偿。时间补偿的定时器必须在该模式下仍能够正常工作,并唤醒系统,否则没有意义!

  • timer_start:启动低功耗定时器,入参为最近的下次任务就绪时间。
  • timer_get_tick:获取系统被唤醒的睡眠时间;
  • timer_stop:用于系统唤醒后停止低功耗定时器。

休眠模式的时间补偿需要在初始化阶段通过设置timer_mask的对应模式的bit控制开启。

rt_uint_t timer_mask = 0;

timer_mask = 1UL << PM_SLEEP_MODE_DEEP;
rt_system_pm_init(&ops, timer_mask, RT_NULL);

外设的功耗管理是低功耗管理的一个重要部分,在进入某些级别的休眠模式时,通常需要对一些外设进行处理,如清空DMA,关闭时钟或是设置IO为复位状态;并在退出休眠后进行恢复。
此类情况可以通过rt_pm_device_register接口注册PM设备,在进入/退出休眠模式时,会执行注册设备的suspend和resume回调;运行模式下的频率改变同样会触发设备的frequency_change回调。

MSH命令

请求休眠模式

pm_request 0
pm_release 0
pm_run 2

可以使用pm_dump命令查看PM组件的模式状态
在这里插入图片描述
在pm_dump的模式列表里,休眠模式的优先级从高到低排列,Counter一栏标识请求的计数值,图中表明LightSleep模式被请求一次,因此当前工作在轻度休眠模式;Timer一栏标识是否开启睡眠时间补偿,图中仅深度睡眠模式进行时间补偿。

### RTT GD 串口通信问题及解决方案 在基于GD32F303微控制器并集成RTT(Real-Time Transfer)技术的开发中,串口通信问题是个常见且关键的技术挑战。此类问题通常涉及硬件连接、调试接口配置、软件环境设置以及多串口使用中的冲突处理。 #### 硬件配置问题 在硬件层面,RTT通常通过SWD接口与调试器(如J-Link)进行通信,因此需要确保调试串口的正确配置。具体包括: - **调试串口配置**:确保SWD接口正确连接,以支持RTT数据在调试器与目标设备之间的高效传输。 - **电源与地线连接**:稳定的供电是通信稳定性的基础,必须确保调试器与目标板之间的电源和地线连接可靠。 - **调试器连接**:使用J-Link调试器连接到目标板的SWD接口,确保物理层通信的稳定性[^1]。 #### 软件开发环境中的串口冲突问题 在RT-Thread操作系统中,多个串口同时使用时可能会出现中断冲突导致系统卡死的问题。例如,在设置控制台输出时,仅允许个串口作为控制台输出设备: ```c #if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE) rt_console_set_device(RT_CONSOLE_UART1DEVICE_NAME); #endif ``` 上述代码片段中,`RT_CONSOLE_UART1DEVICE_NAME`定义了使用哪个串口作为控制台输出。如果尝试同时启用多个串口作为控制台输出,将可能导致中断冲突,进而引发系统异常。解决此类问题的关键在于: - **明确指定唯控制台输出串口**:避免多个串口同时被设置为控制台输出。 - **中断优先级管理**:合理配置不同串口的中断优先级,避免中断嵌套冲突。 - **资源互斥访问控制**:使用互斥锁或信号量机制确保多个任务对串口资源的访问是有序的[^2]。 #### RTT与MQTT通信中的资源占用问题 在使用RTT结合paho-mqtt软件包进行网络通信开发时,虽然paho-mqtt具有广泛的社区支持和官方维护的优势,但也存在资源占用大、传输逻辑缺陷以及功能支持不完全的问题。为优化此类通信: - **资源优化**:通过精简不必要的功能模块,减少内存和CPU资源的占用。 - **传输逻辑优化**:引入缓冲机制和重传策略,提升传输稳定性和效率。 - **功能扩展**:根据项目需求,自行扩展缺失的功能模块,或参考社区已有解决方案进行适配[^3]。 #### 应用场景与网络通信实现 基于RTT和GD32F303的串口通信方案,适用于工业自动化、智能家居、物联网设备等多种嵌入式应用场景。通过合理配置硬件和软件环境,开发者可以快速实现高效的网络通信功能,并在此基础上进行进步的功能扩展与优化[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

饼干饼干圆又圆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值