1Coding Rules
2============
3
4To maintain consistency within the SCP/MCP software source code and to reduce
5the risk of bugs, a series of rules and guidelines have been created; these form
6the project's coding rules.
7
8General Considerations
9----------------------
10The software follows the ISO/IEC 9899:2011 standard (C11). This is enforced
11through the use of compilation flags and all warnings being considered as
12errors. Compilation flags are also used to avoid constructs usually considered
13questionable, and that are easy to avoid.
14
15For robustness and reliability reasons, dynamic memory allocation is allocate-
16only and must be done through the facilities provided by the firmware framework.
17The intent is for memory allocations to be done during the pre-runtime phase or
18early in the runtime phase based on configuration data or hardware detection.
19Allocated memory cannot be freed or reallocated.
20
21Static Analysis
22---------------
23This project uses `cppcheck` to do a static analysis of the codebase for
24possible programmer error and other sources of bugs. This analysis occurs as a
25part of the standard continuous integration flow on pull requests. If the
26analyser identifies potential issues, the patch will be automatically rejected.
27
28To invoke `cppcheck` manually, use:
29
30``` bash
31cppcheck --xml \
32         --enable=all \
33         --force \
34         --suppressions-list="${WORKDIR}/tools/cppcheck_suppress_list.txt" \
35         --includes-file="${WORKDIR}/framework/include/" \
36         -I "${WORKDIR}/CMSIS" \
37         -i cmsis \
38         -U__CSMC__ \
39         ${WORKDIR}
40```
41
42The CMSIS submodule is not checked. Errors are printed in XML format on the
43error output.
44
45Certain checks have been manually suppressed. Checks are generally only
46disabled if they have been triaged as false positives. The list of suppressed
47checks can be found [here](../tools/cppcheck_suppress_list.txt).
48
49## Static analysis using `cmake`
50
51When this project is built using `cmake`, `cppcheck` is performed automatically
52for the current build using the list of suppressed checks mentioned in the
53previous section.
54`cppcheck` can be run standalone with the current build configuration using
55the following commands:
56
57``` bash
58cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \
59      -B ${BUILD_DIR} ... <cmake configuation extra parameters>
60
61cmake --build ${BUILD_DIR} -- -n
62
63cppcheck --xml \
64         --enable=all \
65         --force \
66         --suppressions-list="${WORKDIR}/tools/cppcheck_suppress_list.txt" \
67         --project="${BUILD_DIR}/compile_commands.json"
68```
69
70MISRAC-2012
71-----------
72The SCP-firmware is attempting to achieve compliance with MISRAC-2012.
73
74In order to provide a reference, Juno platform is taken as a first platform to
75attempt alignment with the guidance. At the same time, a MISRAC-2012 checker
76is currently being run upon PR submissions.
77
78To date, *all* violations of the **Mandatory Rules** have been **resolved**:
79
80* Rule 9.1,
81* Rule 12.5
82* Rule 13.6
83* Rules 17.3, 17.4, 17.6,
84* Rule 19.1,
85* Rules 21.13, 21.17, 21.18, 21.19, 21.20,
86* Rules 22.2, 22.4, 22.5, 22.6
87
88Other *Required Directives* have also had *all* their violations **resolved**:
89
90* Directive 1.1
91* Directive 2.1
92* Directive 3.1
93* Directives 4.1, 4.3, 4.7, 4.11, 4.14
94
95Other *Required Rules* have also had *all* their violations **resolved**:
96
97* Rules 1.1, 1.3
98* Rule 3.2
99* Rule 4.1
100* Rules 5.2, 5.3, 5.4, 5.5, 5.6, 5.7
101* Rules 6.1, 6.2
102* Rules 7.1, 7.3, 7.4
103* Rules 8.1, 8.8, 8.10, 8.12
104* Rules 9.2, 9.4
105* Rules 10.1, 10.2, 10.3
106* Rules 11.2, 11.7, 11.9
107* Rules 13.1, 13.2, 13.5
108* Rules 14.1, 15.2, 15.3, 15.6
109* Rules 16.2, 16.5, 16.7
110* Rules 17.2, 17.7
111* Rules 18.1, 18.6
112* Rules 20.2, 20.3, 20.4, 20.6, 20.8, 20.11, 20.13, 20.14
113* Rules 21.4, 21.5, 21.7, 21.8, 21.9, 21.10, 21.11, 21.14, 21.16
114* Rules 22.3, 22.7, 22.8, 22.9, 22.10
115
116The list of *Required Rules and Directives* that are currently being
117**deviated** from can be seen below:
118
119* Directives 4.10, 4.12
120* Rule 2.1
121* Rule 3.1
122* Rules 8.2, 8.4, 8.5, 8.6, 8.14
123* Rules 10.7, 10.8
124* Rules 11.1, 11.3, 11.6, 11.8
125* Rule 12.2
126* Rules 14.2, 14.3
127* Rules 16.1, 16.3, 16.4, 16.6
128* Rules 17.1, 17.7
129* Rules 18.2, 18.3, 18.7, 18.8
130* Rule 20.12
131* Rules 21.1, 21.2, 21.3, 21.6, 21.15
132
133*Advisory rules* are currently **not considered/treated**.
134
135Please note that new patches will have to be compliant with the current status
136of resolved rules/directives.
137
138C Standard Library
139------------------
140When developing a module, only the following headers of the C standard library
141are allowed to be included:
142`<limits.h>`, `<stdarg.h>`, `<stdbool.h>`, `<stddef.h>`, `<stdint.h>`,
143`<stdio.h>`, `<stdlib.h>`, `<string.h>` and `<inttypes.h>`.
144
145Concerning the library functions defined in `<stdio.h>`, only `snprintf()` may
146be used.
147
148Concerning the library functions defined in `<stdlib.h>`, only `bsearch()`,
149`qsort()`, `abs()` and `rand()` may be used.
150
151Concerning the library functions defined in `<string.h>`, `strcat()` and
152`strcpy()` cannot be used. Use `strncat()` and `strncpy()` instead.
153
154If not already defined by another standard library header, include `<stddef.h>`
155and not `<stdlib.h>` to define `size_t`.
156
157Additionally, the framework wraps the following standard library header files:
158`<stdalign.h>`, `<stdnoreturn.h>`, `<assert.h>` and `<errno.h>`. These header
159files must not be directly included in module code, as extended alternatives are
160provided by the framework.
161
162Header Files
163------------
164The contents of a header file should be wrapped in an 'include guard' to prevent
165accidental multiple inclusion of a single header. The definition name should be
166the upper-case file name followed by "_H". An example for fwk_mm.h follows:
167
168```c
169#ifndef FWK_MM_H
170#define FWK_MM_H
171
172(...)
173
174#endif /* FWK_MM_H */
175```
176
177The closing endif statement should be followed directly by a single-line comment
178which replicates the full guard name. In long files this helps to clarify what
179is being closed.
180
181Space between definition inside the header file should be a single line only.
182
183If a unit (header or C file) requires a header, it must include that header
184instead of relying on an indirect inclusion from one of the headers it already
185includes.
186
187Types
188-----
189Import `<stdint.h>` (part of the C Standard Library) for exact-width integer
190types (`uint8_t`, `uint16_t`, etc). These types can be used wherever the width
191of an integer needs to be specified explicitly.
192
193Use `uintptr_t` to handle addresses as integers.
194
195Import `<stdbool.h>` (also part of the C Standard Library) whenever a "boolean"
196type is needed.
197
198Avoid defining custom types with the "typedef" keyword where possible.
199Structures (struct) and enumerators (enum) should be declared and used with
200their respective keyword identifiers. If custom types are used then they must
201have the suffix "_t" appended to their type name where it is defined. This makes
202it easier to recognize types that have been defined using "typedef" when they
203appear in the code.
204
205When using sizeof() pass the variable name as the parameter to be evaluated, and
206not its type. This prevents issues arising if the type of the variable changes
207but the sizeof() parameter is not updated.
208
209```c
210size_t size;
211unsigned int counter;
212
213/* Preferred over sizeof(int) */
214size = sizeof(counter);
215```
216
217Use the `const` type qualifier as appropriate to specify values that cannot be
218modified. Quick reminder:
219
220- `const xyz_t object`, `object` is an object of type xyz_t which value cannot
221be modified.
222- `const xyz_t *ptr` or `xyz_t const *ptr`, `ptr` is a pointer to a constant
223object of type xyz_t. The value of the object cannot be modified, the value of
224the pointer can be modified.
225- `xyz_t * const ptr`, `ptr` is a constant pointer to an object of type xyz_t.
226The value of the object can be modified, the value of the pointer cannot be
227modified.
228- `const xyz_t * const ptr` or `xyz_t const * const ptr`, `ptr` is a constant
229pointer to a constant object of type xyz_t. The value of the object and the
230pointer cannot be modified.
231
232https://cdecl.org may help if in doubt.
233
234Static storage qualifier
235------------------------
236Declare functions and variables private to a C file as static.
237
238Operator Precedence
239-------------------
240Do not rely on the implicit precedence and associativity of C operators. Use
241parenthesis to make precedence and associativity explicit:
242
243```c
244if ((a == 'a') || (x == 'x')) {
245    do_something();
246}
247```
248
249Parenthesis around a unary operator and its operand may be omitted:
250
251```c
252if (!a || &a) {
253    do_something();
254}
255```
256
257Macros and Constants
258--------------------
259Logical groupings of constants should be defined as enumerations, with a common
260prefix, so that they can be used as parameter types. To find out the number of
261items in an "enum", make the last entry to be \<prefix\>_COUNT.
262
263```c
264enum command_id {
265    COMMAND_ID_VERSION,
266    COMMAND_ID_PING,
267    COMMAND_ID_EXIT,
268    /* Do not add entries after this line */
269    COMMAND_ID_COUNT
270};
271
272void process_cmd(enum command_id id)
273{
274    (...)
275}
276```
277
278Prefer inline functions instead of macros.
279
280Initialization
281--------------
282When local variables require being initialized to 0, please use their respective
283type related initializer value:
284- 0 (zero) for integers
285- 0.0 for float/double
286- \0 for chars
287- NULL for pointers
288- false for booleans (stdbool.h)
289
290Array and structure initialization should use designated initializers. These
291allow elements to be initialized using array indexes or structure field names
292and without a fixed ordering.
293
294Array initialization example:
295```c
296uint32_t clock_frequencies[3] = {
297    [2] = 800,
298    [0] = 675
299};
300```
301
302Structure initialization example:
303```c
304struct clock clock_cpu = {
305    .name = "CPU",
306    .frequency = 800,
307};
308```
309
310Integers
311--------
312To mitigate the risk of integer wrap-around, conversion or truncation errors:
313
314- represent integer values that should never be negative with the `unsigned`
315type that you expect to hold all possible values.
316
317- represent integer values that may be negative with the `signed` type that you
318expect to hold all possible values.
319
320- when taking untrusted integer input, ensure you check them against the lower
321and upper bound of the integer type you store them in.
322
323Device Register Definitions
324---------------------------
325The format for structures representing memory-mapped device registers is
326standardized.
327
328- The file containing the device structure must include `<stdint.h>` to gain
329access to the uintxx_t and UINTxx_C definitions.
330- The file containing the device structure must include `<fwk_macros.h>` to
331gain access to the FWK_R, FWK_W and FWK_RW macros.
332- All non-reserved structure fields must be prefixed with one of the above
333macros, defining the read/write access level.
334- Avoid C structure bit-fields when representing hardware registers - how
335bit-fields are represented in memory is implementation-defined.
336- Bit definitions should be declared via UINTxx_C macros.
337- Bit definitions must be prefixed by the register name it relates to. If bit
338definitions apply to multiple registers, then the name must be as common as
339possible and a comment must explicit show which registers it applies to.
340- The structure name for the programmer's view must follow the pattern "struct
341<device_name>_reg { ...registers... };"
342
343```c
344#include <stdint.h>
345#include <fwk_macros.h>
346
347struct devicename_reg {
348    /* Readable and writable register */
349    FWK_RW uint32_t CONFIG;
350           uint32_t RESERVED1;
351
352    /* Write-only register */
353    FWK_W  uint32_t IRQ_CLEAR;
354
355    /* Read-only register */
356    FWK_R  uint32_t IRQ_STATUS;
357           uint32_t RESERVED2[0x40];
358};
359
360/* Register bit definitions */
361#define CONFIG_ENABLE UINT32_C(0x00000001)
362#define CONFIG_SLEEP UINT32_C(0x00000002)
363
364#define IRQ_STATUS_ALERT UINT32_C(0x00000001)
365```
366
367__Note:__ A template file can be found in doc/template/device.h
368