电源管理驱动实现
创建电源管理适配器
电源适配器驱动相关信息位于“libsylixos/SylixOS/system/pm”下,其适配器创建函数原型如下:
#include <SylixOS.h>
PLW_PM_ADAPTER API_PowerMAdapterCreate (CPCHAR pcName,
UINT uiMaxChan,
PLW_PMA_FUNCS pmafuncs);
函数 API_PowerMAdapterCreate 原型分析:
- 函数成功返回电源管理适配器指针,失败返回 LW_NULL 。
- 参数 pcName 是电源管理适配器的名称。
- 参数 uiMaxChan 是电源管理适配器最大通道号。
- 参数 pmafuncs 是电源管理适配器操作函数。
函数 API_PowerMAdapterCreate 使用结构体 PLW_PMA_FUNCS 来向内核提供传输函数集合,其详细描述如下:
typedef struct lw_pma_funcs {
INT (*PMAF_pfuncOn) (PLW_PM_ADAPTER pmadapter,
PLW_PM_DEV pmdev); /* 打开设备电源与时钟 */
INT (*PMAF_pfuncOff) (PLW_PM_ADAPTER pmadapter,
PLW_PM_DEV pmdev); /* 关闭设备电源与时钟 */
INT (*PMAF_pfuncIsOn) (PLW_PM_ADAPTER pmadapter,
PLW_PM_DEV pmdev,
BOOL *pbIsOn); /* 是否打开 */
PVOID PMAF_pvReserve[16]; /* 保留 */
} LW_PMA_FUNCS;
typedef LW_PMA_FUNCS *PLW_PMA_FUNCS;
- PMAF_pfuncOn:打开设备电源与时钟函数。
- 第一个参数 pmadapter 为电源管理适配器指针,第二个参数 pmdev 是电源管理的设备节点指针。
- PMAF_pfuncOff:关闭设备电源与时钟函数。
- 第一个参数 pmadapter 为电源管理适配器指针,第二个参数 pmdev 是电源管理的设备节点指针。
- PMAF_pfuncIsOn:电源管理设备是否打开函数。
- 第一个参数 pmadapter 为电源管理适配器指针,第二个参数 pmdev 是电源管理的设备节点指针,第三个输出参数 pbIsOn 返回节点是否打开。
- PMAF_pvReserve:保留位。
PLW_PM_ADAPTER 数据结构主要包含当前电源管理适配器节点信息,结构体的详细描述如下:
#include <SylixOS.h>
typedef struct {
LW_LIST_LINE PMA_lineManage; /* 管理链表 */
UINT PMA_uiMaxChan; /* 电源管理通道总数 */
struct lw_pma_funcs *PMA_pmafunc; /* 电源管理适配器操作函数 */
PVOID PMA_pvReserve[8];
CHAR PMA_cName[1]; /* 电源管理适配器名称 */
} LW_PM_ADAPTER;
typedef LW_PM_ADAPTER *PLW_PM_ADAPTER;
- PMA_lineManage:管理链表,双向线形管理表。
- PMA_uiMaxChan:管理通道总数。
- PMA_pmafunc:指向电源管理适配器操作函数,即 API_PowerMAdapterCreate 函数注册到系统的操作函数集指针。
- PMA_pvReserve:保留位。
- PMA_cName:电源管理适配器名称。
系统提供 API_PowerMAdapterDelete 函数删除一个电源管理适配器,函数原型如下:
#include <SylixOS.h>
INT API_PowerMAdapterDelete (PLW_PM_ADAPTER pmadapter);
函数 API_PowerMAdapterDelete 原型分析:
- 函数成功返回 ERROR_NONE ,失败返回 PX_ERROR 。
- 参数 pmadapter 是电源管理适配器指针。
注:系统不推荐使用此函数来删除电源管理适配器。
系统提供 API_PowerMAdapterFind 函数查询一个电源管理适配器,函数原型如下:
#include <SylixOS.h>
PLW_PM_ADAPTER API_PowerMAdapterFind (CPCHAR pcName);
函数 API_PowerMAdapterFind 原型分析:
- 函数成功返回电源管理适配器指针,失败返回 LW_NULL 。
- 参数 pcName 是电源管理适配器名称。
创建电源管理适配器节点
编写电源管理外设驱动程序时,需要创建电源管理适配器节点,并把电源管理适配器节点加入到电源管理适配器中,以实现系统统一管理。创建电源管理适配器节点前需要实现外设的休眠、省电等电源管理操作的功能函数。
系统提供 API_PowerMDevInit 函数创建电源管理适配器节点,并完成电源管理适配器节点和电源管理适配器的绑定。函数原型如下:
#include <SylixOS.h>
INT API_PowerMDevInit (PLW_PM_DEV pmdev,
PLW_PM_ADAPTER pmadapter,
UINT uiChan,
PLW_PMD_FUNCS pmdfunc);
函数 API_PowerMDevInit 原型分析:
- 函数成功返回 ERROR_NONE ,失败返回 PX_ERROR 。
- 参数 pmdev 是电源管理适配器设备节点指针。
- 参数 pmadapter 是电源管理节点所在电源管理适配器指针。
- 参数 uiChan 是电源管理节点所在电源管理适配器通道号。
- 参数 pmdfunc 是电源管理适配器节点操作函数。
API_PowerMDevInit 函数使用结构体 PLW_PMD_FUNCS 来向内核提供传输函数集合,其详细描述如下:
typedef struct lw_pmd_funcs {
INT (*PMDF_pfuncSuspend) (PLW_PM_DEV pmdev); /* CPU 休眠 */
INT (*PMDF_pfuncResume) (PLW_PM_DEV pmdev); /* CPU 恢复 */
INT (*PMDF_pfuncPowerSavingEnter)(PLW_PM_DEV pmdev); /* 系统进入省电模式 */
INT (*PMDF_pfuncPowerSavingExit) (PLW_PM_DEV pmdev); /* 系统退出省电模式 */
INT (*PMDF_pfuncIdleEnter) (PLW_PM_DEV pmdev); /* 设备长时间不使用进入空闲 */
INT (*PMDF_pfuncIdleExit) (PLW_PM_DEV pmdev); /* 设备退出空闲 */
INT (*PMDF_pfuncCpuPower) (PLW_PM_DEV pmdev); /* CPU 改变主频能级 */
PVOID PMDF_pvReserve[16]; /* 保留 */
} LW_PMD_FUNCS;
typedef LW_PMD_FUNCS *PLW_PMD_FUNCS;
- PMDF_pfuncSuspend:CPU 休眠函数。
- 参数 pmdev 为电源管理设备节点指针,系统进入休眠状态时,具有电源管理功能的设备将调用此函数进入 Suspend 模式。
- PMDF_pfuncResume:CPU 恢复函数。
- 参数 pmdev 为电源管理设备节点指针,系统需要通过指定事件唤醒,离开休眠模式,将从复位向量处恢复,此时需要 BOOTLOADER 或 BIOS 程序配合。
- PMDF_pfuncPowerSavingEnter:系统进入省电模式函数。
- 参数 pmdev 为电源管理设备节点指针,系统进入省电模式时,所有具有电源管理功能的设备进入省电模式,同时 CPU 降速,多核 CPU 仅保留一个 CPU 运行。
- PMDF_pfuncPowerSavingExit:系统退出省电模式函数。
- 参数 pmdev 为电源管理设备节点指针。
- PMDF_pfuncIdleEnter:设备长时间不使用进入空闲状态函数。
- 参数 pmdev 为电源管理设备节点指针,如果设备功耗管理单元具有看门狗功能,一旦设备空闲时间超过看门狗设置,系统会自动调用 PMDF_pfuncIdleEnter 函数,请求将设备变为空闲状态。
- PMDF_pfuncIdleExit:设备退出空闲状态。
- 参数 pmdev 为电源管理设备节点指针。
- PMDF_pfuncCpuPower:CPU 改变主频能级函数。
- 参数 pmdev 为电源管理设备节点指针。
- PMDF_pvReserve:保留位。
PLW_PM_DEV 数据结构主要包含当前电源管理设备的相关信息,结构体详细描述如下:
typedef struct {
LW_LIST_LINE PMD_lineManage; /* 管理链表 */
PLW_PM_ADAPTER PMD_pmadapter; /* 电源管理适配器 */
UINT PMD_uiChannel; /* 对应电源管理适配器通道号 */
PVOID PMD_pvReserve[8];
PCHAR PMD_pcName; /* 管理节点名 */
PVOID PMD_pvBus; /* 总线信息 (驱动程序自行使用) */
PVOID PMD_pvDev; /* 设备信息 (驱动程序自行使用) */
UINT PMD_uiStatus; /* 初始为 0 */
#define LW_PMD_STAT_NOR 0
#define LW_PMD_STAT_IDLE 1
LW_CLASS_WAKEUP_NODE PMD_wunTimer; /* 空闲时间计算 */
#define PMD_bInQ PMD_wunTimer.WUN_bInQ
#define PMD_ulCounter PMD_wunTimer.WUN_ulCounter
struct lw_pmd_funcs *PMD_pmdfunc; /* 电源管理适配器操作函数 */
} LW_PM_DEV;
typedef LW_PM_DEV *PLW_PM_DEV;
- PMD_lineManage:管理链表,双向线形管理表。
- PMD_pmadapter:设备节点所在的电源管理适配器。
- PMD_uiChannel:对应的电源管理适配器通道号。
- PMD_pvReserve:保留位。
- PMD_pcName:管理设备节点名称。
- PMD_pvBus:总线信息(驱动程序自行使用)。
- PMD_pvDev:设备信息(驱动程序自行使用)。
- PMD_uiStatus:设备状态,取值如下表所示。
设备状态 | 含义 |
---|---|
LW_PMD_STAT_NOR | 设备正常工作 |
LW_PMD_STAT_IDLE | 设备空闲 |
- PMD_wunTimer:设备节点空闲时间计算。
- PMD_pmdfunc:指向电源管理适配器设备节点操作函数。
系统提供 API_PowerMDevTerm 函数删除一个电源管理适配器节点。函数原型如下:
#include <SylixOS.h>
INT API_PowerMDevTerm (PLW_PM_DEV pmdev);
函数 API_PowerMDevTerm 原型分析:
- 函数成功返回 ERROR_NONE ,失败返回 PX_ERROR 。
- 参数 pmdev 是电源管理适配器设备节点指针。
系统提供的API函数 API_PowerMDevOn,提供给用户在第一次打开一个电源管理适配器设备节点时调用。函数原型如下:
#include <SylixOS.h>
INT API_PowerMDevOn (PLW_PM_DEV pmdev);
函数 API_PowerMDevOn 原型分析:
- 函数成功返回 ERROR_NONE ,失败返回 PX_ERROR 。
- 参数 pmdev 是电源管理适配器设备节点指针。
系统提供的API函数 API_PowerMDevOff,提供给用户在最后一次关闭一个电源管理适配器设备节点时调用,函数原型如下:
#include <SylixOS.h>
INT API_PowerMDevOff (PLW_PM_DEV pmdev);
函数 API_PowerMDevOff 原型分析:
- 函数成功返回 ERROR_NONE ,失败返回 PX_ERROR 。
- 参数 pmdev 是电源管理适配器设备节点指针。
电源管理内核线程分析及设备空闲时间管理
在内核启动过程中,内核将会调用 _PowerMInit 函数初始化电源管理,此时会创建一个电源管理线程“t_power”。SylixOS 电源管理系统提供了自动检测设备空闲并管理设备的功能,即对于支持空闲管理的电源设备(如显示器等)在长时间不使用时,应该将其置为休闲模式。对于显示器来说即关闭屏幕显示,从而降低设备的功耗,该功能用用于对产品功耗有要求的开发者使用,可以通过软件层面降低产品的功耗。
SylixOS 电源管理系统提供的电源管理设备的空闲管理功能线程介绍如下:
#include <SylixOS.h>
static PVOID _PowerMThread (PVOID pvArg);
在“t_power”电源管理线程中,会循环判断当前唤醒链表中是否有超时的电源设备,若有则获取当前超时电源设备,从唤醒表中删除该电源设备,同时修改该电源设备状态为空闲状态,执行相关状态切换操作;若没有则将定时器计数自减。
SylixOS 的电源设备空闲时间管理提供了三个接口,包括设置电源设备进入空闲模式的时间,获取电源设备进入空闲模式剩余的时间和关闭电源设备的空闲时间管理功能这三个函数。函数原型分别如下:
#include <SylixOS.h>
INT API_PowerMDevSetWatchDog (PLW_PM_DEV pmdev, ULONG ulSecs);
函数 API_PowerMDevSetWatchDog 原型分析:
- 函数成功返回 ERROR_NONE ,失败返回 PX_ERROR 。
- 参数 pmdev 是电源管理适配器设备节点指针。
- 参数 ulSecs 是设置经过指定的秒数,设备将进入 idle 模式。
#include <SylixOS.h>
INT API_PowerMDevGetWatchDog (PLW_PM_DEV pmdev, ULONG *pulSecs);
函数 API_PowerMDevGetWatchDog 原型分析:
- 函数成功返回 ERROR_NONE ,失败返回 PX_ERROR 。
- 参数 pmdev 是电源管理适配器设备节点指针。
- 参数 ulSecs 是设备将进入 idle 模式剩余的时间。
#include <SylixOS.h>
INT API_PowerMDevWatchDogOff(PLW_PM_DEV pmdev);
函数 PowerMDevWatchDogOff 原型分析:
- 函数成功返回 ERROR_NONE ,失败返回 PX_ERROR 。
- 参数 pmdev 是电源管理适配器设备节点指针。
设备驱动程序中若需要添加空闲管理功能,则应在设备驱动的使用函数(如接收函数、发送函数等)中注册看门狗,即调用函数 API_PowerMDevSetWatchDog,设备被添加到系统唤醒列表中,在“t_power”电源管理线程中进行设备空闲状态检测,从而实现空闲管理功能。
嵌入式系统由硬件环境、嵌入式操作系统和应用程序组成,硬件环境是操作系统和应用程序运行的硬件平台,应用程序的不同会对硬件环境提出不同的要求。因此,对于嵌入式系统来说,其运行的硬件平台具有多样性。为了给操作系统提供统一的运行环境,通常的做法是在硬件平台和操作系统之间提供硬件相关层,来屏蔽硬件差异。这种硬件相关层就是嵌入式系统中的板级支持包(Board Support Package,简称 BSP)。