Considérations de programmation
Les registres avancent masqués Chaque famille de périphérique est définie par une structure Exemple pour les ports E/S contenant les différents registres qui le composent Après instanciation sur une adresse particulière (fournie par STmicro) On accède aux registres qui nous intéressent avec -> typedef struct { vu32 CRL; vu32 CRH; vu32 IDR; vu32 ODR; vu32 BSRR; vu32 BRR; vu32 LCKR; } GPIO_TypeDef; #ifdef _GPIOB #define GPIOB ((GPIO_TypeDef *) GPIOB_BASE) #endif GPIOB->ODR = 0x45A2;
Pourquoi as-tu le masque ? Programmer un périphérique = modification D’un registre entier (rarement le cas) Pas de pb par exemple GPIOB->ODR = 0x45A2; Un bit d’un registre (mise en marche par exemple) Cortex a la possibilité de bit-banding envisageable par une instruction De plusieurs bits ou d’un champ de bits d’un registre Obligation d’appliquer un masque si on ne veut pas modifier le reste du registre .
Exemple de mise à 1 On applique 1 avec l’opérateur OU Ex : mise à 1 des bits de poids 2 et 5 de l’octet Bobo :
Exemple de mise à 0 On applique 0 avec l’opérateur ET Ex : mise à 0 des bits de poids 0 et 3 de l’octet Bibi :
Extension A partir des deux principe de base précédents : Possibilité de l’étendre à des champs de bits Possibilité de contrôler les valeurs maximales applicables à un champ de bits Ce principe permet d’avoir une programmation Sûre Lisible (au final) Générique Voir la documentation rédigée à ce sujet
De la notion d’interruption Un périphérique fait des demandes d’interruption (conversion ADC terminée, débordement de timer, …) Une interruption acceptée = détournement via la table des vecteurs d’interruption (IVT) Soit on gère en assembleur cette table Soit on utilise le compilateur qui connait et impose le nom des routines d’exception va remplir la IVT si on utilise ce nom pour une procédure. Le fichier (assembleur) STM32F10X.s contient les noms prédéfinis Voir la documentation rédigée à ce sujet
Exemple Waouh ! SysTick_Handler (! Majuscule!) /*------------------------------------------------------------------------------ Systick Interrupt Handler SysTick interrupt happens every 10 ms *------------------------------------------------------------------------------*/ void SysTick_Handler (void) { static unsigned long ticks; static unsigned long timetick; static unsigned char leds = 0x01; if (ticks++ >= 99) { // Set Clock1s to 1 every 1 second ticks = 0; Clock1s = 1; } // Blink the LEDs depending on ADC_ConvertedValue if (timetick++ >= (ADC_ConvertedValue>>8)) { timetick = 0; leds <<= 1; if (leds == 0) leds = 0x01; GPIOB->ODR = (GPIOB->ODR & 0xFFFF00FF) | (leds << 8); } // end SysTick_Handler SysTick_Handler (! Majuscule!) Procédure d’interruption pour le timer Systick Sur demande d’IT de ce timer cette routine est exécutée Cette routine est (évidement) void/void Waouh !
Structuration de programme Assez rapidement on vous imposera la structuration suivante pour vos applications : Qualité logicielle Généricité Sûreté
A vous de jouer…