summaryrefslogtreecommitdiff
path: root/bsp/stm32/libraries
diff options
context:
space:
mode:
authorEvalZero <[email protected]>2019-05-06 18:30:24 +0800
committerEvalZero <[email protected]>2019-05-06 19:56:01 +0800
commit943c5ccc66e59537ce00a773aca43978b296751d (patch)
tree0e06eb9d49ba9b80acd305ad2bb5ea797a7b5cb1 /bsp/stm32/libraries
parentc57f2370adb07b450fbff36657f5c5bbba8e0c1a (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/SConscript4
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drv_lptim.c132
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drv_lptim.h23
-rw-r--r--bsp/stm32/libraries/HAL_Drivers/drv_pm.c249
-rw-r--r--bsp/stm32/libraries/STM32L4xx_HAL/SConscript3
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']