drv_pwr.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-07-27 thread-liu first version
  9. */
  10. #include "board.h"
  11. //#define DRV_DEBUG
  12. #define LOG_TAG "drv.pwr"
  13. #include <drv_log.h>
  14. extern int lptim_start(void);
  15. extern int lptim_stop(void);
  16. static RCC_ClkInitTypeDef RCC_ClkInit = {0};
  17. #define __WAIT_EVENT_TIMEOUT(__CONDITION__, __TIMEOUT_VAL__) \
  18. do { \
  19. __IO uint32_t count = __TIMEOUT_VAL__ * (SystemCoreClock / 20U / 1000U); \
  20. do \
  21. { \
  22. if (count-- == 0U) \
  23. { \
  24. return HAL_TIMEOUT; \
  25. } \
  26. } \
  27. while (__CONDITION__ == 0U); \
  28. } while(0)
  29. /* Back up clock tree */
  30. static void backup_cm4_clocks(void)
  31. {
  32. rt_uint32_t *pFLatency = NULL;
  33. /* Back up MCU clock configuration */
  34. HAL_RCC_GetClockConfig(&RCC_ClkInit, pFLatency);
  35. }
  36. /* Restore the CM4 clock source muxer and the CM4 prescaler. */
  37. rt_err_t restore_cm4_clock(void)
  38. {
  39. /* Update SystemCoreClock variable */
  40. SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq();
  41. /* Enable PLL3 if needed */
  42. if (RCC_ClkInit.MCUInit.MCU_Clock == RCC_MCUSSOURCE_PLL3)
  43. {
  44. /* Enable PLL3 */
  45. __HAL_RCC_PLL3_ENABLE();
  46. /* Wait till PLL3 is ready */
  47. __WAIT_EVENT_TIMEOUT(__HAL_RCC_GET_FLAG(RCC_FLAG_PLL3RDY), CLOCKSWITCH_TIMEOUT_VALUE);
  48. /* Enable PLL3 outputs */
  49. __HAL_RCC_PLL3CLKOUT_ENABLE(RCC_PLL3_DIVP | RCC_PLL3_DIVQ | RCC_PLL3_DIVR);
  50. }
  51. /* Configure MCU clock only */
  52. __HAL_RCC_MCU_SOURCE(RCC_ClkInit.MCUInit.MCU_Clock);
  53. /* Wait till MCU is ready */
  54. __WAIT_EVENT_TIMEOUT(__HAL_RCC_GET_FLAG(RCC_FLAG_MCUSSRCRDY),
  55. CLOCKSWITCH_TIMEOUT_VALUE);
  56. /* Update SystemCoreClock variable */
  57. SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq();
  58. /* Reconfigure Systick */
  59. if (HAL_InitTick(uwTickPrio) != HAL_OK)
  60. {
  61. return RT_ERROR;
  62. }
  63. /* Set MCU division factor */
  64. __HAL_RCC_MCU_DIV(RCC_ClkInit.MCUInit.MCU_Div);
  65. /* Wait till MCUDIV is ready */
  66. __WAIT_EVENT_TIMEOUT(__HAL_RCC_GET_FLAG(RCC_FLAG_MCUDIVRDY),
  67. CLOCKSWITCH_TIMEOUT_VALUE);
  68. /* Update SystemCoreClock variable */
  69. SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq();
  70. /* Reconfigure Systick */
  71. if (HAL_InitTick(uwTickPrio) != HAL_OK)
  72. {
  73. return RT_ERROR;
  74. }
  75. return RT_EOK;
  76. }
  77. void RCC_WAKEUP_IRQHandler(void)
  78. {
  79. /* enter interrupt */
  80. rt_interrupt_enter();
  81. HAL_RCC_WAKEUP_IRQHandler();
  82. /* leave interrupt */
  83. rt_interrupt_leave();
  84. }
  85. void HAL_RCC_WAKEUP_Callback()
  86. {
  87. if (__HAL_PWR_GET_FLAG(PWR_FLAG_STOP) == 1U)
  88. {
  89. __HAL_PWR_CLEAR_FLAG(PWR_FLAG_STOP);
  90. }
  91. restore_cm4_clock();
  92. /* All level of ITs can interrupt */
  93. __set_BASEPRI(0U);
  94. rt_kprintf("system exit stop mode success!\n");
  95. }
  96. static void enter_sleep_mode(void)
  97. {
  98. __set_BASEPRI((1) << (8 - __NVIC_PRIO_BITS));
  99. lptim_start();
  100. HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
  101. }
  102. static void enter_stop_mode(void)
  103. {
  104. /*
  105. * Only the IT with the highest priority (0 value) can interrupt.
  106. * RCC_WAKEUP_IRQn IT is intended to have the highest priority and to be the
  107. * only one IT having this value
  108. * RCC_WAKEUP_IRQn is generated only when RCC is completely resumed from
  109. * CSTOP (protection mechanism)
  110. */
  111. __set_BASEPRI((1) << (8 - __NVIC_PRIO_BITS));
  112. __HAL_PWR_CLEAR_FLAG(PWR_FLAG_STOP);
  113. backup_cm4_clocks();
  114. HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
  115. }
  116. static void pm_wackup_key_init(void)
  117. {
  118. GPIO_InitTypeDef GPIO_InitStruct = {0};
  119. __HAL_RCC_GPIOA_CLK_ENABLE();
  120. GPIO_InitStruct.Pin = GPIO_PIN_13;
  121. GPIO_InitStruct.Pull = GPIO_PULLUP;
  122. GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  123. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  124. HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  125. HAL_NVIC_SetPriority(EXTI13_IRQn, 0x01, 0);
  126. HAL_NVIC_EnableIRQ(EXTI13_IRQn);
  127. }
  128. int drv_pm_hw_init(void)
  129. {
  130. pm_wackup_key_init();
  131. return RT_EOK;
  132. }
  133. INIT_BOARD_EXPORT(drv_pm_hw_init);
  134. static int pwr_sample(int argc, char *argv[])
  135. {
  136. if (argc > 1)
  137. {
  138. if (!rt_strcmp(argv[1], "stop"))
  139. {
  140. rt_kprintf("system will enter stop mode! you can press USER2 button to exit this mode\n");
  141. enter_stop_mode();
  142. return RT_EOK;
  143. }
  144. else if (!rt_strcmp(argv[1], "sleep"))
  145. {
  146. rt_kprintf("system will enter sleep mode! lptim1 will wake up the system\n");
  147. enter_sleep_mode();
  148. return RT_EOK;
  149. }
  150. else
  151. {
  152. goto _exit;
  153. }
  154. }
  155. _exit:
  156. {
  157. rt_kprintf("Usage:\n");
  158. rt_kprintf("pwr_sample stop - system enter stop mode\n");
  159. rt_kprintf("pwr_sample sleep - system enter sleep mode\n");
  160. }
  161. return -RT_ERROR;
  162. }
  163. MSH_CMD_EXPORT(pwr_sample, enter low power mode sample);