Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
逝缘~
rt-thread
提交
5fd6aec3
R
rt-thread
项目概览
逝缘~
/
rt-thread
与 Fork 源项目一致
Fork自
RT-Thread / rt-thread
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
rt-thread
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
5fd6aec3
编写于
12月 31, 2020
作者:
B
Bernard Xiong
提交者:
GitHub
12月 31, 2020
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #4097 from zhangsz0516/zhangsz_1127
[update][PM]更新RT-Thread PM2.0框架
上级
a207f221
5b484508
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
374 addition
and
20 deletion
+374
-20
components/drivers/include/drivers/pm.h
components/drivers/include/drivers/pm.h
+49
-1
components/drivers/pm/pm.c
components/drivers/pm/pm.c
+325
-19
未找到文件。
components/drivers/include/drivers/pm.h
浏览文件 @
5fd6aec3
...
...
@@ -8,6 +8,8 @@
* 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
* 2020-11-23 zhangsz update pm mode select
* 2020-11-27 zhangsz update pm 2.0
*/
#ifndef __PM_H__
...
...
@@ -45,7 +47,8 @@ enum
RT_PM_FREQUENCY_PENDING
=
0x01
,
};
#define RT_PM_DEFAULT_SLEEP_MODE PM_SLEEP_MODE_IDLE
#define RT_PM_DEFAULT_SLEEP_MODE PM_SLEEP_MODE_NONE
#define RT_PM_DEFAULT_DEEPSLEEP_MODE PM_SLEEP_MODE_DEEP
#define RT_PM_DEFAULT_RUN_MODE PM_RUN_MODE_NORMAL_SPEED
/* The name of all modes used in the msh command "pm_dump" */
...
...
@@ -67,6 +70,33 @@ enum
"Low Mode", \
}
/**
* Modules used for
* pm_module_request(PM_BOARD_ID, PM_SLEEP_MODE_IDLE)
* pm_module_release(PM_BOARD_ID, PM_SLEEP_MODE_IDLE)
* pm_module_release_all(PM_BOARD_ID, PM_SLEEP_MODE_IDLE)
*/
enum
pm_module_id
{
PM_NONE_ID
=
0
,
PM_POWER_ID
,
PM_BOARD_ID
,
PM_BSP_ID
,
PM_MAIN_ID
,
PM_PMS_ID
,
PM_PMC_ID
,
PM_TASK_ID
,
PM_SPI_ID
,
PM_I2C_ID
,
PM_UART_ID
,
PM_CAN_ID
,
PM_ETH_ID
,
PM_SENSOR_ID
,
PM_LCD_ID
,
PM_KEY_ID
,
PM_TP_ID
,
PM_MODULE_MAX_ID
,
/* enum must! */
};
#else
/* PM_HAS_CUSTOM_CONFIG */
#include <pm_cfg.h>
...
...
@@ -106,6 +136,14 @@ struct rt_device_pm
const
struct
rt_device_pm_ops
*
ops
;
};
struct
rt_pm_module
{
rt_uint8_t
req_status
;
rt_bool_t
busy_flag
;
rt_uint32_t
timeout
;
rt_uint32_t
start_time
;
};
/**
* power management
*/
...
...
@@ -118,6 +156,9 @@ struct rt_pm
rt_uint8_t
sleep_mode
;
/* current sleep mode */
rt_uint8_t
run_mode
;
/* current running mode */
/* modules request status*/
struct
rt_pm_module
module_status
[
PM_MODULE_MAX_ID
];
/* the list of device, which has PM feature */
rt_uint8_t
device_pm_number
;
struct
rt_device_pm
*
device_pm
;
...
...
@@ -143,6 +184,7 @@ struct rt_pm_notify
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
);
void
rt_pm_device_register
(
struct
rt_device
*
device
,
const
struct
rt_device_pm_ops
*
ops
);
...
...
@@ -154,5 +196,11 @@ 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
);
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
);
#endif
/* __PM_H__ */
components/drivers/pm/pm.c
浏览文件 @
5fd6aec3
...
...
@@ -9,6 +9,7 @@
* 2018-08-02 Tanek split run and sleep modes, support custom mode
* 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
*/
#include <rthw.h>
...
...
@@ -18,7 +19,13 @@
#ifdef RT_USING_PM
static
struct
rt_pm
_pm
;
/* default mode : system power on */
static
rt_uint8_t
_pm_default_sleep
=
RT_PM_DEFAULT_SLEEP_MODE
;
/* default deepsleep mode : tick-less mode */
static
rt_uint8_t
_pm_default_deepsleep
=
RT_PM_DEFAULT_DEEPSLEEP_MODE
;
static
struct
rt_pm_notify
_pm_notify
;
static
rt_uint8_t
_pm_init_flag
=
0
;
...
...
@@ -112,7 +119,7 @@ static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm)
int
index
;
rt_uint8_t
mode
;
mode
=
_pm_default_sleep
;
mode
=
_pm_default_
deep
sleep
;
for
(
index
=
PM_SLEEP_MODE_NONE
;
index
<
PM_SLEEP_MODE_MAX
;
index
++
)
{
if
(
pm
->
modes
[
index
])
...
...
@@ -126,42 +133,102 @@ static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm)
return
mode
;
}
/**
* pm module request delay sleep.
*/
void
rt_pm_module_delay_sleep
(
rt_uint8_t
module_id
,
rt_tick_t
timeout
)
{
rt_base_t
level
;
struct
rt_pm
*
pm
;
if
(
_pm_init_flag
==
0
)
return
;
if
(
module_id
>
(
PM_MODULE_MAX_ID
-
1
))
return
;
level
=
rt_hw_interrupt_disable
();
pm
=
&
_pm
;
pm
->
module_status
[
module_id
].
busy_flag
=
RT_TRUE
;
pm
->
module_status
[
module_id
].
timeout
=
timeout
;
pm
->
module_status
[
module_id
].
start_time
=
rt_tick_get
();
rt_hw_interrupt_enable
(
level
);
}
/**
* This function check if all modules in idle status.
*/
static
rt_bool_t
_pm_device_check_idle
(
void
)
{
struct
rt_pm
*
pm
;
if
(
_pm_init_flag
==
0
)
return
RT_TRUE
;
pm
=
&
_pm
;
for
(
int
i
=
0
;
i
<
PM_MODULE_MAX_ID
;
i
++
)
{
if
(
pm
->
module_status
[
i
].
busy_flag
==
RT_TRUE
)
{
if
(
rt_tick_get
()
-
pm
->
module_status
[
i
].
start_time
>
pm
->
module_status
[
i
].
timeout
)
{
pm
->
module_status
[
i
].
busy_flag
=
RT_FALSE
;
pm
->
module_status
[
i
].
timeout
=
0x00
;
}
}
if
(
pm
->
module_status
[
i
].
busy_flag
==
RT_TRUE
)
{
return
RT_FALSE
;
}
}
return
RT_TRUE
;
}
/**
* This function changes the power sleep mode base on the result of selection
*/
static
void
_pm_change_sleep_mode
(
struct
rt_pm
*
pm
,
rt_uint8_t
mode
)
static
void
_pm_change_sleep_mode
(
struct
rt_pm
*
pm
)
{
rt_tick_t
timeout_tick
,
delta_tick
;
rt_base_t
level
;
int
ret
=
RT_EOK
;
if
(
mode
==
PM_SLEEP_MODE_NONE
)
level
=
rt_pm_enter_critical
(
pm
->
sleep_mode
);
/* module busy request */
if
(
_pm_device_check_idle
()
==
RT_FALSE
)
{
pm
->
ops
->
sleep
(
pm
,
PM_SLEEP_MODE_NONE
);
rt_pm_exit_critical
(
level
,
pm
->
sleep_mode
);
return
;
}
if
(
_pm
.
sleep_mode
==
PM_SLEEP_MODE_NONE
)
{
pm
->
sleep_mode
=
mode
;
pm
->
ops
->
sleep
(
pm
,
PM_SLEEP_MODE_NONE
);
rt_pm_exit_critical
(
level
,
pm
->
sleep_mode
);
}
else
{
level
=
rt_pm_enter_critical
(
mode
);
/* Notify app will enter sleep mode */
if
(
_pm_notify
.
notify
)
_pm_notify
.
notify
(
RT_PM_ENTER_SLEEP
,
mode
,
_pm_notify
.
data
);
_pm_notify
.
notify
(
RT_PM_ENTER_SLEEP
,
pm
->
sleep_
mode
,
_pm_notify
.
data
);
/* Suspend all peripheral device */
ret
=
_pm_device_suspend
(
mode
);
ret
=
_pm_device_suspend
(
pm
->
sleep_
mode
);
if
(
ret
!=
RT_EOK
)
{
_pm_device_resume
(
mode
);
_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
,
mode
);
_pm_notify
.
notify
(
RT_PM_EXIT_SLEEP
,
pm
->
sleep_
mode
,
_pm_notify
.
data
);
rt_pm_exit_critical
(
level
,
pm
->
sleep_
mode
);
return
;
}
/* Tickless*/
if
(
pm
->
timer_mask
&
(
0x01
<<
mode
))
if
(
pm
->
timer_mask
&
(
0x01
<<
pm
->
sleep_
mode
))
{
timeout_tick
=
rt_timer_next_timeout_tick
();
if
(
timeout_tick
==
RT_TICK_MAX
)
...
...
@@ -176,7 +243,7 @@ static void _pm_change_sleep_mode(struct rt_pm *pm, rt_uint8_t mode)
timeout_tick
=
timeout_tick
-
rt_tick_get
();
if
(
timeout_tick
<
RT_PM_TICKLESS_THRESH
)
{
mode
=
PM_SLEEP_MODE_IDLE
;
pm
->
sleep_
mode
=
PM_SLEEP_MODE_IDLE
;
}
else
{
...
...
@@ -186,17 +253,16 @@ static void _pm_change_sleep_mode(struct rt_pm *pm, rt_uint8_t mode)
}
/* enter lower power state */
pm
->
ops
->
sleep
(
pm
,
mode
);
pm
->
ops
->
sleep
(
pm
,
pm
->
sleep_
mode
);
/* wake up from lower power state*/
if
(
pm
->
timer_mask
&
(
0x01
<<
mode
))
if
(
pm
->
timer_mask
&
(
0x01
<<
pm
->
sleep_
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
();
}
}
...
...
@@ -204,9 +270,17 @@ static void _pm_change_sleep_mode(struct rt_pm *pm, rt_uint8_t mode)
_pm_device_resume
(
pm
->
sleep_mode
);
if
(
_pm_notify
.
notify
)
_pm_notify
.
notify
(
RT_PM_EXIT_SLEEP
,
mode
,
_pm_notify
.
data
);
_pm_notify
.
notify
(
RT_PM_EXIT_SLEEP
,
pm
->
sleep_mode
,
_pm_notify
.
data
);
rt_pm_exit_critical
(
level
,
pm
->
sleep_mode
);
rt_pm_exit_critical
(
level
,
mode
);
if
(
pm
->
timer_mask
&
(
0x01
<<
pm
->
sleep_mode
))
{
if
(
delta_tick
)
{
rt_timer_check
();
}
}
}
}
...
...
@@ -222,7 +296,7 @@ void rt_system_power_manager(void)
_pm_frequency_scaling
(
&
_pm
);
/* Low Power Mode Processing */
_pm_change_sleep_mode
(
&
_pm
,
_pm
.
sleep_mode
);
_pm_change_sleep_mode
(
&
_pm
);
}
/**
...
...
@@ -276,6 +350,120 @@ void rt_pm_release(rt_uint8_t mode)
rt_hw_interrupt_enable
(
level
);
}
/**
* Upper application or device driver releases all the stall
* of corresponding power mode.
*
* @param parameter the parameter of run mode or sleep mode
*
*/
void
rt_pm_release_all
(
rt_uint8_t
mode
)
{
rt_ubase_t
level
;
struct
rt_pm
*
pm
;
if
(
_pm_init_flag
==
0
)
return
;
if
(
mode
>
(
PM_SLEEP_MODE_MAX
-
1
))
return
;
level
=
rt_hw_interrupt_disable
();
pm
=
&
_pm
;
pm
->
modes
[
mode
]
=
0
;
_pm_select_sleep_mode
(
pm
);
rt_hw_interrupt_enable
(
level
);
}
/**
* Upper application or device driver requests the system
* stall in corresponding power 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_base_t
level
;
struct
rt_pm
*
pm
;
if
(
_pm_init_flag
==
0
)
return
;
if
(
mode
>
(
PM_SLEEP_MODE_MAX
-
1
))
return
;
if
(
module_id
>
(
PM_MODULE_MAX_ID
-
1
))
return
;
level
=
rt_hw_interrupt_disable
();
pm
=
&
_pm
;
pm
->
module_status
[
module_id
].
req_status
=
0x01
;
if
(
pm
->
modes
[
mode
]
<
255
)
pm
->
modes
[
mode
]
++
;
_pm_select_sleep_mode
(
pm
);
rt_hw_interrupt_enable
(
level
);
}
/**
* Upper application or device driver releases the stall
* of corresponding power mode.
*
* @param module_id the application or device module id
* @param mode the system power sleep mode
*
*/
void
rt_pm_module_release
(
uint8_t
module_id
,
rt_uint8_t
mode
)
{
rt_ubase_t
level
;
struct
rt_pm
*
pm
;
if
(
_pm_init_flag
==
0
)
return
;
if
(
mode
>
(
PM_SLEEP_MODE_MAX
-
1
))
return
;
if
(
module_id
>
(
PM_MODULE_MAX_ID
-
1
))
return
;
level
=
rt_hw_interrupt_disable
();
pm
=
&
_pm
;
if
(
pm
->
modes
[
mode
]
>
0
)
pm
->
modes
[
mode
]
--
;
if
(
pm
->
modes
[
mode
]
==
0
)
pm
->
module_status
[
module_id
].
req_status
=
0x00
;
_pm_select_sleep_mode
(
pm
);
rt_hw_interrupt_enable
(
level
);
}
/**
* Upper application or device driver releases all the stall
* of corresponding power mode.
*
* @param module_id the application or device module id
* @param mode the system power sleep mode
*
*/
void
rt_pm_module_release_all
(
uint8_t
module_id
,
rt_uint8_t
mode
)
{
rt_ubase_t
level
;
struct
rt_pm
*
pm
;
if
(
_pm_init_flag
==
0
)
return
;
if
(
mode
>
(
PM_SLEEP_MODE_MAX
-
1
))
return
;
level
=
rt_hw_interrupt_disable
();
pm
=
&
_pm
;
pm
->
modes
[
mode
]
=
0
;
pm
->
module_status
[
module_id
].
req_status
=
0x00
;
_pm_select_sleep_mode
(
pm
);
rt_hw_interrupt_enable
(
level
);
}
/**
* Register a device with PM feature
*
...
...
@@ -508,6 +696,10 @@ void rt_system_pm_init(const struct rt_pm_ops *ops,
rt_memset
(
pm
->
modes
,
0
,
sizeof
(
pm
->
modes
));
pm
->
sleep_mode
=
_pm_default_sleep
;
/* when system power on, set default sleep modes */
pm
->
modes
[
pm
->
sleep_mode
]
=
1
;
pm
->
module_status
[
PM_POWER_ID
].
req_status
=
1
;
pm
->
run_mode
=
RT_PM_DEFAULT_RUN_MODE
;
pm
->
timer_mask
=
timer_mask
;
...
...
@@ -541,6 +733,18 @@ static void rt_pm_release_mode(int argc, char **argv)
}
MSH_CMD_EXPORT_ALIAS
(
rt_pm_release_mode
,
pm_release
,
release
power
management
mode
);
static
void
rt_pm_release_mode_all
(
int
argc
,
char
**
argv
)
{
int
mode
=
0
;
if
(
argc
>=
2
)
{
mode
=
atoi
(
argv
[
1
]);
}
rt_pm_release_all
(
mode
);
}
MSH_CMD_EXPORT_ALIAS
(
rt_pm_release_mode_all
,
pm_release_all
,
release
power
management
mode
count
);
static
void
rt_pm_request_mode
(
int
argc
,
char
**
argv
)
{
int
mode
=
0
;
...
...
@@ -553,6 +757,66 @@ 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_module_release_mode
(
int
argc
,
char
**
argv
)
{
int
module
=
0
;
int
mode
=
0
;
if
(
argc
>=
3
)
{
module
=
atoi
(
argv
[
1
]);
mode
=
atoi
(
argv
[
2
]);
}
rt_pm_module_release
(
module
,
mode
);
}
MSH_CMD_EXPORT_ALIAS
(
rt_module_release_mode
,
pm_module_release
,
release
module
power
mode
);
static
void
rt_module_release_mode_all
(
int
argc
,
char
**
argv
)
{
int
module
=
0
;
int
mode
=
0
;
if
(
argc
>=
3
)
{
module
=
atoi
(
argv
[
1
]);
mode
=
atoi
(
argv
[
2
]);
}
rt_pm_module_release_all
(
module
,
mode
);
}
MSH_CMD_EXPORT_ALIAS
(
rt_module_release_mode_all
,
pm_module_release_all
,
release
power
management
mode
count
);
static
void
rt_module_request_mode
(
int
argc
,
char
**
argv
)
{
int
module
=
0
;
int
mode
=
0
;
if
(
argc
>=
3
)
{
module
=
atoi
(
argv
[
1
]);
mode
=
atoi
(
argv
[
2
]);
}
rt_pm_module_request
(
module
,
mode
);
}
MSH_CMD_EXPORT_ALIAS
(
rt_module_request_mode
,
pm_module_request
,
request
power
management
mode
);
static
void
rt_module_delay_sleep
(
int
argc
,
char
**
argv
)
{
int
module
=
0
;
unsigned
int
timeout
=
0
;
if
(
argc
>=
3
)
{
module
=
atoi
(
argv
[
1
]);
timeout
=
atoi
(
argv
[
2
]);
}
rt_pm_module_delay_sleep
(
module
,
timeout
);
}
MSH_CMD_EXPORT_ALIAS
(
rt_module_delay_sleep
,
pm_module_delay
,
module
request
delay
sleep
);
static
void
rt_pm_run_mode_switch
(
int
argc
,
char
**
argv
)
{
int
mode
=
0
;
...
...
@@ -565,6 +829,32 @@ static void rt_pm_run_mode_switch(int argc, char **argv)
}
MSH_CMD_EXPORT_ALIAS
(
rt_pm_run_mode_switch
,
pm_run
,
switch
power
management
run
mode
);
rt_uint32_t
rt_pm_module_get_status
(
void
)
{
rt_uint8_t
index
=
0
;
struct
rt_pm
*
pm
;
rt_uint32_t
req_status
=
0x00
;
pm
=
&
_pm
;
for
(
index
=
0
;
index
<
32
;
index
++
)
{
if
(
pm
->
module_status
[
index
].
req_status
==
0x01
)
req_status
|=
1
<<
index
;
if
(
index
>=
PM_MODULE_MAX_ID
)
break
;
}
return
req_status
;
}
rt_uint8_t
rt_pm_get_sleep_mode
(
void
)
{
struct
rt_pm
*
pm
;
pm
=
&
_pm
;
return
pm
->
sleep_mode
;
}
static
void
rt_pm_dump_status
(
void
)
{
rt_uint32_t
index
;
...
...
@@ -586,6 +876,22 @@ static void rt_pm_dump_status(void)
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
]);
rt_kprintf
(
"
\n
"
);
rt_kprintf
(
"| module | busy | start time | timeout |
\n
"
);
rt_kprintf
(
"+--------+------+------------+-----------+
\n
"
);
for
(
index
=
0
;
index
<
PM_MODULE_MAX_ID
;
index
++
)
{
if
((
pm
->
module_status
[
index
].
busy_flag
==
RT_TRUE
)
||
(
pm
->
module_status
[
index
].
req_status
!=
0x00
))
{
rt_kprintf
(
"| %04d | %d | 0x%08x | 0x%08x |
\n
"
,
index
,
pm
->
module_status
[
index
].
busy_flag
,
pm
->
module_status
[
index
].
start_time
,
pm
->
module_status
[
index
].
timeout
);
}
}
rt_kprintf
(
"+--------+------+------------+-----------+
\n
"
);
}
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
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录