1 /*
2 * Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Change Logs:
19 * Date Author Notes
20 * 2020-12-15 liuhy the first version
21 */
22
23 #include "drv_pm.h"
24
25 #ifdef RT_USING_PM
26
27 /* 注意:进入睡眠前,如果有中断挂起(SYSTICK、PENDSV、UART、EXTI等),睡眠将被瞬间唤醒。*/
sleep(struct rt_pm * pm,uint8_t mode)28 static void sleep(struct rt_pm *pm, uint8_t mode)
29 {
30 rt_base_t level;
31 level = rt_hw_interrupt_disable();
32 rt_hw_interrupt_enable(0x88);
33
34 switch (mode)
35 {
36 case PM_SLEEP_MODE_NONE:
37 break;
38
39 case PM_SLEEP_MODE_IDLE:
40 break;
41
42 case PM_SLEEP_MODE_LIGHT:
43 ald_pmu_stop_enter();
44 break;
45
46 case PM_SLEEP_MODE_DEEP:
47 ald_pmu_stop_enter();
48 break;
49
50 case PM_SLEEP_MODE_STANDBY:
51 ald_pmu_stop_enter();
52 break;
53
54 case PM_SLEEP_MODE_SHUTDOWN:
55 ald_pmu_stop_enter();
56 break;
57
58 default:
59 RT_ASSERT(0);
60 break;
61 }
62
63 rt_hw_interrupt_enable(level);
64 }
65
run(struct rt_pm * pm,uint8_t mode)66 static void run(struct rt_pm *pm, uint8_t mode)
67 {
68 static uint8_t last_mode;
69
70 if (mode == last_mode)
71 return;
72 last_mode = mode;
73
74 switch (mode)
75 {
76 case PM_RUN_MODE_HIGH_SPEED:
77 case PM_RUN_MODE_NORMAL_SPEED:
78 case PM_RUN_MODE_MEDIUM_SPEED:
79 case PM_RUN_MODE_LOW_SPEED:
80 default:
81 break;
82 }
83 }
84
85 /**
86 * This function caculate the PM tick from OS tick
87 *
88 * @param tick OS tick
89 *
90 * @return the PM tick
91 */
es32f3_pm_tick_from_os_tick(rt_tick_t tick)92 static rt_tick_t es32f3_pm_tick_from_os_tick(rt_tick_t tick)
93 {
94 rt_uint32_t freq = 1;
95
96 return (freq * tick / RT_TICK_PER_SECOND);
97 }
98
99 /**
100 * This function caculate the OS tick from PM tick
101 *
102 * @param tick PM tick
103 *
104 * @return the OS tick
105 */
es32f3_os_tick_from_pm_tick(rt_uint32_t tick)106 static rt_tick_t es32f3_os_tick_from_pm_tick(rt_uint32_t tick)
107 {
108 static rt_uint32_t os_tick_remain = 0;
109 rt_uint32_t ret, freq;
110
111 freq = 1;
112 ret = (tick * RT_TICK_PER_SECOND + os_tick_remain) / freq;
113
114 os_tick_remain += (tick * RT_TICK_PER_SECOND);
115 os_tick_remain %= freq;
116
117 return ret;
118 }
119
120 /**
121 * This function start the timer of pm
122 *
123 * @param pm Pointer to power manage structure
124 * @param timeout How many OS Ticks that MCU can sleep
125 */
pm_timer_start(struct rt_pm * pm,rt_uint32_t timeout)126 static void pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout)
127 {
128 RT_ASSERT(pm != RT_NULL);
129 RT_ASSERT(timeout > 0);
130
131 if (timeout != RT_TICK_MAX)
132 {
133 /* Convert OS Tick to pmtimer timeout value */
134 timeout = es32f3_pm_tick_from_os_tick(timeout);
135 /* MAX 0xFFFF */
136 if (timeout > 0xFFFF)
137 {
138 timeout = 0xFFFF;
139 }
140 }
141 }
142
143 /**
144 * This function stop the timer of pm
145 *
146 * @param pm Pointer to power manage structure
147 */
pm_timer_stop(struct rt_pm * pm)148 static void pm_timer_stop(struct rt_pm *pm)
149 {
150 RT_ASSERT(pm != RT_NULL);
151 }
152
153 /**
154 * This function calculate how many OS Ticks that MCU have suspended
155 *
156 * @param pm Pointer to power manage structure
157 *
158 * @return OS Ticks
159 */
pm_timer_get_tick(struct rt_pm * pm)160 static rt_tick_t pm_timer_get_tick(struct rt_pm *pm)
161 {
162 rt_uint32_t timer_tick;
163
164 RT_ASSERT(pm != RT_NULL);
165
166 timer_tick = 1;
167
168 return es32f3_os_tick_from_pm_tick(timer_tick);
169 }
170
171 /**
172 * This function initialize the power manager
173 */
drv_pm_hw_init(void)174 int drv_pm_hw_init(void)
175 {
176 static const struct rt_pm_ops _ops =
177 {
178 sleep,
179 run,
180 pm_timer_start,
181 pm_timer_stop,
182 pm_timer_get_tick
183 };
184
185 rt_uint8_t timer_mask = 0;
186
187 /* initialize timer mask */
188 timer_mask = 1UL << PM_SLEEP_MODE_DEEP;
189
190 /* initialize system pm module */
191 rt_system_pm_init(&_ops, timer_mask, RT_NULL);
192
193 return 0;
194 }
195 INIT_BOARD_EXPORT(drv_pm_hw_init);
196
197 #endif
198