BBR 1 Ebene

Committer:
borlanic
Date:
Mon May 14 11:29:06 2018 +0000
Revision:
0:fbdae7e6d805
BBR

Who changed what in which revision?

UserRevisionLine numberNew contents of line
borlanic 0:fbdae7e6d805 1 /* mbed Microcontroller Library
borlanic 0:fbdae7e6d805 2 *******************************************************************************
borlanic 0:fbdae7e6d805 3 * Copyright (c) 2016, STMicroelectronics
borlanic 0:fbdae7e6d805 4 * All rights reserved.
borlanic 0:fbdae7e6d805 5 *
borlanic 0:fbdae7e6d805 6 * Redistribution and use in source and binary forms, with or without
borlanic 0:fbdae7e6d805 7 * modification, are permitted provided that the following conditions are met:
borlanic 0:fbdae7e6d805 8 *
borlanic 0:fbdae7e6d805 9 * 1. Redistributions of source code must retain the above copyright notice,
borlanic 0:fbdae7e6d805 10 * this list of conditions and the following disclaimer.
borlanic 0:fbdae7e6d805 11 * 2. Redistributions in binary form must reproduce the above copyright notice,
borlanic 0:fbdae7e6d805 12 * this list of conditions and the following disclaimer in the documentation
borlanic 0:fbdae7e6d805 13 * and/or other materials provided with the distribution.
borlanic 0:fbdae7e6d805 14 * 3. Neither the name of STMicroelectronics nor the names of its contributors
borlanic 0:fbdae7e6d805 15 * may be used to endorse or promote products derived from this software
borlanic 0:fbdae7e6d805 16 * without specific prior written permission.
borlanic 0:fbdae7e6d805 17 *
borlanic 0:fbdae7e6d805 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
borlanic 0:fbdae7e6d805 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
borlanic 0:fbdae7e6d805 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
borlanic 0:fbdae7e6d805 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
borlanic 0:fbdae7e6d805 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
borlanic 0:fbdae7e6d805 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
borlanic 0:fbdae7e6d805 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
borlanic 0:fbdae7e6d805 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
borlanic 0:fbdae7e6d805 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
borlanic 0:fbdae7e6d805 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
borlanic 0:fbdae7e6d805 28 *******************************************************************************
borlanic 0:fbdae7e6d805 29 */
borlanic 0:fbdae7e6d805 30 #if DEVICE_SLEEP
borlanic 0:fbdae7e6d805 31
borlanic 0:fbdae7e6d805 32 #include "sleep_api.h"
borlanic 0:fbdae7e6d805 33 #include "rtc_api_hal.h"
borlanic 0:fbdae7e6d805 34
borlanic 0:fbdae7e6d805 35 extern void HAL_SuspendTick(void);
borlanic 0:fbdae7e6d805 36 extern void HAL_ResumeTick(void);
borlanic 0:fbdae7e6d805 37
borlanic 0:fbdae7e6d805 38 /* Wait loop - assuming tick is 1 us */
borlanic 0:fbdae7e6d805 39 static void wait_loop(uint32_t timeout)
borlanic 0:fbdae7e6d805 40 {
borlanic 0:fbdae7e6d805 41 uint32_t t1, t2, elapsed = 0;
borlanic 0:fbdae7e6d805 42 t1 = us_ticker_read();
borlanic 0:fbdae7e6d805 43 do {
borlanic 0:fbdae7e6d805 44 t2 = us_ticker_read();
borlanic 0:fbdae7e6d805 45 elapsed = (t2 > t1) ? (t2 - t1) : ((uint64_t)t2 + 0xFFFFFFFF - t1 + 1);
borlanic 0:fbdae7e6d805 46 } while (elapsed < timeout);
borlanic 0:fbdae7e6d805 47 return;
borlanic 0:fbdae7e6d805 48 }
borlanic 0:fbdae7e6d805 49
borlanic 0:fbdae7e6d805 50 // On L4 platforms we've seen unstable PLL CLK configuraiton
borlanic 0:fbdae7e6d805 51 // when DEEP SLEEP exits just few µs after being entered
borlanic 0:fbdae7e6d805 52 // So we need to force MSI usage before setting clocks again
borlanic 0:fbdae7e6d805 53 static void ForceClockOutofDeepSleep(void)
borlanic 0:fbdae7e6d805 54 {
borlanic 0:fbdae7e6d805 55 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
borlanic 0:fbdae7e6d805 56 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
borlanic 0:fbdae7e6d805 57 uint32_t pFLatency = 0;
borlanic 0:fbdae7e6d805 58
borlanic 0:fbdae7e6d805 59 /* Enable Power Control clock */
borlanic 0:fbdae7e6d805 60 __HAL_RCC_PWR_CLK_ENABLE();
borlanic 0:fbdae7e6d805 61
borlanic 0:fbdae7e6d805 62 #ifdef PWR_FLAG_VOS
borlanic 0:fbdae7e6d805 63 /* Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 */
borlanic 0:fbdae7e6d805 64 //while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {};
borlanic 0:fbdae7e6d805 65 #endif
borlanic 0:fbdae7e6d805 66
borlanic 0:fbdae7e6d805 67 /* Get the Oscillators configuration according to the internal RCC registers */
borlanic 0:fbdae7e6d805 68 HAL_RCC_GetOscConfig(&RCC_OscInitStruct);
borlanic 0:fbdae7e6d805 69
borlanic 0:fbdae7e6d805 70 #if (TARGET_STM32L4 || TARGET_STM32L1) /* MSI used for L4 */
borlanic 0:fbdae7e6d805 71 /**Initializes the CPU, AHB and APB busses clocks
borlanic 0:fbdae7e6d805 72 */
borlanic 0:fbdae7e6d805 73 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
borlanic 0:fbdae7e6d805 74 RCC_OscInitStruct.MSIState = RCC_MSI_ON;
borlanic 0:fbdae7e6d805 75 RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
borlanic 0:fbdae7e6d805 76 RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_4; // Intermediate freq, 1MHz range
borlanic 0:fbdae7e6d805 77 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
borlanic 0:fbdae7e6d805 78 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
borlanic 0:fbdae7e6d805 79 error("clock issue\r\n");
borlanic 0:fbdae7e6d805 80 }
borlanic 0:fbdae7e6d805 81
borlanic 0:fbdae7e6d805 82 /* Get the Clocks configuration according to the internal RCC registers */
borlanic 0:fbdae7e6d805 83 HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency);
borlanic 0:fbdae7e6d805 84
borlanic 0:fbdae7e6d805 85 // Select HSI ss system clock source as a first step
borlanic 0:fbdae7e6d805 86 #ifdef RCC_CLOCKTYPE_PCLK2
borlanic 0:fbdae7e6d805 87 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK
borlanic 0:fbdae7e6d805 88 | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
borlanic 0:fbdae7e6d805 89 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
borlanic 0:fbdae7e6d805 90 #else
borlanic 0:fbdae7e6d805 91 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK
borlanic 0:fbdae7e6d805 92 | RCC_CLOCKTYPE_PCLK1);
borlanic 0:fbdae7e6d805 93 #endif
borlanic 0:fbdae7e6d805 94 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
borlanic 0:fbdae7e6d805 95 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
borlanic 0:fbdae7e6d805 96 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
borlanic 0:fbdae7e6d805 97 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK) {
borlanic 0:fbdae7e6d805 98 error("clock issue\r\n");
borlanic 0:fbdae7e6d805 99 }
borlanic 0:fbdae7e6d805 100 #else /* HSI used on others */
borlanic 0:fbdae7e6d805 101 /**Initializes the CPU, AHB and APB busses clocks
borlanic 0:fbdae7e6d805 102 */
borlanic 0:fbdae7e6d805 103 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
borlanic 0:fbdae7e6d805 104 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
borlanic 0:fbdae7e6d805 105 RCC_OscInitStruct.HSICalibrationValue = 16;
borlanic 0:fbdae7e6d805 106 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
borlanic 0:fbdae7e6d805 107 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
borlanic 0:fbdae7e6d805 108 error("clock issue");
borlanic 0:fbdae7e6d805 109 }
borlanic 0:fbdae7e6d805 110
borlanic 0:fbdae7e6d805 111 /* Get the Clocks configuration according to the internal RCC registers */
borlanic 0:fbdae7e6d805 112 HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &pFLatency);
borlanic 0:fbdae7e6d805 113
borlanic 0:fbdae7e6d805 114 /**Initializes the CPU, AHB and APB busses clocks
borlanic 0:fbdae7e6d805 115 */
borlanic 0:fbdae7e6d805 116 #ifdef RCC_CLOCKTYPE_PCLK2
borlanic 0:fbdae7e6d805 117 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
borlanic 0:fbdae7e6d805 118 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2);
borlanic 0:fbdae7e6d805 119 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
borlanic 0:fbdae7e6d805 120 #else
borlanic 0:fbdae7e6d805 121 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
borlanic 0:fbdae7e6d805 122 |RCC_CLOCKTYPE_PCLK1);
borlanic 0:fbdae7e6d805 123 #endif
borlanic 0:fbdae7e6d805 124 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
borlanic 0:fbdae7e6d805 125 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
borlanic 0:fbdae7e6d805 126 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
borlanic 0:fbdae7e6d805 127 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, pFLatency) != HAL_OK) {
borlanic 0:fbdae7e6d805 128 error("clock issue");
borlanic 0:fbdae7e6d805 129 }
borlanic 0:fbdae7e6d805 130 #endif // TARGET_STM32L4
borlanic 0:fbdae7e6d805 131 }
borlanic 0:fbdae7e6d805 132
borlanic 0:fbdae7e6d805 133 void hal_sleep(void)
borlanic 0:fbdae7e6d805 134 {
borlanic 0:fbdae7e6d805 135 // Disable IRQs
borlanic 0:fbdae7e6d805 136 core_util_critical_section_enter();
borlanic 0:fbdae7e6d805 137
borlanic 0:fbdae7e6d805 138 // Stop HAL tick to avoid to exit sleep in 1ms
borlanic 0:fbdae7e6d805 139 HAL_SuspendTick();
borlanic 0:fbdae7e6d805 140 // Request to enter SLEEP mode
borlanic 0:fbdae7e6d805 141 HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
borlanic 0:fbdae7e6d805 142 // Restart HAL tick
borlanic 0:fbdae7e6d805 143 HAL_ResumeTick();
borlanic 0:fbdae7e6d805 144
borlanic 0:fbdae7e6d805 145 // Enable IRQs
borlanic 0:fbdae7e6d805 146 core_util_critical_section_exit();
borlanic 0:fbdae7e6d805 147 }
borlanic 0:fbdae7e6d805 148
borlanic 0:fbdae7e6d805 149 void hal_deepsleep(void)
borlanic 0:fbdae7e6d805 150 {
borlanic 0:fbdae7e6d805 151 // Disable IRQs
borlanic 0:fbdae7e6d805 152 core_util_critical_section_enter();
borlanic 0:fbdae7e6d805 153
borlanic 0:fbdae7e6d805 154 // Stop HAL tick
borlanic 0:fbdae7e6d805 155 HAL_SuspendTick();
borlanic 0:fbdae7e6d805 156 uint32_t EnterTimeUS = us_ticker_read();
borlanic 0:fbdae7e6d805 157
borlanic 0:fbdae7e6d805 158 // Request to enter STOP mode with regulator in low power mode
borlanic 0:fbdae7e6d805 159 #if TARGET_STM32L4
borlanic 0:fbdae7e6d805 160 int pwrClockEnabled = __HAL_RCC_PWR_IS_CLK_ENABLED();
borlanic 0:fbdae7e6d805 161 int lowPowerModeEnabled = PWR->CR1 & PWR_CR1_LPR;
borlanic 0:fbdae7e6d805 162
borlanic 0:fbdae7e6d805 163 if (!pwrClockEnabled) {
borlanic 0:fbdae7e6d805 164 __HAL_RCC_PWR_CLK_ENABLE();
borlanic 0:fbdae7e6d805 165 }
borlanic 0:fbdae7e6d805 166 if (lowPowerModeEnabled) {
borlanic 0:fbdae7e6d805 167 HAL_PWREx_DisableLowPowerRunMode();
borlanic 0:fbdae7e6d805 168 }
borlanic 0:fbdae7e6d805 169
borlanic 0:fbdae7e6d805 170 HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
borlanic 0:fbdae7e6d805 171
borlanic 0:fbdae7e6d805 172 if (lowPowerModeEnabled) {
borlanic 0:fbdae7e6d805 173 HAL_PWREx_EnableLowPowerRunMode();
borlanic 0:fbdae7e6d805 174 }
borlanic 0:fbdae7e6d805 175 if (!pwrClockEnabled) {
borlanic 0:fbdae7e6d805 176 __HAL_RCC_PWR_CLK_DISABLE();
borlanic 0:fbdae7e6d805 177 }
borlanic 0:fbdae7e6d805 178 #else /* TARGET_STM32L4 */
borlanic 0:fbdae7e6d805 179 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
borlanic 0:fbdae7e6d805 180 #endif /* TARGET_STM32L4 */
borlanic 0:fbdae7e6d805 181 // Verify Clock Out of Deep Sleep
borlanic 0:fbdae7e6d805 182 ForceClockOutofDeepSleep();
borlanic 0:fbdae7e6d805 183
borlanic 0:fbdae7e6d805 184 // Restart HAL tick
borlanic 0:fbdae7e6d805 185 HAL_ResumeTick();
borlanic 0:fbdae7e6d805 186
borlanic 0:fbdae7e6d805 187 // After wake-up from STOP reconfigure the PLL
borlanic 0:fbdae7e6d805 188 SetSysClock();
borlanic 0:fbdae7e6d805 189
borlanic 0:fbdae7e6d805 190 /* Wait for clock to be stabilized.
borlanic 0:fbdae7e6d805 191 * TO DO: a better way of doing this, would be to rely on
borlanic 0:fbdae7e6d805 192 * HW Flag. At least this ensures proper operation out of
borlanic 0:fbdae7e6d805 193 * deep sleep */
borlanic 0:fbdae7e6d805 194 wait_loop(500);
borlanic 0:fbdae7e6d805 195
borlanic 0:fbdae7e6d805 196 TIM_HandleTypeDef TimMasterHandle;
borlanic 0:fbdae7e6d805 197 TimMasterHandle.Instance = TIM_MST;
borlanic 0:fbdae7e6d805 198 __HAL_TIM_SET_COUNTER(&TimMasterHandle, EnterTimeUS);
borlanic 0:fbdae7e6d805 199
borlanic 0:fbdae7e6d805 200 #if DEVICE_RTC
borlanic 0:fbdae7e6d805 201 /* Wait for RTC RSF bit synchro if RTC is configured */
borlanic 0:fbdae7e6d805 202 #if (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7)
borlanic 0:fbdae7e6d805 203 if (READ_BIT(RCC->BDCR, RCC_BDCR_RTCSEL)) {
borlanic 0:fbdae7e6d805 204 #else /* (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7) */
borlanic 0:fbdae7e6d805 205 if (__HAL_RCC_GET_RTC_SOURCE()) {
borlanic 0:fbdae7e6d805 206 #endif /* (TARGET_STM32F2) || (TARGET_STM32F4) || (TARGET_STM32F7) */
borlanic 0:fbdae7e6d805 207 rtc_synchronize();
borlanic 0:fbdae7e6d805 208 }
borlanic 0:fbdae7e6d805 209 #endif
borlanic 0:fbdae7e6d805 210 // Enable IRQs
borlanic 0:fbdae7e6d805 211 core_util_critical_section_exit();
borlanic 0:fbdae7e6d805 212 }
borlanic 0:fbdae7e6d805 213
borlanic 0:fbdae7e6d805 214 #endif