Projet

Général

Profil

Wiki » Historique » Version 17

Patrice Nadeau, 2023-07-08 18:44

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