Projet

Général

Profil

Wiki » Historique » Version 156

Patrice Nadeau, 2024-01-20 21:20

1 1 Patrice Nadeau
# Règles de codage C
2
3 68 Patrice Nadeau
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/).
4 1 Patrice Nadeau
> `gcc` n'est pas entièrement compatible avec le standard C99 (<https://gcc.gnu.org/c99status.html>).
5
6
---
7 73 Patrice Nadeau
8
{{>toc}}
9 148 Patrice Nadeau
10
---
11 1 Patrice Nadeau
12 154 Patrice Nadeau
[[Style]]
13 20 Patrice Nadeau
14 155 Patrice Nadeau
[[Commentaires Doxygen]]
15 90 Patrice Nadeau
16 156 Patrice Nadeau
[[Fichiers]]
17 104 Patrice Nadeau
18 98 Patrice Nadeau
19 85 Patrice Nadeau
---
20 82 Patrice Nadeau
21 112 Patrice Nadeau
## Objets et macros
22 111 Patrice Nadeau
Variables, fonctions et macros
23 109 Patrice Nadeau
* Comportent au maximum **31** caractères
24 145 Patrice Nadeau
* Si plusieurs mots sont utilisés, ils sont séparées par des traits de soulignement
25 31 Patrice Nadeau
* Exceptions :
26 1 Patrice Nadeau
    * Fonction et variables DOIVENT
27 146 Patrice Nadeau
        * Être en minuscule
28 142 Patrice Nadeau
    * Macros et constantes DOIVENT
29 1 Patrice Nadeau
        * Être en majuscule
30 109 Patrice Nadeau
* Les objets ne devant plus être utilisés, DOIVENT générer un message lors de la compilation (`-Wall`) si un appel est effectué.
31
    * Les attributs`deprecated` ou `unavailable` DOIVENT être ajoutés à la déclaration.
32
    * La documentation DOIT indiquer les substituts à utiliser.
