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) { ... } ... ```