嵌入式代码之编写规范

电子说

1.3w人已加入

描述

嵌入式代码编码规范,用于规范自己的代码,增强可读性,非标准规范。最好能强制自己形成良好的编码风格,有利于开发大规模程序而不显得杂乱。参考STM32固件库编码风格和FreeRTOS编码风格。

一、工程文件组织结构

新建工程文件应包含以下全部或部分文件夹:

usrSrc:用户源文件,用来存放.c文件和其他的源文件。main.c应放在这里。

usrInc:用户头文件,用来存放.h文件。

usrDoc:用户说明文档,用来存放用户在开发过程中书写的文档,一般为.txt格式。例如Readme.txt,指令说明等。

Src:引用库的源文件。

Inc:应用库的头文件。

Lib:引用的库文件。

一个工程一定要包含一个main.c文件,只用来存放main函数。其余函数的定义应在相应的.c文件中,声明在相应的.h文件中。

So can you help to prepare our suggest contents display in the page (e.g. tools intro, feature, which videos, which documents etc) to us first? We will then further discuss with Infineon if anything need to change / add.

二、源文件

文件头,文件的简介

/************************************************************************* * Copyright (c) 2018, Xiaodan * All rights reserved. * * File name : USB_Ctrl.c * Brief : USB API source code. * Introduce the main function or content of this document briefly. * Revision : 1.01 * Author : Xiaodan * Date : 2018.11.06 * Update : Introduce the difference from previous version.*************************************************************************/

必要的注释和说明 

源文件应该只包含它自己的头文件,其他的头文件在他自己的头文件中包含。

源文件中只声明局部函数,全局函数在头文件中声明。

全局变量在相应的源文件中定义,在头文件中用extern声明。

类型定义在头文件中定义。

/* Includes -----------------------------------------------------------*//*only include it's own header file, the others header file included by USB_Ctrl.h*/#include "USB_Ctrl.h"/* Declaration --------------------------------------------------------*//*here are the local function declare, global fuction declare in header file.*/void delay( uint32_t n);/* Global variable ----------------------------------------------------*/

函数头

/****************************************************** * Brief : Delay n ms * Parameter : * n: the number of delay microsecond. * Return : None.*******************************************************/void delay( uint32_t n){for( i=0; i<110; i++) ;}

三、头文件

文件头,文件的简介

/************************************************************************* - Copyright (c) 2018, Xiaodan - All rights reserved. - - File name : USB_Ctrl.h - Brief : The header file of USB_Ctrl.c. - Revision : 1.01 - Author : Xiaodan - Date : 2018.11.06 - Update : Introduce the difference from previous version.*************************************************************************/

必要的注释和声明

/* Includes -----------------------------------------------------------*//* Define -------------------------------------------------------------*//* Typedef ------------------------------------------------------------*/typedef unsigned int apiStatus; //api return code/* Enume --------------------------------------------------------------*//* Extern -------------------------------------------------------------*//* Declaration --------------------------------------------------------*/

四、命名规则

参考FreeRTOS命名规则,MISRA C规范。

定义变量时尽量使用uint8_t 、uint16_t 、uint32_t等。头文件为stdint.h。

typedef signed char int8_t;typedef short int16_t;typedef int int32_t;typedef long long int64_t;typedef unsigned char uint8_t;typedef unsigned short uint16_t;typedef unsigned int uint32_t;typedef unsigned long long uint64_t;

uint32_t类型的变量使用前缀ul,这里’u’表示’unsigned’,’l’表示’long’

uint16_t类型的变量使用前缀us,这里’u’表示’unsigned’,’s’表示’short’

uint8_t类型的变量使用前缀uc,这里’u’表示’unsigned’,’c’表示’char’

枚举类型变量使用前缀e

指针类型变量在类型基础上附加前缀p,比如指向uint16_t的指针变量前缀为pus

与MISRA指南一致,char类型变量仅被允许保存ASCII字符,前缀为c

与MISRA指南一致,char *类型变量仅允许指向ASCII字符串,前缀为pc

宏定义全部使用大写,两个单词之间用下划线隔开。

具有文件作用域的对象尽量声名为static的。

全局变量加前缀’g_’。整个工程都可以用的变量,不局限于文件作用域。

五、代码风格

缩进:缩进使用制表符,一个制表符等于4个空格。

注释:注释单行不超过80列,特殊情况除外。

布局:源代码应被设计成尽可能的易于查看和阅读。

下面的代码片中,第一部分展示文件布局,第二部分展示C代码设计格式。

