睡眠管理
简介
Bluetooth LE SoC支持Active、Idle、Sleep三种功耗模式,在无活跃业务时会进入深度睡眠,将关闭除Always On域、SRAM外所有片上外设的电源,并切换到低速时钟域运行。每个外设模块的状态分为RESET(设备未初始化)、READY(设备就绪)、BUSY(设备忙),当配置为Deep Sleep时,系统会判断每个外设是否处于RESET或者READY状态,只有每个外设都不处于BUSY状态,即外设无活跃业务,系统才会进入深度睡眠模式。当触发系统唤醒后,会执行一次复位启动过程并恢复到睡眠前的上下文。
为保持外设在睡眠唤醒后和进入睡眠前的状态一致,在执行Deep Sleep流程之前,需要备份正在使用的外设模块的寄存器。在APP驱动中有一套备份和恢复的程序框架,实现了外设睡眠恢复的自动管理,用户使用APP驱动时无需自行备份恢复这些寄存器,显著降低了使用复杂度。
- 一种是备份和恢复函数在HAL层实现,且外设状态通过g_devices_state的bit位进行标识。APP驱动接口只实现备份和恢复函数的注册和调用,如pwr_register_sleep_cb、pwr_enter_sleep_check_new和pwr_wake_up_ind_new。该方式适用于GR5526、GR5x25、GR533x。
- 另一种备份和恢复函数在各个外设驱动进行实现,例如xxx_prepare_for_sleep和xxx_wake_up_ind,且外设状态通过外设句柄状态位标识,使用hal_xxx_get_state函数可获取外设状态。各模块在初始化时会调用pwr_register_sleep_cb函数,注册各个模块的备份恢复相关函数。该方式适用于GR551x、GR5405。
系统进入睡眠前,会调用pwr_enter_sleep_check,检查各个模块是否可以进入睡眠,可以睡眠则调用xxx_prepare_for_sleep备份正在使用的外设模块;系统唤醒后,调用pwr_wake_up_ind,从而调用各个模块的xxx_wake_up_ind,将备份的外设寄存器还原。
结构体
pwr_env_t
结构体定义如下:
| 成员 | 描述 | 取值 |
|---|---|---|
| app_sleep_callbacks_t *pwr_sleep_cb[APP_SLEEP_CB_MAX] |
睡眠相关回调函数的数组 |
保存各模块睡眠相关回调函数 |
| wakeup_priority_t wakeup_priority[APP_SLEEP_CB_MAX] |
睡眠唤醒优先级数组 |
保存各个模块的睡眠唤醒优先级 |
详细信息请参考文件:SDK_Folder\drivers\inc\app_pwr_mgmt.c。
app_sleep_callbacks_t
结构体定义如下:
| 成员 | 描述 | 取值 |
|---|---|---|
| bool (*app_prepare_for_sleep)(void) |
睡眠准备函数,该函数能够保存现场并配置相应模块相关寄存器,使得具体模块进入低功耗模式 |
注册时进行赋值 |
| void (*app_wake_up_ind)(void) |
唤醒后,恢复模块相关寄存器,激活相关模块 |
注册时进行赋值 |
详细信息请参考文件:SDK_Folder\drivers\inc\app_pwr_mgmt.c。
枚举
pwr_mgmt_dev_state_t
枚举定义如下:
| 成员 | 描述 |
|---|---|
| DEVICE_BUSY | 外设正忙,不可以进入深度睡眠模式 |
| DEVICE_IDLE | 外设空闲,可以进入深度睡眠模式 |
接口函数
pwr_register_sleep_cb
| 函数原型 | pwr_id_t pwr_register_sleep_cb(const app_sleep_callbacks_t *p_cb, wakeup_priority_t wakeup_priority, pwr_id_t id) |
|---|---|
| 功能说明 | 外设注册睡眠管理 |
| 输入参数 |
|
| 返回值 | pwr_id_t:模块ID |
| 备注 |
pwr_unregister_sleep_cb
| 函数原型 | void pwr_unregister_sleep_cb(pwr_id_t id) |
|---|---|
| 功能说明 | 外设注销睡眠管理 |
| 输入参数 | id:需要注销的模块ID |
| 返回值 | |
| 备注 |
pwr_wake_up_ind
| 函数原型 | void pwr_wake_up_ind(void) |
|---|---|
| 功能说明 | 唤醒时统一恢复外设 |
| 输入参数 | |
| 返回值 | |
| 备注 | 仅适用于GR551x、GR5405 |
pwr_wake_up_ind_new
| 函数原型 | void pwr_wake_up_ind_new(void) |
|---|---|
| 功能说明 | 唤醒时统一恢复外设 |
| 输入参数 | |
| 返回值 | |
| 备注 | 适用于GR5526、GR5x25、GR533x |
pwr_enter_sleep_check
| 函数原型 | pwr_mgmt_dev_state_t pwr_enter_sleep_check(void) |
|---|---|
| 功能说明 | 进入睡眠前检查外设状态 |
| 输入参数 | |
| 返回值 | 系统工作状态 |
| 备注 | 仅适用于GR551x、GR5405 |
pwr_enter_sleep_check_new
| 函数原型 | pwr_mgmt_dev_state_t pwr_enter_sleep_check_new(void) |
|---|---|
| 功能说明 | 进入睡眠前检查外设状态并备份外设寄存器 |
| 输入参数 | |
| 返回值 | 系统工作状态 |
| 备注 | 适用于GR5526、GR5x25、GR533x |
接口使用方法
下文以I2C为例介绍GR551x/GR5405接口使用,GR5526、GR5x25、GR533x备份和恢复在HAL层实现,用户无需关注。
- I2C模块初始化时,注册睡眠回调函数。
uint16_t app_i2c_init(app_i2c_params_t *p_params, app_i2c_evt_handler_t evt_handler) { ... /*注册睡眠回调函数*/ pwr_register_sleep_cb(&i2c_sleep_cb, APP_DRIVER_I2C_WAKEUP_PRIORITY, I2C_PWR_ID); ... } - 实现睡眠回调函数。
static const app_sleep_callbacks_t i2c_sleep_cb = { .app_prepare_for_sleep = i2c_prepare_for_sleep, /*进入睡眠,保存现场 并配置i2c相关寄存器,进入低功耗模式*/ .app_wake_up_ind = i2c_wake_up_ind /*唤醒后,恢复i2c相关寄存器,激活 i2c模块 */ };