AnsweredAssumed Answered

STM32F3 Wake up from stop mode.

Question asked by Arganas on Apr 24, 2014
Latest reply on Apr 25, 2014 by Arganas
Hello everyone, i'd like to get some help and advices on the task i'm trying to do. I connected 3V to PB11 to hold pin at high level, and in my while loop i'm checking this pin state. If pin is low, processor should go to stop mode. I want to wake up it with two ways. First one is with EXTI interrupt. While waiting for interrupt, i want to use RTC, so the processor wake's up lets say every 5 or 10 minutes, because my interrupt may not arrive in that time, so i want to periodically observe the system. The part to wake up processor with EXTI interrupt is working fine, but i can't get them to work both.I don't actually know how should i implement my code to get the result which i want. For RTC i use the code which is provided with ST firmware examples. Maybe i have completely wrong understanding of how it works and maybe some one could look through my code ant say what mistakes i'm making and could give some advices? Here is the code.
/* 
  This example shows how to force processor
  to go to stop mode and how to wake it up
  with EXTI interrupt, or wake up it periodically
  With auto-wake-up ( RTC)
*/


#include "stm32f30x.h"


GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_ClocksTypeDef RCC_ClockFreq;
RTC_TimeTypeDef   RTC_TimeStructure;
RTC_InitTypeDef   RTC_InitStructure;
RTC_AlarmTypeDef  RTC_AlarmStructure;
 
// Debug variables //
uint32_t clock;
uint32_t clock2;
/////////////////////


void nop(int count)
{
  int i = count;
  while(i--)
  asm("nop");
}


void TIM3_IRQHandler(void)
{
  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);// Clear interrupt pending bit, so it can go to interrupt again
  GPIOE->ODR ^= GPIO_Pin_8; // Change LED state
}


void RTC_Alarm_IRQHandler(void)
{
  if (RTC_GetITStatus(RTC_IT_ALRA) != RESET)
  {
    GPIOE->ODR ^= GPIO_Pin_10;
    
    /* Clear the Alarm A Pending Bit */
    RTC_ClearITPendingBit(RTC_IT_ALRA);
    
    /* Clear EXTI line17 pending bit */
    EXTI_ClearITPendingBit(EXTI_Line17);    
  }  
}


void EXTI0_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line0) != RESET) // Check if EXTI_Line0 is asserted 
  {
    
     EXTI_ClearITPendingBit(EXTI_Line0); // Clear EXTI LINE0 pending bit 
    GPIOE->ODR ^= GPIO_Pin_9; // Change led state
    RCC_HSEConfig(RCC_HSE_ON);// Turn on High speed External oscillator
    RCC_WaitForHSEStartUp(); // Wait till HSE is ready
    RCC_PLLConfig(RCC_PLLSource_PREDIV1,RCC_PLLMul_9); // PLL config
     RCC_PLLCmd(ENABLE); // PLL clock enable
     RCC_GetFlagStatus(!(RCC_FLAG_PLLRDY)); // Wait till PLL clock is ready
     RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);// PLL as system clock
     nop(200);// Whait till PLL is system clock
    clock = RCC_GetSYSCLKSource(); // Get clock source (used to observe system)
    /*
        possible clock variable values:
        0x00: HSI used as system clock
        0x04: HSE used as system clock  
        0x08: PLL used as system clock
    */
    RCC_GetClocksFreq(&RCC_ClockFreq); // Get clock frequency (used to observe system)
  }
}