33 1 Patrice Nadeau
34
Justification :
35
* Linux kernel coding style : <https://www.kernel.org/doc/html/v4.10/process/coding-style.html#naming>
36 105 Patrice Nadeau
* GNU Coding Standards <https://www.gnu.org/prep/standards/html_node/Writing-C.html#Writing-C>
37
* Embedded C Coding Standard : <https://barrgroup.com/embedded-systems/books/embedded-c-coding-standard>
38
39
Exemple :
40
``` c
41
/**
42
 * @brief OldFunction
43
 * @deprecated Utiliser NewFunction à la place
44
 * @since Version x.x.xx
45
 */
46
int OldFunction(void) __attribute__((deprecated));
47
48
/**
49
 * @brief OldFunction
50
 * @deprecated Utiliser NewFunction à la place
51
 * @since Version x.x.xx
52
 */
53
int OldFunction(void) __attribute__((unavailable));
54
```
55
56 108 Patrice Nadeau
### Déclarations locales
57
58
Une déclaration n’ayant qu’une visibilité locale DOIT :
59
* Être de classe `static`
60
61
Exemple:
62
``` c
63
/**
64
 * @brief Fonction locale
65
 * @return Une valeur
66
 */
67
static int local_func(void) {
68
    ...
69
    return 0;
70
}
71
```
72
73 62 Patrice Nadeau
### Constantes
74 1 Patrice Nadeau
75
Utilisé au lieu d’une macro quand le type ou la visibilité de la variable doit être définis.
76
77
Exemple :
78
79
``` c
80
/** 
81 38 Patrice Nadeau
 * @name Liste des constantes
82 1 Patrice Nadeau
 * @brief
83
 */
84
/** @{ */
85 38 Patrice Nadeau
/** @brief La chaîne d'initialisation du projet */
86 1 Patrice Nadeau
static const char INIT_STR[6] = "POWER";
87 38 Patrice Nadeau
/** @brief Constante globale de la librairie `random` */
88 1 Patrice Nadeau
extern int RANDOM_MAX = 25;
89
/** @} */
90
91 38 Patrice Nadeau
/** @brief Constante */
92 1 Patrice Nadeau
const int ANSWER 42;
93
```
94
95 63 Patrice Nadeau
### Énumérations
96 1 Patrice Nadeau
97
DOIT être utilisée pour définir une série de valeurs.
98
99
Exemple :
100
```c
101
/**
102 76 Patrice Nadeau
 * @name Liste des valeurs STATUS
103 1 Patrice Nadeau
 * @brief 
104
 * */
105
enum STATUS {
106 76 Patrice Nadeau
	/** @brief Le processus est OK */
107 1 Patrice Nadeau
	STATUS_OK = 0,
108 76 Patrice Nadeau
	/** @brief Le processus est en cours d'initialisation */
109 1 Patrice Nadeau
	STATUS_INIT,
110 76 Patrice Nadeau
	/** @brief Le processus est arrêté */
111 1 Patrice Nadeau
	STATUS_HALTED
112
};
113
```
114
115 64 Patrice Nadeau
### Typedef
116 1 Patrice Nadeau
117
Format :
118
* En minuscule, suivie de **_t**
119
120
Exemple :
121
``` c
122 39 Patrice Nadeau
/** Type de la structure dans la librairie `ds1305` */
123 1 Patrice Nadeau
typedef struct {
124 39 Patrice Nadeau
    /** @brief Dernier deux chiffres : &ge; 00, &le; 99 */
125 1 Patrice Nadeau
    uint8_t year;
126
    /** @brief 01 - 12 */
127
    uint8_t month;
128
    /** @brief 01 - 31 */
129
    uint8_t date;
130
    /** @brief 1 - 7 */
131
    uint8_t day;
132
    /** @brief 00 - 23 */
133
    uint8_t hours;
134
    /** @brief 00 - 59 */
135
    uint8_t minutes;
136
    /** @brief 00 - 59 */
137
    uint8_t seconds;
138
} ds1305_time_t;
139
```
140
141 65 Patrice Nadeau
### Variables
142 1 Patrice Nadeau
143
Exemple :
144
``` c
145 40 Patrice Nadeau
/** @brief Variable locale */
146 1 Patrice Nadeau
static int ctr;
147 40 Patrice Nadeau
/** @brief Variable globale */
148
int RANDOM_CTR;
149 1 Patrice Nadeau
```
150
151 66 Patrice Nadeau
### Structures
152 1 Patrice Nadeau
153
Format
154
* En minuscule, séparé par des «underscores» si nécessaire.
155
156
Exemple :
157
``` c
158
/**
159 76 Patrice Nadeau
* @brief Structure d'un menu local
160 1 Patrice Nadeau
* @see MenuSelect
161
*/
162
struct menu {
163 76 Patrice Nadeau
    /** @brief Caractère utilisé pour l'item */
164 8 Patrice Nadeau
    char choice;
165 76 Patrice Nadeau
    /** @brief Description de l'item */
166 8 Patrice Nadeau
    char *item;
167 1 Patrice Nadeau
};
168
```
169
170 67 Patrice Nadeau
### Fonctions
171 1 Patrice Nadeau
172 153 Patrice Nadeau
* Le nom DOIT être dans le format suivant : *Item***_***Action***_***Attribut*
173 128 Patrice Nadeau
    * *Action* signifie :
174
        * **set**, **get**, **clear** : Règle, obtient ou vide un registre
175
        * **read**, **write** : Lis ou écris dans un fichier
176
        * **init** : Fonction d’initialisation
177
        * **is** : Vérifie un état
178
        * **setup** : Fonction de configuration des ports (AVR)
179
        * Exceptions
180
            * Les fonctions définies dans une librairie de bas niveau pour du matériel (« driver ») devraient utiliser le nom définis dans la fiche technique.
181 1 Patrice Nadeau
182 115 Patrice Nadeau
* Contient les champs Doxygen
183 122 Patrice Nadeau
    * `@brief` : Brève description de la fonction
184 132 Patrice Nadeau
    * `@param[in,out]` *paramètre* *Description* : Si nécessaire, sinon ne pas inclure le champ
185 133 Patrice Nadeau
    * `@arg` : Valeur prédéfinie d'un paramètre (`#`, `* *`), sinon ne pas inclure le champs
