[stm32][pm]lptimer is supported
This commit is contained in:
parent
fccd98747e
commit
568356cc48
|
@ -1,22 +1,51 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
* Copyright (c) 2006-2024 RT-Thread Development Team
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Change Logs:
|
* Change Logs:
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2019-05-06 Zero-Free first version
|
* 2019-05-06 Zero-Free first version
|
||||||
|
* 2024-07-04 wdfk-prog lptimer is supported
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <board.h>
|
#include <board.h>
|
||||||
#include <drv_lptim.h>
|
#include <drv_lptim.h>
|
||||||
#include <rtdevice.h>
|
#include <rtdevice.h>
|
||||||
|
#include <hwtimer.h>
|
||||||
|
|
||||||
static void uart_console_reconfig(void)
|
/*#define DRV_DEBUG*/
|
||||||
|
#define LOG_TAG "drv.pm"
|
||||||
|
#include <drv_log.h>
|
||||||
|
|
||||||
|
#ifdef RT_USING_PM
|
||||||
|
|
||||||
|
#ifndef BSP_USING_PM_TIMER
|
||||||
|
/*
|
||||||
|
! Using LPTIM timer, the maximum sleep time is 65535, less than 1 min. Use RTC alarm timers for longer periods.
|
||||||
|
! For example: packages can be used :https://packages.rt-thread.org/detail.html?package=multi_rtimer
|
||||||
|
*/
|
||||||
|
#ifdef BSP_USING_LPTIM1
|
||||||
|
#define BSP_USING_PM_TIMER "lptim1"
|
||||||
|
#elif BSP_USING_LPTIM2
|
||||||
|
#define BSP_USING_PM_TIMER "lptim2"
|
||||||
|
#elif BSP_USING_LPTIM3
|
||||||
|
#define BSP_USING_PM_TIMER "lptim3"
|
||||||
|
#else
|
||||||
|
#error "Please define BSP_USING_PM_TIMER"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static rt_device_t timer = RT_NULL;
|
||||||
|
|
||||||
|
/* Re-configure the system clock */
|
||||||
|
rt_weak void SystemClock_ReConfig(uint8_t run_mode)
|
||||||
{
|
{
|
||||||
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
|
/*todo add your code here*/
|
||||||
|
}
|
||||||
|
|
||||||
rt_device_control(rt_console_get_device(), RT_DEVICE_CTRL_CONFIG, &config);
|
rt_weak void stm32_pm_device_run(struct rt_pm *pm, uint8_t mode)
|
||||||
|
{
|
||||||
|
/*todo add your code here*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,7 +61,6 @@ static void sleep(struct rt_pm *pm, uint8_t mode)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PM_SLEEP_MODE_IDLE:
|
case PM_SLEEP_MODE_IDLE:
|
||||||
// __WFI();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PM_SLEEP_MODE_LIGHT:
|
case PM_SLEEP_MODE_LIGHT:
|
||||||
|
@ -49,10 +77,12 @@ static void sleep(struct rt_pm *pm, uint8_t mode)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PM_SLEEP_MODE_DEEP:
|
case PM_SLEEP_MODE_DEEP:
|
||||||
|
#if defined(SOC_SERIES_STM32L4)
|
||||||
/* Enter STOP 2 mode */
|
/* Enter STOP 2 mode */
|
||||||
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
|
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
|
||||||
/* Re-configure the system clock */
|
/* Re-configure the system clock */
|
||||||
SystemClock_ReConfig(pm->run_mode);
|
SystemClock_ReConfig(pm->run_mode);
|
||||||
|
#endif /* defined(SOC_SERIES_STM32L4) */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PM_SLEEP_MODE_STANDBY:
|
case PM_SLEEP_MODE_STANDBY:
|
||||||
|
@ -61,74 +91,17 @@ static void sleep(struct rt_pm *pm, uint8_t mode)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PM_SLEEP_MODE_SHUTDOWN:
|
case PM_SLEEP_MODE_SHUTDOWN:
|
||||||
|
#if defined(SOC_SERIES_STM32L4)
|
||||||
/* Enter SHUTDOWNN mode */
|
/* Enter SHUTDOWNN mode */
|
||||||
HAL_PWREx_EnterSHUTDOWNMode();
|
HAL_PWREx_EnterSHUTDOWNMode();
|
||||||
|
#endif /* defined(SOC_SERIES_STM32L4) */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
RT_ASSERT(0);
|
|
||||||
break;
|
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)
|
|
||||||
{
|
|
||||||
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:
|
|
||||||
HAL_PWREx_DisableLowPowerRunMode();
|
|
||||||
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:
|
|
||||||
HAL_PWREx_DisableLowPowerRunMode();
|
|
||||||
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
|
* This function caculate the PM tick from OS tick
|
||||||
*
|
*
|
||||||
|
@ -136,9 +109,19 @@ static void run(struct rt_pm *pm, uint8_t mode)
|
||||||
*
|
*
|
||||||
* @return the PM tick
|
* @return the PM tick
|
||||||
*/
|
*/
|
||||||
static rt_tick_t stm32l4_pm_tick_from_os_tick(rt_tick_t tick)
|
static rt_tick_t stm32_pm_tick_from_os_tick(rt_tick_t tick)
|
||||||
{
|
{
|
||||||
rt_uint32_t freq = stm32l4_lptim_get_countfreq();
|
rt_uint32_t freq = 0;
|
||||||
|
rt_err_t ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_GET_FREQ, &freq);
|
||||||
|
if(ret != RT_EOK)
|
||||||
|
{
|
||||||
|
LOG_E("Get PM timer %s frequency failed %d", timer->parent.name, ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_D("Get PM timer %s frequency %d", timer->parent.name, freq);
|
||||||
|
}
|
||||||
|
|
||||||
return (freq * tick / RT_TICK_PER_SECOND);
|
return (freq * tick / RT_TICK_PER_SECOND);
|
||||||
}
|
}
|
||||||
|
@ -150,18 +133,25 @@ static rt_tick_t stm32l4_pm_tick_from_os_tick(rt_tick_t tick)
|
||||||
*
|
*
|
||||||
* @return the OS tick
|
* @return the OS tick
|
||||||
*/
|
*/
|
||||||
static rt_tick_t stm32l4_os_tick_from_pm_tick(rt_uint32_t tick)
|
static rt_tick_t stm32_os_tick_from_pm_tick(rt_uint32_t tick)
|
||||||
{
|
{
|
||||||
static rt_uint32_t os_tick_remain = 0;
|
static rt_uint32_t os_tick_remain = 0;
|
||||||
rt_uint32_t ret, freq;
|
rt_tick_t os_tick = 0;
|
||||||
|
rt_uint32_t freq = 0;
|
||||||
|
|
||||||
freq = stm32l4_lptim_get_countfreq();
|
rt_err_t ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_GET_FREQ, &freq);
|
||||||
ret = (tick * RT_TICK_PER_SECOND + os_tick_remain) / freq;
|
if(ret != RT_EOK)
|
||||||
|
{
|
||||||
|
LOG_E("Get PM timer %s frequency failed %d", timer->parent.name, ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
os_tick = (tick * RT_TICK_PER_SECOND + os_tick_remain) / freq;
|
||||||
|
|
||||||
os_tick_remain += (tick * RT_TICK_PER_SECOND);
|
os_tick_remain += (tick * RT_TICK_PER_SECOND);
|
||||||
os_tick_remain %= freq;
|
os_tick_remain %= freq;
|
||||||
|
|
||||||
return ret;
|
return os_tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,18 +164,33 @@ static void pm_timer_start(struct rt_pm *pm, rt_uint32_t timeout)
|
||||||
{
|
{
|
||||||
RT_ASSERT(pm != RT_NULL);
|
RT_ASSERT(pm != RT_NULL);
|
||||||
RT_ASSERT(timeout > 0);
|
RT_ASSERT(timeout > 0);
|
||||||
|
RT_ASSERT(timer != RT_NULL);
|
||||||
|
|
||||||
if (timeout != RT_TICK_MAX)
|
if (timeout != RT_TICK_MAX)
|
||||||
{
|
{
|
||||||
/* Convert OS Tick to pmtimer timeout value */
|
rt_uint32_t max_tick = 0;
|
||||||
timeout = stm32l4_pm_tick_from_os_tick(timeout);
|
rt_err_t ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_GET_TICK_MAX, &max_tick);
|
||||||
if (timeout > stm32l4_lptim_get_tick_max())
|
if(ret != RT_EOK)
|
||||||
{
|
{
|
||||||
timeout = stm32l4_lptim_get_tick_max();
|
LOG_E("Get PM timer %s max tick failed %d", timer->parent.name, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert OS Tick to pmtimer timeout value */
|
||||||
|
timeout = stm32_pm_tick_from_os_tick(timeout);
|
||||||
|
|
||||||
|
if (timeout > max_tick)
|
||||||
|
{
|
||||||
|
timeout = max_tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enter PM_TIMER_MODE */
|
/* Enter PM_TIMER_MODE */
|
||||||
stm32l4_lptim_start(timeout);
|
ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_START, &timeout);
|
||||||
|
if(ret != RT_EOK)
|
||||||
|
{
|
||||||
|
LOG_E("Get PM timer %s max tick failed %d", timer->parent.name, ret);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +204,7 @@ static void pm_timer_stop(struct rt_pm *pm)
|
||||||
RT_ASSERT(pm != RT_NULL);
|
RT_ASSERT(pm != RT_NULL);
|
||||||
|
|
||||||
/* Reset pmtimer status */
|
/* Reset pmtimer status */
|
||||||
stm32l4_lptim_stop();
|
rt_device_control(timer, HWTIMER_CTRL_STOP, RT_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -215,29 +220,42 @@ static rt_tick_t pm_timer_get_tick(struct rt_pm *pm)
|
||||||
|
|
||||||
RT_ASSERT(pm != RT_NULL);
|
RT_ASSERT(pm != RT_NULL);
|
||||||
|
|
||||||
timer_tick = stm32l4_lptim_get_current_tick();
|
rt_err_t ret = rt_device_control(timer, DRV_HW_LPTIMER_CTRL_GET_COUNT, &timer_tick);
|
||||||
|
|
||||||
return stm32l4_os_tick_from_pm_tick(timer_tick);
|
if(ret != RT_EOK)
|
||||||
|
{
|
||||||
|
LOG_E("Get PM timer %s count failed %d", timer->parent.name, ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return stm32_os_tick_from_pm_tick(timer_tick);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct rt_pm_ops _ops =
|
||||||
|
{
|
||||||
|
sleep,
|
||||||
|
stm32_pm_device_run,
|
||||||
|
pm_timer_start,
|
||||||
|
pm_timer_stop,
|
||||||
|
pm_timer_get_tick
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function initialize the power manager
|
* This function initialize the power manager
|
||||||
*/
|
*/
|
||||||
int drv_pm_hw_init(void)
|
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;
|
rt_uint8_t timer_mask = 0;
|
||||||
|
|
||||||
/* Enable Power Clock */
|
/* Enable Power Clock */
|
||||||
|
#if !defined(SOC_SERIES_STM32H7) && !defined(SOC_SERIES_STM32WL) && !defined(SOC_SERIES_STM32WB)
|
||||||
__HAL_RCC_PWR_CLK_ENABLE();
|
__HAL_RCC_PWR_CLK_ENABLE();
|
||||||
|
#ifdef SOC_SERIES_STM32F1
|
||||||
|
__HAL_RCC_BKP_CLK_ENABLE();
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* initialize timer mask */
|
/* initialize timer mask */
|
||||||
timer_mask = 1UL << PM_SLEEP_MODE_DEEP;
|
timer_mask = 1UL << PM_SLEEP_MODE_DEEP;
|
||||||
|
@ -245,7 +263,18 @@ int drv_pm_hw_init(void)
|
||||||
/* initialize system pm module */
|
/* initialize system pm module */
|
||||||
rt_system_pm_init(&_ops, timer_mask, RT_NULL);
|
rt_system_pm_init(&_ops, timer_mask, RT_NULL);
|
||||||
|
|
||||||
return 0;
|
timer = rt_device_find(BSP_USING_PM_TIMER);
|
||||||
|
|
||||||
|
if(timer == RT_NULL)
|
||||||
|
{
|
||||||
|
LOG_E("Can't find PM timer device");
|
||||||
|
return -RT_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return rt_device_init(timer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_BOARD_EXPORT(drv_pm_hw_init);
|
INIT_CORE_EXPORT(drv_pm_hw_init);
|
||||||
|
#endif /* RT_USING_PM */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
* Copyright (c) 2006-2024 RT-Thread Development Team
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
#define RTC_BKP_DR1 RT_NULL
|
#define RTC_BKP_DR1 RT_NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define DRV_DEBUG
|
/* #define DRV_DEBUG*/
|
||||||
#define LOG_TAG "drv.rtc"
|
#define LOG_TAG "drv.rtc"
|
||||||
#include <drv_log.h>
|
#include <drv_log.h>
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ static rt_err_t rtc_alarm_time_set(struct rtc_device_object* p_dev)
|
||||||
|
|
||||||
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
|
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
|
||||||
{
|
{
|
||||||
//LOG_D("rtc alarm isr.\n");
|
/*LOG_D("rtc alarm isr.\n");*/
|
||||||
rt_alarm_update(&rtc_device.rtc_dev.parent, 1);
|
rt_alarm_update(&rtc_device.rtc_dev.parent, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,5 +424,5 @@ static int rt_hw_rtc_init(void)
|
||||||
|
|
||||||
return RT_EOK;
|
return RT_EOK;
|
||||||
}
|
}
|
||||||
INIT_DEVICE_EXPORT(rt_hw_rtc_init);
|
INIT_BOARD_EXPORT(rt_hw_rtc_init);
|
||||||
#endif /* BSP_USING_ONCHIP_RTC */
|
#endif /* BSP_USING_ONCHIP_RTC */
|
||||||
|
|
Loading…
Reference in New Issue