痞子衡嵌入式:恩智浦SDK驅動代碼風格、模板、檢查工具


  你們好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給你們講的是恩智浦 SDK 驅動的代碼風格html

  上週痞子衡受領導指示,給 SE 同事作了一個關於 SDK 代碼風格的分享。隨着組內新人的增多,這樣的培訓仍是頗有必要的。一是可讓新同事經過代碼風格來快速瞭解 SDK 驅動代碼結構,另外一方面也有利於新同事養成良好的編碼習慣。
  痞子衡剛畢業時曾經也整理過一篇代碼風格 《飛思卡爾軟件開發C語言編碼規範》,現在雖已經是恩智浦紀元,但規範大多仍是類似的,僅有微小更新。此次痞子衡將新版規範的要點提取了出來,而且還提供了標準模板,這樣你們學習起來更加方便。
  另外鑑於領導指定我做爲組內同事代碼風格人肉審查員(你們寫好的代碼須要由我人肉審查風格),這樣的工做若是真的徹底是人工去作,可想而言有多枯燥和低效,所以痞子衡計劃寫一個配套的自動化檢查工具,暫且叫 MCUXpresso SDK Coding Style Checker,歡迎你們來圍觀這個項目。git

  • 項目地址:https://github.com/JayHeng/MCUX-SDK-Coding-Style

mcux_sdk_coding_style

1.命名

1.1 變量

變量命名使用 CamelCase (小駱駝峯法),即第一個單詞以小寫字母開始,第二個單詞以及後面的每個單詞的首字母大寫,例如 myVariableNamegithub

  • 做用域可在文件外的全局變量加 g_ 前綴,如 g_myVariableName
  • 使用 static 修飾的全局變量加 s_ 前綴,如 s_myVariableName
  • 局部變量不加任何前綴,如 myVariableName
  • 其餘如 volatile, const 修飾或指針型變量,無需任何特殊表示
  • 命名中的大部分單詞都不要縮寫,除非是至關流行的縮寫,如 init 或 config

1.2 宏

宏命名使用下劃線命名法,單詞全大寫,例如 MY_MACRO_NAMEwindows

1.3 枚舉

枚舉類型的命名混合了多種命名法,且加了一些特殊先後綴微信

  • 枚舉類型名使用下劃線命名法,單詞全小寫,且如下劃線開頭
  • 枚舉元素名使用小駱駝峯法,但統一加 k 前綴
  • 可用 typedef 重命名枚舉類型名,使用下劃線命名法,但需加 _t 後綴
  • 枚舉變量名使用小駱駝峯法
typedef enum _my_enumeration_name
{
    kMyEnumerator0     = 0x00U,
    kMyEnumerator1     = 0x01U,

    kMyEnumeratorEnd   = 0x02U,
} my_enumeration_name_t;

static my_enumeration_name_t s_myEnumVariableName;

1.4 結構體

結構體類型的命名混合了多種命名法,且加了一些特殊先後綴函數

  • 結構體類型名使用下劃線命名法,單詞全小寫,且如下劃線開頭
  • 結構體成員名使用小駱駝峯法
  • 可用 typedef 重命名結構體類型名,使用下劃線命名法,但需加 _t 後綴
  • 結構體變量名使用小駱駝峯法
typedef struct _my_struct_name
{
    uint32_t myStructMember0;
    uint32_t myStructMember1;
} my_struct_name_t;

static my_struct_name_t s_myStructVariableName;

1.5 函數

函數命名使用 Pascal (大駱駝峯法),即把變量名稱的第一個字母也大寫,例如 MyFunctionName工具

  • 函數命名可由 [Action][Module][Feature] 組成,動做在前,特性在後。如 InitDeviceClock()
  • 一系列同類函數,可加 MODULE_ 前綴,前綴單詞全大寫。如 SD 卡操做的系列函數,可爲 SD_PowerOnCard()、SD_PowerOffCard()

2.代碼體

2.1 排版

  • 永遠不要使用 Tab 鍵(使用 4 個空格代替 Tab),須要以 4 個空格爲單位的縮進
  • 換行符應使用 "unix"(LF),而不是windows(CR + LF)
  • 文件結尾需空一行

2.2 花括號

