[add] low power and lptim driver.
This commit is contained in:
parent
6d8dbb6756
commit
8880e751f2
|
@ -297,7 +297,7 @@ void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim)
|
|||
/** Initializes the peripherals clock
|
||||
*/
|
||||
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
|
||||
PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_PCLK1;
|
||||
PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
|
|
|
@ -25,6 +25,12 @@ menu "Onboard Peripheral Drivers"
|
|||
select BSP_USING_I2C3
|
||||
default y
|
||||
|
||||
config BSP_USING_PWR
|
||||
bool "Enable PM (power control)"
|
||||
select BSP_USING_LPTIM
|
||||
select BSP_USING_LPTIM1
|
||||
default n
|
||||
|
||||
config BSP_USING_NAND
|
||||
bool "Enable FMC (MT29F8G08ABACAH4)"
|
||||
select RT_USING_FMC
|
||||
|
@ -181,6 +187,16 @@ menu "On-chip Peripheral Drivers"
|
|||
default n
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_LPTIM
|
||||
bool "Enable lptimer"
|
||||
default n
|
||||
select RT_USING_LPTIMER
|
||||
if BSP_USING_LPTIM
|
||||
config BSP_USING_LPTIM1
|
||||
bool "Enable LPTIM1"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_PWM
|
||||
bool "Enable pwm"
|
||||
default n
|
||||
|
|
|
@ -64,6 +64,12 @@ if GetDepend(['BSP_USING_EXTI']):
|
|||
if GetDepend(['BSP_USING_RNG']) or GetDepend(['BSP_USING_HASH']) or GetDepend(['BSP_USING_CRC']) or GetDepend(['BSP_USING_CRYP']):
|
||||
src += Glob('ports/crypto_sample.c')
|
||||
|
||||
if GetDepend(['BSP_USING_PWR']):
|
||||
src += Glob('ports/drv_pwr.c')
|
||||
|
||||
if GetDepend(['BSP_USING_LPTIM1']):
|
||||
src += Glob('ports/drv_lptim.c')
|
||||
|
||||
if GetDepend(['BSP_USING_OPENAMP']):
|
||||
src += Glob('CubeMX_Config/CM4/Src/ipcc.c')
|
||||
src += Glob('CubeMX_Config/CM4/Src/openamp.c')
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020-06-19 thread-liu first version
|
||||
*/
|
||||
|
||||
#include <board.h>
|
||||
|
||||
#ifdef BSP_USING_LPTIM
|
||||
#include "drv_config.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//#define DRV_DEBUG
|
||||
#define LOG_TAG "drv.lptimer"
|
||||
#include <drv_log.h>
|
||||
|
||||
#define LED5_PIN GET_PIN(D, 9)
|
||||
LPTIM_HandleTypeDef hlptim1;
|
||||
|
||||
extern int lptim_stop(void);
|
||||
|
||||
void LPTIM1_IRQHandler(void)
|
||||
{
|
||||
/* enter interrupt */
|
||||
rt_interrupt_enter();
|
||||
|
||||
HAL_LPTIM_IRQHandler(&hlptim1);
|
||||
|
||||
/* leave interrupt */
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim)
|
||||
{
|
||||
if(hlptim->Instance == LPTIM1)
|
||||
{
|
||||
HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_9);
|
||||
}
|
||||
|
||||
#if defined(BSP_USING_PWR)
|
||||
/* All level of ITs can interrupt */
|
||||
__set_BASEPRI(0U);
|
||||
|
||||
lptim_stop();
|
||||
rt_kprintf("system returns to normal!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int lptim_control(uint8_t pre_value)
|
||||
{
|
||||
if(pre_value > 7)
|
||||
{
|
||||
pre_value = 7;
|
||||
}
|
||||
hlptim1.Instance->CFGR &= ~(7 << 9); /* clear PRESC[2:0] */
|
||||
hlptim1.Instance->CFGR |= pre_value << 9; /* set PRESC[2:0] */
|
||||
rt_kprintf("set lptim pre value [0x%x] success!\n", pre_value);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
int lptim_start(void)
|
||||
{
|
||||
/* ### Start counting in interrupt mode ############################# */
|
||||
if (HAL_LPTIM_Counter_Start_IT(&hlptim1, 32767) != HAL_OK)
|
||||
{
|
||||
LOG_D("lptim1 start counting failed!\n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
LOG_D("lptim1 start counting success!\n");
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
int lptim_stop(void)
|
||||
{
|
||||
if (HAL_LPTIM_Counter_Stop_IT(&hlptim1) != HAL_OK)
|
||||
{
|
||||
LOG_D("lptim1 stop failed!\n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
|
||||
LOG_D("lptim1 stop counting success!\n");
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
int lptim_init(void)
|
||||
{
|
||||
rt_pin_mode(LED5_PIN, PIN_MODE_OUTPUT);
|
||||
|
||||
hlptim1.Instance = LPTIM1;
|
||||
hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;
|
||||
hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV8;
|
||||
hlptim1.Init.UltraLowPowerClock.Polarity = LPTIM_CLOCKPOLARITY_RISING;
|
||||
hlptim1.Init.UltraLowPowerClock.SampleTime = LPTIM_CLOCKSAMPLETIME_DIRECTTRANSITION;
|
||||
hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;
|
||||
hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;
|
||||
hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;
|
||||
hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;
|
||||
hlptim1.Init.Input1Source = LPTIM_INPUT1SOURCE_GPIO;
|
||||
hlptim1.Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO;
|
||||
if (HAL_LPTIM_Init(&hlptim1) != HAL_OK)
|
||||
{
|
||||
LOG_D("lptim init failed!\n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
LOG_D("lptim init success!\n");
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
INIT_DEVICE_EXPORT(lptim_init);
|
||||
|
||||
static int lptim_sample(int argc, char *argv[])
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
if (!strcmp(argv[1], "start"))
|
||||
{
|
||||
lptim_start();
|
||||
return RT_EOK;
|
||||
}
|
||||
else if (!strcmp(argv[1], "stop"))
|
||||
{
|
||||
lptim_stop();
|
||||
return RT_EOK;
|
||||
}
|
||||
else if (!strcmp(argv[1], "set"))
|
||||
{
|
||||
if (argc > 2)
|
||||
{
|
||||
lptim_control(atoi(argv[2]));
|
||||
return RT_EOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto _exit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto _exit;
|
||||
}
|
||||
}
|
||||
_exit:
|
||||
{
|
||||
rt_kprintf("Usage:\n");
|
||||
rt_kprintf("lptim_sample start - start lptim, the LED5 will start blink\n");
|
||||
rt_kprintf("lptim_sample stop - stop lptim, the LED5 will stop blink\n");
|
||||
rt_kprintf("lptim_sample set - set the lptim prescaler to change LED5 blink frquency, lptim_sample set [0 - 7]\n");
|
||||
}
|
||||
|
||||
return -RT_ERROR;
|
||||
}
|
||||
MSH_CMD_EXPORT(lptim_sample, low power timer sample);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright (c) 2006-2022, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2020-07-27 thread-liu first version
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
//#define DRV_DEBUG
|
||||
#define LOG_TAG "drv.pwr"
|
||||
#include <drv_log.h>
|
||||
|
||||
extern int lptim_start(void);
|
||||
extern int lptim_stop(void);
|
||||
|
||||
static RCC_ClkInitTypeDef RCC_ClkInit = {0};
|
||||
|
||||
#define __WAIT_EVENT_TIMEOUT(__CONDITION__, __TIMEOUT_VAL__) \
|
||||
do { \
|
||||
__IO uint32_t count = __TIMEOUT_VAL__ * (SystemCoreClock / 20U / 1000U); \
|
||||
do \
|
||||
{ \
|
||||
if (count-- == 0U) \
|
||||
{ \
|
||||
return HAL_TIMEOUT; \
|
||||
} \
|
||||
} \
|
||||
while (__CONDITION__ == 0U); \
|
||||
} while(0)
|
||||
|
||||
/* Back up clock tree */
|
||||
static void backup_cm4_clocks(void)
|
||||
{
|
||||
rt_uint32_t *pFLatency = NULL;
|
||||
|
||||
/* Back up MCU clock configuration */
|
||||
HAL_RCC_GetClockConfig(&RCC_ClkInit, pFLatency);
|
||||
}
|
||||
|
||||
/* Restore the CM4 clock source muxer and the CM4 prescaler. */
|
||||
rt_err_t restore_cm4_clock(void)
|
||||
{
|
||||
/* Update SystemCoreClock variable */
|
||||
SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq();
|
||||
|
||||
/* Enable PLL3 if needed */
|
||||
if (RCC_ClkInit.MCUInit.MCU_Clock == RCC_MCUSSOURCE_PLL3)
|
||||
{
|
||||
/* Enable PLL3 */
|
||||
__HAL_RCC_PLL3_ENABLE();
|
||||
|
||||
/* Wait till PLL3 is ready */
|
||||
__WAIT_EVENT_TIMEOUT(__HAL_RCC_GET_FLAG(RCC_FLAG_PLL3RDY), CLOCKSWITCH_TIMEOUT_VALUE);
|
||||
|
||||
/* Enable PLL3 outputs */
|
||||
__HAL_RCC_PLL3CLKOUT_ENABLE(RCC_PLL3_DIVP | RCC_PLL3_DIVQ | RCC_PLL3_DIVR);
|
||||
}
|
||||
|
||||
/* Configure MCU clock only */
|
||||
__HAL_RCC_MCU_SOURCE(RCC_ClkInit.MCUInit.MCU_Clock);
|
||||
|
||||
/* Wait till MCU is ready */
|
||||
__WAIT_EVENT_TIMEOUT(__HAL_RCC_GET_FLAG(RCC_FLAG_MCUSSRCRDY),
|
||||
CLOCKSWITCH_TIMEOUT_VALUE);
|
||||
|
||||
/* Update SystemCoreClock variable */
|
||||
SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq();
|
||||
|
||||
/* Reconfigure Systick */
|
||||
if (HAL_InitTick(uwTickPrio) != HAL_OK)
|
||||
{
|
||||
return RT_ERROR;
|
||||
}
|
||||
|
||||
/* Set MCU division factor */
|
||||
__HAL_RCC_MCU_DIV(RCC_ClkInit.MCUInit.MCU_Div);
|
||||
|
||||
/* Wait till MCUDIV is ready */
|
||||
__WAIT_EVENT_TIMEOUT(__HAL_RCC_GET_FLAG(RCC_FLAG_MCUDIVRDY),
|
||||
CLOCKSWITCH_TIMEOUT_VALUE);
|
||||
|
||||
/* Update SystemCoreClock variable */
|
||||
SystemCoreClock = HAL_RCC_GetSystemCoreClockFreq();
|
||||
|
||||
/* Reconfigure Systick */
|
||||
if (HAL_InitTick(uwTickPrio) != HAL_OK)
|
||||
{
|
||||
return RT_ERROR;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void RCC_WAKEUP_IRQHandler(void)
|
||||
{
|
||||
/* enter interrupt */
|
||||
rt_interrupt_enter();
|
||||
|
||||
HAL_RCC_WAKEUP_IRQHandler();
|
||||
|
||||
/* leave interrupt */
|
||||
rt_interrupt_leave();
|
||||
}
|
||||
|
||||
void HAL_RCC_WAKEUP_Callback()
|
||||
{
|
||||
if (__HAL_PWR_GET_FLAG(PWR_FLAG_STOP) == 1U)
|
||||
{
|
||||
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_STOP);
|
||||
}
|
||||
|
||||
restore_cm4_clock();
|
||||
/* All level of ITs can interrupt */
|
||||
__set_BASEPRI(0U);
|
||||
|
||||
rt_kprintf("system exit stop mode success!\n");
|
||||
}
|
||||
|
||||
static void enter_sleep_mode(void)
|
||||
{
|
||||
__set_BASEPRI((1) << (8 - __NVIC_PRIO_BITS));
|
||||
|
||||
lptim_start();
|
||||
|
||||
HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);
|
||||
}
|
||||
|
||||
static void enter_stop_mode(void)
|
||||
{
|
||||
/*
|
||||
* Only the IT with the highest priority (0 value) can interrupt.
|
||||
* RCC_WAKEUP_IRQn IT is intended to have the highest priority and to be the
|
||||
* only one IT having this value
|
||||
* RCC_WAKEUP_IRQn is generated only when RCC is completely resumed from
|
||||
* CSTOP (protection mechanism)
|
||||
*/
|
||||
__set_BASEPRI((1) << (8 - __NVIC_PRIO_BITS));
|
||||
|
||||
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_STOP);
|
||||
backup_cm4_clocks();
|
||||
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
|
||||
}
|
||||
|
||||
static void pm_wackup_key_init(void)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_13;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
HAL_NVIC_SetPriority(EXTI13_IRQn, 0x01, 0);
|
||||
HAL_NVIC_EnableIRQ(EXTI13_IRQn);
|
||||
}
|
||||
|
||||
int drv_pm_hw_init(void)
|
||||
{
|
||||
pm_wackup_key_init();
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
INIT_BOARD_EXPORT(drv_pm_hw_init);
|
||||
|
||||
static int pwr_sample(int argc, char *argv[])
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
if (!rt_strcmp(argv[1], "stop"))
|
||||
{
|
||||
rt_kprintf("system will enter stop mode! you can press USER2 button to exit this mode\n");
|
||||
enter_stop_mode();
|
||||
return RT_EOK;
|
||||
|
||||
}
|
||||
else if (!rt_strcmp(argv[1], "sleep"))
|
||||
{
|
||||
rt_kprintf("system will enter sleep mode! lptim1 will wake up the system\n");
|
||||
enter_sleep_mode();
|
||||
return RT_EOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto _exit;
|
||||
}
|
||||
}
|
||||
_exit:
|
||||
{
|
||||
rt_kprintf("Usage:\n");
|
||||
rt_kprintf("pwr_sample stop - system enter stop mode\n");
|
||||
rt_kprintf("pwr_sample sleep - system enter sleep mode\n");
|
||||
}
|
||||
|
||||
return -RT_ERROR;
|
||||
}
|
||||
MSH_CMD_EXPORT(pwr_sample, enter low power mode sample);
|
Loading…
Reference in New Issue