Projet

Général

Profil

Wiki » Historique » Version 28

Patrice Nadeau, 2023-07-12 21:58

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