[RT thread learning notes] learn the C language coding specification of RT thread together

Keywords: C rt-thread

preface

Recently, bloggers are learning about RT thread, an open source project, and began to slowly learn and understand its open source code, and slowly began to contact its code specifications.
In my opinion, the first step to participate in an open source project is to understand its specifications, of which the code writing specification is a very important part.

RT thread programming style

This is a development guide for RT thread developers. As an open source software, RT thread needs to be completed by different people in a cooperative way. This document is a guide for developers. RT thread developers should follow this programming style. At the same time, users who use RT thread can also understand some internal conventions of RT thread code through this document, so as to easily grasp the implementation method of RT thread.

1. Directory name

If there are no special requirements for the directory name, please use all lowercase form; The directory name should be able to reflect part of the meaning, for example, each chip transplant is composed of its chip name or chip category; The components directory can reflect the meaning of components.

2. Document name

If there are no special requirements for the file name (if it refers to other places, the corresponding name can be retained), please use all lowercase form. In addition, in order to avoid the problem of duplicate file names, please try not to use generic and frequently used names in some places.

Device driver source code file: DRV_ The naming method of class. C, such as:

  • drv_spi.c
  • drv_gpio.c

3. Header file definition

In order to avoid repeated inclusion of C language header files, a symbol needs to be defined. Please use the following style for the definition of this symbol:

    #ifndef __FILE_H__
    #define __FILE_H__
    /* header file content */
    #endif

That is, "_" is used on both sides of the defined symbol to avoid duplicate names. In addition, "" can also be used to connect according to whether the file name contains multiple words.

4. Header comments

The header of each source file should include the corresponding copyright information. Change Log records:

/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-03-18     Bernard      the first version
 * 2006-04-26     Bernard      add semaphore APIs
 */

For example, the above form is adopted.

5. Structure definition

The structure name shall be in the form of lowercase English name, and words shall be connected with "", for example:

    struct rt_list_node
    {
        struct rt_list_node *next;
        struct rt_list_node *prev;
    };

Where "{" and "}" occupy a separate line, and the subsequent member definitions are defined by indentation.

For the type definition of structure, etc., please take the structure name plus "_t" as the name, for example:

    typedef struct rt_list_node rt_list_t;

Because of the convenience of object reference in the kernel, the object kernel pointer is used as the form of type definition, for example:

    typedef struct rt_timer* rt_timer_t;

6. Macro definition

In RT thread, please use the capitalized English name as the macro definition, and use "" connection between words, for example:

    #define RT_TRUE                         1

7. Function name and declaration

The function name shall be in lowercase English, and "_" shall be used to connect words. API interface provided to upper application must be declared in corresponding header file; If the function entry parameter is empty, void must be used as the entry parameter, for example:

rt_thread_t rt_thread_self(void);

Internal static function naming: start with underscore and use_ class_method format, not carried_ rt_ Beginning, such as function naming in kernel or driver file:

/* IPC object init */
static rt_err_t _ipc_object_init()

/* UART driver ops */
static rt_err_t _uart_configure()
static rt_err_t _uart_control()                    

Call the function name of the registered device interface: use rt_hw_class_init() format, for example:

int rt_hw_uart_init(void)
int rt_hw_spi_init(void)

8. Preparation of notes

Please use English as comments. Using Chinese comments will mean that you need to switch Chinese and English input methods back and forth when writing code, so as to interrupt the idea of writing code. And the use of English notes can also better communicate with technicians outside China.

Statement comments:

There should not be too many comments on the source code. It should be more about what the code does. Only when individual key points need some corresponding prompt comments to explain how a complex algorithm works. Comments on a statement can only be written above or to the right, and other positions are illegal.

/* Your English notes */

Function comments:

The comment starts with / * * and ends with * /. The function comment is written in the middle. The constituent elements are as follows. There is an empty line between the description of each element, and the first column is aligned:

  • @brief + briefly describe the function. In the description, the function is emphasized. The first letter of each sentence is capitalized and the end of each sentence is added with an English period.
  • @note + function description. Some points of function or function that are not reflected in the above brief description can be explained. The first letter of each sentence is capitalized and the end of each sentence is added with an English period.
  • @see + related APIs are listed. If there are APIs that are highly related to the current function, you can list them.
  • @param + take the parameter as the subject + be verb + description to explain the meaning or source of the parameter.
  • @Return + enumeration return value + return value means that if the return value is data, it directly introduces the function of data.
  • @Precautions for using the warning + function. When using the function, describe the matters needing attention, such as the use environment, use mode, etc. Each sentence begins with a capital letter and ends with an English full stop.

Please refer to the RT thread / SRC / IPC. C source code file for the annotation template. Please refer to grammarly and Google translation for English annotations.

