Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
BaiXuePrincess
rt-thread
提交
7455e248
R
rt-thread
项目概览
BaiXuePrincess
/
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,发现更多精彩内容 >>
提交
7455e248
编写于
12月 05, 2021
作者:
张
张世争
提交者:
Bernard Xiong
12月 14, 2021
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[components] PM框架更新
上级
153ab5c2
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
700 addition
and
41 deletion
+700
-41
bsp/stm32/stm32l475-atk-pandora/board/pm_cfg.h
bsp/stm32/stm32l475-atk-pandora/board/pm_cfg.h
+25
-0
components/drivers/Kconfig
components/drivers/Kconfig
+36
-0
components/drivers/include/drivers/lptimer.h
components/drivers/include/drivers/lptimer.h
+38
-0
components/drivers/include/drivers/pm.h
components/drivers/include/drivers/pm.h
+30
-8
components/drivers/pm/SConscript
components/drivers/pm/SConscript
+1
-0
components/drivers/pm/lptimer.c
components/drivers/pm/lptimer.c
+176
-0
components/drivers/pm/pm.c
components/drivers/pm/pm.c
+394
-33
未找到文件。
bsp/stm32/stm32l475-atk-pandora/board/pm_cfg.h
0 → 100644
浏览文件 @
7455e248
#ifndef __PM_CFG_H__
#define __PM_CFG_H__
enum
pm_module_id
{
PM_NONE_ID
=
0
,
PM_POWER_ID
,
PM_BOARD_ID
,
PM_LCD_ID
,
PM_KEY_ID
,
PM_TP_ID
,
PM_OTA_ID
,
PM_SPI_ID
,
PM_I2C_ID
,
PM_ADC_ID
,
PM_RTC_ID
,
PM_GPIO_ID
,
PM_UART_ID
,
PM_SENSOR_ID
,
PM_ALARM_ID
,
PM_BLE_ID
,
PM_MODULE_MAX_ID
,
/* enum must! */
};
#endif
components/drivers/Kconfig
浏览文件 @
7455e248
...
...
@@ -145,6 +145,42 @@ config RT_USING_PM
bool "Using Power Management device drivers"
default n
if RT_USING_PM
config PM_TICKLESS_THRESHOLD_TIME
int "PM tickless threashold time"
default 2
config PM_USING_CUSTOM_CONFIG
bool "PM using custom pm config"
default n
config PM_ENABLE_DEBUG
bool "PM Enable Debug"
default n
config PM_ENABLE_SUSPEND_SLEEP_MODE
bool "PM Device suspend change sleep mode"
default n
config PM_ENABLE_THRESHOLD_SLEEP_MODE
bool "PM using threshold time change sleep mode"
default n
if PM_ENABLE_THRESHOLD_SLEEP_MODE
config PM_LIGHT_THRESHOLD_TIME
int "PM light mode threashold time"
default 5
config PM_DEEP_THRESHOLD_TIME
int "PM deep mode threashold time"
default 20
config PM_STANDBY_THRESHOLD_TIME
int "PM standby mode threashold time"
default 100
endif
endif
config RT_USING_RTC
bool "Using RTC device drivers"
default n
...
...
components/drivers/include/drivers/lptimer.h
0 → 100644
浏览文件 @
7455e248
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-10-11 zhangsz the first version
*/
#ifndef __LPTIMER_H__
#define __LPTIMER_H__
#include <rtthread.h>
struct
rt_lptimer
{
struct
rt_timer
timer
;
rt_list_t
list
;
};
typedef
struct
rt_lptimer
*
rt_lptimer_t
;
void
rt_lptimer_init
(
rt_lptimer_t
timer
,
const
char
*
name
,
void
(
*
timeout
)(
void
*
parameter
),
void
*
parameter
,
rt_tick_t
time
,
rt_uint8_t
flag
);
rt_err_t
rt_lptimer_detach
(
rt_lptimer_t
timer
);
rt_err_t
rt_lptimer_start
(
rt_lptimer_t
timer
);
rt_err_t
rt_lptimer_stop
(
rt_lptimer_t
timer
);
rt_err_t
rt_lptimer_control
(
rt_lptimer_t
timer
,
int
cmd
,
void
*
arg
);
rt_tick_t
rt_lptimer_next_timeout_tick
(
void
);
#endif
components/drivers/include/drivers/pm.h
浏览文件 @
7455e248
...
...
@@ -17,8 +17,7 @@
#include <stdint.h>
#include <rtthread.h>
#ifndef PM_HAS_CUSTOM_CONFIG
#include <drivers/lptimer.h>
/* All modes used for rt_pm_request() and rt_pm_release() */
enum
...
...
@@ -48,10 +47,6 @@ enum
RT_PM_FREQUENCY_PENDING
=
0x01
,
};
#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" */
#define PM_SLEEP_MODE_NAMES \
{ \
...
...
@@ -71,6 +66,7 @@ enum
"Low Mode", \
}
#ifndef PM_USING_CUSTOM_CONFIG
/**
* Modules used for
* pm_module_request(PM_BOARD_ID, PM_SLEEP_MODE_IDLE)
...
...
@@ -98,11 +94,23 @@ enum pm_module_id {
PM_MODULE_MAX_ID
,
/* enum must! */
};
#else
/* PM_HAS_CUSTOM_CONFIG */
#else
#include <pm_cfg.h>
#endif
/* PM_HAS_CUSTOM_CONFIG */
#endif
/* PM_USING_CUSTOM_CONFIG */
#ifndef RT_PM_DEFAULT_SLEEP_MODE
#define RT_PM_DEFAULT_SLEEP_MODE PM_SLEEP_MODE_NONE
#endif
#ifndef RT_PM_DEFAULT_DEEPSLEEP_MODE
#define RT_PM_DEFAULT_DEEPSLEEP_MODE PM_SLEEP_MODE_DEEP
#endif
#ifndef RT_PM_DEFAULT_RUN_MODE
#define RT_PM_DEFAULT_RUN_MODE PM_RUN_MODE_NORMAL_SPEED
#endif
/**
* device control flag to request or release power
...
...
@@ -160,6 +168,9 @@ struct rt_pm
/* modules request status*/
struct
rt_pm_module
module_status
[
PM_MODULE_MAX_ID
];
/* sleep request table */
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
;
struct
rt_device_pm
*
device_pm
;
...
...
@@ -203,5 +214,16 @@ 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
);
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
);
#endif
/* __PM_H__ */
components/drivers/pm/SConscript
浏览文件 @
7455e248
...
...
@@ -7,6 +7,7 @@ group = []
if
GetDepend
([
'RT_USING_PM'
]):
src
=
src
+
[
'pm.c'
]
src
=
src
+
[
'lptimer.c'
]
if
len
(
src
):
group
=
DefineGroup
(
'DeviceDrivers'
,
src
,
depend
=
[
''
],
CPPPATH
=
CPPPATH
)
...
...
components/drivers/pm/lptimer.c
0 → 100644
浏览文件 @
7455e248
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-10-11 zhangsz the first version
*/
#include <rtthread.h>
#include <rthw.h>
#include <drivers/lptimer.h>
static
rt_list_t
rt_soft_lptimer_list
=
RT_LIST_OBJECT_INIT
(
rt_soft_lptimer_list
);
/* lptimer init */
void
rt_lptimer_init
(
rt_lptimer_t
timer
,
const
char
*
name
,
void
(
*
timeout
)(
void
*
parameter
),
void
*
parameter
,
rt_tick_t
time
,
rt_uint8_t
flag
)
{
rt_timer_init
(
&
timer
->
timer
,
name
,
timeout
,
parameter
,
time
,
flag
);
rt_list_init
(
&
timer
->
list
);
}
/* lptimer detach */
rt_err_t
rt_lptimer_detach
(
rt_lptimer_t
timer
)
{
rt_base_t
level
;
rt_err_t
ret
=
RT_EOK
;
RT_ASSERT
(
timer
!=
RT_NULL
);
/* disable interrupt */
level
=
rt_hw_interrupt_disable
();
ret
=
rt_timer_detach
(
&
timer
->
timer
);
rt_list_remove
(
&
timer
->
list
);
/* enable interrupt */
rt_hw_interrupt_enable
(
level
);
return
ret
;
}
/* lptimer start */
rt_err_t
rt_lptimer_start
(
rt_lptimer_t
timer
)
{
rt_base_t
level
;
RT_ASSERT
(
timer
!=
RT_NULL
);
/* disable interrupt */
level
=
rt_hw_interrupt_disable
();
rt_list_remove
(
&
timer
->
list
);
/* remove first */
if
(
rt_timer_start
(
&
timer
->
timer
)
==
RT_EOK
)
{
/* insert to lptimer list */
rt_list_insert_after
(
&
rt_soft_lptimer_list
,
&
(
timer
->
list
));
}
else
{
/* enable interrupt */
rt_hw_interrupt_enable
(
level
);
return
-
RT_ERROR
;
}
/* enable interrupt */
rt_hw_interrupt_enable
(
level
);
return
RT_EOK
;
}
/* lptimer stop */
rt_err_t
rt_lptimer_stop
(
rt_lptimer_t
timer
)
{
rt_base_t
level
;
RT_ASSERT
(
timer
!=
RT_NULL
);
/* disable interrupt */
level
=
rt_hw_interrupt_disable
();
rt_list_remove
(
&
timer
->
list
);
if
(
rt_timer_stop
(
&
timer
->
timer
)
==
RT_EOK
)
{
/* enable interrupt */
rt_hw_interrupt_enable
(
level
);
return
RT_EOK
;
}
else
{
/* enable interrupt */
rt_hw_interrupt_enable
(
level
);
return
-
RT_ERROR
;
}
}
rt_err_t
rt_lptimer_control
(
rt_lptimer_t
timer
,
int
cmd
,
void
*
arg
)
{
RT_ASSERT
(
timer
!=
RT_NULL
);
return
rt_timer_control
(
&
timer
->
timer
,
cmd
,
arg
);
}
/* get the next soft lptimer timeout */
rt_tick_t
rt_lptimer_next_timeout_tick
(
void
)
{
struct
rt_lptimer
*
timer
;
rt_base_t
level
;
rt_tick_t
timeout_tick
=
RT_TICK_MAX
;
struct
rt_list_node
*
node
=
RT_NULL
;
rt_tick_t
temp_tick
=
0
;
rt_tick_t
min_tick
=
RT_TICK_MAX
;
rt_tick_t
cur_tick
=
rt_tick_get
();
/* disable interrupt */
level
=
rt_hw_interrupt_disable
();
if
(
!
rt_list_isempty
(
&
rt_soft_lptimer_list
))
{
/* find the first active timer's timeout */
rt_list_for_each
(
node
,
&
rt_soft_lptimer_list
)
{
timer
=
rt_list_entry
(
node
,
struct
rt_lptimer
,
list
);
if
(
timer
->
timer
.
parent
.
flag
&
RT_TIMER_FLAG_ACTIVATED
)
{
temp_tick
=
timer
->
timer
.
timeout_tick
-
cur_tick
;
/* find the least timeout_tick */
if
(
min_tick
>
temp_tick
)
{
min_tick
=
temp_tick
;
timeout_tick
=
timer
->
timer
.
timeout_tick
;
}
}
}
}
/* enable interrupt */
rt_hw_interrupt_enable
(
level
);
return
timeout_tick
;
}
void
lptimer_dump
(
void
)
{
struct
rt_lptimer
*
timer
;
rt_base_t
level
;
struct
rt_list_node
*
node
=
RT_NULL
;
/* disable interrupt */
level
=
rt_hw_interrupt_disable
();
rt_kprintf
(
"| lptimer | periodic | timeout | flag |
\n
"
);
rt_kprintf
(
"+---------------+------------+------------+-------------+
\n
"
);
if
(
!
rt_list_isempty
(
&
rt_soft_lptimer_list
))
{
rt_list_for_each
(
node
,
&
rt_soft_lptimer_list
)
{
timer
=
rt_list_entry
(
node
,
struct
rt_lptimer
,
list
);
rt_kprintf
(
"| %-13s | 0x%08x | 0x%08x |"
,
timer
->
timer
.
parent
.
name
,
timer
->
timer
.
init_tick
,
timer
->
timer
.
timeout_tick
);
if
(
timer
->
timer
.
parent
.
flag
&
RT_TIMER_FLAG_ACTIVATED
)
rt_kprintf
(
" activated |
\n
"
);
else
rt_kprintf
(
" deactivated |
\n
"
);
}
}
/* enable interrupt */
rt_hw_interrupt_enable
(
level
);
rt_kprintf
(
"+---------------+------------+------------+-------------+
\n
"
);
}
MSH_CMD_EXPORT
(
lptimer_dump
,
soft
lptimer
dump
);
components/drivers/pm/pm.c
浏览文件 @
7455e248
...
...
@@ -15,9 +15,44 @@
#include <rthw.h>
#include <rtthread.h>
#include <drivers/pm.h>
#include <stdlib.h>
#ifdef RT_USING_PM
/* tickless threshold time */
#ifndef PM_TICKLESS_THRESHOLD_TIME
#define PM_TICKLESS_THRESHOLD_TIME 2
#endif
/* tickless threshold : sleep mode */
#ifndef PM_TICKLESS_THRESHOLD_MODE
#define PM_TICKLESS_THRESHOLD_MODE PM_SLEEP_MODE_IDLE
#endif
/* busy : sleep mode */
#ifndef PM_BUSY_SLEEP_MODE
#define PM_BUSY_SLEEP_MODE PM_SLEEP_MODE_IDLE
#endif
/* suspend : suspend sleep mode */
#ifndef PM_SUSPEND_SLEEP_MODE
#define PM_SUSPEND_SLEEP_MODE PM_SLEEP_MODE_IDLE
#endif
#ifdef PM_ENABLE_THRESHOLD_SLEEP_MODE
#ifndef PM_LIGHT_THRESHOLD_TIME
#define PM_LIGHT_THRESHOLD_TIME 5
#endif
#ifndef PM_DEEP_THRESHOLD_TIME
#define PM_DEEP_THRESHOLD_TIME 20
#endif
#ifndef PM_STANDBY_THRESHOLD_TIME
#define PM_STANDBY_THRESHOLD_TIME 100
#endif
#endif
static
struct
rt_pm
_pm
;
/* default mode : system power on */
...
...
@@ -29,8 +64,6 @@ 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
;
#define RT_PM_TICKLESS_THRESH (2)
RT_WEAK
rt_uint32_t
rt_pm_enter_critical
(
rt_uint8_t
sleep_mode
)
{
return
rt_hw_interrupt_disable
();
...
...
@@ -41,6 +74,48 @@ RT_WEAK void rt_pm_exit_critical(rt_uint32_t ctx, rt_uint8_t sleep_mode)
rt_hw_interrupt_enable
(
ctx
);
}
/* 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
);
}
/* 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
);
}
/* 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
);
return
RT_TICK_MAX
;
}
/* 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
);
}
/**
* This function will suspend all registered devices
*/
...
...
@@ -111,6 +186,30 @@ static void _pm_frequency_scaling(struct rt_pm *pm)
}
}
/**
* judge sleep mode from sleep request
*
* @param none
*
* @return sleep mode
*/
static
rt_uint8_t
_judge_sleep_mode
(
void
)
{
rt_uint16_t
index
;
rt_uint16_t
len
;
for
(
index
=
0
;
index
<
PM_SLEEP_MODE_MAX
-
1
;
index
++
)
{
for
(
len
=
0
;
len
<
((
PM_MODULE_MAX_ID
+
31
)
/
32
);
len
++
)
{
if
(
_pm
.
sleep_status
[
index
][
len
]
!=
0x00
)
return
index
;
}
}
return
PM_SLEEP_MODE_MAX
;
/* default sleep mode */
}
/**
* This function selects the sleep mode according to the rt_pm_request/rt_pm_release count.
*/
...
...
@@ -120,6 +219,7 @@ static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm)
rt_uint8_t
mode
;
mode
=
_pm_default_deepsleep
;
rt_uint8_t
request_mode
=
_judge_sleep_mode
();
for
(
index
=
PM_SLEEP_MODE_NONE
;
index
<
PM_SLEEP_MODE_MAX
;
index
++
)
{
if
(
pm
->
modes
[
index
])
...
...
@@ -128,7 +228,10 @@ static rt_uint8_t _pm_select_sleep_mode(struct rt_pm *pm)
break
;
}
}
pm
->
sleep_mode
=
mode
;
/* select the high power mode */
if
(
request_mode
<
mode
)
mode
=
request_mode
;
return
mode
;
}
...
...
@@ -185,6 +288,72 @@ static rt_bool_t _pm_device_check_idle(void)
return
RT_TRUE
;
}
RT_WEAK
rt_tick_t
pm_timer_next_timeout_tick
(
rt_uint8_t
mode
)
{
switch
(
mode
)
{
case
PM_SLEEP_MODE_LIGHT
:
return
rt_timer_next_timeout_tick
();
case
PM_SLEEP_MODE_DEEP
:
case
PM_SLEEP_MODE_STANDBY
:
return
rt_lptimer_next_timeout_tick
();
}
return
RT_TICK_MAX
;
}
/**
* This function will judge sleep mode from threshold timeout.
*
* @param cur_mode the current pm sleep mode
* @param timeout_tick the threshold timeout
*
* @return none
*/
RT_WEAK
rt_uint8_t
pm_get_sleep_threshold_mode
(
rt_uint8_t
cur_mode
,
rt_tick_t
timeout_tick
)
{
rt_uint8_t
sleep_mode
=
cur_mode
;
if
(
_pm_init_flag
==
0
)
return
sleep_mode
;
if
(
cur_mode
>=
PM_SLEEP_MODE_MAX
)
return
sleep_mode
;
#ifdef PM_ENABLE_THRESHOLD_SLEEP_MODE
switch
(
cur_mode
)
{
case
PM_SLEEP_MODE_NONE
:
case
PM_SLEEP_MODE_IDLE
:
break
;
case
PM_SLEEP_MODE_LIGHT
:
if
(
timeout_tick
<
PM_LIGHT_THRESHOLD_TIME
)
sleep_mode
=
PM_SLEEP_MODE_IDLE
;
break
;
case
PM_SLEEP_MODE_DEEP
:
if
(
timeout_tick
<
PM_LIGHT_THRESHOLD_TIME
)
sleep_mode
=
PM_SLEEP_MODE_IDLE
;
else
if
(
timeout_tick
<
PM_DEEP_THRESHOLD_TIME
)
sleep_mode
=
PM_SLEEP_MODE_LIGHT
;
break
;
case
PM_SLEEP_MODE_STANDBY
:
if
(
timeout_tick
<
PM_LIGHT_THRESHOLD_TIME
)
sleep_mode
=
PM_SLEEP_MODE_IDLE
;
else
if
(
timeout_tick
<
PM_DEEP_THRESHOLD_TIME
)
sleep_mode
=
PM_SLEEP_MODE_LIGHT
;
else
if
(
timeout_tick
<
PM_STANDBY_THRESHOLD_TIME
)
sleep_mode
=
PM_SLEEP_MODE_DEEP
;
}
#else
if
(
timeout_tick
<
PM_TICKLESS_THRESHOLD_TIME
)
{
cur_mode
=
PM_SLEEP_MODE_IDLE
;
}
#endif
return
cur_mode
;
}
/**
* This function changes the power sleep mode base on the result of selection
*/
...
...
@@ -192,16 +361,21 @@ 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
;
uint8_t
sleep_mode
=
PM_SLEEP_MODE_DEEP
;
level
=
rt_pm_enter_critical
(
pm
->
sleep_mode
);
/* module busy request */
/* judge sleep mode from module request */
pm
->
sleep_mode
=
_pm_select_sleep_mode
(
pm
);
/* module busy request check */
if
(
_pm_device_check_idle
()
==
RT_FALSE
)
{
pm
->
ops
->
sleep
(
pm
,
PM_SLEEP_MODE_NONE
);
rt_pm_exit_critical
(
level
,
pm
->
sleep_mode
);
return
;
sleep_mode
=
PM_BUSY_SLEEP_MODE
;
if
(
sleep_mode
<
pm
->
sleep_mode
)
{
pm
->
sleep_mode
=
sleep_mode
;
/* judge the highest sleep mode */
}
}
if
(
_pm
.
sleep_mode
==
PM_SLEEP_MODE_NONE
)
...
...
@@ -216,50 +390,54 @@ static void _pm_change_sleep_mode(struct rt_pm *pm)
_pm_notify
.
notify
(
RT_PM_ENTER_SLEEP
,
pm
->
sleep_mode
,
_pm_notify
.
data
);
/* Suspend all peripheral device */
ret
=
_pm_device_suspend
(
pm
->
sleep_mode
);
#ifdef PM_ENABLE_SUSPEND_SLEEP_MODE
int
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
;
}
pm
->
ops
->
sleep
(
pm
,
pm
->
sleep_mode
);
/* suspend failed */
rt_pm_exit_critical
(
level
,
pm
->
sleep_mode
);
return
;
}
#else
_pm_device_suspend
(
pm
->
sleep_mode
);
#endif
/* Tickless*/
if
(
pm
->
timer_mask
&
(
0x01
<<
pm
->
sleep_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
=
pm_timer_next_timeout_tick
(
pm
->
sleep_mode
);
timeout_tick
=
timeout_tick
-
rt_tick_get
();
/* Judge sleep_mode from threshold time */
pm
->
sleep_mode
=
pm_get_sleep_threshold_mode
(
pm
->
sleep_mode
,
timeout_tick
);
if
(
pm
->
timer_mask
&
(
0x01
<<
pm
->
sleep_mode
))
{
timeout_tick
=
timeout_tick
-
rt_tick_get
();
if
(
timeout_tick
<
RT_PM_TICKLESS_THRESH
)
if
(
timeout_tick
==
RT_TICK_MAX
)
{
pm
->
sleep_mode
=
PM_SLEEP_MODE_IDLE
;
pm
_lptimer_start
(
pm
,
RT_TICK_MAX
)
;
}
else
{
pm
->
ops
->
timer_start
(
pm
,
timeout_tick
);
pm
_lp
timer_start
(
pm
,
timeout_tick
);
}
}
}
/* enter lower power state */
pm
->
ops
->
sleep
(
pm
,
pm
->
sleep_mode
);
pm
_
sleep
(
pm
,
pm
->
sleep_mode
);
/* wake up from lower power state*/
if
(
pm
->
timer_mask
&
(
0x01
<<
pm
->
sleep_mode
))
{
delta_tick
=
pm
->
ops
->
timer_get_tick
(
pm
);
pm
->
ops
->
timer_stop
(
pm
);
delta_tick
=
pm
_lptimer_get_timeout
(
pm
);
pm
_lp
timer_stop
(
pm
);
if
(
delta_tick
)
{
rt_tick_set
(
rt_tick_get
()
+
delta_tick
);
...
...
@@ -320,7 +498,6 @@ void rt_pm_request(rt_uint8_t mode)
pm
=
&
_pm
;
if
(
pm
->
modes
[
mode
]
<
255
)
pm
->
modes
[
mode
]
++
;
_pm_select_sleep_mode
(
pm
);
rt_hw_interrupt_enable
(
level
);
}
...
...
@@ -346,7 +523,6 @@ void rt_pm_release(rt_uint8_t mode)
pm
=
&
_pm
;
if
(
pm
->
modes
[
mode
]
>
0
)
pm
->
modes
[
mode
]
--
;
_pm_select_sleep_mode
(
pm
);
rt_hw_interrupt_enable
(
level
);
}
...
...
@@ -371,7 +547,6 @@ void rt_pm_release_all(rt_uint8_t mode)
level
=
rt_hw_interrupt_disable
();
pm
=
&
_pm
;
pm
->
modes
[
mode
]
=
0
;
_pm_select_sleep_mode
(
pm
);
rt_hw_interrupt_enable
(
level
);
}
...
...
@@ -401,7 +576,6 @@ void rt_pm_module_request(uint8_t module_id, rt_uint8_t mode)
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
);
}
...
...
@@ -433,7 +607,6 @@ void rt_pm_module_release(uint8_t module_id, rt_uint8_t mode)
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
);
}
...
...
@@ -460,10 +633,135 @@ void rt_pm_module_release_all(uint8_t module_id, rt_uint8_t mode)
pm
=
&
_pm
;
pm
->
modes
[
mode
]
=
0
;
pm
->
module_status
[
module_id
].
req_status
=
0x00
;
_pm_select_sleep_mode
(
pm
);
rt_hw_interrupt_enable
(
level
);
}
/**
* This function will let current module work with specified sleep mode.
*
* @param module_id the pm module id
* @param mode the pm sleep mode
*
* @return none
*/
void
rt_pm_sleep_request
(
rt_uint16_t
module_id
,
rt_uint8_t
mode
)
{
rt_uint32_t
level
;
if
(
module_id
>=
PM_MODULE_MAX_ID
)
{
return
;
}
if
(
mode
>=
(
PM_SLEEP_MODE_MAX
-
1
))
{
return
;
}
level
=
rt_hw_interrupt_disable
();
_pm
.
sleep_status
[
mode
][
module_id
/
32
]
|=
1
<<
(
module_id
%
32
);
rt_hw_interrupt_enable
(
level
);
}
/**
* This function will let current module work with PM_SLEEP_MODE_NONE mode.
*
* @param module_id the pm module id
*
* @return NULL
*/
void
rt_pm_sleep_none_request
(
rt_uint16_t
module_id
)
{
rt_pm_sleep_request
(
module_id
,
PM_SLEEP_MODE_NONE
);
}
/**
* This function will let current module work with PM_SLEEP_MODE_IDLE mode.
*
* @param module_id the pm module id
*
* @return NULL
*/
void
rt_pm_sleep_idle_request
(
rt_uint16_t
module_id
)
{
rt_pm_sleep_request
(
module_id
,
PM_SLEEP_MODE_IDLE
);
}
/**
* This function will let current module work with PM_SLEEP_MODE_LIGHT mode.
*
* @param module_id the pm module id
*
* @return NULL
*/
void
rt_pm_sleep_light_request
(
rt_uint16_t
module_id
)
{
rt_pm_sleep_request
(
module_id
,
PM_SLEEP_MODE_LIGHT
);
}
/**
* When current module don't work, release requested sleep mode.
*
* @param module_id the pm module id
* @param mode the pm sleep mode
*
* @return NULL
*/
void
rt_pm_sleep_release
(
rt_uint16_t
module_id
,
rt_uint8_t
mode
)
{
rt_uint32_t
level
;
if
(
module_id
>=
PM_MODULE_MAX_ID
)
{
return
;
}
if
(
mode
>=
(
PM_SLEEP_MODE_MAX
-
1
))
{
return
;
}
level
=
rt_hw_interrupt_disable
();
_pm
.
sleep_status
[
mode
][
module_id
/
32
]
&=
~
(
1
<<
(
module_id
%
32
));
rt_hw_interrupt_enable
(
level
);
}
/**
* The specified module release the requested PM_SLEEP_MODE_NONE mode
*
* @param module_id the pm module id
*
* @return none
*/
void
rt_pm_sleep_none_release
(
rt_uint16_t
module_id
)
{
rt_pm_sleep_release
(
module_id
,
PM_SLEEP_MODE_NONE
);
}
/**
* The specified module release the requested PM_SLEEP_MODE_IDLE mode
*
* @param module_id the pm module id
*
* @return none
*/
void
rt_pm_sleep_idle_release
(
rt_uint16_t
module_id
)
{
rt_pm_sleep_release
(
module_id
,
PM_SLEEP_MODE_IDLE
);
}
/**
* The specified module release the requested PM_SLEEP_MODE_LIGHT mode
*
* @param module_id the pm module id
*
* @return none
*/
void
rt_pm_sleep_light_release
(
rt_uint16_t
module_id
)
{
rt_pm_sleep_release
(
module_id
,
PM_SLEEP_MODE_LIGHT
);
}
/**
* Register a device with PM feature
*
...
...
@@ -853,6 +1151,69 @@ rt_uint8_t rt_pm_get_sleep_mode(void)
return
pm
->
sleep_mode
;
}
/* get pm entity pointer */
struct
rt_pm
*
rt_pm_get_handle
(
void
)
{
return
&
_pm
;
}
#ifdef PM_ENABLE_DEBUG
/**
* print current module sleep request list
*
* @param none
*
* @return none
*/
void
pm_sleep_dump
(
void
)
{
uint8_t
index
;
uint16_t
len
;
rt_kprintf
(
"+-------------+--------------+
\n
"
);
rt_kprintf
(
"| Sleep Mode | Request List |
\n
"
);
rt_kprintf
(
"+-------------+--------------+
\n
"
);
for
(
index
=
0
;
index
<
PM_SLEEP_MODE_MAX
-
1
;
index
++
)
{
for
(
len
=
0
;
len
<
((
PM_MODULE_MAX_ID
+
31
)
/
32
);
len
++
)
{
rt_kprintf
(
"| Mode[%d] : %d | 0x%08x |
\n
"
,
index
,
len
,
_pm
.
sleep_status
[
index
][
len
]);
}
}
rt_kprintf
(
"+-------------+--------------+
\n
"
);
}
MSH_CMD_EXPORT
(
pm_sleep_dump
,
dump
pm
request
list
);
static
void
pm_sleep_request
(
int
argc
,
char
**
argv
)
{
int
module
=
0
;
int
mode
=
0
;
if
(
argc
>=
3
)
{
module
=
atoi
(
argv
[
1
]);
mode
=
atoi
(
argv
[
2
]);
rt_pm_sleep_request
(
module
,
mode
);
}
}
MSH_CMD_EXPORT
(
pm_sleep_request
,
pm_sleep_request
module
sleep_mode
);
static
void
pm_sleep_release
(
int
argc
,
char
**
argv
)
{
int
module
=
0
;
int
mode
=
0
;
if
(
argc
>=
3
)
{
module
=
atoi
(
argv
[
1
]);
mode
=
atoi
(
argv
[
2
]);
rt_pm_sleep_release
(
module
,
mode
);
}
}
MSH_CMD_EXPORT
(
pm_sleep_release
,
pm_sleep_release
module
sleep_mode
);
#endif
static
void
rt_pm_dump_status
(
void
)
{
rt_uint32_t
index
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录