5.15 LPMGR设备
2026/7/19大约 6 分钟设备驱动驱动低功耗LPMGR睡眠模式Tickless
5.15 LPMGR设备
📚 本节导读
学习时长: 约 40 分钟
难度级别: ⭐⭐⭐⭐☆
前置知识: C 语言基础、MCU 低功耗模式基础知识、5.1 设备驱动框架、4.5 时间管理
🎯 学习目标
- 理解 OneOS 低功耗管理框架的分层设计
- 掌握四种睡眠模式的区别与选择
- 掌握设备挂起/恢复的注册与回调机制
- 理解 Tickless 机制在低功耗场景下的作用
- 掌握低功耗通知机制的注册与使用
一、概述
LPMGR(Low Power Manager)是 OneOS 提供的低功耗管理框架,负责在系统空闲时协调各外设进入低功耗状态,并在唤醒时恢复。LPMGR 设备驱动位于 drivers/lpmgr/ 目录下,核心头文件为 lpmgr.h 和 lpm.h,实现文件为 lpmgr.c 和 lpm.c。
LPMGR 框架的特点:
- 多级睡眠模式:支持 Idle / LightSleep / DeepSleep / Standby / Shutdown 多级模式
- 设备协调机制:外设驱动通过注册 suspend/resume 回调参与功耗管理
- Tickless 补偿:唤醒后自动补偿睡眠期间的系统时钟
- 通知机制:支持注册睡眠/唤醒通知回调
- 请求/释放模式:多个模块可独立请求睡眠模式,由框架综合决策
二、睡眠模式
2.1 模式定义
typedef enum
{
SYS_SLEEP_MODE_NONE = 0, /* 无睡眠(正常运行) */
SYS_SLEEP_MODE_IDLE, /* 空闲模式(仅 CPU 暂停,外设运行) */
SYS_SLEEP_MODE_LIGHT, /* 轻度睡眠(部分外设关闭) */
SYS_SLEEP_MODE_DEEP, /* 深度睡眠(大部分外设关闭) */
SYS_SLEEP_MODE_MAX, /* 模式数量(用于数组大小) */
} lpmgr_sleep_mode_e;| 模式 | 功耗 | 唤醒延迟 | 典型场景 |
|---|---|---|---|
| NONE | 正常运行 | — | 系统繁忙 |
| IDLE | 极低 | ~0 μs | CPU 空闲时自动进入 |
| LIGHT | 低 | ~10 μs | 短暂空闲 |
| DEEP | 很低 | ~100 μs | 长时间空闲 |
| Standby | 极低 | ~1 ms | 电池供电待机 |
| Shutdown | 最低 | ~10 ms | 关机前最低功耗 |
2.2 模式决策机制
多个模块通过 os_lpmgr_request(mode) 和 os_lpmgr_release(mode) 声明自己需要的睡眠模式。框架取所有请求中最低功耗模式作为最终睡眠模式:
模块 A 请求: DEEP ─┐
模块 B 请求: IDLE ─┼─→ 最终睡眠模式: IDLE(取最低功耗的)
模块 C 请求: LIGHT ─┘三、核心数据结构
3.1 LPMGR 设备结构体
struct os_lpmgr_dev
{
struct os_device parent;
lpmgr_sleep_mode_e modes[SYS_SLEEP_MODE_MAX]; /* 各模式请求计数 */
lpmgr_sleep_mode_e sleep_mode; /* 当前睡眠模式 */
os_tick_t sleep_tick; /* 睡眠 tick 数 */
os_err_t (*sleep)(lpmgr_sleep_mode_e mode); /* HAL 层睡眠实现 */
os_clockevent_t *lpce; /* 低功耗定时器 */
uint32_t mult; /* time(ns) = tick * mult >> shift */
uint32_t shift;
uint32_t mult_t; /* tick = time(ns) * mult_t >> shift_t */
uint32_t shift_t;
};3.2 外设低功耗操作接口
struct os_lpmgr_device_ops
{
os_err_t (*suspend)(void *priv, lpmgr_sleep_mode_e mode); /* 挂起外设 */
void (*resume)(void *priv, lpmgr_sleep_mode_e mode); /* 恢复外设 */
};3.3 通知结构体
struct lpmgr_notify
{
void (*notify)(os_lpmgr_sys_e event, lpmgr_sleep_mode_e mode, void *data);
void *data;
os_list_node_t list;
};
typedef enum { SYS_ENTER_SLEEP = 0, SYS_EXIT_SLEEP } os_lpmgr_sys_e;四、API 详解
4.1 初始化
void os_lpmgr_init(os_err_t (*sleep)(lpmgr_sleep_mode_e mode));4.2 请求/释放睡眠模式
void os_lpmgr_request(lpmgr_sleep_mode_e sleep_mode); /* 请求允许进入某模式 */
void os_lpmgr_release(lpmgr_sleep_mode_e sleep_mode); /* 释放某模式请求 */4.3 外设注册
os_err_t os_lpmgr_device_register(void *priv, const struct os_lpmgr_device_ops *ops);
os_err_t os_lpmgr_device_register_high_prio(void *priv, const struct os_lpmgr_device_ops *ops);
void os_lpmgr_device_unregister(void *priv, const struct os_lpmgr_device_ops *ops);| 函数 | 说明 |
|---|---|
os_lpmgr_device_register | 注册外设,suspend 时按注册顺序调用 |
os_lpmgr_device_register_high_prio | 高优先级注册,suspend 时优先调用 |
os_lpmgr_device_unregister | 注销外设 |
4.4 通知注册
os_err_t os_lpmgr_notify_register(struct lpmgr_notify *cb_info);
os_err_t os_lpmgr_notify_unregister(struct lpmgr_notify *cb_info);4.5 核心入口
void os_low_power_manager(void); /* 在空闲任务中调用,检查并进入睡眠 */五、睡眠流程
┌──────────────────────────────────────────────────────────────┐
│ 低功耗管理睡眠流程 │
│ │
│ 1. 空闲任务调用 os_low_power_manager() │
│ ↓ │
│ 2. 检查 sleep_mode > IDLE? │
│ ├── NO → 仅执行 WFI/WFE,不进入深度睡眠 │
│ └── YES → 继续 │
│ ↓ │
│ 3. 计算最长睡眠时间(Tickless),时间太短则放弃 │
│ ↓ │
│ 4. pre_gettick_dev_suspend() → 预挂起设备 │
│ ↓ │
│ 5. lpmgr_enter_sleep_call() → 通知 SYS_ENTER_SLEEP │
│ └→ lpmgr_device_suspend() → 逐一挂起所有注册的外设 │
│ ↓ │
│ 6. lpmgr->sleep(mode) → HAL 层执行睡眠(WFI/WFE) │
│ ↓ ← 中断唤醒 │
│ 7. lpmgr_exit_sleep_call() → 通知 SYS_EXIT_SLEEP │
│ └→ lpmgr_device_resume() → 逐一恢复所有注册的外设 │
│ ↓ │
│ 8. pre_gettick_dev_resume() → 恢复预挂起设备 │
│ ↓ │
│ 9. os_lpmgr_update() → 补偿系统时钟 │
│ ↓ │
│ 10. 恢复正常运行 │
└──────────────────────────────────────────────────────────────┘六、代码示例
6.1 外设驱动注册低功耗回调
#include <oneos_config.h>
#include <lpmgr.h>
typedef struct { os_device_t *uart_dev; } my_uart_priv_t;
static my_uart_priv_t g_uart_priv;
static os_err_t uart_suspend(void *priv, lpmgr_sleep_mode_e mode)
{
os_kprintf("UART suspend for mode %d\r\n", mode);
if (mode >= SYS_SLEEP_MODE_DEEP)
hal_uart_disable_clock();
return OS_SUCCESS;
}
static void uart_resume(void *priv, lpmgr_sleep_mode_e mode)
{
os_kprintf("UART resume from mode %d\r\n", mode);
if (mode >= SYS_SLEEP_MODE_DEEP)
{
hal_uart_enable_clock();
hal_uart_reconfigure();
}
}
static const struct os_lpmgr_device_ops uart_lpm_ops = {
.suspend = uart_suspend,
.resume = uart_resume,
};
void uart_lpmgr_init(void)
{
os_lpmgr_device_register(&g_uart_priv, &uart_lpm_ops);
}6.2 应用层请求/释放睡眠模式
void app_power_management(void)
{
/* 应用需要保持外设运行,不允许深度睡眠 */
os_lpmgr_request(SYS_SLEEP_MODE_IDLE);
os_kprintf("Requested IDLE mode (no deep sleep)\r\n");
do_network_communication();
/* 任务完成,允许深度睡眠 */
os_lpmgr_release(SYS_SLEEP_MODE_IDLE);
os_kprintf("Released IDLE restriction\r\n");
}6.3 睡眠/唤醒通知
static void my_sleep_notify(os_lpmgr_sys_e event, lpmgr_sleep_mode_e mode, void *data)
{
switch (event)
{
case SYS_ENTER_SLEEP:
os_kprintf("[App] About to enter sleep mode %d\r\n", mode);
break;
case SYS_EXIT_SLEEP:
os_kprintf("[App] Exited sleep mode %d\r\n", mode);
break;
}
}
static struct lpmgr_notify g_notify = { .notify = my_sleep_notify, .data = "MyApp" };
void register_sleep_notify(void)
{
os_lpmgr_notify_register(&g_notify);
}6.4 初始化低功耗管理
#include <lpmgr.h>
static os_err_t hal_sleep(lpmgr_sleep_mode_e mode)
{
switch (mode)
{
case SYS_SLEEP_MODE_IDLE:
__WFI();
break;
case SYS_SLEEP_MODE_LIGHT:
hal_clock_disable_peripheral();
__WFI();
hal_clock_enable_peripheral();
break;
case SYS_SLEEP_MODE_DEEP:
hal_prepare_stop_mode();
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
hal_restore_from_stop();
break;
default: break;
}
return OS_SUCCESS;
}
void system_lpmgr_init(void)
{
os_lpmgr_init(hal_sleep);
os_kprintf("LPMGR initialized\r\n");
}6.5 Shell 命令调试
power_request 1 # 请求 IDLE 模式(禁止深度睡眠)
power_release 1 # 释放 IDLE 模式限制
power_status # 查看当前低功耗状态输出示例:
| Power Management Mode | Counter | Timer |
+-----------------------+---------+-------+
lpmgr current sleep mode: LightSleep Mode
| no | priv | ops |
+-------+------------+------------+
| 0 | 0x20001234 | 0x08004567 |
total register dev num: 1七、注意事项
- suspend 返回值:如果某外设的
suspend返回失败,框架会回滚已挂起的外设并放弃本次睡眠 - 最小睡眠时间:通过
BSP_USING_MINSLEEP_MS宏配置最小睡眠时间,太短不值得进入深度睡眠 - 低功耗定时器:深度睡眠时系统主时钟停止,需使用低功耗定时器(LPCE)作为唤醒源
- 中断唤醒:任何中断都可以唤醒系统,
os_lpmgr_irq_entry通过OS_IRQ_HOOK注册为中断钩子 - 时间补偿:唤醒后自动补偿系统 tick,保证定时器准确性
📝 本节小结
- LPMGR 是 OneOS 的低功耗管理框架,协调 CPU 和外设进入/退出低功耗状态
- 支持多级睡眠模式(Idle/Light/Deep/Standby/Shutdown),功耗和唤醒延迟逐级增加
- 外设驱动通过
os_lpmgr_device_register注册 suspend/resume 回调参与功耗管理 - 应用通过
os_lpmgr_request/release声明所需的睡眠模式级别 - Tickless 机制 + 时间补偿确保睡眠不影响系统定时器精度
- Shell 命令
power_request/power_release/power_status便于调试