Projet

Général

Profil

Wiki » Historique » Version 97

Patrice Nadeau, 2023-12-31 11:50

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 1 Patrice Nadeau
10
## Style
11
12 6 Patrice Nadeau
Le code DOIT :
13 5 Patrice Nadeau
* Être dans le style [K&R](https://fr.wikipedia.org/wiki/Style_d%27indentation#Style_K&R) avec la variante *one true brace style* (1TBS):
14 1 Patrice Nadeau
* L’indentation est de 4 espaces
15
* Le « backslash » est utilisé pour les lignes de plus de 80 caractères
16
* Une instruction par ligne
17
* Une espace avant et après un opérateur sauf pour les opérateurs « [unaires](https://fr.wikipedia.org/wiki/Op%C3%A9ration_unaire) »
18 52 Patrice Nadeau
* Les commentaires DOIVENT 
19
    * Être de style C (/* ... */) 
20 50 Patrice Nadeau
    * En minuscules et commencer par une majuscule
21 52 Patrice Nadeau
    * En français
22 50 Patrice Nadeau
    * Précéder l’élément à documenté
23 1 Patrice Nadeau
24 46 Patrice Nadeau
Justifications : 
25 1 Patrice Nadeau
* [K&R](https://fr.wikipedia.org/wiki/Style_d%27indentation#Style_K&R)
26
* Prévient les erreurs lors d'ajout dans les boucles n'ayant qu'une instruction comme bloc
27 46 Patrice Nadeau
* Support ASCII 7-bits
28
* Correspondance avec la fiche technique (datasheet)
29 1 Patrice Nadeau
* [Loi sur la langue officielle et commune du Québec, le français](https://www.publicationsduquebec.gouv.qc.ca/fileadmin/Fichiers_client/lois_et_reglements/LoisAnnuelles/fr/2022/2022C14F.PDF)
30
31
Exemple :
32
``` c
33 47 Patrice Nadeau
int fonction(void) {
34 1 Patrice Nadeau
    int x;
35
    if (var != 1) {
36
        x = x + 1;
37 14 Patrice Nadeau
        y++;
38 91 Patrice Nadeau
        /* Longue ligne */
39 1 Patrice Nadeau
        printf("This is a long\
40
        line that should be splitted");
41
    } else {
42 16 Patrice Nadeau
        x--;
43
    };
44 20 Patrice Nadeau
    return 0;
45
}
46
```
47
48 93 Patrice Nadeau
## Commentaires Doxygen
49 96 Patrice Nadeau
La documentation est faite a l'aide de commentaires [Doxygen](https://www.doxygen.nl/) dans la déclaration de tous les objets ayant une visibilité publique.
50
* Dans le format *Javadoc* (`/** */`)
51
* Au minimum, les items suivants doivent être présents :
52 94 Patrice Nadeau
    * `@brief`
53 96 Patrice Nadeau
* Les « décorations » (gras, italique, etc.) sont faites avec la syntaxe *Markdown*
54 94 Patrice Nadeau
    * Gras : `*`
55
    * Italique : `_`
56 96 Patrice Nadeau
* La gradations des notes et remarques se fait selon :
57 95 Patrice Nadeau
   * `@remark` :  Non importante
58
   * `@note` :  Générale
59
   * `@attention` : Important
60
   * `@warning` : Conséquence négative
61 90 Patrice Nadeau
    
62
Exemple :
63
``` c
64
/**
65 97 Patrice Nadeau
 * @brief Compteur global
66 1 Patrice Nadeau
 * @warning Note conséquence négative
67 96 Patrice Nadeau
 */
68 97 Patrice Nadeau
int ctr;
69 90 Patrice Nadeau
```
70
71 1 Patrice Nadeau
## Fichiers
72
Le nom des fichiers DOIT être composé de la manière suivante :
73
* En minuscule
74 79 Patrice Nadeau
* Un préfixe de 8 caractères maximum
75
* Un des suffixe (extensions) suivants : 
76
    * `.h` : entête
77
    * `.c` : sources
78
* Contient une section Doxygen :
79
    * `@file`
80
    * `@brief`
81
    * `@version`
82
    * `@date`
83
    * `@author`
84
    * `@copyright`
85 1 Patrice Nadeau
* Les fichier d’entête contiennent en plus
86
    * Une section Doxygen « mainpage » 
87 79 Patrice Nadeau
    * Une définition macro pour éviter de ré-inclure le fichier.
88 1 Patrice Nadeau
89
Exemple :
90
```c
91
#ifndef _test_h
92
#define _test_h
93
/**
94
 * @file : test.h
95
 * @brief Description
96
 * @version 0.00.01
97
 * @date 2023-02-26
98
 * @author Patrice Nadeau  <pnadeau@patricenadeau.com>
99
 * @copyright 2023 Patrice Nadeau
100
*/
101
102
/**
103
 * @mainpage lcd
104 37 Patrice Nadeau
 * @brief ATMEL AVR 8-bit C librairie
105 1 Patrice Nadeau
 * @author Patrice Nadeau <pnadeau@patricenadeau.com>
106
 * @version 0.0.02
107
 * @date 2023-03-27
108 54 Patrice Nadeau
 * @pre AVR supportés (testés en gras) :
109 1 Patrice Nadeau
 * - ATmega88
110
 * - ATmega168
111 15 Patrice Nadeau
 * - **ATmega328P**
112 1 Patrice Nadeau
 * @copyright 
113 13 Patrice Nadeau
 * @include{doc} LICENSE.txt
114 1 Patrice Nadeau
*/
115
116
...
117
118
#endif /*_usart.h*/
119
```
120
121 85 Patrice Nadeau
---
122 82 Patrice Nadeau
123 60 Patrice Nadeau
## Objets
124 1 Patrice Nadeau
125 31 Patrice Nadeau
* Comporter au maximum **31** caractères
126
* Être séparées par des traits de soulignement si comporte plusieurs mots
127
* Exceptions :
128
    * Fonction et variables DOIVENT
129
        * Être en minuscule
130
    * Macros, constantes et `#define` DOIVENT
131
        * Être en majuscule
132 1 Patrice Nadeau
133
Justification :
134
* Linux kernel coding style : <https://www.kernel.org/doc/html/v4.10/process/coding-style.html#naming>
135
* GNU Coding Standards <https://www.gnu.org/prep/standards/html_node/Writing-C.html#Writing-C>
136
* Embedded C Coding Standard : <https://barrgroup.com/embedded-systems/books/embedded-c-coding-standard>
137
138 61 Patrice Nadeau
### Déclarations locales
139 1 Patrice Nadeau
140
Une déclaration n’ayant qu’une visibilité locale DOIT :
141
* Être de classe `static`
142
143
Exemple:
144
``` c
145
/**
146 75 Patrice Nadeau
 * @brief Fonction locale
147
 * @return Une valeur
148
 */
149 7 Patrice Nadeau
static int local_func(void) {
150 1 Patrice Nadeau
    ...
151
    return 0;
152
}
153
```
154
155 62 Patrice Nadeau
### Constantes
156 1 Patrice Nadeau
157
Utilisé au lieu d’une macro quand le type ou la visibilité de la variable doit être définis.
158
159
Exemple :
160
161
``` c
162
/** 
163 38 Patrice Nadeau
 * @name Liste des constantes
164 1 Patrice Nadeau
 * @brief
165
 */
166
/** @{ */
167 38 Patrice Nadeau
/** @brief La chaîne d'initialisation du projet */
168 1 Patrice Nadeau
static const char INIT_STR[6] = "POWER";
169 38 Patrice Nadeau
/** @brief Constante globale de la librairie `random` */
170 1 Patrice Nadeau
extern int RANDOM_MAX = 25;
171
/** @} */
172
173 38 Patrice Nadeau
/** @brief Constante */
174 1 Patrice Nadeau
const int ANSWER 42;
175
```
176
177 63 Patrice Nadeau
### Énumérations
178 1 Patrice Nadeau
179
DOIT être utilisée pour définir une série de valeurs.
180
181
Exemple :
182
```c
183
/**
184 76 Patrice Nadeau
 * @name Liste des valeurs STATUS
185 1 Patrice Nadeau
 * @brief 
186
 * */
187
enum STATUS {
188 76 Patrice Nadeau
	/** @brief Le processus est OK */
189 1 Patrice Nadeau
	STATUS_OK = 0,
190 76 Patrice Nadeau
	/** @brief Le processus est en cours d'initialisation */
191 1 Patrice Nadeau
	STATUS_INIT,
192 76 Patrice Nadeau
	/** @brief Le processus est arrêté */
193 1 Patrice Nadeau
	STATUS_HALTED
194
};
195
```
196
197 64 Patrice Nadeau
### Typedef
198 1 Patrice Nadeau
199
Format :
200
* En minuscule, suivie de **_t**
201
202
Exemple :
203
``` c
204 39 Patrice Nadeau
/** Type de la structure dans la librairie `ds1305` */
205 1 Patrice Nadeau
typedef struct {
206 39 Patrice Nadeau
    /** @brief Dernier deux chiffres : &ge; 00, &le; 99 */
207 1 Patrice Nadeau
    uint8_t year;
208
    /** @brief 01 - 12 */
209
    uint8_t month;
210
    /** @brief 01 - 31 */
211
    uint8_t date;
212
    /** @brief 1 - 7 */
213
    uint8_t day;
214
    /** @brief 00 - 23 */
215
    uint8_t hours;
216
    /** @brief 00 - 59 */
217
    uint8_t minutes;
218
    /** @brief 00 - 59 */
219
    uint8_t seconds;
220
} ds1305_time_t;
221
```
222
223 65 Patrice Nadeau
### Variables
224 1 Patrice Nadeau
225
Exemple :
226
``` c
227 40 Patrice Nadeau
/** @brief Variable locale */
228 1 Patrice Nadeau
static int ctr;
229 40 Patrice Nadeau
/** @brief Variable globale */
230
int RANDOM_CTR;
231 1 Patrice Nadeau
```
232
233 66 Patrice Nadeau
### Structures
234 1 Patrice Nadeau
235
Format
236
* En minuscule, séparé par des «underscores» si nécessaire.
237
238
Exemple :
239
``` c
240
/**
241 76 Patrice Nadeau
* @brief Structure d'un menu local
242 1 Patrice Nadeau
* @see MenuSelect
243
*/
244
struct menu {
245 76 Patrice Nadeau
    /** @brief Caractère utilisé pour l'item */
246 8 Patrice Nadeau
    char choice;
247 76 Patrice Nadeau
    /** @brief Description de l'item */
248 8 Patrice Nadeau
    char *item;
249 1 Patrice Nadeau
};
250
```
251
252 67 Patrice Nadeau
### Fonctions
253 1 Patrice Nadeau
254
Le nom DOIT être dans le format suivant : *Action***_***Item***_***Attribut*, où *Action* signifie :
255 29 Patrice Nadeau
* **set**, **get**, **clear** : Règle, obtient ou vide un registre
256 1 Patrice Nadeau
* **read**, **write** : Lis ou écris dans un fichier
257
* **init** : Fonction d’initialisation
258
* **is** : Vérifie un état
259 36 Patrice Nadeau
* **setup** : Fonction de configuration des ports (AVR)
260 1 Patrice Nadeau
261
Exceptions
262 41 Patrice Nadeau
* 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.
263 1 Patrice Nadeau
264
Une fonction DEVRAIT retourner une valeur. 
265 28 Patrice Nadeau
* Type entier (oui/non) :
266 1 Patrice Nadeau
  * Succès : **0**
267
  * Erreur : **1**
268
* Type booléen (Librairie `<stdbool.h>`)
269
    * **true**
270
    * **false**
271
* Pointeur :
272
    * **NULL** : Erreur
273
    * Autre valeur  : adresse du pointeur
274
275
Justification :
276
* [AVR1000b](https://ww1.microchip.com/downloads/en/Appnotes/AVR1000b-Getting-Started-Writing-C-Code-for-AVR-DS90003262B.pdf)
277
278
Exemple :
279
280
``` c
281
/**
282 42 Patrice Nadeau
* @brief Vérifie si une horloge est est initialisée
283 76 Patrice Nadeau
* @param[in] nb Timer number. @n Valeurs possibles :
284 24 Patrice Nadeau
* − @arg **TIMER_1**
285
* − @arg **TIMER_2**
286 1 Patrice Nadeau
* @return
287
* @retval true Horloge *nb* est initialisée
288 42 Patrice Nadeau
* @retval false Horloge *nb* n'est PAS initialisée
289 1 Patrice Nadeau
* @pre init_timer
290
**/
291
static bool is_timer_set(uint8_t nb);
292
293
```
294
295
## Items déconseillés et retirés
296 59 Patrice Nadeau
297 76 Patrice Nadeau
Les fonctions et variables ne devant plus être utilisés, DOIVENT générer un message lors de la compilation (`-Wall`) si un appel est effectué.
298 80 Patrice Nadeau
* Les attributs`deprecated` ou `unavailable` DOIVENT être ajoutés à la déclaration.
299 1 Patrice Nadeau
* La documentation DOIT indiquer les substituts à utiliser.
300 59 Patrice Nadeau
301
Exemple :
302
``` c
303
/**
304
 * @brief OldFunction
305 76 Patrice Nadeau
 * @deprecated Utiliser NewFunction à la place
306 59 Patrice Nadeau
 * @since Version x.x.xx
307
 */
308 84 Patrice Nadeau
int OldFunction(void) __attribute__((deprecated));
309 59 Patrice Nadeau
310
/**
311
 * @brief OldFunction
312 76 Patrice Nadeau
 * @deprecated Utiliser NewFunction à la place
313 1 Patrice Nadeau
 * @since Version x.x.xx
314 59 Patrice Nadeau
 */
315 84 Patrice Nadeau
int OldFunction(void) __attribute__((unavailable));
316 59 Patrice Nadeau
```
317 11 Patrice Nadeau
318
## Préprocesseur
319 1 Patrice Nadeau
Directives du préprocesseur gcc.
320
321
### #include
322
323 43 Patrice Nadeau
Pour inclure d’autres fichier comme les fichiers entête.
324 1 Patrice Nadeau
325
### #ifdef / ifndef
326
327 76 Patrice Nadeau
Surtout utilisé pour des options de compilation sur différentes plateforme.
328 1 Patrice Nadeau
Utiliser une forme évitant les répétitions.
329
330
> N’est pas documenté dans Doxygen.
331
332
Exemple :
333
```c
334
const char BLUE =
335
  #if ENABLED(FEATURE_ONE)
336
    '1'
337
  #else
338
    '0'
339
  #endif
340
;
341
```
342
343
### Diagnostiques
344
345 78 Patrice Nadeau
Les macros `#warning` et `#error` sont utilisées pour afficher des avertissements ou des erreurs lors de la compilation.
346 1 Patrice Nadeau
347
> Ne sont pas documentées dans Doxygen.
348
349
Exemple :
350
``` c
351
#ifndef usart_AVR
352
    #error "__FILE_NAME__ is not supported on this AVR !"
353
#endif
354
355
#ifndef __test__
356
    #warning "test is not defined !"
357
#endif
358
```
359
360
### Définitions
361
362
Un `#define` est utilisé pour remplacer une valeur au moment de la compilation
363
> Pour la définition d'une valeur « integer », un `enum` DOIT être utilisé.
364
365
Exemple :
366
``` c
367
/**
368 76 Patrice Nadeau
* @name Nom des registres
369 1 Patrice Nadeau
*/
370
/** @{ */ 
371
/** @brief USART1 */
372
#define USART1 REG1
373
/** @brief USART2 */
374
#define USART2 REG2
375
/** @} */
376
377
USART1 = 0x0F;
378
```
379
380
## Atmel AVR
381
382
Particularités pour les microcontrôleurs 8 bits AVR d’Atmel.
383
384
[Atmel AVR4027: Tips and Tricks to Optimize Your C Code for 8-bit AVR Microcontrollers](https://ww1.microchip.com/downloads/en/AppNotes/doc8453.pdf)
385
386
### Fichier d’en-têtes
387
388 25 Patrice Nadeau
Vérification du modèle de microcontrôleur
389
    > Via l'option `-m` de [gcc](https://github.com/embecosm/avr-gcc/blob/avr-gcc-mainline/gcc/config/avr/avr-mcus.def)
390
391 1 Patrice Nadeau
```c
392 25 Patrice Nadeau
#ifndef defined (__AVR_ATmega48__) || (__AVR_ATmega48P__) || \
393
	(__AVR_ATmega88P__) || defined (__AVR_ATmega88__) || \
394
	(__AVR_ATmega168__) || defined (__AVR_ATmega168P__) || \
395
	(__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
396
#warning "Cette librairie n'as pas été testée sur cette famille de microcontrôleur."
397
#endif
398 1 Patrice Nadeau
```
399
400
### Macros
401 45 Patrice Nadeau
402
Définis dans le fichier `config.h`
403
404
Liste : 
405 1 Patrice Nadeau
* `F_CPU` : La fréquence utilisée par l'horloge (interne ou externe) du microcontrôleur
406
407
    > Les « fuses » doivent correspondent à la bonne source de l'horloge.
408
409
### Types
410
411
De nouveau type d'entier sont fournis avec la librairie `<stdint.h>`.
412
413
L'utilisation de ces types DOIT être utilisé afin d'exprimer le nombre de bit d'un objet.
414
415
### Progmem
416 44 Patrice Nadeau
417
<https://www.avrfreaks.net/s/topic/a5C3l000000U5SFEA0/t034767>
418
419 1 Patrice Nadeau
Pour mettre des variables en lecture seule dans la section FLASH au lieu de SRAM avec `<avr/pgmspace.h>`.
420
> L’accès à ces variables est faite via les macros de la librairie.
421
422
Le nom de la variable DOIT être suivie de **_P**
423
424
Exemple :
425
```c
426
#include <avr/pgmspace.h>
427
...
428
/** @brief Variable en FLASH */
429
const int Variable1_P PROGMEM = 42;
430
```
431
432
### Fonction main
433
Un microcontrôleur AVR ne termine jamais la fonction `main`.
434
435
* Déclarer la fonction main avec l’attribut `noreturn`
436
* La boucle sans fin la plus optimisé est le `for (;;)`
437
438
Justification : [AVR035](https://ww1.microchip.com/downloads/en/AppNotes/doc1497.pdf)
439
440
Exemple :
441
```c
442 26 Patrice Nadeau
#include <avr/io.h>
443
444 1 Patrice Nadeau
/** 
445
 * @brief Never ending loop
446
*/
447 83 Patrice Nadeau
void main(void) __attribute__((noreturn));
448 1 Patrice Nadeau
449
/* main function definition */
450 9 Patrice Nadeau
void main(void) {
451 1 Patrice Nadeau
    ...
452
    /* never return */
453
    for (;;) {
454
    };
455
};
456
```
457
458 70 Patrice Nadeau
### Opérations « atomiques »
459 69 Patrice Nadeau
Opérations ne devant pas être interrompus, comme charger un registre de 16 bits avec un registre de 8 bits.
460 1 Patrice Nadeau
461
La librairie `avr-libc` (util/atomic.h) fournit des macros permettant la gestion entre autre des interruptions.
462
463
Les instructions critiques sont insérées dans un `ATOMIC_BLOCK`.
464
465
Exemple :
466
```c
467 72 Patrice Nadeau
#include <util/atomic.h>
468 1 Patrice Nadeau
...
469
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
470
    ...
471
}
472
...
473
```