In the world of embedded systems development, using consistent naming rules is super important for making your code easy to read, work with, and collaborate on. These naming rules help ensure that you give meaningful names to your modules, data types, functions, and variables. This makes it easier to create software for embedded systems that runs well and is reliable.
One thing to note is that these naming rules don't affect how fast your code runs, but they are absolutely essential for making your code understandable and easy to work with.
This document focuses specifically on naming rules and provides examples to show you how to use them. For the style of writing code, ENDA follows the Linux kernel coding standard, with a few small differences. You can find more details about that in the linked documentation below.
[Insert Exceptions Here]
If you want to learn more about other coding standards and conventions, you can also check out the Linux Kernel coding style, which gives detailed guidelines for how quality code is written in the Linux kernel.
When you create modules, give them names using only lowercase letters and numbers. These names should clearly describe what the module does. Use underscores between words to make them easy to read. Here are some examples:
-
Good Module Names:
- spi_controller.c
- uart_driver.c
-
Avoid:
- spiCtrl.c
- UART.c
- Each module should have one header file, and its name should match the module's name.
- In every header file, put in something called a "header guard" to stop it from being included more than once.
- Name these guards like this:
__<MODULE_NAME>_H
- Also, don't forget to include a license header in each header file.
#ifndef __SPI_CONTROLLER_H
#define __SPI_CONTROLLER_H
// The stuff in the header file goes here
#endif /* __SPI_CONTROLLER_H */
- Add a license header to each source file.
- Each source file should have these sections, in this order: a comment block, include statements, definitions of data types, constants, and macros, declarations of static data, prototypes for private functions, bodies of public functions, and finally, bodies of private functions. Here's an example:
/*
* This is a comment block.
*/
#include <stdio.h>
#include "spi_controller.h"
#define MAX_BUFFER_SIZE 100
static uint8_t buffer[MAX_BUFFER_SIZE];
static void private_function(void);
void public_function(void)
{
// The function's code goes here
}
static void private_function(void)
{
// More code for this function
}
- The names of new data types, like structures, unions, and enumerations, should only use lowercase letters and underscores, and they should end with '_t'.
- When naming these types, it's good to use
typedef
.
// Good Data Type Names
uint8_t
sensor_data_t
config_params_t
// Avoid
Uint8
dataStruct
myStruct
- If possible, use fixed-width integer types. Here's a list of them:
Type | Description |
---|---|
int8_t |
8-bit signed integer |
uint8_t |
8-bit unsigned integer |
int16_t |
16-bit signed integer |
uint16_t |
16-bit unsigned integer |
int32_t |
32-bit signed integer |
uint32_t |
32-bit unsigned integer |
int64_t |
64-bit signed integer |
uint64_t |
64-bit unsigned integer |
Naming your functions is crucial to make your code clear. Function names should use lowercase letters and underscores, just like module and data type names. The names should clearly show what the function does. If a function does something, it's good to use a verb in the name (like adc_read()
). If a function answers a question, you can name it that way (like led_is_on()
). Here are some examples:
-
Good Function Names:
- initialize_system()
- read_sensor_data()
- calculate_average()
-
Avoid:
- init()
- read()
- avg()
-
If a function is an interrupt service routine (ISR), make sure its name ends with
_isr
.
Variables are like building blocks of your code, and their names should tell you what they're used for. Variable names should be clear and not too long. Here are some examples:
-
Good Variable Names:
- temperature_reading
- sensor_data_buffer
- config_setting
-
Avoid:
- temp
- buf
- x
Macros are different from other names because they're usually constants or special commands for the preprocessor. Write macros in all uppercase letters with underscores between words. Also, always explain what your macros do with comments. Here are some examples:
-
Good Macro Names:
- #define MAX_TEMPERATURE 100
- #define ENABLE_SENSOR // Explains what it does
-
Avoid:
- #define maxTemp 100
- #define SENSOR_ON
- Enumarations are like a list of constants, and they should be named like macros.
- The names should start with the name of the data type, and then the name of the constant. Here's an example:
typedef enum {
SPI_CONTROLLER_SUCCESS,
SPI_CONTROLLER_FAILURE
} spi_controller_status_t;
By following the ENDA Embedded C Naming Convention Guide, you can make your code more consistent, easier to read, and simpler to work with. This will lead to more reliable and efficient embedded software development.
- Embedded C Coding Standard by Michael Barr
- Linux kernel coding style
Mainline Linux kernel .clang-format file; https://github.com/torvalds/linux/blob/master/.clang-format