Projet

Général

Profil

Wiki » Historique » Version 18

Patrice Nadeau, 2023-07-08 19:21

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