diff --git a/components/drivers/include/drivers/pm.h b/components/drivers/include/drivers/pm.h index 45b3ae09e6..f625782616 100644 --- a/components/drivers/include/drivers/pm.h +++ b/components/drivers/include/drivers/pm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2023, RT-Thread Development Team + * Copyright (c) 2006-2024 RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -10,6 +10,7 @@ * 2019-04-28 Zero-Free improve PM mode and device ops interface * 2020-11-23 zhangsz update pm mode select * 2020-11-27 zhangsz update pm 2.0 + * 2024-07-04 wdfk-prog The device is registered and uninstalled by linked list */ #ifndef __PM_H__ @@ -134,15 +135,16 @@ struct rt_pm_ops struct rt_device_pm_ops { - int (*suspend)(const struct rt_device *device, rt_uint8_t mode); + rt_err_t (*suspend)(const struct rt_device *device, rt_uint8_t mode); void (*resume)(const struct rt_device *device, rt_uint8_t mode); - int (*frequency_change)(const struct rt_device *device, rt_uint8_t mode); + rt_err_t (*frequency_change)(const struct rt_device *device, rt_uint8_t mode); }; struct rt_device_pm { const struct rt_device *device; const struct rt_device_pm_ops *ops; + rt_slist_t list; }; struct rt_pm_module @@ -172,7 +174,7 @@ struct rt_pm rt_uint32_t sleep_status[PM_SLEEP_MODE_MAX - 1][(PM_MODULE_MAX_ID + 31) / 32]; /* the list of device, which has PM feature */ - rt_uint8_t device_pm_number; + rt_slist_t device_list; struct rt_device_pm *device_pm; /* if the mode has timer, the corresponding bit is 1*/ @@ -194,10 +196,10 @@ struct rt_pm_notify void *data; }; -void rt_pm_request(rt_uint8_t sleep_mode); -void rt_pm_release(rt_uint8_t sleep_mode); -void rt_pm_release_all(rt_uint8_t sleep_mode); -int rt_pm_run_enter(rt_uint8_t run_mode); +rt_err_t rt_pm_request(rt_uint8_t sleep_mode); +rt_err_t rt_pm_release(rt_uint8_t sleep_mode); +rt_err_t rt_pm_release_all(rt_uint8_t sleep_mode); +rt_err_t rt_pm_run_enter(rt_uint8_t run_mode); void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops); void rt_pm_device_unregister(struct rt_device *device); @@ -208,22 +210,22 @@ void rt_pm_default_set(rt_uint8_t sleep_mode); void rt_system_pm_init(const struct rt_pm_ops *ops, rt_uint8_t timer_mask, void *user_data); -void rt_pm_module_request(uint8_t module_id, rt_uint8_t sleep_mode); -void rt_pm_module_release(uint8_t module_id, rt_uint8_t sleep_mode); -void rt_pm_module_release_all(uint8_t module_id, rt_uint8_t sleep_mode); +rt_err_t rt_pm_module_request(uint8_t module_id, rt_uint8_t sleep_mode); +rt_err_t rt_pm_module_release(uint8_t module_id, rt_uint8_t sleep_mode); +rt_err_t rt_pm_module_release_all(uint8_t module_id, rt_uint8_t sleep_mode); void rt_pm_module_delay_sleep(rt_uint8_t module_id, rt_tick_t timeout); rt_uint32_t rt_pm_module_get_status(void); rt_uint8_t rt_pm_get_sleep_mode(void); struct rt_pm *rt_pm_get_handle(void); /* sleep : request or release */ -void rt_pm_sleep_request(rt_uint16_t module_id, rt_uint8_t mode); -void rt_pm_sleep_release(rt_uint16_t module_id, rt_uint8_t mode); -void rt_pm_sleep_none_request(rt_uint16_t module_id); -void rt_pm_sleep_none_release(rt_uint16_t module_id); -void rt_pm_sleep_idle_request(rt_uint16_t module_id); -void rt_pm_sleep_idle_release(rt_uint16_t module_id); -void rt_pm_sleep_light_request(rt_uint16_t module_id); -void rt_pm_sleep_light_release(rt_uint16_t module_id); +rt_err_t rt_pm_sleep_request(rt_uint16_t module_id, rt_uint8_t mode); +rt_err_t rt_pm_sleep_release(rt_uint16_t module_id, rt_uint8_t mode); +rt_err_t rt_pm_sleep_none_request(rt_uint16_t module_id); +rt_err_t rt_pm_sleep_none_release(rt_uint16_t module_id); +rt_err_t rt_pm_sleep_idle_request(rt_uint16_t module_id); +rt_err_t rt_pm_sleep_idle_release(rt_uint16_t module_id); +rt_err_t rt_pm_sleep_light_request(rt_uint16_t module_id); +rt_err_t rt_pm_sleep_light_release(rt_uint16_t module_id); #endif /* __PM_H__ */ diff --git a/components/drivers/pm/pm.c b/components/drivers/pm/pm.c index 024e301792..b4ad3b2bbd 100644 --- a/components/drivers/pm/pm.c +++ b/components/drivers/pm/pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2023, RT-Thread Development Team + * Copyright (c) 2006-2024 RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * @@ -10,6 +10,7 @@ * 2019-04-28 Zero-Free improve PM mode and device ops interface * 2020-11-23 zhangsz update pm mode select * 2020-11-27 zhangsz update pm 2.0 + * 2024-07-04 wdfk-prog The device is registered and uninstalled by linked list */ #include @@ -77,9 +78,6 @@ rt_weak void rt_pm_exit_critical(rt_uint32_t ctx, rt_uint8_t sleep_mode) /* lptimer start */ static void pm_lptimer_start(struct rt_pm *pm, uint32_t timeout) { - if (_pm.ops == RT_NULL) - return; - if (_pm.ops->timer_start != RT_NULL) _pm.ops->timer_start(pm, timeout); } @@ -87,9 +85,6 @@ static void pm_lptimer_start(struct rt_pm *pm, uint32_t timeout) /* lptimer stop */ static void pm_lptimer_stop(struct rt_pm *pm) { - if (_pm.ops == RT_NULL) - return; - if (_pm.ops->timer_stop != RT_NULL) _pm.ops->timer_stop(pm); } @@ -97,9 +92,6 @@ static void pm_lptimer_stop(struct rt_pm *pm) /* lptimer get timeout tick */ static rt_tick_t pm_lptimer_get_timeout(struct rt_pm *pm) { - if (_pm.ops == RT_NULL) - return RT_TICK_MAX; - if (_pm.ops->timer_get_tick != RT_NULL) return _pm.ops->timer_get_tick(pm); @@ -109,9 +101,6 @@ static rt_tick_t pm_lptimer_get_timeout(struct rt_pm *pm) /* enter sleep mode */ static void pm_sleep(struct rt_pm *pm, uint8_t sleep_mode) { - if (_pm.ops == RT_NULL) - return; - if (_pm.ops->sleep != RT_NULL) _pm.ops->sleep(pm, sleep_mode); } @@ -119,17 +108,22 @@ static void pm_sleep(struct rt_pm *pm, uint8_t sleep_mode) /** * This function will suspend all registered devices */ -static int _pm_device_suspend(rt_uint8_t mode) +static rt_err_t _pm_device_suspend(rt_uint8_t mode) { - int index, ret = RT_EOK; + rt_err_t ret = RT_EOK; + struct rt_device_pm *device_pm = RT_NULL; + rt_slist_t *node = RT_NULL; - for (index = 0; index < _pm.device_pm_number; index++) + for (node = rt_slist_first(&_pm.device_list); node; node = rt_slist_next(node)) { - if (_pm.device_pm[index].ops->suspend != RT_NULL) + device_pm = rt_slist_entry(node, struct rt_device_pm, list); + if (device_pm->ops != RT_NULL && device_pm->ops->suspend != RT_NULL) { - ret = _pm.device_pm[index].ops->suspend(_pm.device_pm[index].device, mode); + ret = device_pm->ops->suspend(device_pm->device, mode); if(ret != RT_EOK) + { break; + } } } @@ -141,13 +135,15 @@ static int _pm_device_suspend(rt_uint8_t mode) */ static void _pm_device_resume(rt_uint8_t mode) { - int index; + struct rt_device_pm *device_pm = RT_NULL; + rt_slist_t *node = RT_NULL; - for (index = 0; index < _pm.device_pm_number; index++) + for (node = rt_slist_first(&_pm.device_list); node; node = rt_slist_next(node)) { - if (_pm.device_pm[index].ops->resume != RT_NULL) + device_pm = rt_slist_entry(node, struct rt_device_pm, list); + if (device_pm->ops != RT_NULL && device_pm->ops->resume != RT_NULL) { - _pm.device_pm[index].ops->resume(_pm.device_pm[index].device, mode); + device_pm->ops->resume(device_pm->device, mode); } } } @@ -157,13 +153,16 @@ static void _pm_device_resume(rt_uint8_t mode) */ static void _pm_device_frequency_change(rt_uint8_t mode) { - rt_uint32_t index; + struct rt_device_pm *device_pm = RT_NULL; + rt_slist_t *node = RT_NULL; - /* make the frequency change */ - for (index = 0; index < _pm.device_pm_number; index ++) + for (node = rt_slist_first(&_pm.device_list); node; node = rt_slist_next(node)) { - if (_pm.device_pm[index].ops->frequency_change != RT_NULL) - _pm.device_pm[index].ops->frequency_change(_pm.device_pm[index].device, mode); + device_pm = rt_slist_entry(node, struct rt_device_pm, list); + if (device_pm->ops->frequency_change != RT_NULL) + { + device_pm->ops->frequency_change(device_pm->device, mode); + } } } @@ -172,13 +171,16 @@ static void _pm_device_frequency_change(rt_uint8_t mode) */ static void _pm_frequency_scaling(struct rt_pm *pm) { - rt_base_t level; + rt_base_t level = 0; if (pm->flags & RT_PM_FREQUENCY_PENDING) { level = rt_hw_interrupt_disable(); /* change system runing mode */ - pm->ops->run(pm, pm->run_mode); + if(pm->ops->run != RT_NULL) + { + pm->ops->run(pm, pm->run_mode); + } /* changer device frequency */ _pm_device_frequency_change(pm->run_mode); pm->flags &= ~RT_PM_FREQUENCY_PENDING; @@ -288,6 +290,12 @@ static rt_bool_t _pm_device_check_idle(void) return RT_TRUE; } +/** + * @brief Get the next system wake-up time + * @note When used by default, it goes into STANDBY mode and sleeps forever. tickless external rewriting is required + * @param mode: sleep mode + * @retval timeout_tick + */ rt_weak rt_tick_t pm_timer_next_timeout_tick(rt_uint8_t mode) { switch (mode) @@ -344,6 +352,7 @@ rt_weak rt_uint8_t pm_get_sleep_threshold_mode(rt_uint8_t cur_mode, rt_tick_t ti else if (timeout_tick < PM_STANDBY_THRESHOLD_TIME) sleep_mode = PM_SLEEP_MODE_DEEP; } + cur_mode = sleep_mode; #else if (timeout_tick < PM_TICKLESS_THRESHOLD_TIME) { @@ -359,8 +368,8 @@ rt_weak rt_uint8_t pm_get_sleep_threshold_mode(rt_uint8_t cur_mode, rt_tick_t ti */ static void _pm_change_sleep_mode(struct rt_pm *pm) { - rt_tick_t timeout_tick, delta_tick; - rt_base_t level; + rt_tick_t timeout_tick = 0, delta_tick = 0; + rt_base_t level = 0; uint8_t sleep_mode = PM_SLEEP_MODE_DEEP; level = rt_pm_enter_critical(pm->sleep_mode); @@ -380,23 +389,27 @@ static void _pm_change_sleep_mode(struct rt_pm *pm) if (_pm.sleep_mode == PM_SLEEP_MODE_NONE) { - pm->ops->sleep(pm, PM_SLEEP_MODE_NONE); + pm_sleep(pm, PM_SLEEP_MODE_NONE); rt_pm_exit_critical(level, pm->sleep_mode); } else { /* Notify app will enter sleep mode */ if (_pm_notify.notify) + { _pm_notify.notify(RT_PM_ENTER_SLEEP, pm->sleep_mode, _pm_notify.data); + } /* Suspend all peripheral device */ #ifdef PM_ENABLE_SUSPEND_SLEEP_MODE - int ret = _pm_device_suspend(pm->sleep_mode); + rt_err_t ret = _pm_device_suspend(pm->sleep_mode); if (ret != RT_EOK) { _pm_device_resume(pm->sleep_mode); if (_pm_notify.notify) + { _pm_notify.notify(RT_PM_EXIT_SLEEP, pm->sleep_mode, _pm_notify.data); + } if (pm->sleep_mode > PM_SUSPEND_SLEEP_MODE) { pm->sleep_mode = PM_SUSPEND_SLEEP_MODE; @@ -419,14 +432,7 @@ static void _pm_change_sleep_mode(struct rt_pm *pm) if (pm->timer_mask & (0x01 << pm->sleep_mode)) { - if (timeout_tick == RT_TICK_MAX) - { - pm_lptimer_start(pm, RT_TICK_MAX); - } - else - { - pm_lptimer_start(pm, timeout_tick); - } + pm_lptimer_start(pm, timeout_tick); } } @@ -440,7 +446,9 @@ static void _pm_change_sleep_mode(struct rt_pm *pm) pm_lptimer_stop(pm); if (delta_tick) { - rt_tick_set(rt_tick_get() + delta_tick); + rt_interrupt_enter(); + rt_tick_increase_tick(delta_tick); + rt_interrupt_leave(); } } @@ -451,14 +459,6 @@ static void _pm_change_sleep_mode(struct rt_pm *pm) _pm_notify.notify(RT_PM_EXIT_SLEEP, pm->sleep_mode, _pm_notify.data); rt_pm_exit_critical(level, pm->sleep_mode); - - if (pm->timer_mask & (0x01 << pm->sleep_mode)) - { - if (delta_tick) - { - rt_timer_check(); - } - } } } @@ -467,8 +467,10 @@ static void _pm_change_sleep_mode(struct rt_pm *pm) */ void rt_system_power_manager(void) { - if (_pm_init_flag == 0) + if (_pm_init_flag == 0 || _pm.ops == RT_NULL) + { return; + } /* CPU frequency scaling according to the runing mode settings */ _pm_frequency_scaling(&_pm); @@ -483,22 +485,28 @@ void rt_system_power_manager(void) * * @param parameter the parameter of run mode or sleep mode */ -void rt_pm_request(rt_uint8_t mode) +rt_err_t rt_pm_request(rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; if (_pm_init_flag == 0) - return; + { + return -RT_EPERM; + } if (mode > (PM_SLEEP_MODE_MAX - 1)) - return; + { + return -RT_EINVAL; + } level = rt_hw_interrupt_disable(); pm = &_pm; if (pm->modes[mode] < 255) pm->modes[mode] ++; rt_hw_interrupt_enable(level); + + return RT_EOK; } /** @@ -508,22 +516,28 @@ void rt_pm_request(rt_uint8_t mode) * @param parameter the parameter of run mode or sleep mode * */ -void rt_pm_release(rt_uint8_t mode) +rt_err_t rt_pm_release(rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; if (_pm_init_flag == 0) - return; + { + return -RT_EPERM; + } if (mode > (PM_SLEEP_MODE_MAX - 1)) - return; + { + return -RT_EINVAL; + } level = rt_hw_interrupt_disable(); pm = &_pm; if (pm->modes[mode] > 0) pm->modes[mode] --; rt_hw_interrupt_enable(level); + + return RT_EOK; } /** @@ -533,21 +547,27 @@ void rt_pm_release(rt_uint8_t mode) * @param parameter the parameter of run mode or sleep mode * */ -void rt_pm_release_all(rt_uint8_t mode) +rt_err_t rt_pm_release_all(rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; if (_pm_init_flag == 0) - return; + { + return -RT_EPERM; + } if (mode > (PM_SLEEP_MODE_MAX - 1)) - return; + { + return -RT_EINVAL; + } level = rt_hw_interrupt_disable(); pm = &_pm; pm->modes[mode] = 0; rt_hw_interrupt_enable(level); + + return RT_EOK; } /** @@ -557,19 +577,25 @@ void rt_pm_release_all(rt_uint8_t mode) * @param module_id the application or device module id * @param mode the system power sleep mode */ -void rt_pm_module_request(uint8_t module_id, rt_uint8_t mode) +rt_err_t rt_pm_module_request(uint8_t module_id, rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; if (_pm_init_flag == 0) - return; + { + return -RT_EPERM; + } if (mode > (PM_SLEEP_MODE_MAX - 1)) - return; + { + return -RT_EINVAL; + } if (module_id > (PM_MODULE_MAX_ID - 1)) - return; + { + return -RT_EINVAL; + } level = rt_hw_interrupt_disable(); pm = &_pm; @@ -577,6 +603,8 @@ void rt_pm_module_request(uint8_t module_id, rt_uint8_t mode) if (pm->modes[mode] < 255) pm->modes[mode] ++; rt_hw_interrupt_enable(level); + + return RT_EOK; } /** @@ -587,19 +615,25 @@ void rt_pm_module_request(uint8_t module_id, rt_uint8_t mode) * @param mode the system power sleep mode * */ -void rt_pm_module_release(uint8_t module_id, rt_uint8_t mode) +rt_err_t rt_pm_module_release(uint8_t module_id, rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; if (_pm_init_flag == 0) - return; + { + return -RT_EPERM; + } if (mode > (PM_SLEEP_MODE_MAX - 1)) - return; + { + return -RT_EINVAL; + } if (module_id > (PM_MODULE_MAX_ID - 1)) - return; + { + return -RT_EINVAL; + } level = rt_hw_interrupt_disable(); pm = &_pm; @@ -608,6 +642,8 @@ void rt_pm_module_release(uint8_t module_id, rt_uint8_t mode) if (pm->modes[mode] == 0) pm->module_status[module_id].req_status = 0x00; rt_hw_interrupt_enable(level); + + return RT_EOK; } /** @@ -618,22 +654,28 @@ void rt_pm_module_release(uint8_t module_id, rt_uint8_t mode) * @param mode the system power sleep mode * */ -void rt_pm_module_release_all(uint8_t module_id, rt_uint8_t mode) +rt_err_t rt_pm_module_release_all(uint8_t module_id, rt_uint8_t mode) { rt_base_t level; struct rt_pm *pm; if (_pm_init_flag == 0) - return; + { + return -RT_EPERM; + } if (mode > (PM_SLEEP_MODE_MAX - 1)) - return; + { + return -RT_EINVAL; + } level = rt_hw_interrupt_disable(); pm = &_pm; pm->modes[mode] = 0; pm->module_status[module_id].req_status = 0x00; rt_hw_interrupt_enable(level); + + return RT_EOK; } /** @@ -644,23 +686,24 @@ void rt_pm_module_release_all(uint8_t module_id, rt_uint8_t mode) * * @return none */ -void rt_pm_sleep_request(rt_uint16_t module_id, rt_uint8_t mode) +rt_err_t rt_pm_sleep_request(rt_uint16_t module_id, rt_uint8_t mode) { rt_base_t level; if (module_id >= PM_MODULE_MAX_ID) { - return; + return -RT_EINVAL; } if (mode >= (PM_SLEEP_MODE_MAX - 1)) { - return; + return -RT_EINVAL; } level = rt_hw_interrupt_disable(); _pm.sleep_status[mode][module_id / 32] |= 1 << (module_id % 32); rt_hw_interrupt_enable(level); + return RT_EOK; } /** @@ -670,9 +713,9 @@ void rt_pm_sleep_request(rt_uint16_t module_id, rt_uint8_t mode) * * @return NULL */ -void rt_pm_sleep_none_request(rt_uint16_t module_id) +rt_err_t rt_pm_sleep_none_request(rt_uint16_t module_id) { - rt_pm_sleep_request(module_id, PM_SLEEP_MODE_NONE); + return rt_pm_sleep_request(module_id, PM_SLEEP_MODE_NONE); } /** @@ -682,9 +725,9 @@ void rt_pm_sleep_none_request(rt_uint16_t module_id) * * @return NULL */ -void rt_pm_sleep_idle_request(rt_uint16_t module_id) +rt_err_t rt_pm_sleep_idle_request(rt_uint16_t module_id) { - rt_pm_sleep_request(module_id, PM_SLEEP_MODE_IDLE); + return rt_pm_sleep_request(module_id, PM_SLEEP_MODE_IDLE); } /** @@ -694,9 +737,9 @@ void rt_pm_sleep_idle_request(rt_uint16_t module_id) * * @return NULL */ -void rt_pm_sleep_light_request(rt_uint16_t module_id) +rt_err_t rt_pm_sleep_light_request(rt_uint16_t module_id) { - rt_pm_sleep_request(module_id, PM_SLEEP_MODE_LIGHT); + return rt_pm_sleep_request(module_id, PM_SLEEP_MODE_LIGHT); } /** @@ -707,23 +750,24 @@ void rt_pm_sleep_light_request(rt_uint16_t module_id) * * @return NULL */ -void rt_pm_sleep_release(rt_uint16_t module_id, rt_uint8_t mode) +rt_err_t rt_pm_sleep_release(rt_uint16_t module_id, rt_uint8_t mode) { rt_base_t level; if (module_id >= PM_MODULE_MAX_ID) { - return; + return -RT_EINVAL; } if (mode >= (PM_SLEEP_MODE_MAX - 1)) { - return; + return -RT_EINVAL; } level = rt_hw_interrupt_disable(); _pm.sleep_status[mode][module_id / 32] &= ~(1 << (module_id % 32)); rt_hw_interrupt_enable(level); + return RT_EOK; } /** @@ -733,9 +777,9 @@ void rt_pm_sleep_release(rt_uint16_t module_id, rt_uint8_t mode) * * @return none */ -void rt_pm_sleep_none_release(rt_uint16_t module_id) +rt_err_t rt_pm_sleep_none_release(rt_uint16_t module_id) { - rt_pm_sleep_release(module_id, PM_SLEEP_MODE_NONE); + return rt_pm_sleep_release(module_id, PM_SLEEP_MODE_NONE); } /** @@ -745,9 +789,9 @@ void rt_pm_sleep_none_release(rt_uint16_t module_id) * * @return none */ -void rt_pm_sleep_idle_release(rt_uint16_t module_id) +rt_err_t rt_pm_sleep_idle_release(rt_uint16_t module_id) { - rt_pm_sleep_release(module_id, PM_SLEEP_MODE_IDLE); + return rt_pm_sleep_release(module_id, PM_SLEEP_MODE_IDLE); } /** @@ -757,9 +801,9 @@ void rt_pm_sleep_idle_release(rt_uint16_t module_id) * * @return none */ -void rt_pm_sleep_light_release(rt_uint16_t module_id) +rt_err_t rt_pm_sleep_light_release(rt_uint16_t module_id) { - rt_pm_sleep_release(module_id, PM_SLEEP_MODE_LIGHT); + return rt_pm_sleep_release(module_id, PM_SLEEP_MODE_LIGHT); } /** @@ -770,24 +814,15 @@ void rt_pm_sleep_light_release(rt_uint16_t module_id) */ void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops) { - rt_base_t level; struct rt_device_pm *device_pm; - RT_DEBUG_NOT_IN_INTERRUPT; - - level = rt_hw_interrupt_disable(); - - device_pm = (struct rt_device_pm *)RT_KERNEL_REALLOC(_pm.device_pm, - (_pm.device_pm_number + 1) * sizeof(struct rt_device_pm)); + device_pm = RT_KERNEL_MALLOC(sizeof(struct rt_device_pm)); if (device_pm != RT_NULL) { - _pm.device_pm = device_pm; - _pm.device_pm[_pm.device_pm_number].device = device; - _pm.device_pm[_pm.device_pm_number].ops = ops; - _pm.device_pm_number += 1; + rt_slist_append(&_pm.device_list, &device_pm->list); + device_pm->device = device; + device_pm->ops = ops; } - - rt_hw_interrupt_enable(level); } /** @@ -797,32 +832,18 @@ void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_o */ void rt_pm_device_unregister(struct rt_device *device) { - rt_base_t level; - rt_uint32_t index; - RT_DEBUG_NOT_IN_INTERRUPT; - - level = rt_hw_interrupt_disable(); - - for (index = 0; index < _pm.device_pm_number; index ++) + struct rt_device_pm *device_pm = RT_NULL; + rt_slist_t *node = RT_NULL; + for (node = rt_slist_first(&_pm.device_list); node; node = rt_slist_next(node)) { - if (_pm.device_pm[index].device == device) + device_pm = rt_slist_entry(node, struct rt_device_pm, list); + if (device_pm->device == device) { - /* remove current entry */ - for (; index < _pm.device_pm_number - 1; index ++) - { - _pm.device_pm[index] = _pm.device_pm[index + 1]; - } - - _pm.device_pm[_pm.device_pm_number - 1].device = RT_NULL; - _pm.device_pm[_pm.device_pm_number - 1].ops = RT_NULL; - - _pm.device_pm_number -= 1; - /* break out and not touch memory */ + rt_slist_remove(&_pm.device_list, &device_pm->list); + RT_KERNEL_FREE(device_pm); break; } } - - rt_hw_interrupt_enable(level); } /** @@ -914,10 +935,11 @@ static rt_err_t _rt_pm_device_control(rt_device_t dev, return RT_EOK; } -int rt_pm_run_enter(rt_uint8_t mode) +rt_err_t rt_pm_run_enter(rt_uint8_t mode) { - rt_base_t level; - struct rt_pm *pm; + rt_base_t level = 0; + struct rt_pm *pm = RT_NULL; + rt_err_t ret = RT_EOK; if (_pm_init_flag == 0) return -RT_EIO; @@ -925,12 +947,16 @@ int rt_pm_run_enter(rt_uint8_t mode) if (mode > PM_RUN_MODE_MAX) return -RT_EINVAL; - level = rt_hw_interrupt_disable(); pm = &_pm; + + level = rt_hw_interrupt_disable(); if (mode < pm->run_mode) { /* change system runing mode */ - pm->ops->run(pm, mode); + if(pm->ops != RT_NULL && pm->ops->run != RT_NULL) + { + pm->ops->run(pm, mode); + } /* changer device frequency */ _pm_device_frequency_change(mode); } @@ -941,7 +967,7 @@ int rt_pm_run_enter(rt_uint8_t mode) pm->run_mode = mode; rt_hw_interrupt_enable(level); - return RT_EOK; + return ret; } #ifdef RT_USING_DEVICE_OPS @@ -1004,7 +1030,8 @@ void rt_system_pm_init(const struct rt_pm_ops *ops, pm->ops = ops; pm->device_pm = RT_NULL; - pm->device_pm_number = 0; + + rt_slist_init(&pm->device_list); #if IDLE_THREAD_STACK_SIZE <= 256 #error "[pm.c ERR] IDLE Stack Size Too Small!"