Plan d'expérience pour STM32L476
Objectif
Le programme donnera accés à 16 expériences de mesure de consommation, résumées dans le tableau ci-dessous :
expe | MSI | PLL | Voltage Scaling | Flash Latency | Calibration MSI vs LSE | Sleep (100Hz) | Blue Mode |
1 | 4 Mhz(def.) | 80 MHz | 1 (def.) | 4 | off | off->on | Sleep (100Hz) |
2 | 24 Mhz | off | 1 (def.) | 1 | off->on | off | Calibration MSI/LSE |
3 | 24 Mhz | off | 2 | 3 | off | off->on | Sleep (100Hz) |
4 | 24 Mhz | off | 2 | 3 | off->on | off | Calibration MSI/LSE |
5 | 24 Mhz | off | 2 | 3 | on | on | STOP0, wakeup 7s |
6 | 24 Mhz | off | 2 | 3 | on | on | STOP1, wakeup 7s |
7 | 24 Mhz | off | 2 | 3 | on | on | STOP2, wakeup 7s |
8 | 24 Mhz | off | 2 | 3 | on | on | SHUTDOWN, wakeup 7s |
Séquencement des expériences
- le numéro d'expérience expe sera stocké dans un backup register du module RTC
le module RTC restera actif sur toutes les expériences
- expe sera incrémenté à chaque reset, si le bouton bleu (PC13) est pressé à cet instant (le bouton bleu devra, naturellement, être relaché après le bouton reset)
il bouclera sur 1 après 8
- la LED verte (PA5) clignotera à 0.5 Hz avec une durée active égale à (expe * 50ms)
- le bouton bleu (PC13) produira un changement de mode (irréversible jusqu'au prochain reset), mémorisé dans la variable blue_mode. Il conviendra de différencier
l'appui sur le bouton bleu associé au reset (changement d'expérience) et associé au passage en blue_mode. Pour sortir du blue_mode, un simple
appui sur le bouton reset (uniquement) suffira
- pour mesurer la dérive de l'oscillateur, le port GPIO PC10 produira un signal carré à 50Hz
Déroulement des opérations
Au reset (entrée dans la fonction main()), le programme devra :
- initialiser le module RTC (en distinguant le démarrage à froid d'un
redémarrage consécutif à un reset (manuel ou causé par le wake-up timer)
- lire expe dans le backup register 0, l'incrémenter s'il y a lieu et l'écrire à nouveau
- configurer l'horloge système en fonction de expe,
y compris le voltage scaling et la latence de la mémoire flash
- activer la calibration de MSI vs LSE le cas échéant
- configurer le timer systick en fonction de la variable SystemCoreClock. Le handler de l'interruption systick gèrera :
- le clignotement de la LED
- la détection des actions sur le bouton bleu (détecter la transition repos->pressé)
- l'action sur le GPIO PC10 (sortie 50Hz)
- entrer dans la boucle principale, qui agira en fonction de la variable blue_mode
Initialisation RTC
Pour plus d'informations sur le RTC, voir le
chapitre 38 du
Reference Manual
et le chapitre 101 de la
description des drivers HAL/LL.
Au démarrage "à froid", le programme devra effectuer une initialisation complète du module RTC, incluant principalement :
- le démarrage de l'oscillateur LSE (Low Speed External = quartz 32768 Hz), alimenté par le backup-domain
- le reset du backup-domain (ce qui va notamment mettre à zéro les backup-registers). Cette opération est indispensable pour activer l'oscillateur LSE.
- la config des 2 prescalers du RTC (AsynchPrescaler et SynchPrescaler). Attention, les registres de configuration du RTC sont protégés en écriture ! Il est donc nécessaire
de désactiver cette protection avant de pouvoir entrer en mode initialisation. Il faudra sortir du mode initialisation et remettre la protection en écriture à l'issue
de la confiuration du RTC.
Aux démarrages ultérieurs, "à chaud", le RTC est supposée déjà fonctionner, mais l'interface RTC-MPU n'est pas actif,
il faut l'initialiser avant de tenter l'accés aux backup-registers :
LL_APB1_GRP1_EnableClock( LL_APB1_GRP1_PERIPH_PWR );
LL_PWR_EnableBkUpAccess();
L'identification du démarrage à froid peut se faire en testant l'activité du LSE.
N.B. L'initialisation du wake-up timer n'est pas souhaitable à cette étape.
Horloge Système
Une grande partie des opérations liées aux horloges, oscillateurs et PLL du microcontrôleur est liée au bloc Reset and Clock Control (RCC). Pour plus d'informations, voir le
chapitre 6 du
Reference Manual
et le chapitre 99 de la
description des drivers HAL/LL.
Au reset, l'horloge est le MSI (Multi-Speed Internal Oscillator) à 4MHz par défaut.
Dans les démos ST, ainsi que le projet de départ "L476_ats_blink",
la PLL principale est activée avec une multiplication de 40 et
une post-division par 2 pour arriver à 80 MHz.
Pour fonctionner en MSI 24 MHz il faut :
- ne pas activer ni sélectionner comme source système la PLL
- changer la fréquence du MSI, en changeant de "Range"
N.B. le changement de range se fait en 2 étapes :
- changer le code de 4 bits dans MSISRANGE[3:0] (registre RCC->CR)
- mettre a 1 le bit MSIRGSEL dans le même registre
Si le nouveau scaling nécessite d'augmenter la latence d'accés à la mémoire flash,
cette augmentation doit être effectuée
avant la réduction de voltage.
Voltage Scaling
Le régulateur qui alimente le coeur du STM32L476 supporte deux "scalings" de la tension d'alimentation interne :
- range 1 "high performance" : 1.2 V, max 80 MHz (défaut)
- range 2 "Low power" : 1.0 V, max 26 MHz
Ceci est contrôlé par le registre PWR->CR1 du module PWR.
Si le nouveau scaling nécessite d'augmenter la latence d'accés à la mémoire flash, cette augmentation doit être effectuée
avant la réduction de la tension interne.
La latence flash se configure dans le registre FLASH->ACR (stm32l4xx_ll_system.h -> fonction LL_FLASH_SetLatency).
Calibration du MSI vs LPE
Le mécanisme dit "calibration" utilise une sorte de PLL asservie à l'oscillateur LSE,
totalement indépendante de la PLL principale.
Si le LSE est déjà actif (ce qui est le cas dans toute cette série d'expériences), il suffit
de mettre a 1 le bit MSIPLLEN dans le registre RCC->CR.
Wake-Up Timer
La mise en oeuvre du wake-up timer n'est pas nécessaire pour les mesures de consommation,
mais il est important de vérifier qu'on a une solution pour redémarrer le processeur après
passage en STOPx, STANDBY ou SHUTDOWN.
Le délai d'action du timer se configure en secondes (à condition que son horloge soit à 1Hz comme la RTC).
Le traitement de l'évènement wakeup est différent selon qu'on considère les modes STOPx ou les modes STANDBY et SHUTDOWN
(voir commentaires de l'exemple de code ci-dessous).
// partie commune a toutes les utilisations du wakeup timer
static void RTC_wakeup_init( int delay )
{
LL_RTC_DisableWriteProtection( RTC );
LL_RTC_WAKEUP_Disable( RTC );
while ( !LL_RTC_IsActiveFlag_WUTW( RTC ) )
{ }
// connecter le timer a l'horloge 1Hz de la RTC
LL_RTC_WAKEUP_SetClock( RTC, LL_RTC_WAKEUPCLOCK_CKSPRE );
// fixer la duree de temporisation
LL_RTC_WAKEUP_SetAutoReload( RTC, delay ); // 16 bits
LL_RTC_ClearFlag_WUT(RTC);
LL_RTC_EnableIT_WUT(RTC);
LL_RTC_WAKEUP_Enable(RTC);
LL_RTC_EnableWriteProtection(RTC);
}
// Dans le cas des modes STANDBY et SHUTDOWN, le MPU sera reveille par reset
// causé par 1 wakeup line (interne ou externe) (le NVIC n'est plus alimenté)
void RTC_wakeup_init_from_standby_or_shutdown( int delay )
{
RTC_wakeup_init( delay );
// enable the Internal Wake-up line
LL_PWR_EnableInternWU(); // ceci ne concerne que Standby et Shutdown, pas STOPx
}
// Dans le cas des modes STOPx, le MPU sera reveille par interruption
// le module EXTI et une partie du NVIC sont encore alimentes
// le contenu de la RAM et des registres étant préservé, le MPU
// reprend l'execution après l'instruction WFI
void RTC_wakeup_init_from_stop( int delay )
{
RTC_wakeup_init( delay );
// valider l'interrupt par la ligne 20 du module EXTI, qui est réservée au wakeup timer
LL_EXTI_EnableIT_0_31( LL_EXTI_LINE_20 );
LL_EXTI_EnableRisingTrig_0_31( LL_EXTI_LINE_20 );
// valider l'interrupt chez NVIC
NVIC_SetPriority( RTC_WKUP_IRQn, 1 );
NVIC_EnableIRQ( RTC_WKUP_IRQn );
}
// wakeup timer interrupt Handler (inutile mais doit etre defini)
void RTC_WKUP_IRQHandler()
{
LL_EXTI_ClearFlag_0_31( LL_EXTI_LINE_20 );
}