PM电源管理

初始化

drv_pm_hw_init -> rt_system_pm_init

1
2
3
4
5
6
7
8
9
10
11
12
13
14

/* initialize timer mask */

timer_mask = 1UL << PM_SLEEP_MODE_DEEP;


/* 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设备注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

/**

* Register a device with PM feature

*

* @paramdevice the device with PM feature

* @paramops the PM ops for device

*/

voidrt_pm_device_register(struct rt_device *device, conststruct rt_device_pm_ops *ops)

{

device_pm = (struct rt_device_pm *)RT_KERNEL_REALLOC(_pm.device_pm,

(_pm.device_pm_number + 1) * 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;

}

}


/**

* Unregister device from PM manager.

*

* @paramdevice the device with PM feature

*/

voidrt_pm_device_unregister(struct rt_device *device)

{

if (_pm.device_pm[index].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 */

break;

}

}

频率调整

  1. rt_pm_run_enter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

rt_err_trt_pm_run_enter(rt_uint8_tmode)

{

//切换的模式比当前模式小,则执行立刻切换

if (mode < pm->run_mode)

{

/* change system runing mode */

if(pm->ops != RT_NULL && pm->ops->run != RT_NULL)

{

pm->ops->run(pm, mode);

}

// pm设备进行频率调整

_pm_device_frequency_change(mode);

}

else

{

pm->flags |= RT_PM_FREQUENCY_PENDING;

}

pm->run_mode = mode;

}

调度

  1. 由空闲线程中执行 rt_system_power_manager
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

voidrt_system_power_manager(void)

{

if (_pm_init_flag == 0)

return;


/* CPU frequency scaling according to the runing mode settings */

_pm_frequency_scaling(&_pm);


/* Low Power Mode Processing */

_pm_change_sleep_mode(&_pm);

}

睡眠调度

1._pm_select_sleep_mode 获取sleep模式,选择请求的最高级别的模式

使用 rt_pm_requestrt_pm_release进行请求和释放

对mode进行加减操作

1
2
3
4
5
6
7
8
9
10

if (pm->modes[mode] < 255)

pm->modes[mode] ++;


if (pm->modes[mode] > 0)

pm->modes[mode] --;

2._pm_device_check_idle 检查设备是否在忙

使用 rt_pm_module_requestrt_pm_module_release进行请求和释放

对mode进行加减操作,并设置请求状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

pm->module_status[module_id].req_status = 0x01;

if (pm->modes[mode] < 255)

pm->modes[mode] ++;


if (pm->modes[mode] > 0)

pm->modes[mode] --;

if (pm->modes[mode] == 0)

pm->module_status[module_id].req_status = 0x00;

rt_pm_module_delay_sleep 延迟睡眠

1
2
3
4
5
6
7

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();

  1. 判断idle空闲 可修改模式为idle模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

/* module busy request check */

if (_pm_device_check_idle() == RT_FALSE)

{

sleep_mode = PM_BUSY_SLEEP_MODE;

if (sleep_mode < pm->sleep_mode)

{

pm->sleep_mode = sleep_mode; /* judge the highest sleep mode */

}

}

  1. 进退睡眠模式执行通知函数 rt_pm_notify_set注册通知函数

执行pm 设备 suspendresume

  1. 计算tick补偿
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

/* Tickless*/

if (pm->timer_mask & (0x01 << pm->sleep_mode))

{

timeout_tick = pm_timer_next_timeout_tick(pm->sleep_mode);

timeout_tick = timeout_tick - rt_tick_get();


// 根据需要唤醒时间,计算下一个睡眠模式

pm->sleep_mode = pm_get_sleep_threshold_mode(pm->sleep_mode, timeout_tick);


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);

}

}

}

  1. SLEEP后等待触发唤醒
  2. 获取定时器经过时间,停止定时器;

设置系统滴答时间补偿,并执行调度器时间片检查与定时器检查