设备电源管理驱动
其实之前我们在将设备驱动模型的时候有有一个参数我们一直没说,那就电源管理控制函数。
我们在注册驱动的时候时需要提供一个设备电源管理函数的。
#define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_control_fn, \data_ptr, cfg_ptr, level, prio, api_ptr) \
其中:pm_control_fn就是设备管理控制函数。
函数原型如下:
int dummy_device_pm_ctrl(const struct device *dev,enum pm_device_action action)
其中pm_device_action为设备电源管理操作类型:
/** @brief Device PM actions. */enum pm_device_action {/** Suspend. */PM_DEVICE_ACTION_SUSPEND,/** Resume. */PM_DEVICE_ACTION_RESUME,/** Turn off. */PM_DEVICE_ACTION_TURN_OFF,/** Force suspend. */PM_DEVICE_ACTION_FORCE_SUSPEND,/** Low power. */PM_DEVICE_ACTION_LOW_POWER,};
设备电源管理驱动示例
/** Copyright (c) 2018 Intel Corporation** SPDX-License-Identifier: Apache-2.0*/#include <pm/device_runtime.h>#include <sys/printk.h>#include "dummy_parent.h"static uint32_t store_value;static int dummy_transfer(const struct device *dev, uint32_t cmd,uint32_t *val){printk("transfer()\n");if (cmd == DUMMY_PARENT_WR) {store_value = *val;} else {*val = store_value;}return 0;}static int dummy_parent_pm_ctrl(const struct device *dev,enum pm_device_action action){switch (action) {case PM_DEVICE_ACTION_RESUME:printk("parent resuming..\n");break;case PM_DEVICE_ACTION_SUSPEND:printk("parent suspending..\n");break;default:return -ENOTSUP;}return 0;}static const struct dummy_parent_api funcs = {.transfer = dummy_transfer,};int dummy_parent_init(const struct device *dev){//使能设备运行时设备管理pm_device_enable(dev);return 0;}DEVICE_DEFINE(dummy_parent, DUMMY_PARENT_NAME, &dummy_parent_init,dummy_parent_pm_ctrl, NULL, NULL, POST_KERNEL,CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &funcs);
控制设备电源
系统为我们提供了主动控制设备电源管理的函数:
/*** @brief Set the power state of a device.** This function calls the device PM control callback so that the device does* the necessary operations to put the device into the given state.** @note Some devices may not support all device power states.** @param dev Device instance.* @param state Device power state to be set.** @retval 0 If successful.* @retval -ENOTSUP If requested state is not supported.* @retval -EALREADY If device is already at (or transitioning to) the requested* state.* @retval Errno Other negative errno on failure.*/int pm_device_state_set(const struct device *dev,enum pm_device_state state);/*** @brief Obtain the power state of a device.** @param dev Device instance.* @param state Pointer where device power state will be stored.** @retval 0 If successful.* @retval -ENOSYS If device does not implement power management.*/int pm_device_state_get(const struct device *dev,enum pm_device_state *state);/*** @brief Force usage of given power state.** This function overrides decision made by PM policy forcing* usage of given power state immediately.** @note This function can only run in thread context** @param info Power state which should be used in the ongoing* suspend operation.*/void pm_power_state_force(struct pm_state_info info);
- pm_device_state_set: 设置设备的电源管理状态
- pm_device_state_get: 获取设备的电源管理状态
- pm_power_state_force: 强制设置电源管理的策略信息
控制设备电源示例
void main(void){int rc;const struct device *cons = device_get_binding(CONSOLE_LABEL);printk("\n%s system off demo\n", CONFIG_BOARD);/* Configure to generate PORT event (wakeup) on button 1 press. */nrf_gpio_cfg_input(DT_GPIO_PIN(DT_NODELABEL(button0), gpios),NRF_GPIO_PIN_PULLUP);nrf_gpio_cfg_sense_set(DT_GPIO_PIN(DT_NODELABEL(button0), gpios),NRF_GPIO_PIN_SENSE_LOW);printk("Busy-wait %u s\n", BUSY_WAIT_S);k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);printk("Busy-wait %u s with UART off\n", BUSY_WAIT_S);rc = pm_device_state_set(cons, PM_DEVICE_STATE_SUSPENDED);k_busy_wait(BUSY_WAIT_S * USEC_PER_SEC);rc = pm_device_state_set(cons, PM_DEVICE_STATE_ACTIVE);printk("Sleep %u s\n", SLEEP_S);k_sleep(K_SECONDS(SLEEP_S));printk("Sleep %u s with UART off\n", SLEEP_S);rc = pm_device_state_set(cons, PM_DEVICE_STATE_SUSPENDED);k_sleep(K_SECONDS(SLEEP_S));rc = pm_device_state_set(cons, PM_DEVICE_STATE_ACTIVE);printk("Entering system off; press BUTTON1 to restart\n");/* Above we disabled entry to deep sleep based on duration of* controlled delay. Here we need to override that, then* force entry to deep sleep on any delay.*/pm_power_state_force((struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0});printk("ERROR: System off failed\n");while (true) {/* spin to avoid fall-off behavior */}}
