From 3869b31b03ff8f44eaedccf3050a830f5e8566ad Mon Sep 17 00:00:00 2001 From: Oliver Walter Date: Sat, 18 May 2024 02:11:54 +0200 Subject: [PATCH] Wakeup and Standby systems --- Application/BSP/BSP_POWER.c | 114 +++++++++++++++++++++++++++++++++++- Application/BSP/BSP_POWER.h | 4 ++ Core/Src/freertos.c | 42 ++++++++++++- Core/Src/main.c | 45 +++++--------- 4 files changed, 173 insertions(+), 32 deletions(-) diff --git a/Application/BSP/BSP_POWER.c b/Application/BSP/BSP_POWER.c index 26773ae..ef5e6a8 100644 --- a/Application/BSP/BSP_POWER.c +++ b/Application/BSP/BSP_POWER.c @@ -3,17 +3,127 @@ #include "BSP_POWER.h" #include "lptim.h" #include "ulog.h" +#include "rtc.h" +#include "fdcan.h" +#include "i2c.h" +#include "sdmmc.h" +#include "cmsis_os2.h" +#include "BSP_GPIO.h" #define LPTIM_CLK 500 // Hz -#define SLEEP_TIME 10 // seconds to wait +#define SLEEP_TICK_TIME 1 // seconds to wait +#define STAY_AWAKE_TIME 60 // seconds to stay awake without K15 + + +// Start the sleep counter check void BSP_POWER_Init() { - uint16_t counter = LPTIM_CLK * SLEEP_TIME; + uint16_t counter = LPTIM_CLK * SLEEP_TICK_TIME; HAL_LPTIM_Counter_Start_IT(&hlptim4, counter); } +// This should be called as soon as possible after wakeup +void BSP_POWER_WakeUp() { + + /* Check if the system has resumed from StandBy mode */ + if(__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET) + { + /* Clear Standby flag */ + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB); + } + + + if (__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTF) != 0U) + { + __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF); + } + + +} + +/* The Following Wakeup sequence is highly recommended prior to each Standby mode entry + mainly when using more than one wakeup source this is to not miss any wakeup event. + - Disable all used wakeup sources, + - Clear all related wakeup flags, + - Re-enable all used wakeup sources, + - Enter the Standby mode. +*/ +void BSP_POWER_EnterStandby() { + + // We need to disable all Periperals to minimize parasitic currents + HAL_I2C_DeInit(&hi2c1); + HAL_I2C_MspDeInit(&hi2c1); + HAL_I2C_DeInit(&hi2c2); + HAL_I2C_MspDeInit(&hi2c2); + HAL_FDCAN_DeInit(&hfdcan1); + HAL_FDCAN_MspDeInit(&hfdcan1); + HAL_FDCAN_DeInit(&hfdcan2); + HAL_FDCAN_MspDeInit(&hfdcan2); + HAL_SD_MspDeInit(&hsd1); + + // These Pins interfere with the WAKEUP PINS + HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1| GPIO_PIN_3); + + // cut the power for the Slaves and unused peripherals + BSP_GPIO_ClsOff(); + BSP_GPIO_PeriperalsOff(); + BSP_GPIO_RadioOff(); + + + + // Here now the showdown + PWREx_WakeupPinTypeDef sPinParams; + + /* Disable used wakeup source: PWR_WAKEUP_PIN1 */ + HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN1); + HAL_PWR_DisableWakeUpPin(PWR_WAKEUP_PIN2); + HAL_RTCEx_DeactivateWakeUpTimer(&hrtc); + + HAL_PWREx_ClearPendingEvent(); + /* Clear all related wakeup flags */ + HAL_PWREx_ClearWakeupFlag(PWR_WAKEUP_FLAG_ALL); + HAL_PWREx_ClearWakeupFlag(PWR_WAKEUP_PIN1); + HAL_PWREx_ClearWakeupFlag(PWR_WAKEUP_PIN2); + + /* Clear all related wakeup flags */ + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); + + + //HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0xFFFF, RTC_WAKEUPCLOCK_RTCCLK_DIV16); + HAL_PWREx_ClearWakeupFlag(PWR_WAKEUP_PIN1); + + sPinParams.WakeUpPin = PWR_WAKEUP_PIN1; + sPinParams.PinPolarity = PWR_PIN_POLARITY_HIGH; + sPinParams.PinPull = PWR_PIN_PULL_DOWN; + HAL_PWREx_EnableWakeUpPin(&sPinParams); + + sPinParams.WakeUpPin = PWR_WAKEUP_PIN2; + sPinParams.PinPolarity = PWR_PIN_POLARITY_HIGH; + sPinParams.PinPull = PWR_PIN_PULL_DOWN; + HAL_PWREx_EnableWakeUpPin(&sPinParams); + + + /* Enter the Standby mode */ + HAL_PWR_EnterSTANDBYMode(); + +} + +uint32_t sec_without_k15 = 0; + void HAL_LPTIM_AutoReloadMatchCallback(LPTIM_HandleTypeDef *hlptim) { + if(hlptim == &hlptim4) { + // 1s timer check if K15 is set + if (!BSP_GPIO_K15isSet()) { + sec_without_k15++; + } else { + sec_without_k15 = 0; + } + + if (sec_without_k15 > STAY_AWAKE_TIME) { + BSP_POWER_EnterStandby(); + } + } } \ No newline at end of file diff --git a/Application/BSP/BSP_POWER.h b/Application/BSP/BSP_POWER.h index ff34a81..6861a0f 100644 --- a/Application/BSP/BSP_POWER.h +++ b/Application/BSP/BSP_POWER.h @@ -7,3 +7,7 @@ void BSP_POWER_Init(); +void BSP_POWER_WakeUp(); + + +void BSP_POWER_EnterStandby(); \ No newline at end of file diff --git a/Core/Src/freertos.c b/Core/Src/freertos.c index 5936066..6e802dc 100644 --- a/Core/Src/freertos.c +++ b/Core/Src/freertos.c @@ -36,6 +36,7 @@ #include "BSP_INA.h" #include "BSP_POWER.h" #include "LightTask.h" +#include "BSP_GPIO.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -65,12 +66,20 @@ const osThreadAttr_t defaultTask_attributes = { .priority = (osPriority_t) osPriorityNormal, }; +osThreadId_t waitForStartConfirmHandle; +const osThreadAttr_t waitForStartConfirm_attributes = { + .name = "waitForStartConfirm", + .stack_size = 128 * 4, + .priority = (osPriority_t) osPriorityNormal, +}; + /* Private function prototypes -----------------------------------------------*/ /* USER CODE BEGIN FunctionPrototypes */ /* USER CODE END FunctionPrototypes */ void StartDefaultTask(void *argument); +void WaitForStartConfirm_Task(void *argument); extern void MX_USB_DEVICE_Init(void); void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */ @@ -99,7 +108,6 @@ return __HAL_TIM_GetCounter(&htim2); */ void MX_FREERTOS_Init(void) { /* USER CODE BEGIN Init */ - BSP_POWER_Init(); /* USER CODE END Init */ /* USER CODE BEGIN RTOS_MUTEX */ @@ -123,6 +131,9 @@ void MX_FREERTOS_Init(void) { defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); /* USER CODE BEGIN RTOS_THREADS */ + + waitForStartConfirmHandle = osThreadNew(WaitForStartConfirm_Task, NULL, &waitForStartConfirm_attributes); + ULOG_INFO("Setup UsbDataHandler"); UsbDataHandler_Start(); ULOG_INFO("Setup CanDataTask"); @@ -200,5 +211,34 @@ void StartDefaultTask(void *argument) /* Private application code --------------------------------------------------*/ /* USER CODE BEGIN Application */ +void WaitForStartConfirm_Task(void *argument) { + + // wait for up to 1 s and check if either K15 is set or we got a Car CAN message + // once one of these is true, we can start the power systems. + // after waiting for 1s, the system should shutdown / go to standby mode + uint32_t tick = osKernelGetTickCount(); + uint32_t delayTime = 50; // Set the initial delay time to 50ms + uint32_t maxDelayTime = 1000; // Set the maximum delay time to 1000ms + + while(1) { + osDelayUntil(tick); + tick += delayTime; + if(BSP_GPIO_K15isSet() || CanDataTask_gotCarCanMessage()) { + BSP_GPIO_ClsOn(); + BSP_GPIO_RadioOn(); + ULOG_INFO("Power systems started"); + osThreadExit(); + return; + } + + if(tick > maxDelayTime) { + BSP_POWER_EnterStandby(); + ULOG_INFO("System in standby mode"); + osThreadExit(); + return; + } + } +} + /* USER CODE END Application */ diff --git a/Core/Src/main.c b/Core/Src/main.c index c29e11d..d5ff6a6 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -38,6 +38,8 @@ /* USER CODE BEGIN Includes */ #include "ulog.h" #include "stdio.h" +#include "BSP_POWER.h" +#include "BSP_GPIO.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ @@ -81,7 +83,7 @@ void ULOG_SendLPUART(ulog_level_t level, char *msg); * @retval int */ int main(void) -{ + { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ @@ -108,7 +110,7 @@ int main(void) PeriphCommonClock_Config(); /* USER CODE BEGIN SysInit */ - + BSP_POWER_WakeUp(); /* USER CODE END SysInit */ /* Initialize all configured peripherals */ @@ -129,40 +131,18 @@ int main(void) MX_TIM2_Init(); MX_LPTIM4_Init(); /* USER CODE BEGIN 2 */ - ULOG_INIT(); - ULOG_SUBSCRIBE(ULOG_SendLPUART,ULOG_DEBUG_LEVEL); - GPIO_PinState K15 = HAL_GPIO_ReadPin(K15_Detect_GPIO_Port, K15_Detect_Pin); - while (K15 == GPIO_PIN_RESET) - { - K15 = HAL_GPIO_ReadPin(K15_Detect_GPIO_Port, K15_Detect_Pin); - ULOG_DEBUG("Wait for K15 Signal Wait Wait Wait"); - HAL_Delay(100); - } - - GPIO_PinState HL = HAL_GPIO_ReadPin(Headlight_Detect_GPIO_Port, Headlight_Detect_Pin); - while (HL == GPIO_PIN_RESET) - { - HL = HAL_GPIO_ReadPin(Headlight_Detect_GPIO_Port, Headlight_Detect_Pin); - ULOG_DEBUG("Wait for K15 Signal Wait Wait Wait"); - HAL_Delay(100); - } - + BSP_GPIO_PeriperalsOn(); + BSP_POWER_Init(); + ULOG_INIT(); + ULOG_SUBSCRIBE(ULOG_SendLPUART,ULOG_DEBUG_LEVEL); ULOG_DEBUG("Setup Logger"); - HAL_GPIO_WritePin(Periph_Power_GPIO_Port,Periph_Power_Pin,GPIO_PIN_RESET); - HAL_GPIO_WritePin(CLS_POWER_GPIO_Port, CLS_POWER_Pin, GPIO_PIN_SET); - ULOG_DEBUG("Enable Power on CLS and Periph"); - gCLS_DEVICE_ADDRESS = 0x11; + gCLS_DEVICE_ADDRESS = 0x11; // Address is set to master ULOG_DEBUG("Setting Global CLS address to 0b10001"); ULOG_DEBUG("Init Kernel and start schedule"); - - - /* USER CODE END 2 */ - - /* Init scheduler */ osKernelInitialize(); /* Call init function for freertos objects (in freertos.c) */ MX_FREERTOS_Init(); @@ -364,6 +344,13 @@ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ + + ULOG_ERROR("Error Handler"); + osThreadId_t error_thread = osThreadGetId(); + if(error_thread != NULL) { + const char * osThreadGetName(error_thread); + ULOG_ERROR("Error in thread: %s", osThreadGetName(error_thread)); + } __disable_irq(); while (1) {