Projet

Général

Profil

Wiki » Historique » Version 31

Patrice Nadeau, 2023-07-16 10:16

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 30 Patrice Nadeau
En général : *librairie*\_*action*\_*sujet*
137 1 Patrice Nadeau
138 31 Patrice Nadeau
* Les noms doivent en [anglais américain](https://fr.wikipedia.org/wiki/Anglais_am%C3%A9ricain)
139
* Comporter au maximum **31** caractères
140
* Être séparées par des traits de soulignement si comporte plusieurs mots
141
* Exceptions :
142
    * Fonction et variables DOIVENT
143
        * Être en minuscule
144
    * Macros, constantes et `#define` DOIVENT
145
        * Être en majuscule
146 1 Patrice Nadeau
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 30 Patrice Nadeau
* Support ASCII 127 bits
152 1 Patrice Nadeau
153
## Déclarations locales
154
155
Une déclaration n’ayant qu’une visibilité locale DOIT :
156
* Être de classe `static`
157
158
Exemple:
159
``` c
160
/**
161
* @brief Local function
162
**/
163 7 Patrice Nadeau
static int local_func(void) {
164 1 Patrice Nadeau
    ...
165
    return 0;
166
}
167
```
168
169
## Items déconseillés et retirés
170
171
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é.
172
* Les attributs`__attribute__((deprecated))` ou `__attribute__((unavailable))` DOIVENT être ajoutés à la déclaration.
173
* La documentation DOIT indiquer les substituts à utiliser.
174
175
Exemple :
176
``` c
177
/**
178
 * @brief OldFunction
179
 * @deprecated Use NewFunction instead
180
 * @since Version x.x.xx
181
 */
182
int OldFunction(void) __attribute__((deprecated));
183
184
/**
185
 * @brief OldFunction
186
 * @deprecated Use NewFunction instead
187
 * @since Version x.x.xx
188
 */
189
int OldFunction(void) __attribute__((unavailable));
190
```
191
192
## Constantes
193
194
Utilisé au lieu d’une macro quand le type ou la visibilité de la variable doit être définis.
195
196
DOIVENT être
197 21 Patrice Nadeau
* De classe `static` ou `extern` selon le besoin
198 1 Patrice Nadeau
199
Exemple :
200
201
``` c
202
/** 
203
 * @name List of constants
204
 * @brief
205
 */
206
/** @{ */
207
/** @brief The initialization string of the project */
208
static const char INIT_STR[6] = "POWER";
209
/** @brief Global const in the random library */
210
extern int RANDOM_MAX = 25;
211
/** @} */
212
213
/** @brief Constant */
214
const int ANSWER 42;
215
```
216
217
## Énumérations
218
219
DOIT être utilisée pour définir une série de valeurs.
220
221
Exemple :
222
```c
223
/**
224
 * @name List of STATUS values
225
 * @brief 
226
 * */
227
enum STATUS {
228
	/** @brief Everything is fine */
229
	STATUS_OK = 0,
230
	/** @brief Initialisation in progress */
231
	STATUS_INIT,
232
	/** @brief System halted */
233
	STATUS_HALTED
234
};
235
```
236
237
## Typedef
238
239
Format :
240
* En minuscule, suivie de **_t**
241
242
Exemple :
243
``` c
244
/** Type of structure in the ds1305 library */
245
typedef struct {
246
    /** @brief last two digits : &ge; 00, &le; 99 */
247
    uint8_t year;
248
    /** @brief 01 - 12 */
249
    uint8_t month;
250
    /** @brief 01 - 31 */
251
    uint8_t date;
252
    /** @brief 1 - 7 */
253
    uint8_t day;
254
    /** @brief 00 - 23 */
255
    uint8_t hours;
256
    /** @brief 00 - 59 */
257
    uint8_t minutes;
258
    /** @brief 00 - 59 */
259
    uint8_t seconds;
260
} ds1305_time_t;
261
```
262
263
## Variables
264
265
Exemple :
266
``` c
267
/** @brief Local variable */
268
static int ctr;
269
/** @brief Global variable */
270
int random_ctr;
271
```
272
273
## Structures
274
275
Format
276
* En minuscule, séparé par des «underscores» si nécessaire.
277
278
Exemple :
279
``` c
280
/**
281
* @brief Structure for a local menu
282
* @see MenuSelect
283
*/
284
struct menu {
285 8 Patrice Nadeau
    /** @brief Character used for the item */
286
    char choice;
287
    /** @brief Description of the item */
288
    char *item;
289 1 Patrice Nadeau
};
290
```
291
292
## Fonctions
293
294
295
Le nom DOIT être dans le format suivant : *Action***_***Item***_***Attribut*, où *Action* signifie :
296 29 Patrice Nadeau
* **set**, **get**, **clear** : Règle, obtient ou vide un registre
297 1 Patrice Nadeau
* **read**, **write** : Lis ou écris dans un fichier
298
* **init** : Fonction d’initialisation
299
* **is** : Vérifie un état
300
301
Exceptions
302
* Les fonctions définies dans une librairie de bas niveau pour du matériel (« driver ») devraient utiliser le nom définis dans le « datasheet ».
303
304
Une fonction DEVRAIT retourner une valeur. 
305 28 Patrice Nadeau
* Type entier (oui/non) :
306 1 Patrice Nadeau
  * Succès : **0**
307
  * Erreur : **1**
308
* Type booléen (Librairie `<stdbool.h>`)
309
    * **true**
310
    * **false**
311
* Pointeur :
312
    * **NULL** : Erreur
313
    * Autre valeur  : adresse du pointeur
314
315
Justification :
316
* [AVR1000b](https://ww1.microchip.com/downloads/en/Appnotes/AVR1000b-Getting-Started-Writing-C-Code-for-AVR-DS90003262B.pdf)
317
318
Exemple :
319
320
``` c
321
/**
322
* @brief Check if a timer is set
323
* @param[in] nb Timer number. @n Possible values :
324 24 Patrice Nadeau
* − @arg **TIMER_1**
325
* − @arg **TIMER_2**
326 1 Patrice Nadeau
* @return
327 24 Patrice Nadeau
* @retval true Timer *nb* is set
328
* @retval false Timer *nb* is NOT set
329 1 Patrice Nadeau
* @par Example :
330
* Check if the timer is set
331
* @code
332
* ...
333
* result = is_timer_set();
334
* ...
335
* @endcode
336
* @pre init_timer
337
**/
338
339
static bool is_timer_set(uint8_t nb);
340
341
```
342
343 11 Patrice Nadeau
## Préprocesseur
344
Directives du préprocesseur gcc.
345 1 Patrice Nadeau
346
### #include
347
348
Pour inclure d’autres fichier comme les fichiers entête.
349
> N’est pas documenté dans Doxygen.
350
351
### #ifdef / ifndef
352
353
Surtout utiliser pour des options de compilation sur différentes plateforme.
354
Utiliser une forme évitant les répétitions.
355
356
> N’est pas documenté dans Doxygen.
357
358
Exemple :
359
```c
360
const char BLUE =
361
  #if ENABLED(FEATURE_ONE)
362
    '1'
363
  #else
364
    '0'
365
  #endif
366
;
367
```
368
369
### Diagnostiques
370
371
Les macros `#warning` et `#error` sont utilisées pour afficher des avertissements (continue la compilation) ou des erreurs (arrête la compilation).
372
373
> Ne sont pas documentées dans Doxygen.
374
375
Exemple :
376
``` c
377
#ifndef usart_AVR
378
    #error "__FILE_NAME__ is not supported on this AVR !"
379
#endif
380
381
#ifndef __test__
382
    #warning "test is not defined !"
383
#endif
384
```
385
386
### Définitions
387
388
Un `#define` est utilisé pour remplacer une valeur au moment de la compilation
389
> Pour la définition d'une valeur « integer », un `enum` DOIT être utilisé.
390
391
Exemple :
392
``` c
393
/**
394
* @name Registers name
395
*/
396
/** @{ */ 
397
/** @brief USART1 */
398
#define USART1 REG1
399
/** @brief USART2 */
400
#define USART2 REG2
401
/** @} */
402
403
USART1 = 0x0F;
404
```
405
406
## Atmel AVR
407
408
Particularités pour les microcontrôleurs 8 bits AVR d’Atmel.
409
410
[Atmel AVR4027: Tips and Tricks to Optimize Your C Code for 8-bit AVR Microcontrollers](https://ww1.microchip.com/downloads/en/AppNotes/doc8453.pdf)
411
412
### Fichier d’en-têtes
413
414 25 Patrice Nadeau
Vérification du modèle de microcontrôleur
415
    > Via l'option `-m` de [gcc](https://github.com/embecosm/avr-gcc/blob/avr-gcc-mainline/gcc/config/avr/avr-mcus.def)
416
417 1 Patrice Nadeau
```c
418 25 Patrice Nadeau
#ifndef defined (__AVR_ATmega48__) || (__AVR_ATmega48P__) || \
419
	(__AVR_ATmega88P__) || defined (__AVR_ATmega88__) || \
420
	(__AVR_ATmega168__) || defined (__AVR_ATmega168P__) || \
421
	(__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
422
#warning "Cette librairie n'as pas été testée sur cette famille de microcontrôleur."
423
#endif
424 1 Patrice Nadeau
```
425
426
### Macros
427
Liste des macros définies : 
428
* `F_CPU` : La fréquence utilisée par l'horloge (interne ou externe) du microcontrôleur
429
430
    > Les « fuses » doivent correspondent à la bonne source de l'horloge.
431
432
### Types
433
434
De nouveau type d'entier sont fournis avec la librairie `<stdint.h>`.
435
436
L'utilisation de ces types DOIT être utilisé afin d'exprimer le nombre de bit d'un objet.
437
438
### Progmem
439
Pour mettre des variables en lecture seule dans la section FLASH au lieu de SRAM avec `<avr/pgmspace.h>`.
440
> L’accès à ces variables est faite via les macros de la librairie.
441
442
Le nom de la variable DOIT être suivie de **_P**
443
444
Exemple :
445
```c
446
#include <avr/pgmspace.h>
447
...
448
/** @brief Variable en FLASH */
449
const int Variable1_P PROGMEM = 42;
450
```
451
452
### Fonction main
453
Un microcontrôleur AVR ne termine jamais la fonction `main`.
454
455
* Déclarer la fonction main avec l’attribut `noreturn`
456
* La boucle sans fin la plus optimisé est le `for (;;)`
457
458
Justification : [AVR035](https://ww1.microchip.com/downloads/en/AppNotes/doc1497.pdf)
459
460
Exemple :
461
```c
462 26 Patrice Nadeau
#include <avr/io.h>
463
464 1 Patrice Nadeau
/** 
465
 * @brief Never ending loop
466
*/
467 12 Patrice Nadeau
void main(void) __attribute__ ((noreturn));
468 1 Patrice Nadeau
469
/* main function definition */
470 9 Patrice Nadeau
void main(void) {
471 1 Patrice Nadeau
    ...
472
    /* never return */
473
    for (;;) {
474
    };
475
};
476
```
477
478
### Atomic
479
Opérations ne devant pas être interrompus comme charger un registre de 16 bits avec un registre de 8 bits.
480
481
La librairie `avr-libc` (util/atomic.h) fournit des macros permettant la gestion entre autre des interruptions.
482
483
Les instructions critiques sont insérées dans un `ATOMIC_BLOCK`.
484
485
Exemple :
486
```c
487
...
488
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
489
    ...
490
}
491
...
492
```