Browse Source

[add] low power and lptim driver.

thread-liu 4 years ago
parent
commit
8880e751f2

+ 1 - 1
bsp/stm32/stm32mp157a-st-ev1/board/CubeMX_Config/CM4/Src/stm32mp1xx_hal_msp.c

@@ -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();

+ 16 - 0
bsp/stm32/stm32mp157a-st-ev1/board/Kconfig

@@ -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

+ 6 - 0
bsp/stm32/stm32mp157a-st-ev1/board/SConscript

@@ -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')

+ 163 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_lptim.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

+ 202 - 0
bsp/stm32/stm32mp157a-st-ev1/board/ports/drv_pwr.c

@@ -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);