[compoents][pm]The device is registered and uninstalled by linked list

This commit is contained in:
wdfk-prog 2024-07-11 15:57:51 +08:00 committed by Rbb666
parent 8d3ad68caf
commit bceb6635b0
2 changed files with 178 additions and 149 deletions

View File

@ -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__ */

View File

@ -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 <rthw.h>
@ -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,19 +108,24 @@ 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;
}
}
}
return ret;
}
@ -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 */
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;
@ -418,17 +431,10 @@ static void _pm_change_sleep_mode(struct rt_pm *pm)
pm->sleep_mode = pm_get_sleep_threshold_mode(pm->sleep_mode, timeout_tick);
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);
}
}
}
/* enter lower power state */
pm_sleep(pm, pm->sleep_mode);
@ -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 */
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!"