186 1 Patrice Nadeau
    * `@return` : Description de la valeur retournée, sinon le terme **Sans objet**
187 122 Patrice Nadeau
    * `@retval` : Si une valeur de retour est prédéfinie, une ligne pour chaque valeur, sinon ne pas inclure le champs
188 125 Patrice Nadeau
    * `@pre` : Chaque précondition, sur une ligne séparée, sinon le terme **Sans objet**
189
    * `@post` : Chaque postcondition, sur une ligne séparée, sinon le terme **Sans objet**
190 129 Patrice Nadeau
    * `@sa` : Si une référence a un autre objet doit être faite (#), sinon le terme **Sans objet**
191 123 Patrice Nadeau
    * Le bloc d'exemple, si nécessaire
192
        * `@par Example`
193 124 Patrice Nadeau
        * `@code`
194 123 Patrice Nadeau
        * ...
195
        * `@endcode`
196 1 Patrice Nadeau
197 28 Patrice Nadeau
Une fonction DEVRAIT retourner une valeur. 
198 1 Patrice Nadeau
* Type entier (oui/non) :
199
  * Succès : **0**
200
  * Erreur : **1**
201
* Type booléen (Librairie `<stdbool.h>`)
202
    * **true**
203
    * **false**
204
* Pointeur :
205
    * **NULL** : Erreur
206
    * Autre valeur  : adresse du pointeur
207
208
Justification :
209
* [AVR1000b](https://ww1.microchip.com/downloads/en/Appnotes/AVR1000b-Getting-Started-Writing-C-Code-for-AVR-DS90003262B.pdf)
210
211
Exemple :
212
213
``` c
214 42 Patrice Nadeau
/**
215 120 Patrice Nadeau
* @brief Vérifie si une horloge est initialisée
216 131 Patrice Nadeau
* @param[in] nb Le numéro du timer parmi 
217
* @arg #TIMER_1
218
* @arg #TIMER_2
219 1 Patrice Nadeau
* @return
220 42 Patrice Nadeau
* @retval true Horloge *nb* est initialisée
221 1 Patrice Nadeau
* @retval false Horloge *nb* n'est PAS initialisée
222 114 Patrice Nadeau
* @pre init_timer
223 119 Patrice Nadeau
* @post Sans objet
224 1 Patrice Nadeau
**/
225
static bool is_timer_set(uint8_t nb);
226
```
227 11 Patrice Nadeau
228 1 Patrice Nadeau
## Préprocesseur
229
Directives du préprocesseur gcc.
230
231
### #include
232 43 Patrice Nadeau
233 1 Patrice Nadeau
Pour inclure d’autres fichier comme les fichiers entête.
234
235
### #ifdef / ifndef
236 76 Patrice Nadeau
237 1 Patrice Nadeau
Surtout utilisé pour des options de compilation sur différentes plateforme.
238
Utiliser une forme évitant les répétitions.
239
240
> N’est pas documenté dans Doxygen.
241
242
Exemple :
243
```c
244
const char BLUE =
245
  #if ENABLED(FEATURE_ONE)
246
    '1'
247
  #else
248
    '0'
249
  #endif
250
;
251
```
252
253
### Diagnostiques
254 78 Patrice Nadeau
255 1 Patrice Nadeau
Les macros `#warning` et `#error` sont utilisées pour afficher des avertissements ou des erreurs lors de la compilation.
256
257
> Ne sont pas documentées dans Doxygen.
258
259
Exemple :
260
``` c
261
#ifndef usart_AVR
262
    #error "__FILE_NAME__ is not supported on this AVR !"
263
#endif
264
265
#ifndef __test__
266
    #warning "test is not defined !"
267
#endif
268
```
269
270
### Définitions
271
272
Un `#define` est utilisé pour remplacer une valeur au moment de la compilation
273
> Pour la définition d'une valeur « integer », un `enum` DOIT être utilisé.
274
275
Exemple :
276
``` c
277 76 Patrice Nadeau
/**
278 1 Patrice Nadeau
* @name Nom des registres
279
*/
280
/** @{ */ 
281
/** @brief USART1 */
282
#define USART1 REG1
283
/** @brief USART2 */
284
#define USART2 REG2
285
/** @} */
286
287
USART1 = 0x0F;
288
```
289
290
## Atmel AVR
291
292
Particularités pour les microcontrôleurs 8 bits AVR d’Atmel.
293
294
[Atmel AVR4027: Tips and Tricks to Optimize Your C Code for 8-bit AVR Microcontrollers](https://ww1.microchip.com/downloads/en/AppNotes/doc8453.pdf)
295
296
### Fichier d’en-têtes
297 25 Patrice Nadeau
298
Vérification du modèle de microcontrôleur
299
    > Via l'option `-m` de [gcc](https://github.com/embecosm/avr-gcc/blob/avr-gcc-mainline/gcc/config/avr/avr-mcus.def)
300 1 Patrice Nadeau
301 25 Patrice Nadeau
```c
302
#ifndef defined (__AVR_ATmega48__) || (__AVR_ATmega48P__) || \
303
	(__AVR_ATmega88P__) || defined (__AVR_ATmega88__) || \
304
	(__AVR_ATmega168__) || defined (__AVR_ATmega168P__) || \
305
	(__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
306
#warning "Cette librairie n'as pas été testée sur cette famille de microcontrôleur."
307 1 Patrice Nadeau
#endif
308
```
309
310 45 Patrice Nadeau
### Macros
311
312
Définis dans le fichier `config.h`
313
314 1 Patrice Nadeau
Liste : 
315
* `F_CPU` : La fréquence utilisée par l'horloge (interne ou externe) du microcontrôleur
316
317
    > Les « fuses » doivent correspondent à la bonne source de l'horloge.
318
319
### Types
320
321
De nouveau type d'entier sont fournis avec la librairie `<stdint.h>`.
322
323
L'utilisation de ces types DOIT être utilisé afin d'exprimer le nombre de bit d'un objet.
324
325 44 Patrice Nadeau
### Progmem
326
327
<https://www.avrfreaks.net/s/topic/a5C3l000000U5SFEA0/t034767>
328 1 Patrice Nadeau
329
Pour mettre des variables en lecture seule dans la section FLASH au lieu de SRAM avec `<avr/pgmspace.h>`.
330
> L’accès à ces variables est faite via les macros de la librairie.
331
332
Le nom de la variable DOIT être suivie de **_P**
333
334
Exemple :
335
```c
336
#include <avr/pgmspace.h>
337
...
338
/** @brief Variable en FLASH */
339
const int Variable1_P PROGMEM = 42;
340
```
341
342
### Fonction main
343
Un microcontrôleur AVR ne termine jamais la fonction `main`.
344
345
* Déclarer la fonction main avec l’attribut `noreturn`
346
* La boucle sans fin la plus optimisé est le `for (;;)`
347
348
Justification : [AVR035](https://ww1.microchip.com/downloads/en/AppNotes/doc1497.pdf)
349
350
Exemple :
351 26 Patrice Nadeau
```c
352
#include <avr/io.h>
353 1 Patrice Nadeau
354
/** 
355
 * @brief Never ending loop
356 83 Patrice Nadeau
*/
357 1 Patrice Nadeau
void main(void) __attribute__((noreturn));
358
359 9 Patrice Nadeau
/* main function definition */
360 1 Patrice Nadeau
void main(void) {
361
    ...
362
    /* never return */
363
    for (;;) {
364
    };
365
};
366
```
367 70 Patrice Nadeau
368 113 Patrice Nadeau
### Opérations « atomiques »
369 1 Patrice Nadeau
Opérations ne devant pas être interrompus (Ex. : charger un registre de 16 bits avec un registre de 8 bits).
370
371
La librairie `avr-libc` (util/atomic.h) fournit des macros permettant la gestion entre autre des interruptions.
372
373
Les instructions critiques sont insérées dans un `ATOMIC_BLOCK`.
374
375
Exemple :
376 72 Patrice Nadeau
```c
377 1 Patrice Nadeau
#include <util/atomic.h>
378
...
379
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
380
    ...
381
}
382
...
383
```