¿Qué está causando este pico de energía en el modo de bajo consumo de STM32?

Estoy usando un STM32L073RZ en una placa desnuda con solo la CPU y las tapas de desacoplamiento. Estoy alimentando la placa directamente desde un Otii Arc y midiendo el consumo de corriente. Estoy ejecutando MbedOS 5.11.2.

Cuando llamo a la sleep()función, la CPU entra en un modo de bajo consumo de energía, con un pico ocasional de 5 mA en el consumo de corriente aproximadamente cada segundo, vea la imagen a continuación:

Consumo actual

¿Cuál es la causa de esto? Estoy intentando colocar la CPU en modo STOP con un RTC en ejecución; esto debería generar, según la hoja de datos, una corriente de 1 µA.

Además de esto, ¿cómo puedo saber qué modo de bajo consumo sleep()ha elegido la función? Estoy tratando de mantenerme alejado de HAL porque he tenido muchos problemas para configurar interrupciones y cosas por el estilo.

Para completar, aquí está el código que se ejecuta en el tablero:

#include "mbed.h"

int main() {
    sleep();
}
Supongo que su mcu se está despertando una vez por segundo por alguna razón
Parece bastante plausible que el RTC esté generando una interrupción una vez por segundo. Coloque un punto de interrupción en el controlador de interrupciones RTC.
@Jeremy gracias por la sugerencia, no parece ser una interrupción RTC ya que el controlador no se activa si lo incluyo.
@Adam: incluso si la interrupción está enmascarada, si el RTC está activo, puede estar sacando elementos del modo de bajo consumo de todos modos.
@Jeremy, esa es una sugerencia justa. Creo que tendré que familiarizarme con HAL para poder estar absolutamente seguro de qué temporizadores se están ejecutando, en qué modo de energía está la CPU, etc. ¡Gracias!
Bueno... SysTick Interrumpir, supongo...

Respuestas (4)

No puedo hablar de mbed específicamente, pero la idea general es que sleep()hace que la ejecución del proceso actual se detenga durante una cantidad de segundos, o indefinidamente si no se proporciona ningún argumento (equivalente a un argumento de 0).

En un entorno multiproceso, eso significa que simplemente cede la CPU a otros procesos. Si no hay otros procesos listos para ejecutarse, el sistema operativo puede o no poner la CPU en un estado de bajo consumo de energía mientras espera interrupciones; depende de cómo idle()se escriba la tarea. Sin embargo, este generalmente no sería el estado de menor consumo de energía disponible en la CPU, ya que desea activarse rápidamente cuando se producen interrupciones.

En su caso, parece despertarse una vez por segundo para manejar el tic del temporizador del sistema.

Si realmente desea entrar en un estado de menor potencia, generalmente hay llamadas específicas de la plataforma para eso, y ese es exactamente el tipo de cosas para las que está HAL. No debes evitarlo, debes aprenderlo .


Después de una búsqueda rápida, descubrí que la documentación aquí: API: administración de energía analiza esto específicamente.

Gracias por tu respuesta, muy útil. En Mbed, sleep()se supone que debe colocar la CPU en un modo de bajo consumo, pero no puedo encontrar documentación que explique esta lógica. He deshabilitado SysTick IRQ en el NVIC sin éxito, supongo que seguiré apagando los temporizadores/contadores hasta que desaparezca.
@AdamMitchell: lo más probable es que lo que deba hacer sea leer el código Mbed (es de código abierto, incluso si vinculan una versión binaria de forma predeterminada) y averiguar qué están haciendo, luego decidir si eso se puede traer en alineación con sus objetivos, o si sus objetivos son demasiado diferentes.

Como se explica en la documentación , los siguientes controladores pueden evitar el sueño profundo:

  • Corazón
  • Se acabó el tiempo
  • Temporizador
  • SPI
  • I2C
  • PODER
  • SerialBase

Si necesita identificar qué está bloqueando el sueño profundo, puede compilar desde la línea de comando y habilitar la depuración detallada, aunque parezca que no tiene ninguno en su ejemplo.

También puede revisar la documentación tickless . Creo que este modo es relativamente nuevo, por lo que es posible que su plataforma tenga algunos problemas en el HAL.

Si habilita el modo sin señales (a través de MBED_TICKLESS=1) y simplemente pausa el hilo (a través wait_ms(10000)de ), no verá picos y la MCU permanecerá en modo de parada (al menos en mi placa STM32F4).

Así que me las arreglé para resolver esto; Las respuestas de Sean, Dave y Jan fueron extremadamente útiles y me orientaron en la dirección correcta (al igual que los comentarios).

Como se mencionó, estaba usando MbedOS 5.11.2. Esto contenía este problema por el cual la CPU estaba bloqueada en el modo de suspensión profunda y no deshabilitaba ningún temporizador/ticker, etc. La actualización a la versión 5.11.4 resolvió este problema y permitió que el dispositivo entrara en lo que supongo que era el modo STOP.

Entonces pude utilizar el HAL y pasar al modo STANDBY, el consumo de corriente final resultante de mi bucle inactivo fue de ~ 550 nA. Así es como estoy poniendo el dispositivo en modo de ESPERA:

#include "mbed.h"

int main()
{
    HAL_Init();

    __HAL_RCC_PWR_CLK_ENABLE();

    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOH_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.Pin = GPIO_PIN_All;
    GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStructure.Pull = GPIO_NOPULL;

    HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); 
    HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
    HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
    HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
    HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
    HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);

    /* 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_GPIOH_CLK_DISABLE();
    __HAL_RCC_GPIOE_CLK_DISABLE();

    /* Enable Ultra low power mode */
    HAL_PWREx_EnableUltraLowPower();

    __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
    HAL_PWR_EnterSTANDBYMode();
}
FYI, tengo una biblioteca para el modo de espera en STM32 con Mbed: github.com/janjongboom/stm32-standby-rtc-wakeup