注意

这是最新开发分支配套的文档,可能包含已发布版本中尚未提供的功能。如果您要查看特定版本的文档,请使用左侧的下拉菜单并选择所需要的版本。

PMU HAL 接口文档#

概述#

K230 提供了 PMU HAL 接口,用于在系统运行态处理中长按关机流程,以及配置 RTC 定时关机/定时开机。

  • 用户态 HAL 头文件:src/rtsmart/libs/rtsmart_hal/drivers/pmu/drv_pmu.h

  • 用户态 HAL 实现:src/rtsmart/libs/rtsmart_hal/drivers/pmu/drv_pmu.c

  • 参考示例:src/rtsmart/examples/peripheral/pmu/test_pmu.c

PMU HAL 当前主要覆盖两类能力:

  1. 长按电源键关机通知与用户态 ACK

  2. RTC 定时关机、定时开机(power cycle)

注意:RTC 普通读写时间、普通 alarm/tick 中断配置属于 RTC 设备接口能力,不在 drv_pmu.h 这个 HAL 头文件内。


事件模型#

长按关机流程由内核驱动和用户态 HAL 协同完成:

  1. 用户态调用 drv_pmu_register_notify() 注册信号通知

  2. 用户长按电源键达到阈值后,驱动上报 DRV_PMU_EVENT_LONG_PRESS

  3. 用户态完成保存状态、卸载文件系统等清理动作

  4. 用户松开电源键后,驱动上报 DRV_PMU_EVENT_KEY_RELEASE

  5. 用户态调用 drv_pmu_ack_shutdown() 发送 ACK

  6. 驱动收到 ACK 后执行真正关机

如果用户态不发送 ACK,则系统会保持当前运行状态,不会自动关机。


数据结构说明#

drv_pmu_inst_t#

描述:PMU HAL 实例句柄,内部封装了 /dev/pmu_pwrkey 设备节点、信号等待集和通知注册状态。该类型对用户透明。

drv_pmu_event_t#

描述:PMU 事件位图类型。

DRV_PMU_EVENT_LONG_PRESS#

描述:检测到长按关机事件。

DRV_PMU_EVENT_KEY_RELEASE#

描述:长按之后检测到电源键松开事件。


函数接口说明#

int drv_pmu_inst_create(drv_pmu_inst_t **inst);#

功能:创建 PMU HAL 实例并打开 /dev/pmu_pwrkey

参数

  • inst:返回创建好的 PMU 实例

返回值

  • 0:成功

  • -1:失败


void drv_pmu_inst_destroy(drv_pmu_inst_t **inst);#

功能:销毁 PMU HAL 实例,自动注销通知并关闭设备。

参数

  • inst:PMU 实例指针的指针


int drv_pmu_register_notify(drv_pmu_inst_t *inst, int signo);#

功能:注册 PMU 事件通知。

注册成功后,驱动会向当前进程发送指定信号,用户态可通过 drv_pmu_wait_event() 等待并读取事件。

参数

  • inst:PMU 实例

  • signo:通知信号编号;小于等于 0 时默认使用 SIGUSR1

返回值

  • 0:成功

  • -1:失败

说明

  • HAL 内部会自动阻塞该信号,并在销毁或注销时恢复

  • 重复调用会先注销旧通知,再重新注册


int drv_pmu_unregister_notify(drv_pmu_inst_t *inst);#

功能:注销 PMU 事件通知。

参数

  • inst:PMU 实例

返回值

  • 0:成功

  • -1:失败


int drv_pmu_wait_event(drv_pmu_inst_t *inst, drv_pmu_event_t *event, int timeout_ms);#

功能:等待 PMU 事件并读取事件位图。

参数

  • inst:PMU 实例

  • event:返回的事件位图

  • timeout_ms:等待超时,单位 ms;小于 0 表示永久等待

返回值

  • 0:成功收到事件

  • 1:超时,或等待被信号中断

  • -1:失败

说明

  • 调用前必须已经执行 drv_pmu_register_notify()

  • 成功时返回的事件可能同时包含多个 bit


int drv_pmu_ack_shutdown(drv_pmu_inst_t *inst);#

功能:向驱动发送关机 ACK。

通常应在收到 DRV_PMU_EVENT_KEY_RELEASE 后调用,表示用户态清理完成并允许系统关机。

参数

  • inst:PMU 实例

返回值

  • 0:成功

  • -1:失败


int drv_pmu_schedule_power_cycle(drv_pmu_inst_t *inst, uint32_t shutdown_after_s, uint32_t poweron_after_s);#

功能:配置一次 RTC 定时关机/开机流程。

