|
@@ -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,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!"
|