From c57f2370adb07b450fbff36657f5c5bbba8e0c1a Mon Sep 17 00:00:00 2001 From: EvalZero Date: Mon, 6 May 2019 18:17:55 +0800 Subject: [PATCH] [components][pm]improve low power management components --- components/drivers/include/drivers/pm.h | 170 ++++----- components/drivers/pm/pm.c | 460 ++++++++++++------------ src/idle.c | 4 + 3 files changed, 312 insertions(+), 322 deletions(-) diff --git a/components/drivers/include/drivers/pm.h b/components/drivers/include/drivers/pm.h index 94d4c8559b..5cffd8d465 100644 --- a/components/drivers/include/drivers/pm.h +++ b/components/drivers/include/drivers/pm.h @@ -7,6 +7,7 @@ * Date Author Notes * 2012-06-02 Bernard the first version * 2018-08-02 Tanek split run and sleep modes, support custom mode + * 2019-04-28 Zero-Free improve PM mode and device ops interface */ #ifndef __PM_H__ @@ -16,91 +17,62 @@ #ifndef PM_HAS_CUSTOM_CONFIG -/* All modes used for rt_pm_request() adn rt_pm_release() */ +/* All modes used for rt_pm_request() and rt_pm_release() */ enum { - /* run modes */ - PM_RUN_MODE_NORMAL = 0, - /* sleep modes */ - PM_SLEEP_MODE_SLEEP, - PM_SLEEP_MODE_TIMER, + PM_SLEEP_MODE_NONE = 0, + PM_SLEEP_MODE_IDLE, + PM_SLEEP_MODE_LIGHT, + PM_SLEEP_MODE_DEEP, + PM_SLEEP_MODE_STANDBY, PM_SLEEP_MODE_SHUTDOWN, + PM_SLEEP_MODE_MAX, }; +enum +{ + /* run modes*/ + PM_RUN_MODE_HIGH_SPEED = 0, + PM_RUN_MODE_NORMAL_SPEED, + PM_RUN_MODE_MEDIUM_SPEED, + PM_RUN_MODE_LOW_SPEED, + PM_RUN_MODE_MAX, +}; + +enum +{ + RT_PM_FREQUENCY_PENDING = 0x01, +}; + +#define RT_PM_DEFAULT_SLEEP_MODE PM_SLEEP_MODE_IDLE +#define RT_PM_DEFAULT_RUN_MODE PM_RUN_MODE_NORMAL_SPEED + /* The name of all modes used in the msh command "pm_dump" */ -#define PM_MODE_NAMES \ +#define PM_SLEEP_MODE_NAMES \ { \ - "Running Mode", \ - \ - "Sleep Mode", \ - "Timer Mode", \ + "None Mode", \ + "Idle Mode", \ + "LightSleep Mode", \ + "DeepSleep Mode", \ + "Standby Mode", \ "Shutdown Mode", \ } -/* run mode count : 1 */ -#define PM_RUN_MODE_COUNT 1 -/* sleep mode count : 3 */ -#define PM_SLEEP_MODE_COUNT 3 - -/* support redefining default run mode */ -#ifndef PM_RUN_MODE_DEFAULT -#define PM_RUN_MODE_DEFAULT 0 -#endif - -/* support redefining default sleep mode */ -#ifndef PM_SLEEP_MODE_DEFAULT -#define PM_SLEEP_MODE_DEFAULT (PM_SLEEP_MODE_START) -#endif - -/* support redefining the minimum tick into sleep mode */ -#ifndef PM_MIN_ENTER_SLEEP_TICK -#define PM_MIN_ENTER_SLEEP_TICK (1) -#endif +#define PM_RUN_MODE_NAMES \ +{ \ + "High Speed", \ + "Normal Speed", \ + "Medium Speed", \ + "Low Mode", \ +} #else /* PM_HAS_CUSTOM_CONFIG */ #include -#ifndef PM_RUN_MODE_COUNT -#error "You must defined PM_RUN_MODE_COUNT on pm_cfg.h" -#endif - -#ifndef PM_SLEEP_MODE_COUNT -#error "You must defined PM_SLEEP_MODE_COUNT on pm_cfg.h" -#endif - -#ifndef PM_MODE_DEFAULT -#error "You must defined PM_MODE_DEFAULT on pm_cfg.h" -#endif - -#ifndef PM_MODE_NAMES -#error "You must defined PM_MODE_NAMES on pm_cfg.h" -#endif - -#ifndef PM_RUN_MODE_DEFAULT -#error "You must defined PM_RUN_MODE_DEFAULT on pm_cfg.h" -#endif - -/* The default sleep mode(PM_SLEEP_MODE_DEFAULT) are not required. - * If the default mode is defined, it is requested once in rt_system_pm_init() - */ - #endif /* PM_HAS_CUSTOM_CONFIG */ -/* run mode must start at 0 */ -#define PM_RUN_MODE_START 0 -/* the values of the run modes and sleep mode must be consecutive */ -#define PM_SLEEP_MODE_START PM_RUN_MODE_COUNT -/* all mode count */ -#define PM_MODE_COUNT (PM_RUN_MODE_COUNT + PM_SLEEP_MODE_COUNT) -/* The last mode, will be request in rt_system_pm_init() */ -#define PM_MODE_MAX (PM_RUN_MODE_COUNT + PM_SLEEP_MODE_COUNT - 1) - -#if PM_MODE_COUNT > 32 -#error "The number of modes cannot exceed 32" -#endif - /** * device control flag to request or release power */ @@ -114,13 +86,8 @@ struct rt_pm; */ struct rt_pm_ops { - void (*enter)(struct rt_pm *pm); - void (*exit)(struct rt_pm *pm); - -#if PM_RUN_MODE_COUNT > 1 - void (*frequency_change)(struct rt_pm *pm, rt_uint32_t frequency); -#endif - + void (*sleep)(struct rt_pm *pm, uint8_t mode); + void (*run)(struct rt_pm *pm, uint8_t mode, uint32_t frequency); void (*timer_start)(struct rt_pm *pm, rt_uint32_t timeout); void (*timer_stop)(struct rt_pm *pm); rt_tick_t (*timer_get_tick)(struct rt_pm *pm); @@ -128,18 +95,15 @@ struct rt_pm_ops struct rt_device_pm_ops { -#if PM_RUN_MODE_COUNT > 1 - void (*frequency_change)(const struct rt_device* device); -#endif - - void (*suspend)(const struct rt_device* device); - void (*resume) (const struct rt_device* device); + int (*suspend)(const struct rt_device *device, uint8_t mode); + void (*resume)(const struct rt_device *device, uint8_t mode); + int (*frequency_change)(const struct rt_device *device, uint8_t mode, uint32_t frequency); }; struct rt_device_pm { - const struct rt_device* device; - const struct rt_device_pm_ops* ops; + const struct rt_device *device; + const struct rt_device_pm_ops *ops; }; /** @@ -150,32 +114,46 @@ struct rt_pm struct rt_device parent; /* modes */ - rt_uint8_t modes[PM_MODE_COUNT]; - rt_uint8_t current_mode; /* current pm mode */ - rt_uint8_t exit_count; + rt_uint8_t modes[PM_SLEEP_MODE_MAX]; + rt_uint8_t sleep_mode; /* current sleep mode */ + rt_uint8_t run_mode; /* current running mode */ /* the list of device, which has PM feature */ rt_uint8_t device_pm_number; - struct rt_device_pm* device_pm; - struct rt_semaphore device_lock; + struct rt_device_pm *device_pm; + rt_uint32_t frequency; /* if the mode has timer, the corresponding bit is 1*/ - rt_uint32_t timer_mask; + rt_uint8_t timer_mask; + rt_uint8_t flags; const struct rt_pm_ops *ops; }; -void rt_pm_enter(void); -void rt_pm_exit(void); +enum +{ + RT_PM_ENTER_SLEEP = 0, + RT_PM_EXIT_SLEEP, +}; -void rt_pm_request(rt_ubase_t mode); -void rt_pm_release(rt_ubase_t mode); +struct rt_pm_notify +{ + void (*notify)(uint8_t event, uint8_t mode, void *data); + void *data; +}; -void rt_pm_register_device(struct rt_device* device, const struct rt_device_pm_ops* ops); -void rt_pm_unregister_device(struct rt_device* device); +void rt_pm_request(uint8_t sleep_mode); +void rt_pm_release(uint8_t sleep_mode); +int rt_pm_run_mode_set(uint8_t run_mode, uint32_t frequency); + +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); + +void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), void *data); +void rt_pm_default_set(uint8_t sleep_mode); void rt_system_pm_init(const struct rt_pm_ops *ops, - rt_uint8_t timer_mask, - void *user_data); + uint8_t timer_mask, + void *user_data); #endif /* __PM_H__ */ diff --git a/components/drivers/pm/pm.c b/components/drivers/pm/pm.c index c300414444..c273754914 100644 --- a/components/drivers/pm/pm.c +++ b/components/drivers/pm/pm.c @@ -7,6 +7,7 @@ * Date Author Notes * 2012-06-02 Bernard the first version * 2018-08-02 Tanek split run and sleep modes, support custom mode + * 2019-04-28 Zero-Free improve PM mode and device ops interface */ #include @@ -16,11 +17,25 @@ #ifdef RT_USING_PM static struct rt_pm _pm; +static uint8_t _pm_default_sleep = RT_PM_DEFAULT_SLEEP_MODE; +static struct rt_pm_notify _pm_notify; + +#define RT_PM_TICKLESS_THRESH (2) + +RT_WEAK uint32_t rt_pm_enter_critical(void) +{ + return rt_hw_interrupt_disable(); +} + +RT_WEAK void rt_pm_exit_critical(uint32_t ctx) +{ + rt_hw_interrupt_enable(ctx); +} /** * This function will suspend all registered devices */ -static void _pm_device_suspend(void) +static int _pm_device_suspend(uint8_t mode) { int index; @@ -28,15 +43,17 @@ static void _pm_device_suspend(void) { if (_pm.device_pm[index].ops->suspend != RT_NULL) { - _pm.device_pm[index].ops->suspend(_pm.device_pm[index].device); + return _pm.device_pm[index].ops->suspend(_pm.device_pm[index].device, mode); } } + + return RT_EOK; } /** * This function will resume all registered devices */ -static void _pm_device_resume(void) +static void _pm_device_resume(uint8_t mode) { int index; @@ -44,16 +61,15 @@ static void _pm_device_resume(void) { if (_pm.device_pm[index].ops->resume != RT_NULL) { - _pm.device_pm[index].ops->resume(_pm.device_pm[index].device); + _pm.device_pm[index].ops->resume(_pm.device_pm[index].device, mode); } } } -#if PM_RUN_MODE_COUNT > 1 /** * This function will update the frequency of all registered devices */ -static void _pm_device_frequency_change(void) +static void _pm_device_frequency_change(uint8_t mode, uint32_t frequency) { rt_uint32_t index; @@ -61,152 +77,148 @@ static void _pm_device_frequency_change(void) for (index = 0; index < _pm.device_pm_number; index ++) { if (_pm.device_pm[index].ops->frequency_change != RT_NULL) - _pm.device_pm[index].ops->frequency_change(_pm.device_pm[index].device); + _pm.device_pm[index].ops->frequency_change(_pm.device_pm[index].device, mode, frequency); + } +} + +/** + * This function will update the system clock frequency when idle + */ +static void _pm_frequency_scaling(struct rt_pm *pm) +{ + rt_base_t level; + + if (pm->flags & RT_PM_FREQUENCY_PENDING) + { + level = rt_hw_interrupt_disable(); + /* change system runing mode */ + pm->ops->run(pm, pm->run_mode, pm->frequency); + /* changer device frequency */ + _pm_device_frequency_change(pm->run_mode, pm->frequency); + pm->flags &= ~RT_PM_FREQUENCY_PENDING; + rt_hw_interrupt_enable(level); + } +} + +/** + * This function selects the sleep mode according to the rt_pm_request/rt_pm_release count. + */ +static uint8_t _pm_select_sleep_mode(struct rt_pm *pm) +{ + int index; + uint8_t mode; + + mode = _pm_default_sleep; + for (index = PM_SLEEP_MODE_NONE; index < PM_SLEEP_MODE_MAX; index ++) + { + if (pm->modes[index]) + { + mode = index; + break; + } + } + pm->sleep_mode = mode; + + return mode; +} + +/** + * This function changes the power sleep mode base on the result of selection + */ +static void _pm_change_sleep_mode(struct rt_pm *pm, uint8_t mode) +{ + rt_tick_t timeout_tick, delta_tick; + rt_base_t level; + int ret = RT_EOK; + + if (mode == PM_SLEEP_MODE_NONE) + { + pm->sleep_mode = mode; + pm->ops->sleep(pm, PM_SLEEP_MODE_NONE); + } + else + { + level = rt_pm_enter_critical(); + + /* Notify app will enter sleep mode */ + if (_pm_notify.notify) + _pm_notify.notify(RT_PM_ENTER_SLEEP, mode, _pm_notify.data); + + /* Suspend all peripheral device */ + ret = _pm_device_suspend(mode); + if (ret != RT_EOK) + { + _pm_device_resume(mode); + if (_pm_notify.notify) + _pm_notify.notify(RT_PM_EXIT_SLEEP, mode, _pm_notify.data); + rt_pm_exit_critical(level); + + return; + } + + /* Tickless*/ + if (pm->timer_mask & (0x01 << mode)) + { + timeout_tick = rt_timer_next_timeout_tick(); + if (timeout_tick == RT_TICK_MAX) + { + if (pm->ops->timer_start) + { + pm->ops->timer_start(pm, RT_TICK_MAX); + } + } + else + { + timeout_tick = timeout_tick - rt_tick_get(); + if (timeout_tick < RT_PM_TICKLESS_THRESH) + { + mode = PM_SLEEP_MODE_IDLE; + } + else + { + pm->ops->timer_start(pm, timeout_tick); + } + } + } + + /* enter lower power state */ + pm->ops->sleep(pm, mode); + + /* wake up from lower power state*/ + if (pm->timer_mask & (0x01 << mode)) + { + delta_tick = pm->ops->timer_get_tick(pm); + pm->ops->timer_stop(pm); + if (delta_tick) + { + rt_tick_set(rt_tick_get() + delta_tick); + rt_timer_check(); + } + } + + /* resume all device */ + _pm_device_resume(pm->sleep_mode); + + if (_pm_notify.notify) + _pm_notify.notify(RT_PM_EXIT_SLEEP, mode, _pm_notify.data); + + rt_pm_exit_critical(level); } } -#endif /** * This function will enter corresponding power mode. */ -void rt_pm_enter(void) +void rt_system_power_manager(void) { - rt_ubase_t level; - struct rt_pm *pm; - rt_uint32_t index; - rt_tick_t timeout_tick; + uint8_t mode; - pm = &_pm; + /* CPU frequency scaling according to the runing mode settings */ + _pm_frequency_scaling(&_pm); - /* disable interrupt before check run modes */ - level = rt_hw_interrupt_disable(); - /* check each run mode, and decide to swithc to run mode or sleep mode */ - for (index = 0; index < PM_RUN_MODE_COUNT; index++) - { - if (pm->modes[index]) - { - if (index > pm->current_mode) - { - pm->ops->exit(pm); - pm->current_mode = index; - pm->ops->enter(pm); -#if PM_RUN_MODE_COUNT > 1 - pm->ops->frequency_change(pm, 0); - _pm_device_frequency_change(); -#endif - } - - rt_hw_interrupt_enable(level); - /* The current mode is run mode, no need to check sleep mode */ - return ; - } - } - /* enable interrupt after check run modes */ - rt_hw_interrupt_enable(level); - - level = rt_hw_interrupt_disable(); - /* check each sleep mode to decide which mode can system sleep. */ - for (index = PM_SLEEP_MODE_START; index < PM_SLEEP_MODE_START + PM_SLEEP_MODE_COUNT; index++) - { - if (pm->modes[index]) - { - /* let mcu sleep when system is idle */ - - /* run mode to sleep mode */ - if (pm->current_mode < PM_SLEEP_MODE_START) - { - /* exit run mode */ - pm->ops->exit(pm); - } - - /* set current power mode */ - pm->current_mode = index; - pm->exit_count = 1; - - /* suspend all of devices with PM feature */ - _pm_device_suspend(); - - /* should start pm timer */ - if (pm->timer_mask & (1 << index)) - { - /* get next os tick */ - timeout_tick = rt_timer_next_timeout_tick(); - if (timeout_tick != RT_TICK_MAX) - { - timeout_tick -= rt_tick_get(); - -#if defined(PM_MIN_ENTER_SLEEP_TICK) && PM_MIN_ENTER_SLEEP_TICK > 0 - if (timeout_tick < PM_MIN_ENTER_SLEEP_TICK) - { - rt_hw_interrupt_enable(level); - /* limit the minimum time to enter timer sleep mode */ - return ; - } -#endif - } - /* startup pm timer */ - pm->ops->timer_start(pm, timeout_tick); - } - - /* enter sleep and wait to be waken up */ - pm->ops->enter(pm); - - /* exit from low power mode */ - rt_pm_exit(); - - rt_hw_interrupt_enable(level); - return ; - } - } - - rt_hw_interrupt_enable(level); -} - -/** - * This function exits from sleep mode. - */ -void rt_pm_exit(void) -{ - rt_ubase_t level; - struct rt_pm *pm; - rt_tick_t delta_tick; - - pm = &_pm; - - level = rt_hw_interrupt_disable(); - - if (pm->exit_count) - { - pm->exit_count = 0; - - if (pm->current_mode >= PM_SLEEP_MODE_START) - { - /* sleep mode with timer */ - if (pm->timer_mask & (1 << pm->current_mode)) - { - /* get the tick of pm timer */ - delta_tick = pm->ops->timer_get_tick(pm); - - /* stop pm timer */ - pm->ops->timer_stop(pm); - - if (delta_tick) - { - /* adjust OS tick */ - rt_tick_set(rt_tick_get() + delta_tick); - /* check system timer */ - rt_timer_check(); - } - } - - /* exit from sleep mode */ - pm->ops->exit(pm); - /* resume the device with PM feature */ - _pm_device_resume(); - } - } - - rt_hw_interrupt_enable(level); + /* Low Power Mode Processing */ + mode = _pm_select_sleep_mode(&_pm); + _pm_change_sleep_mode(&_pm, mode); } /** @@ -215,60 +227,18 @@ void rt_pm_exit(void) * * @param parameter the parameter of run mode or sleep mode */ -void rt_pm_request(rt_ubase_t mode) +void rt_pm_request(uint8_t mode) { - rt_ubase_t level; + rt_base_t level; struct rt_pm *pm; - pm = &_pm; - - if (mode > PM_MODE_MAX) + if (mode > (PM_SLEEP_MODE_MAX - 1)) return; level = rt_hw_interrupt_disable(); - - /* update pm modes table */ - pm->modes[mode] ++; - - /* request higter mode with a smaller mode value*/ - if (mode < pm->current_mode) - { - /* the old current mode is RUN mode, need to all pm->ops->exit(), - * if not, it has already called in rt_pm_exit() - */ - if (pm->current_mode < PM_SLEEP_MODE_START) - { - pm->ops->exit(pm); - } - else if (pm->exit_count) - { - /* call exeit when global interrupt is disable */ - pm->ops->exit(pm); - pm->exit_count = 0; - } - - /* update current mode */ - pm->current_mode = mode; - - /* current mode is higher run mode */ - if (mode < PM_SLEEP_MODE_START) - { - /* enter run mode */ - pm->ops->enter(pm); -#if PM_RUN_MODE_COUNT > 1 - /* frequency change */ - pm->ops->frequency_change(pm, 0); - _pm_device_frequency_change(); -#endif - } - else - { - /* do nothing when request higher sleep mode, - * and swithc to new sleep mode in rt_pm_enter() - */ - } - } - + pm = &_pm; + if (pm->modes[mode] < 255) + pm->modes[mode] ++; rt_hw_interrupt_enable(level); } @@ -279,21 +249,18 @@ void rt_pm_request(rt_ubase_t mode) * @param parameter the parameter of run mode or sleep mode * */ -void rt_pm_release(rt_ubase_t mode) +void rt_pm_release(uint8_t mode) { rt_ubase_t level; struct rt_pm *pm; - pm = &_pm; - - if (mode > PM_MODE_MAX) + if (mode > (PM_SLEEP_MODE_MAX - 1)) return; level = rt_hw_interrupt_disable(); - + pm = &_pm; if (pm->modes[mode] > 0) pm->modes[mode] --; - rt_hw_interrupt_enable(level); } @@ -303,9 +270,9 @@ void rt_pm_release(rt_ubase_t mode) * @param device the device with PM feature * @param ops the PM ops for device */ -void rt_pm_register_device(struct rt_device *device, const struct rt_device_pm_ops *ops) +void rt_pm_device_register(struct rt_device *device, const struct rt_device_pm_ops *ops) { - rt_ubase_t level; + rt_base_t level; struct rt_device_pm *device_pm; RT_DEBUG_NOT_IN_INTERRUPT; @@ -322,8 +289,6 @@ void rt_pm_register_device(struct rt_device *device, const struct rt_device_pm_o _pm.device_pm_number += 1; } - rt_sem_release(&(_pm.device_lock)); - rt_hw_interrupt_enable(level); } @@ -332,7 +297,7 @@ void rt_pm_register_device(struct rt_device *device, const struct rt_device_pm_o * * @param device the device with PM feature */ -void rt_pm_unregister_device(struct rt_device *device) +void rt_pm_device_unregister(struct rt_device *device) { rt_ubase_t level; rt_uint32_t index; @@ -362,6 +327,23 @@ void rt_pm_unregister_device(struct rt_device *device) rt_hw_interrupt_enable(level); } +/** + * This function set notification callback for application + */ +void rt_pm_notify_set(void (*notify)(uint8_t event, uint8_t mode, void *data), void *data) +{ + _pm_notify.notify = notify; + _pm_notify.data = data; +} + +/** + * This function set default sleep mode when no pm_request + */ +void rt_pm_default_set(uint8_t sleep_mode) +{ + _pm_default_sleep = sleep_mode; +} + /** * RT-Thread device interface for PM device */ @@ -377,7 +359,7 @@ static rt_size_t _rt_pm_device_read(rt_device_t dev, pm = (struct rt_pm *)dev; RT_ASSERT(pm != RT_NULL); - if (pos <= PM_MODE_MAX) + if (pos < PM_SLEEP_MODE_MAX) { int mode; @@ -434,6 +416,34 @@ static rt_err_t _rt_pm_device_control(rt_device_t dev, return RT_EOK; } +int rt_pm_run_mode_set(uint8_t mode, uint32_t frequency) +{ + rt_base_t level; + struct rt_pm *pm; + + if (mode > PM_RUN_MODE_MAX) + return -RT_EINVAL; + + level = rt_hw_interrupt_disable(); + pm = &_pm; + if (mode < pm->run_mode) + { + /* change system runing mode */ + pm->ops->run(pm, mode, frequency); + /* changer device frequency */ + _pm_device_frequency_change(mode, frequency); + } + else + { + pm->flags |= RT_PM_FREQUENCY_PENDING; + } + pm->frequency = frequency; + pm->run_mode = mode; + rt_hw_interrupt_enable(level); + + return RT_EOK; +} + /** * This function will initialize power management. * @@ -466,37 +476,23 @@ void rt_system_pm_init(const struct rt_pm_ops *ops, /* register PM device to the system */ rt_device_register(device, "pm", RT_DEVICE_FLAG_RDWR); - /* todo : add to kernel source code */ - rt_thread_idle_sethook(rt_pm_enter); - rt_memset(pm->modes, 0, sizeof(pm->modes)); - pm->current_mode = PM_RUN_MODE_DEFAULT; - + pm->sleep_mode = _pm_default_sleep; + pm->run_mode = RT_PM_DEFAULT_RUN_MODE; pm->timer_mask = timer_mask; pm->ops = ops; pm->device_pm = RT_NULL; pm->device_pm_number = 0; - - /* initialize semaphore */ - rt_sem_init(&(pm->device_lock), "pm", 1, RT_IPC_FLAG_FIFO); - - /* request in default running mode */ - rt_pm_request(PM_RUN_MODE_DEFAULT); - -#ifdef PM_SLEEP_MODE_DEFAULT - /* request in default sleep mode */ - rt_pm_request(PM_SLEEP_MODE_DEFAULT); -#endif - - /* must hold on deep shutdown mode */ - rt_pm_request(PM_MODE_MAX); } #ifdef RT_USING_FINSH #include +static const char *_pm_sleep_str[] = PM_SLEEP_MODE_NAMES; +static const char *_pm_run_str[] = PM_RUN_MODE_NAMES; + static void rt_pm_release_mode(int argc, char **argv) { int mode = 0; @@ -521,9 +517,20 @@ static void rt_pm_request_mode(int argc, char **argv) } MSH_CMD_EXPORT_ALIAS(rt_pm_request_mode, pm_request, request power management mode); +static void rt_pm_run_mode_switch(int argc, char **argv) +{ + int mode = 0; + if (argc >= 2) + { + mode = atoi(argv[1]); + } + + rt_pm_run_mode_set(mode, 0); +} +MSH_CMD_EXPORT_ALIAS(rt_pm_run_mode_switch, pm_run_set, switch power management run mode); + static void rt_pm_dump_status(void) { - static const char *pm_str[] = PM_MODE_NAMES; rt_uint32_t index; struct rt_pm *pm; @@ -531,17 +538,18 @@ static void rt_pm_dump_status(void) rt_kprintf("| Power Management Mode | Counter | Timer |\n"); rt_kprintf("+-----------------------+---------+-------+\n"); - for (index = 0; index <= PM_MODE_MAX; index ++) + for (index = 0; index < PM_SLEEP_MODE_MAX; index ++) { int has_timer = 0; if (pm->timer_mask & (1 << index)) has_timer = 1; - rt_kprintf("| %021s | %7d | %5d |\n", pm_str[index], pm->modes[index], has_timer); + rt_kprintf("| %021s | %7d | %5d |\n", _pm_sleep_str[index], pm->modes[index], has_timer); } rt_kprintf("+-----------------------+---------+-------+\n"); - rt_kprintf("pm current mode: %s\n", pm_str[pm->current_mode]); + rt_kprintf("pm current sleep mode: %s\n", _pm_sleep_str[pm->sleep_mode]); + rt_kprintf("pm current run mode: %s\n", _pm_run_str[pm->run_mode]); } FINSH_FUNCTION_EXPORT_ALIAS(rt_pm_dump_status, pm_dump, dump power management status); MSH_CMD_EXPORT_ALIAS(rt_pm_dump_status, pm_dump, dump power management status); diff --git a/src/idle.c b/src/idle.c index e685a7ddfc..77b0424892 100644 --- a/src/idle.c +++ b/src/idle.c @@ -228,6 +228,7 @@ void rt_thread_idle_excute(void) } } +extern void rt_system_power_manager(void); static void rt_thread_idle_entry(void *parameter) { #ifdef RT_USING_SMP @@ -255,6 +256,9 @@ static void rt_thread_idle_entry(void *parameter) #endif rt_thread_idle_excute(); +#ifdef RT_USING_PM + rt_system_power_manager(); +#endif } }