/* #defines, 在合理的位置添加括号. */#define A_DEFINITION ( 1 )/* * 随后是Static (文件内部的)函数原型, * 如果注释有多行,参照本条注释风格---每一行都以’*’起始. */static void prvAFunction( uint32_t ulParameter );/* 文件作用域变量(本文件内部使用),要在函数体定义之前. */static BaseType_t xMyVariable./* 每一个函数的结束都有一行破折号,破折号与下面的第一个函数之间留一行空白。*//*-----------------------------------------------------------*/void vAFunction( void ){/* 函数体在此定义,注意要用大括号括住 */}/*-----------------------------------------------------------*/static UBaseType_t prvNextFunction( void ){/* 函数体在此定义. */}/*-----------------------------------------------------------*//* * 函数名字总是占一行,包括返回类型。左括号之前没有空格左括号之后有一个空格, * 每个参数后面有一个空格,参数的命名应该具有一定的描述性. */void vAnExampleFunction( long lParameter1, unsigned short usParameter2 ){/* 变量声明没有缩进. */uint8_t ucByte;/* 代码要对齐. 大括号占独自一行. */for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ ) {/* 这里再次缩进. */ }}/* * for、while、do、if结构具有相似的模式。这些关键字和左括号之间没有空格。 * 左括号之后有一个空格,右括号前面也有一个空格,每个分号后面有一个空格。 * 每个运算符的前后各一个空格。使用圆括号明确运算符的优先级。不允许有0 * 以外的数字(魔鬼数)出现,必要时将这些数字换成能表示出数字含义的常量或 * 宏定义。 */for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ ){}while( ucByte < fileBUFFER_LENGTH ){}/* * 由于运算符优先级的复杂性,我们不能相信自己对运算符优先级时刻保持警惕 * 并能正确的使用,因此对于多个表达式运算时,使用括号明确优先级顺序 */if( ( ucByte < fileBUFFER_LENGTH ) && ( ucByte != 0U ) ){ ulResult = ( ( ulValue1 + ulValue2 ) - ulValue3 ) * ulValue4;}/* 条件表达式也要像其它代码那样对齐。*/#if( configUSE_TRACE_FACILITY == 1 ){/* 向TCB增加一个用于跟踪的计数器. */ pxNewTCB->uxTCBNumber = uxTaskNumber;}#endif/*方括号前后各留一个空格*/ucBuffer[ 0 ] = 0U;ucBuffer[ fileBUFFER_LENGTH - 1U ] = 0U;

六、编程思想

将特定功能的代码封装成函数。

七、C语言编程规则

参考MISRA

Rule1:不得使用三元操作符(? : )。

Rule2:不得残留被注释掉的废代码。

Rule3:所有标识符不超过31字符。

Rule4:不同名空间中的变量名不得相同。

例如:

typedef struct MyStruct {... } MyStruct; (违规) struct Person { char* name; ...};char name[32]; (违规)

Rule5: 不得使用char, int, float, double, long等基本类型,应该用stdint.h中定义的类型显示表示类型的大小,如uint16_t、int32_t等。

Rule6:禁止使用八进制数。(因为086U这样的常数很容易引起误解)。

Rule7:不得定义与外部作用域中某个标识符同名的对象,以避免遮盖外部作用域中的标识符。

Rule8:具有文件作用域的对象尽量声名为static的。

Rule9:自动对象(栈对象)使用前必须赋初值。

Rule10:操作符&&和||的右侧表达式不得具有副作用(side-effect)。

也就是说,象 if (x == 20 && ++y == 19)这样的表达式被禁止。

Rule11:不得对有符号数施加位操作,例如 1 << 4 将被禁止,必须写 1UL << 4。

Rule12:不得对有副作用的表达式施加sizeof操作符。

Rule13:除了循环控制语句,不得使用逗号表达式。

Rule14:不得显式判断浮点数的相等性和不等性。

Rule15:不得遗留“永远不会用到”的代码。

Rule16:除了switch语句,不得使用标号(label)。

Rule17:不得使用goto。

Rule18:不得使用continue。

Rule19:除了switch语句,不得使用break

Rule20:if, else if, else, while, do..while, for语句块必须使用{}括起。

Rule21:循环计数器的值不得在循环体内修改。

Rule22:禁止任何直接和间接的递归函数调用。

Rule23:不应该使用#undef。

Rule24:不得将宏作为参数传给宏函数。

Rule25:在一个宏定义中,#或##符号只能出现一次。

Rule26:禁止指针运算(代之以数组下标运算)。

Rule27:禁止超过两级的指针。

Rule28:禁止使用指向函数的非常量指针。

Rule29:禁止使用setjmp, longjmp。

Rule30:禁止使用atoi, atof, atol。(这个我很赞成,建议使用strtol, strtod等函数)

Rule31:禁止使用abort, exit, getenv。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分