1*10465441SEvalZero# RT-Thread 编程风格 2*10465441SEvalZero 3*10465441SEvalZero这是一份 RT-Thread 开发人员的开发指引。RT-Thread 做为一份开源软件,它需要由不同 4*10465441SEvalZero的人采用合作的方式完成,这份文档是开发人员的一个指引。RT-Thread 的开发人员请遵 5*10465441SEvalZero守这样的编程风格。同时对于使用 RT-Thread 的用户,也可通过这份文档了解 RT-Thread 6*10465441SEvalZero代码内部一些约定从而比较容易的把握到 RT-Thread 的实现方式。 7*10465441SEvalZero 8*10465441SEvalZero## 1.目录名称 9*10465441SEvalZero 10*10465441SEvalZero目录名称如果无特殊的需求,请使用全小写的形式;目录名称应能够反应部分的意思,例 11*10465441SEvalZero如各芯片移植由其芯片名称构成或芯片类别构成;components 目录下能够反映组件的意义。 12*10465441SEvalZero 13*10465441SEvalZero## 2.文件名称 14*10465441SEvalZero 15*10465441SEvalZero文件名称如果无特殊的需求(如果是引用其他地方,可以保留相应的名称),请使用全小写 16*10465441SEvalZero的形式。另外为了避免文件名重名的问题,一些地方请尽量不要使用通用化、使用频率高 17*10465441SEvalZero的名称。 18*10465441SEvalZero 19*10465441SEvalZero## 3.头文件定义 20*10465441SEvalZero 21*10465441SEvalZeroC语言头文件为了避免多次重复包含,需要定义一个符号。这个符号的定义形式请采用如下 22*10465441SEvalZero的风格: 23*10465441SEvalZero 24*10465441SEvalZero```c 25*10465441SEvalZero #ifndef __FILE_H__ 26*10465441SEvalZero #define __FILE_H__ 27*10465441SEvalZero /* header file content */ 28*10465441SEvalZero #endif 29*10465441SEvalZero``` 30*10465441SEvalZero 31*10465441SEvalZero即定义的符号两侧采用 "__" 以避免重名,另外也可以根据文件名中是否包含多个词语而 32*10465441SEvalZero采用 "_" 连接起来。 33*10465441SEvalZero 34*10465441SEvalZero## 4.文件头注释 35*10465441SEvalZero 36*10465441SEvalZero在每个源文件文件头上,应该包括相应的版权信息,Change Log 记录: 37*10465441SEvalZero 38*10465441SEvalZero```c 39*10465441SEvalZero /* 40*10465441SEvalZero * File : rtthread.h 41*10465441SEvalZero * This file is part of RT-Thread RTOS 42*10465441SEvalZero * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team 43*10465441SEvalZero * 44*10465441SEvalZero * This program is free software; you can redistribute it and/or modify 45*10465441SEvalZero * it under the terms of the GNU General Public License as published by 46*10465441SEvalZero * the Free Software Foundation; either version 2 of the License, or 47*10465441SEvalZero * (at your option) any later version. 48*10465441SEvalZero * 49*10465441SEvalZero * This program is distributed in the hope that it will be useful, 50*10465441SEvalZero * but WITHOUT ANY WARRANTY; without even the implied warranty of 51*10465441SEvalZero * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 52*10465441SEvalZero * GNU General Public License for more details. 53*10465441SEvalZero * 54*10465441SEvalZero * You should have received a copy of the GNU General Public License along 55*10465441SEvalZero * with this program; if not, write to the Free Software Foundation, Inc., 56*10465441SEvalZero * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 57*10465441SEvalZero * 58*10465441SEvalZero * Change Logs: 59*10465441SEvalZero * Date Author Notes 60*10465441SEvalZero * 2006-03-18 Bernard the first version 61*10465441SEvalZero * 2006-04-26 Bernard add semaphore APIs 62*10465441SEvalZero * ... 63*10465441SEvalZero */ 64*10465441SEvalZero``` 65*10465441SEvalZero 66*10465441SEvalZero例如采用如上的形式。 67*10465441SEvalZero 68*10465441SEvalZero## 5.结构体定义 69*10465441SEvalZero 70*10465441SEvalZero结构体名称请使用小写英文名的形式,单词与单词之间采用 "_" 连接,例如: 71*10465441SEvalZero 72*10465441SEvalZero```c 73*10465441SEvalZero struct rt_list_node 74*10465441SEvalZero { 75*10465441SEvalZero struct rt_list_node *next; 76*10465441SEvalZero struct rt_list_node *prev; 77*10465441SEvalZero }; 78*10465441SEvalZero``` 79*10465441SEvalZero 80*10465441SEvalZero其中,"{","}" 独立占用一行,后面的成员定义使用缩进的方式定义。 81*10465441SEvalZero 82*10465441SEvalZero结构体等的类型定义请以结构体名称加上 "_t" 的形式作为名称,例如: 83*10465441SEvalZero 84*10465441SEvalZero```c 85*10465441SEvalZero typedef struct rt_list_node rt_list_t; 86*10465441SEvalZero``` 87*10465441SEvalZero 88*10465441SEvalZero因为内核中对象引用方便的缘故,采用了对象内核指针作为类型定义的形式,例如: 89*10465441SEvalZero 90*10465441SEvalZero```c 91*10465441SEvalZero typedef struct rt_timer* rt_timer_t; 92*10465441SEvalZero``` 93*10465441SEvalZero 94*10465441SEvalZero## 6.宏定义 95*10465441SEvalZero 96*10465441SEvalZero在RT-Thread中,请使用大写英文名称作为宏定义,单词之间使用 "_" 连接,例如: 97*10465441SEvalZero 98*10465441SEvalZero```c 99*10465441SEvalZero #define RT_TRUE 1 100*10465441SEvalZero``` 101*10465441SEvalZero 102*10465441SEvalZero## 7.函数名称、声明 103*10465441SEvalZero 104*10465441SEvalZero函数名称请使用小写英文的形式,单词之间使用 "_" 连接。提供给上层应用使用的 API 105*10465441SEvalZero接口,必须在相应的头文件中声明;如果函数入口参数是空,必须使用 void 作为入口参 106*10465441SEvalZero数,例如: 107*10465441SEvalZero 108*10465441SEvalZero```c 109*10465441SEvalZero rt_thread_t rt_thread_self(void); 110*10465441SEvalZero``` 111*10465441SEvalZero 112*10465441SEvalZero## 8.注释编写 113*10465441SEvalZero 114*10465441SEvalZero请使用英文做为注释,使用中文注释将意味着在编写代码时需要来回不停的切换中英文输 115*10465441SEvalZero入法从而打断编写代码的思路。并且使用英文注释也能够比较好的与中国以外的技术者进 116*10465441SEvalZero行交流。 117*10465441SEvalZero 118*10465441SEvalZero源代码的注释不应该过多,更多的说明应该是代码做了什么,仅当个别关键点才需要一些 119*10465441SEvalZero相应提示性的注释以解释一段复杂的算法它是如何工作的。对语句的注释只能写在它的上 120*10465441SEvalZero方或右方,其他位置都是非法的。 121*10465441SEvalZero 122*10465441SEvalZero## 9.缩进及分行 123*10465441SEvalZero 124*10465441SEvalZero缩进请采用 4 个空格的方式。如果没有什么特殊意义,请在 "{" 后进行分行,并在下一 125*10465441SEvalZero行都采用缩进的方式,例如: 126*10465441SEvalZero 127*10465441SEvalZero```c 128*10465441SEvalZero if (condition) 129*10465441SEvalZero { 130*10465441SEvalZero /* others */ 131*10465441SEvalZero } 132*10465441SEvalZero``` 133*10465441SEvalZero 134*10465441SEvalZero唯一的例外是 swtich 语句,switch-case 语句采用 case 语句与 swtich 对齐的方式, 135*10465441SEvalZero例如: 136*10465441SEvalZero 137*10465441SEvalZero```c 138*10465441SEvalZero switch (value) 139*10465441SEvalZero { 140*10465441SEvalZero case value1: 141*10465441SEvalZero break; 142*10465441SEvalZero } 143*10465441SEvalZero``` 144*10465441SEvalZero 145*10465441SEvalZerocase 语句与前面的 switch 语句对齐,后续的语句则采用缩进的方式。 146*10465441SEvalZero 147*10465441SEvalZero分行上,如果没有什么特殊考虑,请**不要在代码中连续使用两个以上的空行**。 148*10465441SEvalZero 149*10465441SEvalZero## 10.大括号与空格 150*10465441SEvalZero 151*10465441SEvalZero从代码阅读角度,建议每个大括号单独占用一行,而不是跟在语句的后面,例如: 152*10465441SEvalZero 153*10465441SEvalZero```c 154*10465441SEvalZero if (condition) 155*10465441SEvalZero { 156*10465441SEvalZero /* others */ 157*10465441SEvalZero } 158*10465441SEvalZero``` 159*10465441SEvalZero 160*10465441SEvalZero匹配的大括号单独占用一行,代码阅读起来就会有相应的层次而不会容易出现混淆的情况。 161*10465441SEvalZero 162*10465441SEvalZero空格建议在非函数方式的括号调用前留一个空格以和前面的进行区分,例如: 163*10465441SEvalZero 164*10465441SEvalZero```c 165*10465441SEvalZero if (x <= y) 166*10465441SEvalZero { 167*10465441SEvalZero /* others */ 168*10465441SEvalZero } 169*10465441SEvalZero 170*10465441SEvalZero for (index = 0; index < MAX_NUMBER; index ++) 171*10465441SEvalZero { 172*10465441SEvalZero /* others */ 173*10465441SEvalZero } 174*10465441SEvalZero``` 175*10465441SEvalZero 176*10465441SEvalZero建议在括号前留出一个空格(涉及的包括 if、for、while、swtich 语句),而运算表达式 177*10465441SEvalZero中,运算符与字符串间留一个空格。另外,不要在括号的表达式两侧留空格,例如: 178*10465441SEvalZero 179*10465441SEvalZero```c 180*10465441SEvalZero if ( x <= y ) 181*10465441SEvalZero { 182*10465441SEvalZero /* other */ 183*10465441SEvalZero } 184*10465441SEvalZero``` 185*10465441SEvalZero 186*10465441SEvalZero这样括号内两侧的空格是不允许的。 187*10465441SEvalZero 188*10465441SEvalZero## 11.trace、log信息 189*10465441SEvalZero 190*10465441SEvalZero在 RT-Thread 中,普遍使用的 log 方式是 rt_kprintf。rt_kprintf 在 RT-Thread 被实 191*10465441SEvalZero现成一个采用轮询、非中断方式的字串输出,能够适合于在中断这类"即时"显示日志的场 192*10465441SEvalZero合。因为这种轮询方式的存在,也必然会影响到日志输出的时序关系。 193*10465441SEvalZero 194*10465441SEvalZero建议在代码中不要频繁的使用 rt_kprintf 作为日志输出,除非你真正的明白,你的代码 195*10465441SEvalZero运行占用的时间多一些也没什么关系。 196*10465441SEvalZero 197*10465441SEvalZero日志输出应该被设计成正常情况下是关闭状态(例如通过一个变量或宏就能够开启),并且 198*10465441SEvalZero当真正输出日志时,日志是易懂易定位问题的方式。"天书式"的日志系统是糟糕的,不合 199*10465441SEvalZero理的。 200*10465441SEvalZero 201*10465441SEvalZero## 12.函数 202*10465441SEvalZero 203*10465441SEvalZero在内核编程中,函数应该尽量精简,仅完成相对独立的简单功能。函数的实现不应该太长 204*10465441SEvalZero,函数实现太长,应该反思能够如何修改(或拆分)使得函数更为精简、易懂。 205*10465441SEvalZero 206*10465441SEvalZero## 13.对象 207*10465441SEvalZero 208*10465441SEvalZeroRT-Thread 内核采用了 C 语言对象化技术,命名表现形式是:对象名结构体表示类定义、 209*10465441SEvalZero对象名 + 动词短语形式表示类方法,例如: 210*10465441SEvalZero 211*10465441SEvalZero```c 212*10465441SEvalZero struct rt_timer 213*10465441SEvalZero { 214*10465441SEvalZero struct rt_object parent; 215*10465441SEvalZero /* other fields */ 216*10465441SEvalZero }; 217*10465441SEvalZero typedef struct rt_timer* rt_timer_t; 218*10465441SEvalZero``` 219*10465441SEvalZero 220*10465441SEvalZero结构体定义 rt_timer 代表了 timer 对象的类定义; 221*10465441SEvalZero 222*10465441SEvalZero```c 223*10465441SEvalZero rt_timer_t rt_timer_create(const char* name, 224*10465441SEvalZero void (*timeout)(void* parameter), void* parameter, 225*10465441SEvalZero rt_tick_t time, rt_uint8_t flag); 226*10465441SEvalZero rt_err_t rt_timer_delete(rt_timer_t timer); 227*10465441SEvalZero rt_err_t rt_timer_start(rt_timer_t timer); 228*10465441SEvalZero rt_err_t rt_timer_stop(rt_timer_t timer); 229*10465441SEvalZero``` 230*10465441SEvalZero 231*10465441SEvalZerort_timer + 动词短语的形式表示能够应用于 timer 对象的方法。 232*10465441SEvalZero 233*10465441SEvalZero在创建一个新的对象时,应该思考好,对象的内存操作处理:是否允许一个静态对象存在 234*10465441SEvalZero,或仅仅支持从堆中动态分配的对象。 235*10465441SEvalZero 236*10465441SEvalZero## 14. 用 astyle 自动格式化代码 237*10465441SEvalZero 238*10465441SEvalZero 参数:--style=allman 239*10465441SEvalZero --indent=spaces=4 240*10465441SEvalZero --indent-preproc-block 241*10465441SEvalZero --pad-oper 242*10465441SEvalZero --pad-header 243*10465441SEvalZero --unpad-paren 244*10465441SEvalZero --suffix=none 245*10465441SEvalZero --align-pointer=name 246*10465441SEvalZero --lineend=linux 247*10465441SEvalZero --convert-tabs 248*10465441SEvalZero --verbose 249