Projet

Général

Profil

Wiki » Historique » Révision 158

Révision 157 (Patrice Nadeau, 2024-01-20 21:20) → Révision 158/170 (Patrice Nadeau, 2024-01-20 21:21)

# Règles de codage C 

 Le langage C, version [C99] (https://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf) utilisé avec le compilateur [GCC](https://gcc.gnu.org/). 
 > `gcc` n'est pas entièrement compatible avec le standard C99 (<https://gcc.gnu.org/c99status.html>). 

 --- 

 {{>toc}} 

 --- 

 [[Style]] 

 [[Commentaires Doxygen]] 

 [[Fichiers]] 


 --- 

 [[Objets et macros]] 

 [[Préprocesseur]] 


 ## Préprocesseur 
 Directives du préprocesseur gcc. 

 ### #include 

 Pour inclure d’autres fichier comme les fichiers entête. 

 ### #ifdef / ifndef 

 Surtout utilisé pour des options de compilation sur différentes plateforme. 
 Utiliser une forme évitant les répétitions. 

 > N’est pas documenté dans Doxygen. 

 Exemple : 
 ```c 
 const char BLUE = 
   #if ENABLED(FEATURE_ONE) 
     '1' 
   #else 
     '0' 
   #endif 
 ; 
 ``` 

 ### Diagnostiques 

 Les macros `#warning` et `#error` sont utilisées pour afficher des avertissements ou des erreurs lors de la compilation. 

 > Ne sont pas documentées dans Doxygen. 

 Exemple : 
 ``` c 
 #ifndef usart_AVR 
     #error "__FILE_NAME__ is not supported on this AVR !" 
 #endif 

 #ifndef __test__ 
     #warning "test is not defined !" 
 #endif 
 ``` 

 ### Définitions 

 Un `#define` est utilisé pour remplacer une valeur au moment de la compilation 
 > Pour la définition d'une valeur « integer », un `enum` DOIT être utilisé. 

 Exemple : 
 ``` c 
 /** 
 * @name Nom des registres 
 */ 
 /** @{ */  
 /** @brief USART1 */ 
 #define USART1 REG1 
 /** @brief USART2 */ 
 #define USART2 REG2 
 /** @} */ 

 USART1 = 0x0F; 
 ``` 

 ## Atmel AVR 

 Particularités pour les microcontrôleurs 8 bits AVR d’Atmel. 

 [Atmel AVR4027: Tips and Tricks to Optimize Your C Code for 8-bit AVR Microcontrollers](https://ww1.microchip.com/downloads/en/AppNotes/doc8453.pdf) 

 ### Fichier d’en-têtes 

 Vérification du modèle de microcontrôleur 
     > Via l'option `-m` de [gcc](https://github.com/embecosm/avr-gcc/blob/avr-gcc-mainline/gcc/config/avr/avr-mcus.def) 

 ```c 
 #ifndef defined (__AVR_ATmega48__) || (__AVR_ATmega48P__) || \ 
	 (__AVR_ATmega88P__) || defined (__AVR_ATmega88__) || \ 
	 (__AVR_ATmega168__) || defined (__AVR_ATmega168P__) || \ 
	 (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) 
 #warning "Cette librairie n'as pas été testée sur cette famille de microcontrôleur." 
 #endif 
 ``` 

 ### Macros 

 Définis dans le fichier `config.h` 

 Liste :  
 * `F_CPU` : La fréquence utilisée par l'horloge (interne ou externe) du microcontrôleur 

     > Les « fuses » doivent correspondent à la bonne source de l'horloge. 

 ### Types 

 De nouveau type d'entier sont fournis avec la librairie `<stdint.h>`. 

 L'utilisation de ces types DOIT être utilisé afin d'exprimer le nombre de bit d'un objet. 

 ### Progmem 

 <https://www.avrfreaks.net/s/topic/a5C3l000000U5SFEA0/t034767> 

 Pour mettre des variables en lecture seule dans la section FLASH au lieu de SRAM avec `<avr/pgmspace.h>`. 
 > L’accès à ces variables est faite via les macros de la librairie. 

 Le nom de la variable DOIT être suivie de **_P** 

 Exemple : 
 ```c 
 #include <avr/pgmspace.h> 
 ... 
 /** @brief Variable en FLASH */ 
 const int Variable1_P PROGMEM = 42; 
 ``` 

 ### Fonction main 
 Un microcontrôleur AVR ne termine jamais la fonction `main`. 

 * Déclarer la fonction main avec l’attribut `noreturn` 
 * La boucle sans fin la plus optimisé est le `for (;;)` 

 Justification : [AVR035](https://ww1.microchip.com/downloads/en/AppNotes/doc1497.pdf) 

 Exemple : 
 ```c 
 #include <avr/io.h> 

 /**  
  * @brief Never ending loop 
 */ 
 void main(void) __attribute__((noreturn)); 

 /* main function definition */ 
 void main(void) { 
     ... 
     /* never return */ 
     for (;;) { 
     }; 
 }; 
 ``` 

 ### Opérations « atomiques » 
 Opérations ne devant pas être interrompus (Ex. : charger un registre de 16 bits avec un registre de 8 bits). 

 La librairie `avr-libc` (util/atomic.h) fournit des macros permettant la gestion entre autre des interruptions. 

 Les instructions critiques sont insérées dans un `ATOMIC_BLOCK`. 

 Exemple : 
 ```c 
 #include <util/atomic.h> 
 ... 
 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { 
     ... 
 } 
 ... 
 ```