Modo de suspensión STM32: la interrupción se ejecuta pero la CPU permanece en WFI

4

Soy bastante nuevo en la arquitectura ARM y estoy trabajando con una placa que contiene un microcontrolador STM32F0 y un módem RF, que envía una interrupción cada vez que recibe un mensaje. Estoy tratando de implementar un modo de suspensión en un microcontrolador para ahorrar energía, pero no entiendo muy bien por qué se comporta como lo hace.

Comencé con un programa simple que pone la CPU en modo de suspensión al comienzo de la ejecución. Luego espera la interrupción externa para activarlo, ejecutar la interrupción y continuar con el programa principal. En el ISR, alterno un LED en el pin PA0 cada vez que se llama a la rutina, pero luego se usa el pin PA1 en el main () que enciende y apaga el LED con un breve retraso, lo que indica que el microcontrolador salió del modo de suspensión.

Mi código básicamente tiene este aspecto:

int main()
{
    periph_init();
    modem_init();

    HAL_PWR_EnterSLEEPMode(0,1);

    while(1)
    {
        HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
        Delay();
    }
}

Y el ISR para el EXTI

void EXTI0_1_IRQHandler(void)
{
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_0);

    // Some other stuff

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
}

El Manual de referencia de arquitectura ARMv6 establece lo siguiente con respecto a la espera de interrupción en la página B1-243:

  

Cuando un procesador emite una instrucción WFI, puede suspender la ejecución e ingresar a un estado de bajo consumo. Puede permanecer   en ese estado hasta que el procesador detecte uno de los siguientes eventos de activación de WFI:

     
  • Un reinicio.

  •   
  • Una excepción asíncrona en una prioridad que, si PRIMASK.PM se configuró en 0, se adelantaría a cualquier excepción actualmente activa.

  •   
  • Si la depuración está habilitada, un evento de depuración.

  •   
  • Un evento de activación WFI DEFINIDO POR IMPLEMENTACIÓN.

  •   

Si mi entendimiento es correcto, la segunda línea se aplica en este caso. Lo que significa que llamar a cualquier interrupción, independientemente de su prioridad, activaría el procesador, ya que se llamó a la WFI desde la red principal. Para obtener información, todas las prioridades de interrupción implementadas se establecen en 0, excepto la EXTI, que se establece en -1.

Ahora esto es lo que realmente sucede. El LED en PA0 alterna apropiadamente, indicando que el ISR efectivamente se ejecuta. Pero el LED en PA1 permanece apagado, lo que significa que al completar el ISR, la CPU permanece en una WFI. Esto se confirma incluso durante la depuración, mientras insertaba un punto de interrupción en la rutina de servicio de interrupción. Después de dejar que el código se ejecute, se detiene con éxito en el punto de interrupción. Si luego continúo la depuración con una función paso a paso, el programa salta a la instrucción WFI (sobre la cual continúa al principal, ya que la depuración puede provocar la finalización de la WFI).

Mi pregunta es, ¿por qué la CPU regresa a la WFI cuando se llama claramente a la interrupción? Según tengo entendido, si la CPU está en WFI, debería continuar con su funcionamiento allí donde se detuvo tan pronto como se llame a cualquier interrupción.

    
pregunta aljaz41

1 respuesta

5

Compruebe si el bit SLEEPONEXIT en SCB->SCR está establecido. Establecer eso en 1 causaría exactamente lo que has descrito:

  

Bit 1 SLEEPONEXIT

     

Configura el modo de espera al salir cuando regresa de Handler   modo a modo hilo. Poner este bit a 1 habilita una activación por interrupción   aplicación para evitar volver a una aplicación principal vacía.

     

0: no   dormir al volver al modo Hilo.

     

1: Ingresa el sueño, o el sueño profundo, en   volver de una rutina de servicio de interrupción.

    
respondido por el berendi

Lea otras preguntas en las etiquetas