Reputation: 33
I am currently working on a device that requires a button press to put the device into STOP low-power mode and then a different button press to cause an interrupt to wake-up the device again. Currently the first button press interrupt does work and the and the device is put into STOP mode. However, rather than waiting for the other button to be pressed the device instantly exits STOP mode. I have tried searching but I haven't found any other indication of another interrupt being called that would cause the WFI to trigger and wake-up the device. Below is my code that I am using:
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_hal.h"
#define BUTTON_WAKE_PIN GPIO_PIN_0
#define BUTTON_WAKE_PORT GPIOA
#define BUTTON_SLEEP_PIN GPIO_PIN_9
#define BUTTON_SLEEP_PORT GPIOE
#define LED_GR_PIN GPIO_PIN_0
#define LED_GR_PORT GPIOD
#define LED_RG_PIN GPIO_PIN_1
#define LED_RG_PORT GPIOD
/* Private variables ---------------------------------------------------------*/
static uint8_t buttonPress = 0;
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config ( void );
static void Gpio_Sleep_Mode ( void );
/**
* @brief This function handles (wakeup) interrupts.
*/
void EXTI0_IRQHandler ( void )
{
/* Clear pending */
HAL_GPIO_EXTI_IRQHandler(BUTTON_WAKE_PIN); /* IRQ_CH0 */
}
/**
* @brief This function handles (sleep) interrupts.
*/
void EXTI9_5_IRQHandler(void)
{
if ( EXTI->PR & EXTI_PR_PR9 ) /* IRQ_CH9 */
{
HAL_GPIO_EXTI_IRQHandler(BUTTON_SLEEP_PIN);
buttonPress = 1;
}
}
/* Turn on LED */
void LED_Off ( void )
{
HAL_GPIO_WritePin( LED_GR_PORT, LED_GR_PIN, GPIO_PIN_RESET );
HAL_GPIO_WritePin( LED_RG_PORT, LED_RG_PIN, GPIO_PIN_RESET );
}
/* Turn off LED */
void LED_On ( void )
{
HAL_GPIO_WritePin( LED_GR_PORT, LED_GR_PIN, GPIO_PIN_SET );
HAL_GPIO_WritePin( LED_RG_PORT, LED_RG_PIN, GPIO_PIN_RESET );
}
/* Initialize LED GPIOs */
void LED_Init ( void )
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Start clock */
__HAL_RCC_GPIOD_CLK_ENABLE();
/* Default input settings */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = LED_GR_PIN;
HAL_GPIO_WritePin( LED_GR_PORT, LED_GR_PIN, GPIO_PIN_RESET );
HAL_GPIO_Init(LED_GR_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LED_RG_PIN;
HAL_GPIO_WritePin( LED_RG_PORT, LED_RG_PIN, GPIO_PIN_RESET );
HAL_GPIO_Init(LED_RG_PORT, &GPIO_InitStruct);
LED_On();
HAL_Delay(50);
LED_Off();
HAL_Delay(50);
LED_On();
HAL_Delay(50);
LED_Off();
HAL_Delay(50);
}
/* Initialize button used for wakeup */
void Wake_Button_Init ( void )
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Start clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
/* Default input settings */
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = BUTTON_WAKE_PIN;
HAL_GPIO_WritePin( BUTTON_WAKE_PORT, BUTTON_WAKE_PIN, GPIO_PIN_RESET );
HAL_GPIO_Init(BUTTON_WAKE_PORT, &GPIO_InitStruct);
__HAL_GPIO_EXTI_CLEAR_IT ( BUTTON_WAKE_PIN );
__HAL_GPIO_EXTI_CLEAR_IT ( BUTTON_SLEEP_PIN );
HAL_NVIC_SetPriority ( EXTI0_IRQn, 0, 0);
HAL_NVIC_ClearPendingIRQ ( EXTI9_5_IRQn );
HAL_NVIC_ClearPendingIRQ ( EXTI0_IRQn );
HAL_NVIC_EnableIRQ ( EXTI0_IRQn );
}
/* Initialize button used for sleep */
void Sleep_Button_Init ( void )
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Start clock */
__HAL_RCC_GPIOE_CLK_ENABLE();
/* Default input settings */
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = BUTTON_SLEEP_PIN;
HAL_GPIO_WritePin( BUTTON_SLEEP_PORT, BUTTON_SLEEP_PIN, GPIO_PIN_RESET );
HAL_GPIO_Init(BUTTON_SLEEP_PORT, &GPIO_InitStruct);
__HAL_GPIO_EXTI_CLEAR_IT ( BUTTON_SLEEP_PIN );
HAL_NVIC_SetPriority ( EXTI9_5_IRQn, 0, 0);
HAL_NVIC_ClearPendingIRQ ( EXTI9_5_IRQn );
HAL_NVIC_EnableIRQ ( EXTI9_5_IRQn );
}
void System_Init ( void )
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
buttonPress = 0;
LED_Init();
Sleep_Button_Init();
}
/* All GPIOs analog */
void Gpio_Sleep_Mode ( void )
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
/* Configure as analog */
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Pin = GPIO_PIN_All;
HAL_GPIO_Init( GPIOA, &GPIO_InitStruct );
HAL_GPIO_Init( GPIOB, &GPIO_InitStruct );
HAL_GPIO_Init( GPIOC, &GPIO_InitStruct );
HAL_GPIO_Init( GPIOD, &GPIO_InitStruct );
HAL_GPIO_Init( GPIOE, &GPIO_InitStruct );
HAL_GPIO_Init( GPIOH, &GPIO_InitStruct );
/* Disable GPIOs clock */
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOD_CLK_DISABLE();
__HAL_RCC_GPIOE_CLK_DISABLE();
__HAL_RCC_GPIOH_CLK_DISABLE();
/* Disble all interrupt sources */
EXTI->IMR = 0;
}
/**
* @brief Puts the system into sleep mode
*/
void System_Sleep ( void )
{
Gpio_Sleep_Mode();
/* Enable button interrupt */
Wake_Button_Init();
/* FLASH Deep Power Down Mode enabled */
HAL_PWREx_EnableFlashPowerDown();
/* Enter Stop Mode */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
System_Init();
}
/**
* @brief The application entry point.
*/
int main(void)
{
System_Init();
// Allow debugger to work in stop mode
DBGMCU->CR = DBGMCU_CR_DBG_STOP;
/* Infinite loop */
while (1)
{
LED_On();
HAL_Delay(500);
LED_Off();
HAL_Delay(500);
if ( buttonPress == 1 )
{
HAL_Delay ( 500 );
buttonPress = 0;
System_Sleep();
}
}
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
/* Configure the main internal regulator output voltage */
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/* Initializes the CPU, AHB and APB busses clocks */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_LSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 2;
RCC_OscInitStruct.PLL.PLLN = 96;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV6;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/* Initializes the CPU, AHB and APB busses clocks */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time */
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick */
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
/**
* @brief This function is executed in case of error occurrence.
*/
void _Error_Handler(char *file, int line)
{
/* User can add his own implementation to report the HAL error return state */
while(1);
}
Upvotes: 2
Views: 5639
Reputation: 7057
You have enabled the SysTick interrupt. Could the SysTick interrupt be waking up the processor? Do you know if the SysTick clock source stops or if the SysTick interrupt gets disabled when you enter stop mode?
Try suspending and resuming the SysTick interrupt like this.
HAL_SuspendTick();
/* Enter Stop Mode */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
HAL_ResumeTick();
Upvotes: 9