/**
 * @brief    The function will initialize a static event object.
 *
 * @note     For the static event object, its memory space is allocated by the compiler during compiling,
 *           and shall placed on the read-write data segment or on the uninitialized data segment.
 *           By contrast, the rt_event_create() function will allocate memory space automatically
 *           and initialize the event.
 *
 * @see      rt_event_create()
 *
 * @param    event is a pointer to the event to initialize. It is assumed that storage for the event
 *           will be allocated in your application.
 *
 * @param    name is a pointer to the name that given to the event.
 *
 * @param    value is the initial value for the event.
 *           If want to share resources, you should initialize the value as the number of available resources.
 *           If want to signal the occurrence of an event, you should initialize the value as 0.
 *
 * @param    flag is the event flag, which determines the queuing way of how multiple threads wait
 *           when the event is not available.
 *           The event flag can be ONE of the following values:
 *
 *               RT_IPC_FLAG_PRIO          The pending threads will queue in order of priority.
 *
 *               RT_IPC_FLAG_FIFO          The pending threads will queue in the first-in-first-out method
 *                                         (also known as first-come-first-served (FCFS) scheduling strategy).
 *
 *               NOTE: RT_IPC_FLAG_FIFO is a non-real-time scheduling mode. It is strongly recommended to
 *               use RT_IPC_FLAG_PRIO to ensure the thread is real-time UNLESS your applications concern about
 *               the first-in-first-out principle, and you clearly understand that all threads involved in
 *               this event will become non-real-time threads.
 *
 * @return   Return the operation status. When the return value is RT_EOK, the initialization is successful.
 *           If the return value is any other values, it represents the initialization failed.
 *
 * @warning  This function can ONLY be called from threads.
 */
rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag)
{
   ... 
}

9. Indent and branch

Please indent with 4 spaces. If there is no special meaning, please branch after "{" and indent the next line, for example:

    if (condition)
    {
        /* others */
    }

The only exception is the switch statement. The switch case statement aligns the case statement with the switch, for example:

    switch (value)
    {
    case value1:
        break;
    }

The case statement is aligned with the previous switch statement, and the subsequent statements are indented. On the branch line, if there is no special consideration, please do not use more than two empty lines in the code continuously.

10. Braces and spaces

From the perspective of code reading, it is recommended that each brace occupy a separate line instead of following the statement, for example:

    if (condition)
    {
        /* others */
    }

The matched braces occupy a single line, and the code will have a corresponding level when reading without confusion. It is recommended to leave a space before non functional bracket calls to distinguish them from the previous ones, for example:

    if (x <= y)
    {
        /* others */
    }

    for (index = 0; index < MAX_NUMBER; index ++)
    {
        /* others */
    }

It is recommended to leave a space before the parenthesis (including if, for, while and switch statements), and a space between the operator and the string in the operation expression. In addition, do not leave spaces on both sides of the parenthesis expression, for example:

    if ( x <= y )
    {
        /* other */
    }

In this way, spaces on both sides of brackets are not allowed.

11.trace and log information

In RT thread, the commonly used log mode is rt_kprintf. Rt_kprintf is implemented as a polling and non interrupting string output in RT thread, which can be suitable for "instant" log display such as interruption. Because of the existence of this polling mode, it will also affect the timing relationship of log output.

It is recommended not to use rt_kprintf as log output frequently in your code, unless you really understand that it doesn't matter if your code takes more time to run.

The log output should be designed to be closed under normal circumstances (for example, it can be turned on through a variable or macro), and when the log is actually output, the log is an easy to understand and locate problem. The "heavenly book" log system is bad and unreasonable.

12. Function

In kernel programming, functions should be as concise as possible and only complete relatively independent simple functions. The function implementation should not be too long. The function implementation should be too long. We should reflect on how to modify (or split) to make the function more concise and easy to understand.

13. Object

RT thread kernel adopts C language objectification technology. The naming expression forms are: object name structure represents class definition, object name + verb phrase represents class method, for example:

    struct rt_timer
    {
        struct rt_object parent;
        /* other fields */
    };
    typedef struct rt_timer* rt_timer_t;

Structure definition rt_timer represents the class definition of timer object;

rt_timer_t rt_timer_create(const char* name,
                           void (*timeout)(void* parameter), 
                           void* parameter,
                           rt_tick_t time, rt_uint8_t flag);
rt_err_t rt_timer_delete(rt_timer_t timer);
rt_err_t rt_timer_start(rt_timer_t timer);
rt_err_t rt_timer_stop(rt_timer_t timer);

rt_ The form of timer + verb phrase represents the method that can be applied to the timer object.

When creating a new object, you should think about the memory operation of the object: whether to allow a static object to exist, or only support objects dynamically allocated from the heap.

14. Format code

Formatting code is to automatically organize your code through scripts and make it conform to the coding specification of RT thread. This article provides the following two methods of automatically formatting code, which can be selected or used together.

Format with style

Use astyle to automatically format the code. The parameters are as follows:

      --style=allman
      --indent=spaces=4
      --indent-preproc-block
      --pad-oper
      --pad-header
      --unpad-paren
      --suffix=none
      --align-pointer=name
      --lineend=linux
      --convert-tabs
      --verbose

It can meet the specifications of function spaces, indents, function statements, etc.

Formatting with formatting

use formatting Scan files to format code: formatting can meet the basic requirements of coding rules, such as:

  • Unify the source file encoding to UTF-8
  • Replace the TAB key with 4 spaces
  • Delete the extra space at the end of each line, and unify the line feed character as' \ n '

important clause

This specification comes from RT thread project. See: RT thread programming style , invasion and deletion!

More sharing

Welcome to my github warehouse 01workstation , daily share some development notes and project practice, welcome to correct the problem.

You are also welcome to follow my RT thread homepage, CSDN homepage and columns:

[RT thread homepage: Architect Li Ken]

[CSDN homepage: http://yyds.recan-li.cn ]

[C/C + + language programming column]

[GCC column]

[information security column]

[RT thread Development Notes]

[freeRTOS Development Notes]

If you have any questions, you can discuss with me and answer them. Thank you.

Posted by dr.wong on Tue, 30 Nov 2021 16:39:11 -0800