cancel
Showing results for 
Search instead for 
Did you mean: 

How to exit Stop 2 mode

vik_modam
Associate II

I have implemented a fully working usart keyboard with interrupts in a Nucleo L412Kb. The main code loop checks whether a pending-key flag and no-bouncing flag are set, then scans the rows in the selected keyboard matrix column, and sends the key via usart.

The ISR for the GPIOs (columns) sets the pending flag, selects the column to scan, and starts a debouncing timer TIM2. The ISR for the timer TIM2 interrup is setting the no-bouncing flag.

void TIM2_IRQHandler(void) {
  if (TIM2->SR & (1<<0)) {
    TIM2->SR &= ~(1<<0); // clear flag
    bouncing = 0;
    TIM2->CR1 &= ~(1<<0); // Disable timer
}
}

 void col_IRQ(uint8_t col) {
if (pendingkey == 0) {
pendingkey = 1;
bouncing = 1;
coln = col;
set_triggers(0);
TIM2->CNT = 0;
TIM2->CR1 |= (1<<0); // Enable timer
set_all_rows(0);
}
}

void EXTI0_IRQHandler(void) {
if (EXTI->PR1 & (1 << 0)) {
EXTI->PR1 |= (1 << 0);
col_IRQ(0);
}
}

Now I want the MCU to go into STOP2 mode and wake up with the EXTI interrupts, but my main code get blocked.

Im using ony GPIOs, a timer (TIM2), the systicks, and one USART. In the stopkbd() function I disable the clocks for the peripherals, call the __WFI() function and restore the clocks. What Im missing?

Im running with the HSI16 oscillator only, and I have the STOPWUCK bit set in order to wake up with the HSI16.

Do I need to clear the SLEEPDEEP bit after? Or do I need to wait for the HSI16 or something else?

From the RM manual, I can not get to understand how the GPIOs EXTI interrupts can work if the clocks are stopped or the peripherals are disabled. Do I need to perhaps enable at least one clock in order for the interrupts to trigger? I see in the manual that the LSI can be enabled in STOP2.

 

4 REPLIES 4
MM..1
Chief II

I dont see NVIC init part code. Without this interrupts dont works.

Interrupts work (for the IO). NVIC init part code is called with the function col_trigger_init(). The code attached is fully working for me, except for the line stopkbd(), responsible of starting the STOP2 mode, and coming back from it. Otherwise, commenting the stopkbd() line the program is ok. The question is What I am missing/needing to come back from STOP2 mode...

Is your trouble enter STOP2 or exit ? Try inspire

 

void HAL_PWREx_EnterSTOP2Mode(uint8_t STOPEntry)
{
  /* Check the parameter */
  assert_param(IS_PWR_STOP_ENTRY(STOPEntry));

  /* Set Stop mode 2 */
  MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_CR1_LPMS_STOP2);

  /* Set SLEEPDEEP bit of Cortex System Control Register */
  SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));

  /* Select Stop mode entry --------------------------------------------------*/
  if(STOPEntry == PWR_STOPENTRY_WFI)
  {
    /* Request Wait For Interrupt */
    __WFI();
  }
  else
  {
    /* Request Wait For Event */
    __SEV();
    __WFE();
    __WFE();
  }

  /* Reset SLEEPDEEP bit of Cortex System Control Register */
  CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
}

and manage HSI or any clock before enter isnt required, is managed by design.

 

vik_modam
Associate II

Unfortunately I haven't run any debugger or so...But the MCU stall right after executing the stokbd() function. My guess is my trouble is to come back from the STOP2 mode.

static inline void stopkbd(void) {
  RCC->APB1ENR1 &= ~RCC_APB1ENR1_USART2EN; // disable USART2
  SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; // disable SysTicks
  RCC->APB1ENR1 &= ~(1UL<<0); // Disable clock for TIM2
  RCC->AHB2ENR = 0; // disable all GPIO clock
  RCC->CR &= ~RCC_CR_HSION;
  __WFI();
  clock_init();
  RCC->APB1ENR1 |= (1<<0); // Enable clock for TIM2
  RCC->AHB2ENR |= 3; // enable GPIO clocks for bit 0 and 1 (A and B banks)
  SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
  RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN; // re-enable USART2
}

static inline void stop2_init(void) {
  PWR->CR1 &= ~PWR_CR1_LPMS_STOP2_Msk;
  PWR->CR1 |= PWR_CR1_LPMS_STOP2;
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; // set Cortex SLEEPDEEP bit
  SCB->SCR &= ~SCB_SCR_SLEEPONEXIT_Msk; // disable re-entering in sleep mode after ISR
  RCC->CFGR |= RCC_CFGR_STOPWUCK; // select the HSI16 clock for wakeup
}

The stop2_init() function is executed before the main loop. So far, everything looks like the same as the HAL function you propose  HAL_PWREx_EnterSTOP2Mode(). 

I set the stop2 mode in the PWR_CR1 register, I set the SLEEPDEEP bit in the cortex SCB_SCR register, and then call __WFI.

After returning from WFI, I set back the clocks, enable GPIOs, USART, and Systicks...