注意

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

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. 长按电源键关机通知与用户态确认

  2. 应用主动立即关机

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

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

接口按功能分组:key_* 只处理电源键长按事件,rtc_* 只处理 RTC 定时 power cycle,drv_pmu_shutdown_now() 是应用主动立即关机接口。


内核配置#

PMU 驱动和关机后唤醒源需要在 RT-Smart 内核配置中打开。配置入口:

Drivers Configuration
  -> InterDriver
    -> Using RTC/PMU device drivers

启用 Using RTC/PMU device drivers 后,对应的 Kconfig 符号为 RT_USING_RTC_PMU。该选项会启用 PMU/RTC 内核驱动,并生成 /dev/pmu_pwrkey 等设备节点。

长按关机时间#

Using RTC/PMU device drivers 菜单内,可以配置:

PMU long press shutdown seconds

对应符号为 RT_PMU_SOFT_SHUTDOWN_SECONDS,用于设置系统运行态的软件长按关机时间,单位为秒。该配置不改变关机后 PMU 硬件长按开机阈值。

关机后 PAD 唤醒#

Using RTC/PMU device drivers 菜单内,可以打开:

PMU shutdown wakeup

对应符号为 RT_PMU_SHUTDOWN_WAKEUP。打开后,系统在执行关机流程前会配置一个额外的 PMU 输入 PAD 作为关机后的唤醒源。

可配置项如下:

配置项

Kconfig 符号

说明

PMU shutdown wakeup PAD

RT_PMU_SHUTDOWN_WAKEUP_PAD65 ~ RT_PMU_SHUTDOWN_WAKEUP_PAD69

选择 PAD65、PAD66、PAD67、PAD68、PAD69 之一作为关机后唤醒源。默认选择 PAD68。

PMU shutdown wakeup trigger type

RT_PMU_SHUTDOWN_WAKEUP_HIGH_LEVELRT_PMU_SHUTDOWN_WAKEUP_LOW_LEVELRT_PMU_SHUTDOWN_WAKEUP_RISING_EDGERT_PMU_SHUTDOWN_WAKEUP_FALLING_EDGE

选择高电平、低电平、上升沿或下降沿触发。默认选择上升沿。

PMU shutdown wakeup PAD pull bias

RT_PMU_SHUTDOWN_WAKEUP_BIAS_KEEPRT_PMU_SHUTDOWN_WAKEUP_BIAS_PULL_UPRT_PMU_SHUTDOWN_WAKEUP_BIAS_PULL_DOWNRT_PMU_SHUTDOWN_WAKEUP_BIAS_DISABLE

选择关机前是否修改所选 PAD 对应 PMU_IO_CFG_xPU/PD 位。默认保持当前寄存器状态。

PMU shutdown wakeup debounce ticks

RT_PMU_SHUTDOWN_WAKEUP_DEBOUNCE_TICKS

配置 PAD65、PAD66、PAD67 的 debounce 时间,单位为 32 KHz PMU 时钟周期,取值范围为 0 ~ 4095,默认 256。

说明:

  1. PAD64 不在该配置项中。PAD64 保留给现有电源键长按开关机流程使用。

  2. PAD68 和 PAD69 没有 debounce 寄存器,因此选择 PAD68 或 PAD69 时菜单不会显示 PMU shutdown wakeup debounce ticks

  3. PAD65、PAD66、PAD67 支持 debounce 配置。选择这些 PAD 时,菜单会显示 PMU shutdown wakeup debounce ticks

  4. PMU_IO_CFG_0 ~ PMU_IO_CFG_5 分别对应 PAD64 ~ PAD69。按照 K230 TRM,PAD64 ~ PAD69 的复位默认值为 0x1124,其中 IO_SEL=010(interrupt input)、IE=1OE=0PU=0PD=1,即默认作为中断输入并打开内部下拉。运行过程中寄存器可能已被驱动或板级代码修改,不能把复位值当作当前值。

  5. 如果按键是低电平有效,且选择低电平或下降沿唤醒,建议在 PMU shutdown wakeup PAD pull bias 中选择 Pull up,或者确保板级电路已经提供稳定外部上拉。

  6. 如果按键是高电平有效,且选择高电平或上升沿唤醒,可以选择 Pull down,或者依赖板级外部下拉。

  7. 如果板级电路已经有明确的外部上下拉且不希望内部上下拉影响外部电路,可以选择 Disable pull up/down

  8. 该功能是关机后的 PMU 硬件唤醒源配置,不需要用户态 HAL 在关机后继续运行。

  9. 如果同时配置了 RTC 定时开机,关机前驱动会同时打开 RTC alarm 唤醒源和所选 PAD 唤醒源。

配置完成后重新编译固件。下次系统执行 PMU 关机流程时,驱动会在关机前根据上述配置写入 PMU 中断检测和唤醒路由配置,使所选 PAD 可以作为关机后的唤醒条件。


按键关机模型#

短按、长按计时和按键松开均由内核驱动处理,用户态不接收这些底层事件。

  1. 用户态调用 drv_pmu_key_register_notify() 注册电源键关机请求通知

  2. 内核过滤短按;达到长按阈值后,只向用户态发送一次关机请求通知

  3. 用户态调用 drv_pmu_key_wait_shutdown() 等待关机请求

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

  5. 用户态调用 drv_pmu_key_confirm_shutdown() 确认清理完成

  6. 接口返回后,驱动继续等待用户释放电源键;确认按键已经释放后才执行真正关机

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


