drv_pm.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. * 2019-04-08 wangyq the first version
  21. * 2019-11-01 wangyq adapt to the new power management interface
  22. * 2020-12-15 liuhy the first version
  23. */
  24. #include "drv_pm.h"
  25. #ifdef RT_USING_PM
  26. static void uart_console_reconfig(void)
  27. {
  28. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  29. rt_device_control(rt_console_get_device(), RT_DEVICE_CTRL_CONFIG, &config);
  30. }
  31. /**
  32. * This function will put ES32F065x into sleep mode.
  33. *
  34. * @param pm pointer to power manage structure
  35. */
  36. /* 注意:进入睡眠前,如果有中断挂起(SYSTICK、PENDSV、UART、EXTI等),睡眠将被瞬间唤醒。*/
  37. static void sleep(struct rt_pm *pm, uint8_t mode)
  38. {
  39. switch (mode)
  40. {
  41. case PM_SLEEP_MODE_NONE:
  42. break;
  43. case PM_SLEEP_MODE_IDLE:
  44. break;
  45. case PM_SLEEP_MODE_LIGHT:
  46. /* Enter SLEEP Mode, Main regulator is ON */
  47. ald_pmu_stop1_enter();
  48. break;
  49. case PM_SLEEP_MODE_DEEP:
  50. /* Enter STOP 2 mode */
  51. ald_pmu_stop2_enter();
  52. break;
  53. case PM_SLEEP_MODE_STANDBY:
  54. /* Enter STANDBY mode */
  55. ald_pmu_stop2_enter();
  56. break;
  57. case PM_SLEEP_MODE_SHUTDOWN:
  58. /* Enter SHUTDOWNN mode */
  59. ald_pmu_stop2_enter();
  60. break;
  61. default:
  62. RT_ASSERT(0);
  63. break;
  64. }
  65. }
  66. static uint8_t run_speed[PM_RUN_MODE_MAX][2] =
  67. {
  68. {48, 0},
  69. {48, 1},
  70. {24, 2},
  71. {2, 3},
  72. };
  73. static void run(struct rt_pm *pm, uint8_t mode)
  74. {
  75. static uint8_t last_mode;
  76. static char *run_str[] = PM_RUN_MODE_NAMES;
  77. extern uint32_t __system_clock;
  78. if (mode == last_mode)
  79. return;
  80. last_mode = mode;
  81. ald_cmu_clock_config_default();
  82. __system_clock = 24000000;
  83. switch (mode)
  84. {
  85. case PM_RUN_MODE_HIGH_SPEED:
  86. case PM_RUN_MODE_NORMAL_SPEED:
  87. /* hosc 12MHz, from hosc/3 pll to 48MHz */
  88. ald_cmu_pll1_config(CMU_PLL1_INPUT_HRC_6, CMU_PLL1_OUTPUT_48M);
  89. /* MCLK 48MHz */
  90. ald_cmu_clock_config(CMU_CLOCK_PLL1, 48000000);
  91. break;
  92. case PM_RUN_MODE_MEDIUM_SPEED:
  93. break;
  94. case PM_RUN_MODE_LOW_SPEED:
  95. ald_cmu_clock_config(CMU_CLOCK_HRC, 2000000);
  96. break;
  97. default:
  98. break;
  99. }
  100. /* 4. 更新外设时钟 */
  101. uart_console_reconfig();
  102. /* Re-Configure the Systick time */
  103. SysTick_Config(ald_cmu_get_sys_clock() / RT_TICK_PER_SECOND);
  104. rt_kprintf("switch to %s mode, frequency = %d MHz\n", run_str[mode], run_speed[mode][0]);
  105. }
  106. /**
  107. * This function caculate the PM tick from OS tick
  108. *
  109. * @param tick OS tick
  110. *
  111. * @return the PM tick
  112. */
  113. static rt_tick_t es32f0_pm_tick_from_os_tick(rt_tick_t tick)
  114. {
  115. rt_uint32_t freq = 1;
  116. return (freq * tick / RT_TICK_PER_SECOND);
  117. }
  118. /**
  119. * This function caculate the OS tick from PM tick
  120. *
  121. * @param tick PM tick
  122. *
  123. * @return the OS tick
  124. */
  125. static rt_tick_t es32f0_os_tick_from_pm_tick(rt_uint32_t tick)
  126. {
  127. static rt_uint32_t os_tick_remain = 0;
  128. rt_uint32_t ret, freq;
  129. freq = 1;
  130. ret = (tick * RT_TICK_PER_SECOND + os_tick_remain) / freq;
  131. os_tick_remain += (tick * RT_TICK_PER_SECOND);
  132. os_tick_remain %= freq;
  133. return ret;
  134. }
  135. /**
  136. * This function start the timer of pm
  137. *
  138. * @param pm Pointer to power manage structure
  139. * @param timeout How many OS Ticks that MCU can sleep
  140. */
  141. static void pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout)
  142. {
  143. RT_ASSERT(pm != RT_NULL);
  144. RT_ASSERT(timeout > 0);
  145. if (timeout != RT_TICK_MAX)
  146. {
  147. /* Convert OS Tick to pmtimer timeout value */
  148. timeout = es32f0_pm_tick_from_os_tick(timeout);
  149. /* MAX 0xFFFF */
  150. if (timeout > 0xFFFF)
  151. {
  152. timeout = 0xFFFF;
  153. }
  154. }
  155. }
  156. /**
  157. * This function stop the timer of pm
  158. *
  159. * @param pm Pointer to power manage structure
  160. */
  161. static void pm_timer_stop(struct rt_pm *pm)
  162. {
  163. RT_ASSERT(pm != RT_NULL);
  164. }
  165. /**
  166. * This function calculate how many OS Ticks that MCU have suspended
  167. *
  168. * @param pm Pointer to power manage structure
  169. *
  170. * @return OS Ticks
  171. */
  172. static rt_tick_t pm_timer_get_tick(struct rt_pm *pm)
  173. {
  174. rt_uint32_t timer_tick;
  175. RT_ASSERT(pm != RT_NULL);
  176. timer_tick = 1;
  177. return es32f0_os_tick_from_pm_tick(timer_tick);
  178. }
  179. /**
  180. * This function initialize the power manager
  181. */
  182. int drv_pm_hw_init(void)
  183. {
  184. static const struct rt_pm_ops _ops =
  185. {
  186. sleep,
  187. run,
  188. pm_timer_start,
  189. pm_timer_stop,
  190. pm_timer_get_tick
  191. };
  192. rt_uint8_t timer_mask = 0;
  193. /* initialize timer mask */
  194. timer_mask = 1UL << PM_SLEEP_MODE_DEEP;
  195. /* initialize system pm module */
  196. rt_system_pm_init(&_ops, timer_mask, RT_NULL);
  197. return 0;
  198. }
  199. INIT_BOARD_EXPORT(drv_pm_hw_init);
  200. #endif