Projet

Général

Profil

Wiki » Historique » Version 21

Patrice Nadeau, 2023-07-08 20:00

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