Skip to content

Instantly share code, notes, and snippets.

@arifbalik
Last active September 4, 2023 19:36
Show Gist options
  • Save arifbalik/55f11e611400aa8b40fa8f500b5df768 to your computer and use it in GitHub Desktop.
Save arifbalik/55f11e611400aa8b40fa8f500b5df768 to your computer and use it in GitHub Desktop.
ENDA C Language Naming Convention Guide

ENDA Embedded C Naming Convention Guide

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.

Exceptions to the Linux Kernel Coding Style

[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.

Files (Modules)

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

Header Files

  • 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 */

Source Files

  • 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
}

Data Types

  • 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

Functions

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

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

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

Enums

  • 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.

References

  • Embedded C Coding Standard by Michael Barr
  • Linux kernel coding style
@arifbalik
Copy link
Author

Mainline Linux kernel .clang-format file; https://github.com/torvalds/linux/blob/master/.clang-format

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment