1. CONFIG配置总开关
CONFIG_SYS_POWER_MANAGEMENT=y
CONFIG_DEVICE_POWER_MANAGEMENT=y
CONFIG_DEVICE_IDLE_PM=y
2. 设备注册API接口
设备
/**
* @brief Device PM info
*
* @param dev pointer to device structure
* @param lock lock to synchronize the get/put operations
* @param enable device pm enable flag
* @param usage device usage count
* @param fsm_state device idle internal power state
* @param event event object to listen to the sync request events
* @param signal signal to notify the Async API callers
*/
struct device_pm {
struct device *dev;
struct k_sem lock;
bool enable;
atomic_t usage;
atomic_t fsm_state;
struct k_work work;
struct k_poll_event event;
struct k_poll_signal signal;
};
/**
* @brief Static device information (In ROM) Per driver instance
*
* @param name name of the device
* @param init init function for the driver
* @param config_info address of driver instance config information
*/
struct device_config {
const char *name;
int (*init)(struct device *device);
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
int (*device_pm_control)(struct device *device, u32_t command,
void *context, device_pm_cb cb, void *arg);
struct device_pm *pm;
#endif
const void *config_info;
};
/**
* @brief Runtime device structure (In memory) Per driver instance
* @param device_config Build time config information
* @param driver_api pointer to structure containing the API functions for
* the device type. This pointer is filled in by the driver at init time.
* @param driver_data driver instance data. For driver use only
*/
struct device {
struct device_config *config;
const void *driver_api;
void *driver_data;
#if defined(__x86_64) && __SIZEOF_POINTER__ == 4
/* The x32 ABI hits an edge case. This is a 12 byte struct,
* but the x86_64 linker will pack them only in units of 8
* bytes, leading to alignment problems when iterating over
* the link-time array.
*/
void *padding;
#endif
};
API 接口定义
#define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, \
data, cfg_info, level, prio, api) \
static struct device_pm _CONCAT(__pm_, dev_name) __used \
= { \
.usage = ATOMIC_INIT(0), \
.lock = _K_SEM_INITIALIZER( \
_CONCAT(__pm_, dev_name).lock, 1, 1), \
.signal = K_POLL_SIGNAL_INITIALIZER( \
_CONCAT(__pm_, dev_name).signal), \
.event = K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, \
K_POLL_MODE_NOTIFY_ONLY, \