Coding Style and Methods

  • This section contains information about the Coding style and methods for the RAPIDSEA stack’s.

Coding Style

Indentation & Formatting

  • Use 4 spaces per indentation level.

  • Keep lines under 80 characters.

General Rules

  • Use 1 space between keyword and opening bracket

Example:

/* Correct */
if (condition)
while (condition)
for (init; condition; step)
do {} while (condition)

/* Wrong */
if(condition)
while(condition)
for(init;condition;step)
do {} while(condition)
  • Do not use space between function name and opening bracket

Example:

int32_t s32_result = add(4, 3);              /* Correct */
int32_t s32_result = add (4, 3);             /* Wrong */
  • Opening curly bracket is always at the same line as keyword (for, while, do, switch, if, …)

Example:

uint8_t u8_index;
for (u8_index = 0; u8_index < 5; u8_index++)      /* Correct */
{

}

for (u8_index = 0; u8_index < 5; u8_index++){     /* Wrong */
}

for (u8_index = 0; u8_index < 5; u8_index++) {    /* Wrong */

}
  • Use single space before and after comparison and assignment operators

Example:

int32_t s32_value;
s32_value = 3 + 4;                              /* Correct */
for (s32_value = 0; s32_value < 5; s32_value++) /* Correct */

s32_value=3+4;                                  /* Wrong */
s32_value = 3+4;                                /* Wrong */
for (s32_value=0;s32_value<5;s32_value++)       /* Wrong */
  • Use single space after every comma

Example:

function_name(5, 4);        /* Correct */

function_name(4,3);         /* Wrong */
  • Declare all local variables of the same type in the same line

Example:

void rs_func(void)
{
    /* Type : 1 */
    uint8_t u8_val_1;                     /* Correct */

    /* Type : 2 */
    uint8_t u8_val_1, u8_val_2;           /* Correct */

    /* Type : 3 */
    uint8_t u8_val_1;
    uint8_t u8_val_2;                     /* Wrong, variable with char type already exists */
}
  • Declare local variables in order
    1. Structures and enumerations

    2. Integer types, wider unsigned type first

    3. Single/Double floating point

Example:

void rs_func(void)
{
    /* 1 */
    rs_struct_t data;     /* First custom structures */
    rs_struct_t* ptr_data;    /* Pointers too */

    /* 2 */
    uint32_t u32_data;
    int32_t s32_data;
    uint16_t u16_data;
    int16_t s16_data;
    uint8_t u8_data;
    /* ... */

    /* 3 */
    double d_data;
    float f_data;
}
  • Avoid variable assignment with function call in declaration, except for single variables

Example:

void rs_func(void)
{
    /* Avoid function calls when declaring variable */
    int32_t s32_val_1, s32_val_2 = add(1, 2);

    /* Use this */
    int32_t s32_val_1, s32_val_2;
    s32_val_2 = add(1, 2);

    /* This is correct */
    uint8_t u8_val_1 = 3, u8_val_2 = 4;
}
  • Always compare pointers against `NULL` value

Example:

  void* ptr_data;

/* ... */

/* Correct, compare against NULL */
if (ptr_data == NULL || ptr_data != NULL)
{
  //Operation
}

/* Wrong */
if (ptr_data || !ptr_data)
{
  //Operation
}
  • Always compare variable against zero, except if it is treated as boolean type

  • Never compare boolean-treated variables against zero or one. Use NOT (!) instead

Example:

int32_t s32_length = 5;  /* Counter variable */
uint8_t u8_status = 0;  /* Boolean-treated variable */
if (s32_length)         /* Wrong, s32_length is not treated as boolean */
if (s32_length > 0)     /* Correct, s32_length is treated as counter variable containing multi values, not only 0 or 1 */
if (s32_length == 0)    /* Correct, s32_length is treated as counter variable containing multi values, not only 0 or 1 */

if (u8_status)          /* Correct, variable is treated as boolean */
if (!u8_status)         /* Correct, -||- */
if (u8_status == 1)     /* Wrong, never compare boolean variable against 1! */
if (u8_status == 0)     /* Wrong, use ! for negative check */

Methods

Modules, Formats and Utils

  • In RAPIDSEA stack, Components(Modules, Formats and Utils) must use the init-based method instead of the handle-based method.

  • In the init-based method, the Components(Modules, Formats and Utils) info structure should be used for configuration.

  • Components(Modules, Formats and Utils) APIs must use the module info structure pointer as the first argument.

  • For Components(Modules, Formats and Utils), every operation is provided through an API. For example, in a ring buffer, the operations include push, pop, and peek.

Example:

Please refer below section,

Modules:

Formats:

Utils:

Protocols

  • In the RAPIDSEA stack, protocol stacks must use the handle-based method instead of the init-based method.

  • In the handle-based method (instance and configuration), the configuration structure is used only for configuration, while the instance is used for storing runtime information.

  • In this method, the protocol open call is used to initialize the protocol and return a handle value. This handle must be used as an argument for all other APIs (rs_ and rcb_) related to the corresponding protocol.

  • The reason for introducing the handle-based method is to allow a single protocol stack to manage multiple handles.

  • Example: If there are two or more RS232 ports, the stack should configure all ports and return a unique handle for each. The application can then operate each port separately using its handle.

  • Do not use blocking methods inside the stack.

  • The stack must be designed to run on both OS and Non-OS platforms

Example:

Please refer below section,

Devices Drivers

  • In the RAPIDSEA stack, Device drivers must use the handle-based method instead of the init-based method.

  • In the handle-based method (instance and configuration), the configuration structure is used only for configuration, while the instance is used for storing runtime information.

  • In this method, the open call is used to initialize the device and return a handle value. This handle must be used as an argument for all other APIs (rs_ and rcb_) related to the corresponding device drivers.

Example:

Please refer below section,

Manager

  • In the RAPIDSEA stack, “Manager” refers to the software logic responsible for controlling the device or hardware.

  • It must use the handle-based method instead of the init-based method.

  • In the handle-based method (instance and configuration), the configuration structure is used only for configuration, while the instance is used for storing runtime information.

  • In this method, the open call is used to initialize the manager and return a handle value. This handle must be used as an argument for all other APIs (rs_ and rcb_) related to the corresponding device managers.

Example:

Please refer below section,

Platform & HAL

Platform:

  • It must use the handle-based method instead of the init-based method.

  • In the handle-based method (instance and configuration), the configuration structure is used only for configuration, while the instance is used for storing runtime information.

  • In this method, the open call is used to initialize the Platform (Serial, socket) and return a handle value. This handle must be used as an argument for all other APIs (rs_ and rcb_) related to the corresponding Platform.

HAL:

  • The platform API functions call the HAL layer API directly, where the instance is a mandatory argument for the HAL layer APIs.

  • Example: For serial communication, the protocol stack’s API functions call rs_serial_open(..), which then routes to rs_hal_serial_open(…). This HAL call is further directed to the corresponding platform-specific implementation, such as Windows, Linux, i.MX RT, etc.

Example:

Please refer below section,