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
Structures and enumerations
Integer types, wider unsigned type first
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,