系统会在 shutdown_after_s 秒后关机,并在关机后再等待 poweron_after_s 秒自动开机。

参数

  • inst:PMU 实例

  • shutdown_after_s:距离关机的延迟时间,单位秒

  • poweron_after_s:距离重新开机的延迟时间,单位秒

返回值

  • 0:成功

  • -1:失败

说明

  • 当前驱动要求两个参数通常都不小于 2

  • poweron_after_s 是从关机时刻开始计时,不是从调用接口时刻开始计时


int drv_pmu_cancel_power_cycle(drv_pmu_inst_t *inst);#

功能:取消当前已配置的 RTC 定时关机/开机流程。

参数

  • inst:PMU 实例

返回值

  • 0:成功

  • -1:失败


int drv_pmu_event_has_long_press(drv_pmu_event_t event);#

功能:判断事件位图中是否包含长按事件。

参数

  • event:PMU 事件位图

返回值

  • 0:包含 DRV_PMU_EVENT_LONG_PRESS

  • 0:不包含


int drv_pmu_event_has_key_release(drv_pmu_event_t event);#

功能:判断事件位图中是否包含按键松开事件。

参数

  • event:PMU 事件位图

返回值

  • 0:包含 DRV_PMU_EVENT_KEY_RELEASE

  • 0:不包含


推荐使用流程#

长按关机场景#

  1. 调用 drv_pmu_inst_create() 创建设备句柄

  2. 调用 drv_pmu_register_notify() 注册 PMU 事件通知

  3. 循环调用 drv_pmu_wait_event() 等待事件

  4. 收到 DRV_PMU_EVENT_LONG_PRESS 后执行用户态清理

  5. 收到 DRV_PMU_EVENT_KEY_RELEASE 后调用 drv_pmu_ack_shutdown()

  6. 退出前调用 drv_pmu_inst_destroy() 释放资源

RTC 定时开关机场景#

  1. 调用 drv_pmu_inst_create() 创建设备句柄

  2. 调用 drv_pmu_schedule_power_cycle() 配置关机与开机延时

  3. 如需取消,调用 drv_pmu_cancel_power_cycle()

  4. 结束后调用 drv_pmu_inst_destroy() 释放资源


最小示例#

长按关机监听示例#

#include <stdio.h>
#include "drv_pmu.h"

int pmu_wait_shutdown(void)
{
    drv_pmu_inst_t *pmu = NULL;
    drv_pmu_event_t event;

    if (drv_pmu_inst_create(&pmu) < 0)
        return -1;

    if (drv_pmu_register_notify(pmu, 0) < 0)
        goto err;

    for (;;) {
        int ret = drv_pmu_wait_event(pmu, &event, -1);

        if (ret < 0)
            goto err;
        if (ret > 0)
            continue;

        if (drv_pmu_event_has_long_press(event)) {
            /* 执行用户态清理 */
        }

        if (drv_pmu_event_has_key_release(event)) {
            if (drv_pmu_ack_shutdown(pmu) < 0)
                goto err;
            break;
        }
    }

    drv_pmu_inst_destroy(&pmu);
    return 0;

err:
    drv_pmu_inst_destroy(&pmu);
    return -1;
}

RTC 定时开关机示例#

#include <stdint.h>
#include "drv_pmu.h"

int pmu_schedule_cycle(uint32_t shutdown_after_s, uint32_t poweron_after_s)
{
    drv_pmu_inst_t *pmu = NULL;
    int ret = -1;

    if (drv_pmu_inst_create(&pmu) < 0)
        return -1;

    if (drv_pmu_schedule_power_cycle(pmu,
                                     shutdown_after_s,
                                     poweron_after_s) < 0)
        goto out;

    ret = 0;

out:
    drv_pmu_inst_destroy(&pmu);
    return ret;
}

注意事项#

  1. 使用前需要确保系统已启用 RT_USING_RTC_PMU,并且存在设备节点 /dev/pmu_pwrkey

  2. drv_pmu_wait_event() 依赖信号通知机制,建议由专门线程统一等待和处理。

  3. drv_pmu_ack_shutdown() 应在收到 DRV_PMU_EVENT_KEY_RELEASE 后调用。

  4. 如果应用决定不关机,可以不发送 ACK,系统会继续运行。

  5. drv_pmu_schedule_power_cycle() 依赖 RTC 当前时间正确,使用前建议先确认 RTC 时间已设置。

  6. 当前 HAL 不配置“关机后长按开机”的硬件长按阈值,该阈值由底层 PMU 寄存器策略决定。


使用示例#

请参考 src/rtsmart/examples/peripheral/pmu/test_pmu.c

评论列表
条评论
登录