数据结构说明#

drv_pmu_inst_t#

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


函数接口说明#

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_key_register_notify(drv_pmu_inst_t *inst, int signo);#

功能:注册 PMU 事件通知。

注册成功后,驱动会向当前进程发送指定信号,用户态可通过 drv_pmu_key_wait_shutdown() 等待关机请求。

参数

  • inst:PMU 实例

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

返回值

  • 0:成功

  • -1:失败

说明

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

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


int drv_pmu_key_unregister_notify(drv_pmu_inst_t *inst);#

功能:注销 PMU 事件通知。

参数

  • inst:PMU 实例

返回值

  • 0:成功

  • -1:失败


int drv_pmu_key_wait_shutdown(drv_pmu_inst_t *inst, int timeout_ms);#

功能:等待内核确认过的长按关机请求。

参数

  • inst:PMU 实例

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

返回值

  • 0:收到关机请求

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

  • -1:失败

说明

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

  • 短按不会返回关机请求


int drv_pmu_key_confirm_shutdown(drv_pmu_inst_t *inst);#

功能:确认电源键长按关机流程中的用户态清理已经完成。

收到 drv_pmu_key_wait_shutdown() 返回成功后,完成用户态清理即可调用。调用后驱动会继续等待用户释放电源键,用户态不需要等待或判断松开事件。

参数

  • inst:PMU 实例

返回值

  • 0:成功

  • -1:失败


int drv_pmu_shutdown_now(drv_pmu_inst_t *inst);#

功能:立即执行 PMU 关机。

该接口不依赖电源键长按事件,也不会等待 KEY_RELEASE,因此会绕过“必须长按才能关机”的按键策略。应用调用前应自行完成必要的清理动作。正常产品的电源键关机流程不应调用此接口。


int drv_pmu_wakeup_pad_get_level(drv_pmu_inst_t *inst, int *level);#

功能:读取当前配置的关机唤醒 PAD 的 IO 电平。

参数

  • inst:PMU 实例

  • level:输出当前电平,0 表示低电平,1 表示高电平

返回值

  • 0:成功

  • -1:失败;未启用关机唤醒 PAD 配置时也会失败

说明

  • 使用编译配置中选择的 RT_PMU_SHUTDOWN_WAKEUP_PAD,调用者不需要传入 PAD 编号

  • 系统初始化后会将该 PAD 配置为 GPIO 输入,接口可以直接读取当前电平,不会在每次调用时切换复用功能

  • 进入关机流程时,驱动会先恢复该 PAD 的 PMU 输入功能,再配置唤醒检测

  • 驱动保存并使用初始化前的寄存器配置作为恢复基础,但会确保进入关机流程时 IO_SEL 为 PMU 输入功能

  • 读取的是当前运行态电平,不是 PMU 唤醒触发条件的逻辑判断结果


int drv_pmu_rtc_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:失败

说明

  • 该接口用于取消尚未开始执行的 RTC 定时关机/开机任务

  • 没有待取消任务时调用也会返回成功,接口可以安全地重复调用

  • 如果 RTC 关机流程已经进入实际关机阶段,再调用该接口不能保证阻止关机

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

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


int drv_pmu_rtc_cancel_power_cycle(drv_pmu_inst_t *inst);#

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

参数

  • inst:PMU 实例

返回值

  • 0:成功

  • -1:失败


推荐使用流程#

应用主动立即关机#

  1. 调用 drv_pmu_inst_create() 创建实例

  2. 应用完成必要的资源清理

  3. 调用 drv_pmu_shutdown_now() 立即关机

该接口不代表电源键策略,也不会检查长按状态。若产品要求“只有长按才能关机”,业务代码不应调用该接口,而应只使用下面的电源键监听流程。

长按关机场景#

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

  2. 调用 drv_pmu_key_register_notify() 注册电源键事件通知

  3. 循环调用 drv_pmu_key_wait_shutdown() 等待关机请求

  4. 收到关机请求后执行用户态清理

  5. 调用 drv_pmu_key_confirm_shutdown() 确认清理完成

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

RTC 定时开关机场景#

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

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

  3. 如需取消,调用 drv_pmu_rtc_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;
    if (drv_pmu_inst_create(&pmu) < 0)
        return -1;

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

    for (;;) {
        int ret = drv_pmu_key_wait_shutdown(pmu, -1);

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

        /* 执行用户态清理 */
        if (drv_pmu_key_confirm_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_rtc_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_key_wait_shutdown() 依赖信号通知机制,建议由专门线程统一等待和处理。

  3. drv_pmu_key_confirm_shutdown() 只适用于内核发出的关机请求;调用确认后驱动会等待电源键释放,再执行关机。短按会在内核侧直接消化,不会触发通知或关机。

  4. drv_pmu_shutdown_now() 会绕过长按策略,使用时必须由应用自行负责清理。

  5. 如果应用决定不关机,可以不调用 drv_pmu_key_confirm_shutdown(),系统会继续运行。

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

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


使用示例#

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

评论列表
条评论
登录