STOP mode su STM32U5: trattare la corrente di wakeup come un'interfaccia firmware
Il lavoro low-power su STM32U5 non finisce quando il codice entra in STOP mode. In un prodotto, la parte difficile è rendere il percorso di wakeup ripetibile, misurabile e di proprietà del firmware, non una somma di checkbox CubeMX e assunzioni hardware.
Perché i bug di STOP mode arrivano tardi nei test
Gli STM32U5 sono pensati per progetti a bassissimo consumo, ma la corrente reale del prodotto è comunque la somma di stato firmware, configurazione GPIO, circuiti esterni, ripristino dei clock e comportamento RTOS dopo il wakeup. Una scheda può essere perfetta in un esempio ST e mancare il budget batteria di un ordine di grandezza quando entrano in gioco sensori, pull-up, level shifter, LED, header di debug e task periodici.
Il problema più comune è la confusione di ownership. L'hardware si aspetta che il firmware lasci i pin in uno stato tranquillo. Il firmware assume che CubeMX abbia generato lo stato low-power corretto. L'applicazione tratta il wakeup come una semplice latenza di interrupt. Il risultato è un prodotto che supera i test funzionali ma fallisce durata batteria, standby current o test intermittenti di wakeup.
Rendere il low power un'interfaccia esplicita
Preferisco trattare il low power come una piccola interfaccia di piattaforma con tre responsabilità: preparare la scheda, entrare nella modalità scelta e ripristinare il contratto runtime dopo il wakeup. Questa interfaccia deve sapere quali pin possono svegliare l'MCU, quali periferiche vanno quiescenti, quali rail restano alimentati e quali clock devono essere ricostruiti.
Su STM32U5 le varianti STOP mantengono abbastanza stato per prodotti event-driven, ma i dettagli contano comunque. GPIO lasciati come input digitali possono creare leakage tramite reti esterne. Un clock periferico non ripristinato può generare un errore che sembra scollegato dal low power. SysTick e timekeeping RTOS possono falsare la schedulazione dopo un sonno lungo se il progetto non definisce cosa significa “tempo trascorso”.
Una forma minima per entrare in STOP
Il codice sotto è volutamente essenziale. Mostra la struttura che vorrei trovare in un codice cliente: un punto prepara i pin, un punto entra in STOP2 e un punto ripristina clock e ownership delle periferiche. Pin e periferiche reali devono seguire la scheda reale.
#include "stm32u5xx_hal.h"
static void app_prepare_gpio_for_stop(void)
{
GPIO_InitTypeDef gpio = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
gpio.Mode = GPIO_MODE_ANALOG;
gpio.Pull = GPIO_NOPULL;
gpio.Pin = GPIO_PIN_All;
HAL_GPIO_Init(GPIOA, &gpio);
HAL_GPIO_Init(GPIOB, &gpio);
HAL_GPIO_Init(GPIOC, &gpio);
/* Reconfigure only the real wakeup pins after the blanket analog pass. */
gpio.Pin = GPIO_PIN_13;
gpio.Mode = GPIO_MODE_IT_FALLING;
gpio.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOC, &gpio);
}
void app_enter_stop2_until_event(void)
{
app_prepare_gpio_for_stop();
HAL_SuspendTick();
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
HAL_ResumeTick();
SystemClock_Config(); /* Restore PLL/sysclk after STOP. */
MX_GPIO_Init(); /* Restore product pin ownership. */
MX_I2C1_Init(); /* Re-init peripherals whose clocks were gated. */
}
La configurazione analogica generale non è una regola da copiare alla cieca. È un modo per forzare la review. Ogni pin che non può restare tranquillo deve essere nominato di nuovo: ingresso di wakeup, chip-select mantenuto, enable di rail, linea di interrupt o eccezione per debug. È molto più facile da verificare rispetto a piccoli fix low-power sparsi nei driver.
Esempio pratico: nodo sensore a batteria con interrupt esterno
Immaginiamo un sensore industriale a batteria con STM32U5, accelerometro con interrupt esterno, sensore ambientale I2C e modulo radio. Il nodo dorme quasi sempre, si sveglia su movimento o evento RTC, acquisisce i dati, trasmette un pacchetto compatto e torna in STOP. L'implementazione ingenua entra in STOP quando l'ultimo task applicativo finisce. L'implementazione di prodotto ha invece un contratto di sleep della scheda.
Prima dello STOP, il driver radio deve aver completato o abortito i trasferimenti, il bus I2C non deve essere in una transazione pendente, le linee di interrupt dei sensori devono avere i pull corretti e i GPIO non usati per wakeup vanno portati nello stato a minore leakage. Dopo il wakeup, il firmware deve ricostruire il clock di sistema, ricreare i driver periferici dipendenti dai clock gated, leggere e pulire la causa di wakeup e pubblicare un contatore di salute. Se il wakeup arriva dall'accelerometro, la prima lettura I2C può richiedere un settling delay specifico del dispositivo. Se arriva da RTC, l'applicazione può saltare operazioni costose quando la batteria è bassa.
Misurare le transizioni, non solo lo stato stabile
I numeri di corrente del datasheet sono utili, ma molti problemi di prodotto vivono nelle transizioni. Un dispositivo può consumare microampere in STOP ma bruciare milliampere troppo a lungo dopo il wakeup perché il firmware aspetta un delay fisso, riavvia i clock in modo inefficiente o ritenta una periferica ancora spenta. Io registrerei causa di wakeup, tempo al primo campione, tempo alla radio pronta e numero di re-inizializzazioni fallite.
In laboratorio, conviene combinare un power analyzer o una sonda di corrente con marker firmware. Mettere GPIO marker intorno a “preparo sleep”, “entrato in STOP”, “wakeup”, “clock ripristinato” e “applicazione pronta” trasforma il debug low-power da supposizione a diagramma temporale discutibile da firmware e hardware insieme.
Checklist pratica
- Elenca ogni sorgente di wakeup e definisci se è level, edge, RTC, EXTI o periferica.
- Rivedi ogni GPIO contro lo schematico: analogico, output mantenuto, pull-up, pull-down, wake input o controllo di rail esterno.
- Disabilita o parcheggia le periferiche prima dello STOP; non lasciare transazioni I2C/SPI a metà in un task RTOS.
- Sospendi SysTick o definisci come viene gestito il tempo RTOS durante il sonno.
- Ripristina esplicitamente i clock di sistema dopo STOP e reinizializza le periferiche dipendenti.
- Misura latenza ed energia di wakeup, non solo la corrente statica in STOP.
- Esponi contatori per causa di wakeup, restore falliti, reset inattesi e tempo dall'ultimo ciclo sleep riuscito.
Come lo affronterei su un progetto cliente
Partirei dallo schematico, non dal file CubeMX. Per ogni net collegata all'MCU scriverei stato di sleep, owner, rischio di leakage e ruolo nel wakeup. Poi implementerei un singolo modulo board low-power e obbligherei l'applicazione a richiedere lo sleep solo tramite quel modulo. Al banco misurerei tre casi separati: baseline solo MCU, STOP a livello scheda con circuiti esterni popolati e cicli completi applicativi sleep/wakeup con timing realistico di radio e sensori.
Il deliverable non è “STOP2 abilitato”. È un contratto di sleep ripetibile: il prodotto sa spiegare perché si è svegliato, recupera clock e periferiche, e dimostra che corrente di standby ed energia di wakeup restano nel budget attraverso le release firmware.
Commenti
Hai un caso concreto STM32U5 low-power o un bug di wakeup visto sul campo? Mandami una nota breve via email.