FreeRTOS系列第4篇---FreeRTOS編碼標(biāo)準(zhǔn)及風(fēng)格指南
1.編碼標(biāo)準(zhǔn)
FreeRTOS的核心源代碼遵從MISRA編碼標(biāo)準(zhǔn)指南。這個標(biāo)準(zhǔn)篇幅稍長,你可以在MISRA官方網(wǎng)站花少量錢買到,這里不再復(fù)制任何標(biāo)準(zhǔn)。
「FreeRTOS源代碼不符合MISRA標(biāo)準(zhǔn)的項目如下所示:」
-
有兩個API函數(shù)有多個返回點(diǎn)。MISRA編碼標(biāo)準(zhǔn)強(qiáng)制規(guī)定:一個函數(shù)在其結(jié)尾應(yīng)該有單一的返回點(diǎn)。 -
指針?biāo)銛?shù)運(yùn)算,在創(chuàng)建任務(wù)時,為了兼容8、16、20、24、32位總線,不可避免的使用了指針?biāo)銛?shù)運(yùn)算。MISRA編碼標(biāo)準(zhǔn)強(qiáng)制規(guī)定:指針的算術(shù)運(yùn)算只能用在指向數(shù)組或數(shù)組元素的指針上。 -
默認(rèn)情況下,跟蹤宏為空語句,因此不符合MISRA的規(guī)定。MISRA編碼標(biāo)準(zhǔn)強(qiáng)制規(guī)定:預(yù)處理指令在句法上應(yīng)該是有意義的。
FreeRTOS可以在很多不同編譯器中編譯,其中的一些編譯器比同類有更高級特性。因為這個原因,F(xiàn)reeRTOS不使用任何非C語言標(biāo)準(zhǔn)的特性或語法。一個例外情況是頭文件stdint.h。在文件夾FreeRTOS/Source/include下包含一個叫做stdint.readme的文件,如果你的編譯器不提供stdint類型定義,可以將stdint.readme文件重命名為stdint.h。
2命名規(guī)則
RTOS內(nèi)核和演示例程源代碼使用以下規(guī)則:
1> 變量
-
uint32_t類型的變量使用前綴ul,這里’u’表示’unsigned’,’l’表示’long’ -
uint16_t類型的變量使用前綴us,這里’u’表示’unsigned’,’s’表示’short’ -
uint8_t類型的變量使用前綴uc,這里’u’表示’unsigned’,’c’表示’char’ -
非stdint類型的變量使用前綴x,比如基本的Type_t和TickType_t類型,這些類型在移植層定義,定義成符合處理器架構(gòu)的最高效類型; -
非stdint類型的無符號變量使用前綴ux,比如UbaseType_t(unsigned BaseType_t) -
size_t類型的變量使用前綴x; -
枚舉類型變量使用前綴e -
指針類型變量在類型基礎(chǔ)上附加前綴p,比如指向uint16_t的指針變量前綴為pus -
與MISRA指南一致,char類型變量僅被允許保存ASCII字符,前綴為c -
與MISRA指南一致,char *類型變量僅允許指向ASCII字符串,前綴為pc
2> 函數(shù)
-
在文件作用域范圍的函數(shù)前綴為prv -
API函數(shù)的前綴為它們的返回類型,當(dāng)返回為空時,前綴為v -
API函數(shù)名字起始部分為該函數(shù)所在的文件名。比如vTaskDelete函數(shù)定義在tasks.c,并且該函數(shù)返回空。
3> 宏
-
宏的名字起始部分為該宏定義所在的文件名的一部分。比如configUSE_PREEMPTION定義在FreeRTOSConfig.h文件中。 -
除了前綴,宏剩下的字母全部為大寫,兩個單詞間用下劃線(’_’)隔開。
3數(shù)據(jù)類型
只有stdint.h和RTOS自己定義的數(shù)據(jù)類型可以使用,但也有例外情況,如下所示:
-
char:與MISRA編碼標(biāo)準(zhǔn)指南一致,char類型變量僅被允許保存ASCII字符
-
char *:與MISRA編碼標(biāo)準(zhǔn)指南一致,char *類型變量僅允許指向ASCII字符串。當(dāng)標(biāo)準(zhǔn)庫函數(shù)期望一個char *參數(shù)時,這樣做可以消除一些編譯器警告;特別是考慮到有些編譯器將char類型當(dāng)做signed類型,還有些編譯器將char類型當(dāng)做unsigned類型。有三種類型會在移植層定義,它們是:
-
TickType_t:如果configUSE_16_BIT_TICKS為非零(條件為真),TickType_t定義為無符號16位類型。如果configUSE_16_BIT_TICKS為零(條件為假),TickType_t定義為無符號32位類型。注:32位架構(gòu)的微處理器應(yīng)設(shè)置configUSE_16_BIT_TICKS為零。
-
BaseType_t:定義為微處理器架構(gòu)效率最高的數(shù)據(jù)類型。比如,在32位架構(gòu)處理器上,BaseType_t應(yīng)該定義為32位類型。在16位架構(gòu)處理器上,BaseType_t應(yīng)該定義為16位類型。如果BaseType_t定義為char,對于函數(shù)返回值一定要確保使用的是signed char,否則可能造成負(fù)數(shù)錯誤。
-
UbaseType_t:這是一個無符號BaseType_t類型
4風(fēng)格指南
-
縮進(jìn):縮進(jìn)使用制表符,一個制表符等于4個空格。 -
注釋:注釋單行不超過80列,特殊情況除外。不使用C++風(fēng)格的雙斜線(//)注釋 -
布局:FreeRTOS的源代碼被設(shè)計成盡可能的易于查看和閱讀。下面的代碼片中,第一部分展示文件布局,第二部分展示C代碼設(shè)計格式。
/* 首先在這里包含庫文件... */
#include <stdlib.h>
/* ...然后是FreeRTOS的頭文件... */
#include "FreeRTOS.h"
/* ...緊接著包含其它頭文件. */
#include "HardwareSpecifics.h"
/* 隨后是#defines, 在合理的位置添加括號. */
#define A_DEFINITION ( 1 )
/*
* 隨后是Static (文件內(nèi)部的)函數(shù)原型,
* 如果注釋有多行,參照本條注釋風(fēng)格---每一行都以’*’起始.
*/
static void prvAFunction( uint32_t ulParameter );
/* 文件作用域變量(本文件內(nèi)部使用)緊隨其后,要在函數(shù)體定義之前. */
static BaseType_t xMyVariable.
/* 每一個函數(shù)的結(jié)束都有一行破折號,破折號與下面的第一個函數(shù)之間留一行空白。*/
/*-----------------------------------------------------------*/
void vAFunction( void )
{
/* 函數(shù)體在此定義,注意要用大括號括住 */
}
/*-----------------------------------------------------------*/
static UBaseType_t prvNextFunction( void )
{
/* 函數(shù)體在此定義. */
}
/*-----------------------------------------------------------*/
/*
* 函數(shù)名字總是占一行,包括返回類型。左括號之前沒有空格左括號之后有一個空格,
* 每個參數(shù)后面有一個空格參數(shù)的命名應(yīng)該具有一定的描述性.
*/
void vAnExampleFunction( long lParameter1, unsigned short usParameter2 )
{
/* 變量聲明沒有縮進(jìn). */
uint8_t ucByte;
/* 代碼要對齊. 大括號占獨(dú)自一行. */
for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ )
{
/* 這里再次縮進(jìn). */
}
}
/*
* for、while、do、if結(jié)構(gòu)具有相似的模式。這些關(guān)鍵字和左括號之間沒有空格。
* 左括號之后有一個空格,右括號前面也有一個空格,每個分號后面有一個空格。
* 每個運(yùn)算符的前后各一個空格。使用圓括號明確運(yùn)算符的優(yōu)先級。不允許有0
* 以外的數(shù)字(魔鬼數(shù))出現(xiàn),必要時將這些數(shù)字換成能表示出數(shù)字含義的常量或
* 宏定義。
*/
for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ )
{
}
while( ucByte < fileBUFFER_LENGTH )
{
}
/*
* 由于運(yùn)算符優(yōu)先級的復(fù)雜性,我們不能相信自己對運(yùn)算符優(yōu)先級時刻保持警惕
* 并能正確的使用,因此對于多個表達(dá)式運(yùn)算時,使用括號明確優(yōu)先級順序
*/
if( ( ucByte < fileBUFFER_LENGTH ) && ( ucByte != 0U ) )
{
ulResult = ( ( ulValue1 + ulValue2 ) - ulValue3 ) * ulValue4;
}
/* 條件表達(dá)式也要像其它代碼那樣對齊。*/
#if( configUSE_TRACE_FACILITY == 1 )
{
/* 向TCB增加一個用于跟蹤的計數(shù)器. */
pxNewTCB->uxTCBNumber = uxTaskNumber;
}
#endif
/*方括號前后各留一個空格*/
ucBuffer[ 0 ] = 0U;
ucBuffer[ fileBUFFER_LENGTH - 1U ] = 0U;
推薦閱讀
(點(diǎn)擊標(biāo)題可跳轉(zhuǎn)閱讀)
【編程之美】用C語言實現(xiàn)狀態(tài)機(jī)(實用)
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點(diǎn),不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!