int main(void)
{
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE); // Laikrodis portui B
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); // Laikrodis portui B
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // Laikrodis portui B
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // Enable TIM3 clock
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);// Enable PWR clock
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // Enable the SYSCFG APB clock to get write access to comparator register and EXTI line interrupts


  PWR_BackupAccessCmd(ENABLE); // Allow access to RTC
  RCC_BackupResetCmd(ENABLE); // These two lines used to reset back up registers
  RCC_BackupResetCmd(DISABLE); 
  
    /* Allow access to RTC */
 // PWR_BackupAccessCmd(ENABLE);
  
  RCC_LSICmd(ENABLE); // LSI is used as RTC clock source
  while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET); // Wait till LSI is ready
  
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); // Select RTC clock source
  // Enable RTC clock
  RCC_RTCCLKCmd(ENABLE);
    
  RTC_WaitForSynchro(); // Wait until the RTC Time and Date registers (RTC_TR and RTC_DR) are synchronized with RTC APB clock.
  
    // Set RTC calendar clock to 1 HZ (1 second)
  RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
  RTC_InitStructure.RTC_AsynchPrediv = 88;
  RTC_InitStructure.RTC_SynchPrediv = 470;
  
   if (RTC_Init(&RTC_InitStructure) == ERROR)
  {
    while(1);
  }


 // nop(200); // small delay
  
    // Set the time to 01h 00mn 00s AM 
  RTC_TimeStructure.RTC_H12     = RTC_H12_AM  ;
  RTC_TimeStructure.RTC_Hours   = 0x01;
  RTC_TimeStructure.RTC_Minutes = 0x00;
  RTC_TimeStructure.RTC_Seconds = 0x00;  
  
  RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure); // Write values to registers
  
    // LED pins configuration
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOE, &GPIO_InitStructure);
  
  // Wake up pin configuration
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  // Random pin to see pin state
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
  EXTI_InitStructure.EXTI_Line = EXTI_Line0; // Line0
  EXTI_InitStructure.EXTI_Mode =  EXTI_Mode_Interrupt; // Interrupt mode
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; // Detect falling edge of the external signal connected to PA1
  EXTI_InitStructure.EXTI_LineCmd = ENABLE; // Enable EXTI line
  EXTI_Init(&EXTI_InitStructure); // Send parameters to the registers
  
    // EXTI17 line configuration
    EXTI_ClearITPendingBit(EXTI_Line17);
    EXTI_InitStructure.EXTI_Line = EXTI_Line17;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
    
    // Enable the RTC Alarm Interrupt
    NVIC_InitStructure.NVIC_IRQChannel = RTC_Alarm_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
  
  // NVIC structure
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x03;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn ; // Select NVIC channel to be configured
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; // Set priority to the lowest
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00; // Set sub-priority to highiest
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // Enable IRQ channel
  NVIC_Init(&NVIC_InitStructure); // Send parameters to the registers
  
  //Timer3 settings
  TIM_TimeBaseInitStructure.TIM_Period = 10000; // 0.01ms*10000 = 0.1s. Means counter will count to 10000 exactly 0.1 second.
  TIM_TimeBaseInitStructure.TIM_Prescaler = 720-1; // Divide clock freq. 72Mhz from 720. so it gives 0.01ms ticks.
  TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; // count from 0 to ARR
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure );
  


  TIM_Cmd(TIM3, ENABLE);  // Enable counter
  TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // Enable Timer3 interrupts
  PWR_WakeUpPinCmd(PWR_WakeUpPin_1, ENABLE); // Wake up pin 1 (PA. 0)
  GPIOE->BRR = GPIO_Pin_8;
  GPIOE->BSRR = GPIO_Pin_9;
  clock2 = RCC_GetSYSCLKSource(); // Get clock source (used to observe system)
  RCC_GetClocksFreq(&RCC_ClockFreq); // Get clock frequency (used to observe system)
  
  while(1)
  {
    if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0x00)
    {
     
       GPIOE->ODR ^= GPIO_Pin_9;
      PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
      
      while(1)
      {
             // This piece of code is taken from ST examples
    // Get current time
    RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
    
    /* Set the alarm to current time + 5s */
    RTC_AlarmStructure.RTC_AlarmTime.RTC_H12     = RTC_H12_AM;
    RTC_AlarmStructure.RTC_AlarmTime.RTC_Hours   = RTC_TimeStructure.RTC_Hours;
    RTC_AlarmStructure.RTC_AlarmTime.RTC_Minutes = RTC_TimeStructure.RTC_Minutes;
    RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = RTC_TimeStructure.RTC_Seconds + 10;
    RTC_AlarmStructure.RTC_AlarmDateWeekDay = 0x31;
    RTC_AlarmStructure.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
    RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay | RTC_AlarmMask_Minutes | RTC_AlarmMask_Hours;
    RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);
    
    // Enable the RTC Alarm A interrupt
    RTC_ITConfig(RTC_IT_ALRA, ENABLE);
    
    // Enable the alarm
    RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
    
    // Clear the Alarm A Pending Bit
    RTC_ClearITPendingBit(RTC_IT_ALRA);  
    
   // PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
    
    // GPIOE->ODR ^= GPIO_Pin_10;
   //  nop(500000);
     
       /* Disable the RTC Alarm interrupt */
    RTC_ITConfig(RTC_IT_ALRA, DISABLE);
    RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
    
    RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_CFGR_PLLMULL16); // Configure pll clock
    
    /* Enable PLL */
    RCC_PLLCmd(ENABLE);
    
    /* Wait till PLL is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);


    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); 
    
    /* Wait till PLL is used as system clock source */
    while (RCC_GetSYSCLKSource() != RCC_CFGR_SWS_PLL);
      }
    } 
}
}

Outcomes