Plan d'expérience pour STM32L476
Cahier des charges du programme de démonstration
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 MCU | Etat transceiver hors TX |
1 | 4 Mhz(def.) | 80 MHz | 1 (def.) | 4 | off | off->on | Sleep (100Hz) | Stand-by I |
2 | 24 Mhz | off | 1 (def.) | 1 | off->on | off | Calibration MSI/LSE | Stand-by I |
3 | 24 Mhz | off | 2 | 3 | off | off->on | Sleep (100Hz) | Stand-by I |
4 | 24 Mhz | off | 2 | 3 | off->on | off | Calibration MSI/LSE | Stand-by I |
5 | 24 Mhz | off | 2 | 3 | on | on | STOP0, wakeup 7s | Power-down |
6 | 24 Mhz | off | 2 | 3 | on | on | STOP1, wakeup 7s | Power-down |
7 | 24 Mhz | off | 2 | 3 | on | on | STOP2, wakeup 7s | Power-down |
8 | 24 Mhz | off | 2 | 3 | on | on | SHUTDOWN, wakeup 7s | Power-down |
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
- le microcontrôleur et le transceiver forment le noeud d'un réseau en étoile 6:1, fonctionnant uniquement en mode transmission.
- le transceiver RF émettra un paquet toutes les 2 secondes, au moment de l'allumage de la LED. Il attendra un paquet d'acknowledgment d'un récepteur. En cas de non-réception de ce paquet,
il retransmettra 10 fois ce paquet, avec un délai entre deux retransmissions de 500 µs.
Configuration du transceiver RF
- le transceiver émettra sur le canal RF centré sur 2460 MHz (canal n°60)
- sa puissance d'émission sera limitée à -18 dBm
- le débit de transmission sera de 250 kbps
- les adresses des data pipes seront codées sur 5 octets. Six data pipes, différenciés par un canal logique unique, peuvent coexister sur un canal radio. On conservera les adresses par défaut.
- Les paquets transmis contiendront un message utile (payload) d'une taille égale à 32 octets. Le payload sera constitué de caractère ASCII et aura le format suivant :
- il commencera par les noms du binome
- il sera suivi du commentaire "_EXPN_", où N indiquera le numéro de l'expérience
- il se terminera par le compteur de paquets (codé sur un octet), qui s'incrémentera toutes les 2 secondes.
- si le payload a une taille inférieure à 32 octets, vous pourrrez le compléter par des espaces.
Vous pouvez vous reporter à la
description du transceiver RF pour plus d'informations concernant sa configuration.
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
- lire le compteur de paquet dans le backup register 1
- 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
- initialiser le transceiver RF
- 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 );
}