C-Coding Guidelines for making embedded systems safe

C-Coding Guidelines for making embedded systems safe.


C languages and its possible problems

C Programming language is widely used in the programming of Embedded software because of the specific reasons like

- Availability: For most of controllers, C is only efficient programming language available other than assembly language.

- Support for low level operations.

-Availability of optimizing compilers which produces faster, smaller and less RAM efficient codes.

- Requirement for portable code due to changing environment and market competition.

- Availability of auto code tools and open systems etc.

- Assembly language will not be suitable for critical applications since the possibility of bug getting introduced and testing efforts are very high.


Some of the problems which can be found in programs written in C language are

- Typing and careless mistakes done by programmer

- Wrong understanding of language by the programmer

- Program not compiles as programmer expects.

- Errors/Bugs in compiler

- Logical/Runtime errors in program.


So we should be very careful in wring C-programs for safety critical embedded systems.

Since C is highly matured and long been in use, lot of possible mistakes are known and also there are tools are available for the analysis of C code. So if we are coding in a constrained way keeping the guidelies collected from experienced programmers, then we can avoid most of the bugs and their by reduce the debugging efforts and  time to market.

There are standards available for the developement of C codes. Some standards are


ISO 9001/ISO 90003/TicKIT, MISRA, MIL, ANSI etc. Tools can be used for the static analysis of the code written.



Things to remember

  1. Avoid nesting of comments.
  2. Do not rely upon implementation defined behaviors. If using any implementation defined features, Then use with proper documentation and care.
  3. Keep a note on the character set and encodings supported by the compiler.
  4. Avoid using same variables names for variables in the inner scope of a block and outer scope of a block.
  5. Avoid reuse of variable names across modules.
  6. Use typedefs indicating type and signdness instead of basic types. eg:- typedef unsigned char uint8t; typedef unsigned char uint8 t; unsigned char uint8t;
  7. Use prototype declarations for functions which are visible at both the function and call.
  8. Data type of variables or functions which are declared in multiple locations should be compatible.
  9. Do not comment out code sections - Use #if, #ifdef etc. Because effect of comments inside the commented section of the code will be unexpected. eg:- Use bitfields only to keep shorter data variables to reduce the memory usage.
  10. Keep the length of signed bitfields to two or more. (Because one bit will be necessary for keeping the sign)
  11. Do not mix scope and linkages of variables. eg:- identifier name with internal linkage in one file and the same identifier name with external linkage in another file will cause confusion.
  12. Use prototypes for functions which are visible to modules containg function definition as well as function usage. (This will help in avoiding bugs caused due to function parameter mismatch)
  13. Use complete type for declaring a function name. eg:- const x = 10; should be const int x = 10; (In the first case the type is explicitly mentioned, which might cause confusion), extern x; should extern int x; (Do not relay upon the explicit type given by the compiler)
  14. Do not define objects or functions in header file. Use only declarations in header file. (Defining in header file will cause problems and confusion like multiple definitions)
  15. Restrict the scope of object or function only to the required module. (This will avoid accidental use of objects/functions by other modules).



==== Will be updated ===

1 comment :

  1. Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again.