2025-01-09 01:52 AM
Hello everyone,
I want to try to wakeup my system from the the STOP2 mode with a button press. The button is also in use in the rest of the application and works just fine. But when going to STOP2 it does not wake up the system again.
I've tried it with the preconfigured interrupt, which also handles the button presses while the system is active, as well as a change to an event based trigger setup right before going to STOP2. Both do not wake up the system.
void setEXTIEvent(void)
{
LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
EXTI_InitStruct.LineCommand = ENABLE;
EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_6;
EXTI_InitStruct.Mode = LL_EXTI_MODE_EVENT;
EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;
LL_EXTI_Init(&EXTI_InitStruct);
HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
}
void setEXTIInt(void)
{
LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
EXTI_InitStruct.LineCommand = ENABLE;
EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_6;
EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;
LL_EXTI_Init(&EXTI_InitStruct);
NVIC_EnableIRQ(EXTI9_5_IRQn);
}
void EnterStop2Mode(void)
{
SaveParamConfig();
printf("Entering STOP2 mode...\n");
setEXTIEvent();
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
HAL_SuspendTick();
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFE);
HAL_ResumeTick();
setEXTIInt();
MX_SUBGHZ_Init();
printf("Woke up from STOP2\n");
}
I've included the code for the current event based implementation. The interrupt based implementation just doesn't call the two setEXTI functions and PWR_STOPENTRY_WFI ist used instead. The general pin configuration is done through the code generator.
As the tag is not available I'm working on a STM32WLE5 MCU.
Solved! Go to Solution.
2025-01-10 06:40 AM
Hi Rico
I have successfully run the following code on the Nucleo-WL55JC development board, which is based on your code.
Are you sure that the MCU is not waking up from STOP2 mode and that the code isn't getting stuck somewhere in the LCD functions?
Are you measuring power consumption?
Does your board have an available LED?
I suggest simplifying the code by commenting out all unnecessary parts (such as LCD and I2C parts) and at first ensure that you can wake up from STOP2 mode upon a button press. After waking up, turn on an LED, add a delay, switch off the LED, and then return to STOP2 mode.
Once you've confirmed this is working, you can proceed with the LCD.
Considering your clock settings, you may also want to set the STOPWUCK bit in the RCC_CFGR register to use the HSI16 oscillator as the wake-up clock from STOP2 mode (otherwise, it defaults to the MSI oscillator).
You can use my code as a reference.
//main.c:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void EnterStop2Mode(void)
{
// sl_segment_lcd_all_off();
// sl_segment_lcd_disable();
HAL_SuspendTick();
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
HAL_ResumeTick();
// sl_segment_lcd_init(false);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t counter = 10;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(2000);
LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_9);
EnterStop2Mode();
counter++;
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_9);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @PAram None
* @retval None
*/
static void MX_GPIO_Init(void)
{
LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
/**/
LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTA, LL_SYSCFG_EXTI_LINE6);
/**/
EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_6;
EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE;
EXTI_InitStruct.LineCommand = ENABLE;
EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;
LL_EXTI_Init(&EXTI_InitStruct);
/**/
LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_6, LL_GPIO_PULL_UP);
/**/
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_6, LL_GPIO_MODE_INPUT);
/* EXTI interrupt init*/
NVIC_SetPriority(EXTI9_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(EXTI9_5_IRQn);
/* USER CODE BEGIN MX_GPIO_Init_2 */
LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_9);
/**/
GPIO_InitStruct.Pin = LL_GPIO_PIN_9;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @PAram file: pointer to the source file name
* @PAram line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
//stm32wlxx_it.c:
void EXTI9_5_IRQHandler(void)
{
/* USER CODE BEGIN EXTI9_5_IRQn 0 */
/* USER CODE END EXTI9_5_IRQn 0 */
if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_6) != RESET)
{
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6);
/* USER CODE BEGIN LL_EXTI_LINE_6 */
/* USER CODE END LL_EXTI_LINE_6 */
}
/* USER CODE BEGIN EXTI9_5_IRQn 1 */
/* USER CODE END EXTI9_5_IRQn 1 */
}
2025-01-09 05:18 AM
Hello @RWalko, welcome to ST Community,
Following this wiki, you should be able to make it work: Getting started with EXTI - stm32mcu
Could you try that?
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-01-09 05:35 AM
Thanks for the welcome, and thanks for the resource.
As I have written, the EXTI Interrupt generally works, and the button is used to switch between modes in my application, which works just fine, so I am already beyond the example you have given me. I have checked in regardlessly but found no differences between my solution and the example. The only problem is that in the STOP2 low power mode the interrupt or the event does not wake up the MCU.
I noticed in the data sheet that EXTI is an 'optional' wakeup source for STOP2. But all the resources I've found said that if I have configured the interrupt or event, it should work as a wakeup. Is there maybe something else that warrants that 'optional' tag that I missed?
2025-01-09 05:43 AM
This is the table you should refer to, to know the wake up capabilities in every low power mode:
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-01-09 06:03 AM
Hi Rico
Please find below my code that runs on the Nucleo-WL55JC development board. I've achieved around 880 nA current consumption in STOP2 mode. By pressing user button 1 (PA0), the system wakes up (interrupt), toggles an LED (PB9) a few times, and then returns to STOP2 mode, reaching the same current consumption as before.
I've included everything in the main function so you can see all the necessary steps. I didn't have much time for code refactoring.
Remember to clear the corresponding EXTI flag in the ISR handler (file stm32wlxx_it.c).
Should the problem persists, feel free to contact me.
Hope this helps!
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
/* USER CODE BEGIN 2 */
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
/* GPIO Ports Clock Enable */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
/**/
LL_GPIO_ResetOutputPin(LED2_GPIO_Port, LED2_Pin);
/**/
GPIO_InitStruct.Pin = LED2_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(LED2_GPIO_Port, &GPIO_InitStruct);
/* Configure PA0 (user button 1) as EXTI */
LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTA, LL_SYSCFG_EXTI_LINE0);
EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_0;
EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE;
EXTI_InitStruct.LineCommand = ENABLE;
EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;
LL_EXTI_Init(&EXTI_InitStruct);
LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_0, LL_GPIO_PULL_UP);
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_0, LL_GPIO_MODE_INPUT);
/* EXTI interrupt init*/
NVIC_SetPriority(EXTI0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(EXTI0_IRQn);
/* Enter Stop 2 mode */
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2);
/* Set SLEEPDEEP bit of Cortex System Control Register */
LL_LPM_EnableDeepSleep();
/* Request Wait For Interrupt */
__WFI();
/* Here Device is in Stop 2 mode */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
LED_Blinking_5s();
__WFI();
}
/* USER CODE END 3 */
}
void LED_Blinking_5s(void)
{
uint32_t i = 0;
/* Toggle IO in during 5s (25*200ms) */
for(i = 0; i < 24; i++)
{
LL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
LL_mDelay(50);
}
}
void EXTI0_IRQHandler(void)
{
/* USER CODE BEGIN EXTI0_IRQn 0 */
/* USER CODE END EXTI0_IRQn 0 */
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_0);
/* USER CODE BEGIN EXTI0_IRQn 1 */
/* USER CODE END EXTI0_IRQn 1 */
}
2025-01-09 06:09 AM
Thanks for the info, but it only shows me that it should work as I have explained it. But if there is something I overlooked, it's not there.
I have checked in the reference manual and have seen that any activated EXTI line is also activated as a wakeup source, no matter if it's event or interrupt based. So I'm still stumped.
2025-01-09 06:47 AM - edited 2025-01-09 06:56 AM
Thanks a lot for the example, I was able to cross check. I wrote a smaller example that just displays something on a LCD display that is connected via I2C, turns off after a time and goes to STOP2 and is supposed to be reactivated with a button press. The used Pin is PA6, which is not a wakeup pin, but it should not matter if I do not go in standby/shutdown.
Generally, the code generated by CubeMX is the same, except that I use HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
void EnterStop2Mode(void)
{
sl_segment_lcd_all_off();
sl_segment_lcd_disable();
HAL_SuspendTick();
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
HAL_ResumeTick();
sl_segment_lcd_init(false);
}
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t counter = 10;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
sl_segment_lcd_init(false);
/* USER CODE END 2 */
/* Infinite loop */
while (1)
{
sl_segment_lcd_number(counter);
HAL_Delay(10000);
EnterStop2Mode();
counter++;
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
/* GPIO Ports Clock Enable */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
/**/
LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTA, LL_SYSCFG_EXTI_LINE6);
/**/
EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_6;
EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE;
EXTI_InitStruct.LineCommand = ENABLE;
EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;
LL_EXTI_Init(&EXTI_InitStruct);
/**/
LL_GPIO_SetPinPull(TAMP_GPIO_Port, TAMP_Pin, LL_GPIO_PULL_UP);
/**/
LL_GPIO_SetPinMode(TAMP_GPIO_Port, TAMP_Pin, LL_GPIO_MODE_INPUT);
/* EXTI interrupt init*/
NVIC_SetPriority(EXTI9_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(EXTI9_5_IRQn);
}
And in the stm32wlxx_it.c (which I have not modified, as it does not need to do anything).
void EXTI9_5_IRQHandler(void)
{
/* USER CODE BEGIN EXTI9_5_IRQn 0 */
/* USER CODE END EXTI9_5_IRQn 0 */
if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_6) != RESET)
{
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6);
/* USER CODE BEGIN LL_EXTI_LINE_6 */
/* USER CODE END LL_EXTI_LINE_6 */
}
/* USER CODE BEGIN EXTI9_5_IRQn 1 */
/* USER CODE END EXTI9_5_IRQn 1 */
}
2025-01-09 06:54 AM
Hi Rico,
great. Nice example!
Does this mean the issue has been resolved and you can now wake up from STOP2 mode by pressing the button or does the problem still persist?
Best regards
Jaroslav
2025-01-09 11:44 PM
I fear that it does not work to wake up from STOP2, that is the example that I have the problem with.
2025-01-10 06:40 AM
Hi Rico
I have successfully run the following code on the Nucleo-WL55JC development board, which is based on your code.
Are you sure that the MCU is not waking up from STOP2 mode and that the code isn't getting stuck somewhere in the LCD functions?
Are you measuring power consumption?
Does your board have an available LED?
I suggest simplifying the code by commenting out all unnecessary parts (such as LCD and I2C parts) and at first ensure that you can wake up from STOP2 mode upon a button press. After waking up, turn on an LED, add a delay, switch off the LED, and then return to STOP2 mode.
Once you've confirmed this is working, you can proceed with the LCD.
Considering your clock settings, you may also want to set the STOPWUCK bit in the RCC_CFGR register to use the HSI16 oscillator as the wake-up clock from STOP2 mode (otherwise, it defaults to the MSI oscillator).
You can use my code as a reference.
//main.c:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void EnterStop2Mode(void)
{
// sl_segment_lcd_all_off();
// sl_segment_lcd_disable();
HAL_SuspendTick();
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
HAL_ResumeTick();
// sl_segment_lcd_init(false);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
uint32_t counter = 10;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(2000);
LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_9);
EnterStop2Mode();
counter++;
LL_GPIO_SetOutputPin(GPIOB, LL_GPIO_PIN_9);
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief GPIO Initialization Function
* @PAram None
* @retval None
*/
static void MX_GPIO_Init(void)
{
LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);
/**/
LL_SYSCFG_SetEXTISource(LL_SYSCFG_EXTI_PORTA, LL_SYSCFG_EXTI_LINE6);
/**/
EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_6;
EXTI_InitStruct.Line_32_63 = LL_EXTI_LINE_NONE;
EXTI_InitStruct.LineCommand = ENABLE;
EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;
LL_EXTI_Init(&EXTI_InitStruct);
/**/
LL_GPIO_SetPinPull(GPIOA, LL_GPIO_PIN_6, LL_GPIO_PULL_UP);
/**/
LL_GPIO_SetPinMode(GPIOA, LL_GPIO_PIN_6, LL_GPIO_MODE_INPUT);
/* EXTI interrupt init*/
NVIC_SetPriority(EXTI9_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(EXTI9_5_IRQn);
/* USER CODE BEGIN MX_GPIO_Init_2 */
LL_GPIO_ResetOutputPin(GPIOB, LL_GPIO_PIN_9);
/**/
GPIO_InitStruct.Pin = LL_GPIO_PIN_9;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @PAram file: pointer to the source file name
* @PAram line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
//stm32wlxx_it.c:
void EXTI9_5_IRQHandler(void)
{
/* USER CODE BEGIN EXTI9_5_IRQn 0 */
/* USER CODE END EXTI9_5_IRQn 0 */
if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_6) != RESET)
{
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_6);
/* USER CODE BEGIN LL_EXTI_LINE_6 */
/* USER CODE END LL_EXTI_LINE_6 */
}
/* USER CODE BEGIN EXTI9_5_IRQn 1 */
/* USER CODE END EXTI9_5_IRQn 1 */
}