Initial commit

Dependencies:   FastPWM

Committer:
lypinator
Date:
Wed Sep 16 01:11:49 2020 +0000
Revision:
0:bb348c97df44
Added PWM

Who changed what in which revision?

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