diff options
| author | EvalZero <[email protected]> | 2019-05-06 18:30:24 +0800 |
|---|---|---|
| committer | EvalZero <[email protected]> | 2019-05-06 19:56:01 +0800 |
| commit | 943c5ccc66e59537ce00a773aca43978b296751d (patch) | |
| tree | 0e06eb9d49ba9b80acd305ad2bb5ea797a7b5cb1 /bsp/stm32/libraries | |
| parent | c57f2370adb07b450fbff36657f5c5bbba8e0c1a (diff) | |
[bsp][stm32l476-st-nucleo]add low power feature support for stm32l476-st-nucleo
Diffstat (limited to 'bsp/stm32/libraries')
| -rw-r--r-- | bsp/stm32/libraries/HAL_Drivers/SConscript | 4 | ||||
| -rw-r--r-- | bsp/stm32/libraries/HAL_Drivers/drv_lptim.c | 132 | ||||
| -rw-r--r-- | bsp/stm32/libraries/HAL_Drivers/drv_lptim.h | 23 | ||||
| -rw-r--r-- | bsp/stm32/libraries/HAL_Drivers/drv_pm.c | 249 | ||||
| -rw-r--r-- | bsp/stm32/libraries/STM32L4xx_HAL/SConscript | 3 |
5 files changed, 411 insertions, 0 deletions
diff --git a/bsp/stm32/libraries/HAL_Drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/SConscript index 413cc61a7b..99f1e9e520 100644 --- a/bsp/stm32/libraries/HAL_Drivers/SConscript +++ b/bsp/stm32/libraries/HAL_Drivers/SConscript @@ -39,6 +39,10 @@ if GetDepend(['RT_USING_ADC']): if GetDepend(['RT_USING_CAN']): src += ['drv_can.c'] +if GetDepend(['RT_USING_PM', 'SOC_SERIES_STM32L4']): + src += ['drv_pm.c'] + src += ['drv_lptim.c'] + if GetDepend('BSP_USING_SDRAM'): src += ['drv_sdram.c'] diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_lptim.c b/bsp/stm32/libraries/HAL_Drivers/drv_lptim.c new file mode 100644 index 0000000000..2360cdad78 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drv_lptim.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2017-08-01 tanek the first version + */ + +#include <board.h> +#include <drv_lptim.h> + +static LPTIM_HandleTypeDef LptimHandle; + +void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef *hlptim) +{ + if (hlptim->Instance == LPTIM1) + { + /* Peripheral clock enable */ + __HAL_RCC_LPTIM1_CLK_ENABLE(); + } +} + +void LPTIM1_IRQHandler(void) +{ + HAL_LPTIM_IRQHandler(&LptimHandle); +} + +void HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * This function get current count value of LPTIM + * + * @return the count vlaue + */ +rt_uint32_t stm32l4_lptim_get_current_tick(void) +{ + return HAL_LPTIM_ReadCounter(&LptimHandle); +} + +/** + * This function get the max value that LPTIM can count + * + * @return the max count + */ +rt_uint32_t stm32l4_lptim_get_tick_max(void) +{ + return (0xFFFF); +} + +/** + * This function start LPTIM with reload value + * + * @param reload The value that LPTIM count down from + * + * @return RT_EOK + */ +rt_err_t stm32l4_lptim_start(rt_uint32_t reload) +{ + HAL_LPTIM_TimeOut_Start_IT(&LptimHandle, 0xFFFF, reload); + + return (RT_EOK); +} + +/** + * This function stop LPTIM + */ +void stm32l4_lptim_stop(void) +{ + rt_uint32_t _ier; + + _ier = LptimHandle.Instance->IER; + LptimHandle.Instance->ICR = LptimHandle.Instance->ISR & _ier; +} + +/** + * This function get the count clock of LPTIM + * + * @return the count clock frequency in Hz + */ +rt_uint32_t stm32l4_lptim_get_countfreq(void) +{ + return 32000 / 32; +} + +/** + * This function initialize the lptim + */ +int stm32l4_hw_lptim_init(void) +{ + RCC_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0}; + + /* Enable LSI clock */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI; + RCC_OscInitStruct.LSIState = RCC_LSI_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + /* Select the LSI clock as LPTIM peripheral clock */ + RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1; + RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSI; + HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct); + + LptimHandle.Instance = LPTIM1; + LptimHandle.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC; + LptimHandle.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV32; + LptimHandle.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE; + LptimHandle.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH; + LptimHandle.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE; + LptimHandle.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL; + if (HAL_LPTIM_Init(&LptimHandle) != HAL_OK) + { + return -1; + } + + NVIC_ClearPendingIRQ(LPTIM1_IRQn); + NVIC_SetPriority(LPTIM1_IRQn, 0); + NVIC_EnableIRQ(LPTIM1_IRQn); + + return 0; +} + +INIT_DEVICE_EXPORT(stm32l4_hw_lptim_init); diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_lptim.h b/bsp/stm32/libraries/HAL_Drivers/drv_lptim.h new file mode 100644 index 0000000000..32853c9e73 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drv_lptim.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2012-08-21 heyuanjie87 the first version + */ + +#ifndef __DRV_PMTIMER_H__ +#define __DRV_PMTIMER_H__ + +#include <rtthread.h> + +rt_uint32_t stm32l4_lptim_get_countfreq(void); +rt_uint32_t stm32l4_lptim_get_tick_max(void); +rt_uint32_t stm32l4_lptim_get_current_tick(void); + +rt_err_t stm32l4_lptim_start(rt_uint32_t load); +void stm32l4_lptim_stop(void); + +#endif /* __DRV_PMTIMER_H__ */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_pm.c b/bsp/stm32/libraries/HAL_Drivers/drv_pm.c new file mode 100644 index 0000000000..66f00b3e02 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drv_pm.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-07-31 tanek first version + * 2018-05-05 Zero-Free adapt to the new power management interface + */ + +#include <board.h> +#include <drv_lptim.h> + +static void uart_console_reconfig(void) +{ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + + rt_device_control(rt_console_get_device(), RT_DEVICE_CTRL_CONFIG, &config); +} + +/** + * This function will put STM32L4xx into sleep mode. + * + * @param pm pointer to power manage structure + */ +static void sleep(struct rt_pm *pm, uint8_t mode) +{ + switch (mode) + { + case PM_SLEEP_MODE_NONE: + break; + + case PM_SLEEP_MODE_IDLE: + // __WFI(); + break; + + case PM_SLEEP_MODE_LIGHT: + if (pm->run_mode == PM_RUN_MODE_LOW_SPEED) + { + /* Enter LP SLEEP Mode, Enable low-power regulator */ + HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI); + } + else + { + /* Enter SLEEP Mode, Main regulator is ON */ + HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); + } + break; + + case PM_SLEEP_MODE_DEEP: + /* Enter STOP 2 mode */ + HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI); + /* Re-configure the system clock */ + SystemClock_ReConfig(pm->run_mode); + break; + + case PM_SLEEP_MODE_STANDBY: + /* Enter STANDBY mode */ + HAL_PWR_EnterSTANDBYMode(); + break; + + case PM_SLEEP_MODE_SHUTDOWN: + /* Enter SHUTDOWNN mode */ + HAL_PWREx_EnterSHUTDOWNMode(); + break; + + default: + RT_ASSERT(0); + break; + } +} + +static uint8_t run_speed[PM_RUN_MODE_MAX][2] = +{ + {80, 0}, + {80, 1}, + {24, 2}, + {2, 3}, +}; + +static void run(struct rt_pm *pm, uint8_t mode, uint32_t frequency) +{ + static uint8_t last_mode; + static char *run_str[] = PM_RUN_MODE_NAMES; + + if (mode == last_mode) + return; + last_mode = mode; + + /* 1. 设置 MSI 作为 SYSCLK 时钟源,以修改 PLL */ + SystemClock_MSI_ON(); + + /* 2. 根据RUN模式切换时钟频率(HSI) */ + switch (mode) + { + case PM_RUN_MODE_HIGH_SPEED: + case PM_RUN_MODE_NORMAL_SPEED: + SystemClock_80M(); + /* Configure the main internal regulator output voltage (Range1 by default)*/ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); + break; + case PM_RUN_MODE_MEDIUM_SPEED: + SystemClock_24M(); + /* Configure the main internal regulator output voltage */ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2); + break; + case PM_RUN_MODE_LOW_SPEED: + SystemClock_2M(); + /* Enter LP RUN mode */ + HAL_PWREx_EnableLowPowerRunMode(); + break; + default: + break; + } + + /* 3. 关闭 MSI 时钟 */ + // SystemClock_MSI_OFF(); + + /* 4. 更新外设时钟 */ + uart_console_reconfig(); + /* Re-Configure the Systick time */ + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / RT_TICK_PER_SECOND); + /* Re-Configure the Systick */ + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); + + rt_kprintf("switch to %s mode, frequency = %d MHz\n", run_str[mode], run_speed[mode][0]); +} + +/** + * This function caculate the PM tick from OS tick + * + * @param tick OS tick + * + * @return the PM tick + */ +static rt_tick_t stm32l4_pm_tick_from_os_tick(rt_tick_t tick) +{ + rt_uint32_t freq = stm32l4_lptim_get_countfreq(); + + return (freq * tick / RT_TICK_PER_SECOND); +} + +/** + * This function caculate the OS tick from PM tick + * + * @param tick PM tick + * + * @return the OS tick + */ +static rt_tick_t stm32l4_os_tick_from_pm_tick(rt_uint32_t tick) +{ + static rt_uint32_t os_tick_remain = 0; + rt_uint32_t ret, freq; + + freq = stm32l4_lptim_get_countfreq(); + ret = (tick * RT_TICK_PER_SECOND + os_tick_remain) / freq; + + os_tick_remain += (tick * RT_TICK_PER_SECOND); + os_tick_remain %= freq; + + return ret; +} + +/** + * This function start the timer of pm + * + * @param pm Pointer to power manage structure + * @param timeout How many OS Ticks that MCU can sleep + */ +static void pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout) +{ + RT_ASSERT(pm != RT_NULL); + RT_ASSERT(timeout > 0); + + if (timeout != RT_TICK_MAX) + { + /* Convert OS Tick to pmtimer timeout value */ + timeout = stm32l4_pm_tick_from_os_tick(timeout); + if (timeout > stm32l4_lptim_get_tick_max()) + { + timeout = stm32l4_lptim_get_tick_max(); + } + + /* Enter PM_TIMER_MODE */ + stm32l4_lptim_start(timeout); + } +} + +/** + * This function stop the timer of pm + * + * @param pm Pointer to power manage structure + */ +static void pm_timer_stop(struct rt_pm *pm) +{ + RT_ASSERT(pm != RT_NULL); + + /* Reset pmtimer status */ + stm32l4_lptim_stop(); +} + +/** + * This function calculate how many OS Ticks that MCU have suspended + * + * @param pm Pointer to power manage structure + * + * @return OS Ticks + */ +static rt_tick_t pm_timer_get_tick(struct rt_pm *pm) +{ + rt_uint32_t timer_tick; + + RT_ASSERT(pm != RT_NULL); + + timer_tick = stm32l4_lptim_get_current_tick(); + + return stm32l4_os_tick_from_pm_tick(timer_tick); +} + +/** + * This function initialize the power manager + */ +int drv_pm_hw_init(void) +{ + static const struct rt_pm_ops _ops = + { + sleep, + run, + pm_timer_start, + pm_timer_stop, + pm_timer_get_tick + }; + + rt_uint8_t timer_mask = 0; + + /* Enable Power Clock */ + __HAL_RCC_PWR_CLK_ENABLE(); + + /* initialize timer mask */ + timer_mask = 1UL << PM_SLEEP_MODE_DEEP; + + /* initialize system pm module */ + rt_system_pm_init(&_ops, timer_mask, RT_NULL); + + return 0; +} + +INIT_BOARD_EXPORT(drv_pm_hw_init); diff --git a/bsp/stm32/libraries/STM32L4xx_HAL/SConscript b/bsp/stm32/libraries/STM32L4xx_HAL/SConscript index 5b130f5aa3..5eb48c406c 100644 --- a/bsp/stm32/libraries/STM32L4xx_HAL/SConscript +++ b/bsp/stm32/libraries/STM32L4xx_HAL/SConscript @@ -84,6 +84,9 @@ if GetDepend(['RT_USING_MTD_NOR']): if GetDepend(['RT_USING_MTD_NAND']): src += ['STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_nand.c'] +if GetDepend(['RT_USING_PM']): + src += ['STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_lptim.c'] + if GetDepend(['BSP_USING_ON_CHIP_FLASH']): src += ['STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash.c'] src += ['STM32L4xx_HAL_Driver/Src/stm32l4xx_hal_flash_ex.c'] |
