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