drv_pm.c 5.0 KB

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