#include "stm32l1xx_hal.h" #include "stm32l1xx_hal_pwr.h" #include "stm32l1xx_hal_pwr_ex.h" #include "stm32l1xx_hal_pcd.h" #include "core/gpio.h" #include "core/main.h" #include "core/sleep_and_exti.h" #include "core/csect.h" #include #include "core/config.h" #include "core/config_pins.h" // USB_VBUS_WKPIN // Specifies the special wake up pin (WKUP1..WKUP3) for waking up from USB_VBUS signal // Possible values: PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3, or undefined #define USB_VBUS_WKPIN (CONFIG_PIN__USB__VBUSWKUP) // USB_VBUS_LINE // Specifies the GPIO line number for USB_VBUS detecting using EXTI GPIO // Possible values: GPIO_PIN_0 .. GPIO_PIN_15 #define USB_VBUS_LINE (CONFIG_PIN__USB__VBUSDETECT) // USB_VBUS_PORT // Specifies the GPIO port for USB_VBUS detecting using EXTI GPIO // Possible values: GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOH #define USB_VBUS_PORT (CONFIG_PORT__USB__VBUSDETECT) // USB_VBUS_PORT_CLKEN // Enables the corresponding port clocking (see USB_VBUS_PORT) #define USB_VBUS_PORT_CLKEN() __HAL_RCC_GPIOC_CLK_ENABLE() #define USB_VBUS_PORT_CLKDS() __HAL_RCC_GPIOC_CLK_DISABLE() // USB_VBUS_EXTI_IRQ // Specifies the IRQ-number for USB_VBUS detecting using EXTI GPIO // Possible values: EXTI15_10_IRQn, EXTI9_5_IRQn, EXTI4_IRQn, EXTI3_IRQn, EXTI2_IRQn, EXTI1_IRQn, EXTI0_IRQn #define USB_VBUS_EXTI_IRQ (EXTI15_10_IRQn) // USB_INTERNAL_WKUP_SUPPORT // Enables internal USB wakeup-event support #define USB_INTERNAL_WKUP_SUPPORT CONFIG_USB_INTERNAL_WKUP_SUPPORT // USB_DEBUG_SUPRESS_VBUS_WKUP // Debug: do not wakeup on VBUS line changing #define USB_DEBUG_SUPRESS_VBUS_WKUP CONFIG_DEBUG_USB_SUPRESS_VBUS_WKUP #if CONFIG_SLEEPMANAGER // This module uses WakeUp Pin #2 as a wakeup source // This WakeUp Pin (PC13, Pin #2) is connected to USB_VBUS // Rising edge means the USB cable plugging in // Falling edge means the USB cable unplugging static bool bInitialized = false; static bool bUSBActive = false; // shows if USB in suspend mode or not static bool bUSBPlugged = false; // shows if USB cable connected (USB VBUS Pin monitoring) static eSleepManager_WakeupReason_t xWakeupReason = eSleepManager_GenericWakeup; static bool SleepManager_Init(); static void SleepManager_DeInit(); static bool SleepManager_SetUSBWakeUp( bool ); static bool SleepManager_EnterSleepTimeout( uint32_t ); static bool SleepManager_EnterSleep(); static bool SleepManager_GetUSBPlugged(); static bool SleepManager_GetUSBActive(); static eSleepManager_WakeupReason_t SleepManager_Sleep(); static eSleepManager_WakeupReason_t SleepManager_SleepTimeout( uint32_t ); static bool SleepManager_USBPlugStatusUpdate(); const sSleepManager_Handle_t SleepManagerHandle = { .Init = SleepManager_Init, .SetUSBWakeup = SleepManager_SetUSBWakeUp, .Sleep = SleepManager_Sleep, .SleepTimeout = SleepManager_SleepTimeout, .GetUSBPlugged = SleepManager_GetUSBPlugged, .GetUSBActive = SleepManager_GetUSBActive, .DeInit = SleepManager_DeInit, }; static void SleepManager_USBSuspendEvent(); static void SleepManager_USBResumeEvent(); const sSleepManager_Notify_t SleepManagerNotify = { .USBSuspendEvent = SleepManager_USBSuspendEvent, .USBResumeEvent = SleepManager_USBResumeEvent, }; static bool SleepManager_Init() { __DI__ HAL_PWR_DisableSleepOnExit(); HAL_PWREx_EnableFastWakeUp(); HAL_PWREx_DisableLowPowerRunMode(); bInitialized = true; SleepManager_SetUSBWakeUp( false ); SleepManager_USBPlugStatusUpdate(); __EI__ return true; } static void SleepManager_DeInit() { __DI__ HAL_PWREx_DisableFastWakeUp(); HAL_PWR_DisableSleepOnExit(); HAL_PWREx_DisableLowPowerRunMode(); SleepManager_SetUSBWakeUp( false ); bInitialized = false; __EI__ } static bool SleepManager_USBPlugStatusUpdate() { bool bValue = (GPIO_PIN_SET == HAL_GPIO_ReadPin( USB_VBUS_PORT, USB_VBUS_LINE )); __DI__ bUSBPlugged = bValue; __EI__ return bValue; } static bool SleepManager_SetUSBWakeUp( bool state ) { bool ret = false; GPIO_InitTypeDef GPIO_InitStruct = {0}; __DI__ if( bInitialized ) { if( state ) { // Configure GPIO pins for VBUS #if USB_DEBUG_SUPRESS_VBUS_WKUP == 0 // Enable port clocking USB_VBUS_PORT_CLKEN(); // Configure EXTI line GPIO_InitStruct.Pin = USB_VBUS_LINE; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; // use rising and falling edges GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init( USB_VBUS_PORT, &GPIO_InitStruct ); // Enable EXTI Interrupt HAL_NVIC_EnableIRQ( USB_VBUS_EXTI_IRQ ); #ifdef USB_VBUS_WKPIN HAL_PWR_EnableWakeUpPin( USB_VBUS_WKPIN ); #endif #endif #if USB_INTERNAL_WKUP_SUPPORT __HAL_USB_WAKEUP_EXTI_ENABLE_IT(); // Enable corresponding internal EXTI line (USB Wakeup) HAL_NVIC_EnableIRQ( USB_FS_WKUP_IRQn ); #endif } else { #if USB_INTERNAL_WKUP_SUPPORT HAL_NVIC_DisableIRQ( USB_FS_WKUP_IRQn ); __HAL_USB_WAKEUP_EXTI_DISABLE_IT(); // Disable corresponding internal EXTI line (USB Wakeup) #endif #if USB_DEBUG_SUPRESS_VBUS_WKUP == 0 #ifdef USB_VBUS_WKPIN HAL_PWR_DisableWakeUpPin( PWR_WAKEUP_PIN2 ); #endif // DeConfigure EXTI line, configure as Input GPIO_InitStruct.Pin = USB_VBUS_LINE; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // use port as input to poll signal GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; HAL_GPIO_Init( USB_VBUS_PORT, &GPIO_InitStruct ); // Disable EXTI Interrupt HAL_NVIC_DisableIRQ( USB_VBUS_EXTI_IRQ ); // DO NOT DISABLE PORT CLOCKING DUE TO IT CAN BE IN USE!!! /* __ USB_VBUS_PORT_CLKDS(); __ */ #else // DeConfigure EXTI line, configure as Input GPIO_InitStruct.Pin = USB_VBUS_LINE; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // use port as input to poll signal GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; HAL_GPIO_Init( USB_VBUS_PORT, &GPIO_InitStruct ); #endif } ret = true; } __EI__ return ret; } // SleepManager_USBSuspendEvent callback // Is called by Low-Level PCD Module (USB HAL) to inform the high level // about the fact that USB enters in SUSPEND mode static void SleepManager_USBSuspendEvent() { __DI__ if( bInitialized ) { bUSBActive = false; } __EI__ } // SleepManager_USBResumeEvent callback // Is called by Low-Level PCD Module (USB HAL) to inform the high level // about the fact that USB enters in RUN mode static void SleepManager_USBResumeEvent() { __DI__ if( bInitialized ) { bUSBActive = true; } __EI__ } static bool SleepManager_GetUSBPlugged() { // Check if initialized: DI(); if( !bInitialized ) { EI(); return false; } EI(); return SleepManager_USBPlugStatusUpdate(); } static bool SleepManager_GetUSBActive() { bool ret = false; __DI__ ret = bInitialized && bUSBActive; __EI__ return ret; } static eSleepManager_WakeupReason_t SleepManager_GetWakeupReason() { eSleepManager_WakeupReason_t xValue; __DI__ xValue = xWakeupReason; __EI__ return xValue; } static bool SleepManager_EnterSleepTimeout( uint32_t timeout ) { xWakeupReason = eSleepManager_Error; // HAL_PWR_EnterSLEEPMode( PWR_LOWPOWERREGULATOR_ON, // PWR_SLEEPENTRY_WFE ); // return false; } static bool SleepManager_EnterSleep( ) { xWakeupReason = eSleepManager_GenericWakeup; // disable some clocks for the power consumption reducing? //RCC_AHBENR //RCC_AHB1ENR //RCC_AHB2ENR // HAL_PWR_EnableSleepOnExit(); #if CONFIG_SLEEPMANAGER_KEEPDEBUGCLK HAL_DBGMCU_EnableDBGSleepMode(); HAL_DBGMCU_EnableDBGStopMode(); #endif #if CONFIG_SLEEPMANAGER_DEBUGPIN CONFIG_SLEEPMANAGER_DEBUGPIN_SETPIN #endif #if CONFIG_SLEEPMANAGER_DEBUG_NOSLEEP __NOP(); #else HAL_PWR_EnterSLEEPMode( PWR_MAINREGULATOR_ON, // OK PWR_SLEEPENTRY_WFI ); // OK // HAL_PWR_EnterSLEEPMode( PWR_LOWPOWERREGULATOR_ON, //?? // PWR_SLEEPENTRY_WFI ); //?? //HAL_PWR_EnterSLEEPMode( PWR_MAINREGULATOR_ON, // PWR_SLEEPENTRY_WFE ); //HAL_PWR_EnterSTOPMode( PWR_LOWPOWERREGULATOR_ON, //PWR_MAINREGULATOR_ON, // PWR_STOPENTRY_WFI ); //HAL_PWR_EnterSTOPMode( PWR_LOWPOWERREGULATOR_ON, //PWR_MAINREGULATOR_ON, // PWR_STOPENTRY_WFE ); #endif #if CONFIG_SLEEPMANAGER_DEBUGPIN CONFIG_SLEEPMANAGER_DEBUGPIN_CLRPIN #endif return true; } static eSleepManager_WakeupReason_t SleepManager_Sleep() { if( SleepManager_EnterSleep() ) return SleepManager_GetWakeupReason(); return eSleepManager_Error; } static eSleepManager_WakeupReason_t SleepManager_SleepTimeout( uint32_t timeout ) { if( SleepManager_EnterSleepTimeout( timeout ) ) return SleepManager_GetWakeupReason(); return eSleepManager_Error; } #endif #if USB_INTERNAL_WKUP_SUPPORT // // USB-Wakeup Interrupt Event Routing // void USB_FS_WKUP_IRQHandler() // startup_stm32l151xb.s { xWakeupReason = eSleepManager_USBPlugWakeup; HAL_PWR_DisableSleepOnExit(); } #endif // EXTI line detection callbacks. // Note: It is required to route the interrupt routine to the // HAL-function HAL_GPIO_EXTI_IRQHandler() // e.g. void EXTI4_IRQHandler { HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4); } // void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) // stm32l1xx_hal_gpio.c { // USB VBUS is connected to PC13. // This callback is called if any GPIO pin is triggered and // the corresponding EXTI-line is configured. // Check if the pin number is corresponds to PC13: if( USB_VBUS_LINE == GPIO_Pin ) { #if CONFIG_SLEEPMANAGER SleepManager_USBPlugStatusUpdate(); xWakeupReason = eSleepManager_USBPlugWakeup; #endif HAL_PWR_DisableSleepOnExit(); } }