不使用 K&R 風格花括號,左右括號都須要獨佔一行學習

2.3 局部變量定義

局部變量定義應老是放在所在最小做用域(即最近的 內)裏的最前面,而且一行代碼僅定義一個變量ui

void MyFunctionName(void)
{
    uint8_t myVariableName0;
    uint8_t myVariableName1;

    /* 代碼體 */

    for (;;)
    {
        uint8_t myVariableName2;

        /* 代碼體 */
    }
}

2.4 數字

代碼中全部無符號整型數字,均應加 "U" 後綴編碼

Hex: 0x1234ABCDU
Dec: 1234U

2.5 註釋

僅使用 /* */ 來註釋

/* 註釋風格1,單獨佔一行 */
uint8_t i = 0;

for (; i < 5;)
{
    i++; /* 註釋風格2,與代碼共享一行 */
}

2.6 條件編譯

#endif 後面須要加以下注釋

#if MY_MACRO_NAME

/* 代碼體 */

#endif /* MY_MACRO_NAME */

2.7 頭文件保護宏

任何一個 .h 文件都須要包含下面格式的頭文件保護宏代碼,宏的命名與頭文件名保持一致。如文件名爲 hello_world.h,則宏名爲 _HELLO_WORLD_H_

#ifndef _HEADER_FILENAME_
#define _HEADER_FILENAME_

/* 頭文件內容 */

#endif /* _HEADER_FILENAME_ */

3.總體模板

3.1 源文件(.c)

/* 包含頭文件代碼 */

#include "template.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/* 私有(僅本源文件內使用)宏、枚舉、結構體的定義 */

#define MAX_DEVICES  (128U)

/*******************************************************************************
 * Variables
 ******************************************************************************/

/* 全部全局變量(外部,靜態,常量,指針)的定義 */

uint32_t g_deviceIndex = 0;

static device_config_t s_deviceConfig;

const uint32_t g_maxDevices = MAX_DEVICES;

static volatile uint8_t *s_deviceData;

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/* 內部函數(即 static 修飾)的聲明 */

static uint32_t GetDeviceIndex(void);

/*******************************************************************************
 * Code
 ******************************************************************************/

/* 全部函數(外部,內部)的定義 */

void InitDevice(void)
{
    s_deviceConfig.index = 1;
    s_deviceConfig.mode = kDeviceMode1;
    memset(s_deviceConfig.data, 5, sizeof(s_deviceConfig.data));
    s_deviceConfig.isEnabled = true;
}

static uint32_t GetDeviceIndex(void)
{
    return s_deviceConfig.index;
}

int main(void)
{
    InitDevice();
    g_deviceIndex = GetDeviceIndex();

    while (1)
    {
    }
}

3.2 頭文件(.h)

/*
 * Copyright xxx
 * All rights reserved.
 *
 * xxx License
 *
 * Revision History:
 * v1.0 - Description
 */

#ifndef _TEMPLATE_H_
#define _TEMPLATE_H_

/* 包含頭文件代碼 */

#include <stdbool.h>
#include <stdint.h>
#include <string.h>

/*******************************************************************************
 * Definitions
 ******************************************************************************/

/* 公共(可被其餘源文件使用)宏、枚舉、結構體的定義 */

enum _device_mode
{
    kDeviceMode0    = 0x00U,
    kDeviceMode1    = 0x01U,

    kDeviceModeEnd  = 0x02U,
};

typedef struct _device_config
{
    uint32_t index;
    uint32_t mode;
    uint8_t data[16];
    bool isEnabled;
} device_config_t;

/* 外部全局變量的聲明 */

extern uint32_t g_deviceIndex;

extern const uint32_t g_maxDevices;

/*******************************************************************************
 * API
 ******************************************************************************/

#if defined(__cplusplus)
extern "C" {
#endif /*_cplusplus*/

/* 外部函數(可加 extern 修飾)的聲明 */

void InitDevice(void);

#if defined(__cplusplus)
}
#endif /*_cplusplus*/

#endif /* _TEMPLATE_H_ */

歡迎訂閱

文章會同時發佈到個人 博客園主頁CSDN主頁微信公衆號 平臺上。

微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就能夠在手機上第一時間看了哦。

相關文章
相關標籤/搜索