Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
天中雨水
rt-thread
提交
c57f2370
R
rt-thread
项目概览
天中雨水
/
rt-thread
该项目与 Fork 源项目分叉
Fork自
RT-Thread / rt-thread
通知
2
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c57f2370
编写于
5月 06, 2019
作者:
E
EvalZero
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[components][pm]improve low power management components
上级
4a2242b9
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
287 addition
and
297 deletion
+287
-297
components/drivers/include/drivers/pm.h
components/drivers/include/drivers/pm.h
+74
-96
components/drivers/pm/pm.c
components/drivers/pm/pm.c
+209
-201
src/idle.c
src/idle.c
+4
-0
未找到文件。
components/drivers/include/drivers/pm.h
浏览文件 @
c57f2370
...
...
@@ -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() a
dn
rt_pm_release() */
/* All modes used for rt_pm_request() a
nd
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 <pm_cfg.h>
#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
,
};
struct
rt_pm_notify
{
void
(
*
notify
)(
uint8_t
event
,
uint8_t
mode
,
void
*
data
);
void
*
data
;
};
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_
request
(
rt_ubase_t
mode
);
void
rt_pm_
release
(
rt_ubase_t
mod
e
);
void
rt_pm_
device_register
(
struct
rt_device
*
device
,
const
struct
rt_device_pm_ops
*
ops
);
void
rt_pm_
device_unregister
(
struct
rt_device
*
devic
e
);
void
rt_pm_
register_device
(
struct
rt_device
*
device
,
const
struct
rt_device_pm_ops
*
ops
);
void
rt_pm_
unregister_device
(
struct
rt_device
*
devic
e
);
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_mod
e
);
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__ */
components/drivers/pm/pm.c
浏览文件 @
c57f2370
...
...
@@ -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 <rthw.h>
...
...
@@ -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
].
devic
e
);
return
_pm
.
device_pm
[
index
].
ops
->
suspend
(
_pm
.
device_pm
[
index
].
device
,
mod
e
);
}
}
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
);
}
}
#endif
/**
* This function will
enter corresponding power mode.
* This function will
update the system clock frequency when idle
*/
void
rt_pm_enter
(
void
)
static
void
_pm_frequency_scaling
(
struct
rt_pm
*
pm
)
{
rt_ubase_t
level
;
struct
rt_pm
*
pm
;
rt_uint32_t
index
;
rt_tick_t
timeout_tick
;
rt_base_t
level
;
pm
=
&
_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
->
flags
&
RT_PM_FREQUENCY_PENDING
)
{
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
;
}
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
);
}
/* 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
++
)
/**
* 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
])
{
/* 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
;
mode
=
index
;
break
;
}
}
pm
->
sleep_mode
=
mode
;
r
t_hw_interrupt_enable
(
level
)
;
r
eturn
mode
;
}
/**
* This function
exits from sleep mode.
* This function
changes the power sleep mode base on the result of selection
*/
void
rt_pm_exit
(
void
)
static
void
_pm_change_sleep_mode
(
struct
rt_pm
*
pm
,
uint8_t
mode
)
{
rt_
ubase_t
level
;
struct
rt_pm
*
pm
;
rt_tick_t
delta_tick
;
rt_
tick_t
timeout_tick
,
delta_tick
;
rt_base_t
level
;
int
ret
=
RT_EOK
;
pm
=
&
_pm
;
level
=
rt_hw_interrupt_disable
();
if
(
pm
->
exit_count
)
if
(
mode
==
PM_SLEEP_MODE_NONE
)
{
pm
->
sleep_mode
=
mode
;
pm
->
ops
->
sleep
(
pm
,
PM_SLEEP_MODE_NONE
);
}
else
{
pm
->
exit_count
=
0
;
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
);
if
(
pm
->
current_mode
>=
PM_SLEEP_MODE_START
)
/* Suspend all peripheral device */
ret
=
_pm_device_suspend
(
mode
);
if
(
ret
!=
RT_EOK
)
{
/* 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
);
_pm_device_resume
(
mode
);
if
(
_pm_notify
.
notify
)
_pm_notify
.
notify
(
RT_PM_EXIT_SLEEP
,
mode
,
_pm_notify
.
data
);
rt_pm_exit_critical
(
level
);
/* stop pm timer */
pm
->
ops
->
timer_stop
(
pm
);
return
;
}
if
(
delta_tick
)
/* 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
{
/* adjust OS tick */
rt_tick_set
(
rt_tick_get
()
+
delta_tick
);
/* check system timer */
rt_timer_check
();
pm
->
ops
->
timer_start
(
pm
,
timeout_tick
);
}
}
}
/* enter lower power state */
pm
->
ops
->
sleep
(
pm
,
mode
);
/* exit from sleep mode */
pm
->
ops
->
exit
(
pm
);
/* resume the device with PM feature */
_pm_device_resume
();
/* 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
);
}
}
rt_hw_interrupt_enable
(
level
);
/**
* This function will enter corresponding power mode.
*/
void
rt_system_power_manager
(
void
)
{
uint8_t
mode
;
/* CPU frequency scaling according to the runing mode settings */
_pm_frequency_scaling
(
&
_pm
);
/* 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_
u
base_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_
u
base_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 <finsh.h>
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
);
...
...
src/idle.c
浏览文件 @
c57f2370
...
...
@@ -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
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录