AnsweredAssumed Answered

STM32L152C6 Enter STOP Mode

Question asked by mihaylov.kaloyan on Dec 28, 2016
Latest reply on Jan 2, 2017 by mihaylov.kaloyan

Good day!

 

I can't make STM32L152 enter stop mode. It enters standby mode w/o any problems. Using the debugger I can see that PWR_CSR->WUF is set w/o any reason for that.

 

Please note that the MCU enters Standby mode even if the WUF bit is high and I get low current consumption (around 10uA).

 

Even if I have disabled the external wake up lines and I clear the WUF flag a moment before entering Stop mode the MCU doesn't respond to the command. It only waits for the specified time (wakeup counter) and then the program continues as expected.

 

Also note that I put the USART only to detach the debugger (otherwise I can't get the real current consumption). So there is no difference with Dummy_USART_Init() and w/o it.

 

Please help! I will buy a beer!

void main() {
PWR_RTCAccessCmd(ENABLE);
RTC_ClearFlag(RTC_FLAG_WUTF);
PWR_RTCAccessCmd(DISABLE);
    sysinit();
    RTC_Config();
    PWR_VoltageScalingConfig( PWR_VoltageScaling_Range3 );
    Dummy_USART_Init();
    printf("start\r\n");


    while(0) {
        setRtcWakeUp( 0x04 );
        PWR_EnterSTANDBYMode();
    }

    while(1) {
        printf("woke up\r\n");
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
        NVIC_Init(&NVIC_InitStructure);

        PWR_WakeUpPinCmd( PWR_WakeUpPin_1, DISABLE );
        PWR_WakeUpPinCmd( PWR_WakeUpPin_2, DISABLE );
        PWR_WakeUpPinCmd( PWR_WakeUpPin_3, DISABLE );

        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //PA0,3
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_400KHz;
        GPIO_Init( GPIOA, &GPIO_InitStructure );
        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //PA0,3
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
        GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_400KHz;
        GPIO_Init( GPIOC, &GPIO_InitStructure );

        setRtcWakeUp( 0x04 );

        PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
    }
    while(1);

 

 

Dummy_USART_Init()

void Dummy_USART_Init() {

    // set GPIO - speeds, AF, enable APB, AHB, whatever needed..

    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA, ENABLE );

    GPIO_InitTypeDef GPIO_InitStructure;
    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //push-pull output
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_400KHz; //400kHz, 2,10,40 MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    //GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //push-pull output
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_400KHz; //400kHz, 2,10,40 MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    GPIO_PinAFConfig( GPIOA, GPIO_PinSource9, GPIO_AF_USART1 );
    GPIO_PinAFConfig( GPIOA, GPIO_PinSource10, GPIO_AF_USART1 );
    
    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_GPIOA, ENABLE );
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE );

    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    
    USART_DeInit( USART1 );
    USART_Init( USART1, &USART_InitStructure );
    USART_Cmd( USART1, ENABLE );
}

sysinit()

void sysinit() {
    //RCC_SYSCLKConfig( RCC_SYSCLKSource_MSI ); // MSI, HSI, HSE or PLL
    RCC_HCLKConfig( RCC_SYSCLK_Div1 ); //  AHB clock = SYSCLK

    /* For APB1 and APB2 (PCLK2 related to APB2) see Table 18
    from the STM32F100 datasheet (Peripheral current consumption) */
    RCC_PCLK1Config( RCC_HCLK_Div1 );
    RCC_PCLK2Config( RCC_HCLK_Div1 ); //RCC_HCLK_Div1: APB2 clock = HCLK (from AHB clock)

    //RCC_PLLConfig( RCC_PLLSource_HSI_Div2, RCC_PLLMul_6 );
    //RCC_PLLCmd( ENABLE );
    //RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); //use PLL as the SYSCLK clock source

    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK); //MISC in the help file...
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    SysTick_Config(SystemCoreClock / 1000); //ticks - number of ticks btw. 2 interrupts
}

 

RTC_Config()

void RTC_Config(void)
{
  RTC_InitTypeDef RTC_InitStructure;

  /* Enable the PWR clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

  /* Allow access to RTC */
  PWR_RTCAccessCmd(ENABLE);

/* LSI used as RTC source clock */
/* The RTC Clock may varies due to LSI frequency dispersion. */   
  /* Enable the LSI OSC */
  RCC_LSICmd(ENABLE);
  //RCC_LSEConfig(RCC_LSE_ON);
 
  /* Wait till LSI is ready */  
  while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
  {
  }

  /* Select the RTC Clock Source */
  RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
   
  /* Enable the RTC Clock */
  RCC_RTCCLKCmd(ENABLE);

  /* Wait for RTC APB registers synchronisation */
  RTC_WaitForSynchro();

  /* Calendar Configuration */
  RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
  RTC_InitStructure.RTC_SynchPrediv    =  0x120; /* (37KHz / 128) - 1 = 0x120*/
  RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
  RTC_Init(&RTC_InitStructure);
}

 

setRtcWakeUp()

void setRtcWakeUp( uint16_t seconds ) {
  NVIC_InitTypeDef NVIC_InitStructure;
  EXTI_InitTypeDef EXTI_InitStructure;
  /*
  To enable the RTC Wakeup interrupt, the following sequence is required:
  1. Configure and enable the EXTI Line 20 in interrupt mode and select the rising edge
  sensitivity.
  2. Configure and enable the RTC_WKUP IRQ channel in the NVIC.
  3. Configure the RTC to generate the RTC wakeup timer event.
 
  System reset, as well as low power modes (Sleep, Stop and Standby) have no influence on
  the wakeup timer.
  */
  /* EXTI configuration *******************************************************/
  EXTI_ClearITPendingBit(EXTI_Line20);
  EXTI_InitStructure.EXTI_Line = EXTI_Line20;
  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 Wakeup Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
 
  NVIC_InitStructure.NVIC_IRQChannel = SysTick_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
  NVIC_Init(&NVIC_InitStructure);
 
  RTC_WakeUpCmd(DISABLE); //to set WakeUpCounter
  PWR_RTCAccessCmd(ENABLE);
  /* 3.1.3 from AN3371 using hardware RTC
  RTC->CR
  WUCKSEL -> (only when RTC->CR WUTE = 0; RTC->ISR WUTWF = 1)
  000: RTC/16 clock is selected
  001: RTC/8 clock is selected
  010: RTC/4 clock is selected
  011: RTC/2 clock is selected
  10x: ck_spre (usually 1 Hz) clock is selected
  11x: ck_spre (usually 1 Hz) clock is selected and 216 is added to the WUT counter value
  from 1s to 18 hours when WUCKSEL [2:1] = 10
  WUTE - Enable Control Bit
  WUTIE - Interrupt enable bit
  RTC->ISR
  WUTF - efent flag
  */
  RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
  RTC_SetWakeUpCounter( seconds );
  PWR_ClearFlag( PWR_FLAG_WU );
  //The WUTF flag must then be cleared by software.
  RTC_ClearITPendingBit(RTC_IT_WUT); //ClearITPendingBit clears also the flag
  RTC_ClearFlag(RTC_FLAG_WUTF); //MANDATORY!
  RTC_ITConfig(RTC_IT_WUT, ENABLE); //enable interrupt
  RTC_WakeUpCmd(ENABLE);
  PWR_RTCAccessCmd(DISABLE);
}

Outcomes