你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32 FreeRTOS编码风格

[复制链接]
STMCU小助手 发布时间:2022-6-17 14:14
01. FreeRTOS编码标准
2 R5 ^5 P5 a. ]+ z2 n) t8 n% RFreeRTOS核心的源代码遵从MISRA编码标准指南。这个标准篇幅稍长,大家可以在MISRA官方网站找到对应的文档。: p0 m7 L" @! G. d. D. m8 B/ L3 X
) L0 z/ \: @0 X4 h
FreeRTOS源代码不符合MISRA标准的项目如下所示:. r4 J+ d. v, E' H1 P5 F0 O
7 K& {" P: w: v" S
1.有两个API函数有多个返回点。MISRA编码标准强制规定:一个函数在其结尾应该有单一的返回点。: [+ p4 q9 c1 _0 w6 E- Y  x0 n$ ]% [
  ]6 y4 U/ A* d/ R, P" L+ b
2.指针算数运算,在创建任务时,为了兼容8、16、20、24、32位总线,不可避免的使用了指针算数运算。MISRA编码标准强制规定:指针的算术运算只能用在指向数组或数组元素的指针上。
1 z: b3 \$ U# y* t" j+ @
8 {8 T+ N' r! A3.默认情况下,跟踪宏为空语句,因此不符合MISRA的规定。MISRA编码标准强制规定:预处理指令在句法上应该是有意义的。( X  j& P+ S) a1 K! }

2 M. \; `" \2 h. D) Z: U7 mFreeRTOS可以在很多不同编译器中编译,其中的一些编译器比同类有更高级特性。因为这个原因,FreeRTOS不使用任何非C语言标准的特性或语法。一个例外情况是头文件stdint.h。在文件夹FreeRTOS/include下包含一个叫做stdint.readme的文件,如果你的编译器不提供stdint类型定义,可以将stdint.readme文件重命名为stdint.h。( [  K9 W3 @) _/ _
3 r5 `7 o+ F3 [% x6 C& N- {/ z
02. FreeRTOS变量命名规则0 e# A/ b# J7 h4 c( D
uint32_t类型的变量使用前缀ul,这里’u’表示’unsigned’,’l’表示’long’+ p! U/ M- i4 p
uint16_t类型的变量使用前缀us,这里’u’表示’unsigned’,’s’表示’short’
; E5 H. D1 q6 H  [2 v' e- D1 w3 w* ^uint8_t类型的变量使用前缀uc,这里’u’表示’unsigned’,’c’表示’char’
; |* c1 ?' w5 W3 I9 D5 _, j非stdint类型的变量使用前缀x,比如基本的Type_t和TickType_t类型,这些类型在移植层定义,定义成符合处理器架构的最高效类型;
: {- _; N: {! k8 p' N. J5 q非stdint类型的无符号变量使用前缀ux,比如UbaseType_t(unsigned BaseType_t)- j; Z5 o0 q0 r! c; f9 s1 D
size_t类型的变量使用前缀x;
3 P7 b) i, f" j2 @3 t" H枚举类型变量使用前缀e
' N% h2 r8 ^1 Q% ^8 g指针类型变量在类型基础上附加前缀p,比如指向uint16_t的指针变量前缀为pus6 l( Y2 g- k6 N+ X* Q1 o8 ^# F
与MISRA指南一致,char类型变量仅被允许保存ASCII字符,前缀为c
/ y% s0 `% Z$ i8 p7 i+ Y与MISRA指南一致,char *类型变量仅允许指向ASCII字符串,前缀为pc
5 Y! }9 g9 ?9 D8 e03. FreeRTOS函数命名规则
: t, u, I" k. B, t# O: {在文件作用域范围的函数前缀为prv. |3 h& Q" L' ?: I  a
API函数的前缀为它们的返回类型,当返回为空时,前缀为v) `8 k2 ], R6 k# ~/ W
API函数名字起始部分为该函数所在的文件名。比如vTaskDelete函数定义在tasks.c,并且该函数返回空。1 J7 U8 D1 ^. N2 b$ n1 H
5 K1 G  I4 y" d1 X9 q& ^$ M
04. FreeRTOS宏命名规则( s& i9 f1 j  n1 [6 X4 y4 M
宏的名字起始部分为该宏定义所在的文件名的一部分。比如configUSE_PREEMPTION定义在FreeRTOSConfig.h文件中。4 C' I$ ]& P  p
除了前缀,宏剩下的字母全部为大写,两个单词间用下划线(’_’)隔开。0 [  c2 l9 J# R8 b2 _

* q, ]* ~5 C' @. o6 }05. FreeRTOS数据类型

0 M$ x! B' {' u& G, ]! Y只有stdint.h和RTOS自己定义的数据类型可以使用,但也有例外情况,如下所示:
4 V0 i$ X9 w4 s% k- z- t, X7 A4 l% u* k, ochar:与MISRA编码标准指南一致,char类型变量仅被允许保存ASCII字符: d3 h  V+ G" H- G2 I
char *:与MISRA编码标准指南一致,char *类型变量仅允许指向ASCII字符串。当标准库函数期望一个char *参数时,这样做可以消除一些编译器警告;特别是考虑到有些编译器将char类型当做signed类型,还有些编译器将char类型当做unsigned类型。
  K, E7 y  z% I
/ V) t$ \! o+ \0 t有三种类型会在移植层定义,它们是:
# B$ C% h) K2 T/ q( y5 D  S+ YTickType_t:如果configUSE_16_BIT_TICKS为非零(条件为真),TickType_t定义为无符号16位类型。如果configUSE_16_BIT_TICKS为零(条件为假),TickType_t定义为无符号32位类型。注:32位架构的微处理器应设置configUSE_16_BIT_TICKS为零。
* o7 X( E) {% T" y* ?  H5 K, a  ~BaseType_t:定义为微处理器架构效率最高的数据类型。比如,在32位架构处理器上,BaseType_t应该定义为32位类型。在16位架构处理器上,BaseType_t应该定义为16位类型。如果BaseType_t定义为char,对于函数返回值一定要确保使用的是signed char,否则可能造成负数错误。6 m; k" o2 P9 N5 \, z
UbaseType_t:这是一个无符号BaseType_t类型$ B! w) k; h' t

! D  d3 _! I. D# G06. 其它' l' d( V" x+ U1 U7 C
风格说明+ O3 c0 j( |- k2 R- q/ W3 ?" ]2 d% ^
1.缩进:缩进使用制表符,一个制表符等于4个空格。, A7 X, W( Y# v) c
2.注释:注释单行不超过80列,特殊情况除外。不使用C++风格的双斜线(//)注释- j6 m4 J  k# u4 E
3.布局:FreeRTOS的源代码被设计成尽可能的易于查看和阅读。下面的代码片中,第一部分展示文件布局,第二部分展示C代码设计格式。
* i& G( Z+ m/ ~0 U# E  b8 k: v' K. g% c
示例, q, @- _) T- G; {

( F7 I: d- T, x% ~& \7 z# h6 O) S# K( N
  1. /* 首先在这里包含库文件... */  
    ! H$ q% s. N) r5 @
  2. #include <stdlib.h>  , C5 T( G% V3 F, C6 E1 V

  3. 4 d" D; V* O3 J3 E& s- ^3 G; P4 k
  4. /* 然后是FreeRTOS的头文件... */  
    : B" `0 b4 ?9 `- B2 V7 B* y" K9 ?) Z
  5. #include "FreeRTOS.h"  
    ; |3 k/ T5 f& z5 s/ @& e
  6. % K: Q& K3 F' A- l+ y
  7. /* 紧接着包含其它头文件. */  
    + n! \/ L# R, C2 R6 l2 ]9 N4 M
  8. #include "HardwareSpecifics.h"  
    3 L1 Y2 x$ B( P8 |

  9. 1 f5 \( M! h- J% e' z
  10. /* 随后是#defines, 在合理的位置添加括号. */  
    / y3 t3 n! {0 x4 a
  11. #define A_DEFINITION    ( 1 )  6 [  m2 K# x2 Z9 O4 B

  12. 8 Q) q3 ]; u) W/ I  T
  13. /*
    ( W" b3 }* B# I1 `; r
  14. * 随后是Static (文件内部的)函数原型,  5 _7 S: Y' a6 c
  15. * 如果注释有多行,参照本条注释风格---每一行都以’*’起始. 7 J  a1 E2 l7 e1 G1 I
  16. */  
    / a0 b5 q: ^% {2 E6 d; `4 g
  17. static void prvAFunction( uint32_t ulParameter );  ; _. O% ~8 b" n6 `% r+ X
  18. . n2 @- `5 f8 q, |5 f7 [, u
  19. /* 文件作用域变量(本文件内部使用)紧随其后,要在函数体定义之前. */  + U. e2 {# r2 d+ G) k. Z
  20. static BaseType_t xMyVariable.  
    # \4 F2 J: o( g* M) p3 ]2 B. i
  21. % A/ C% j7 C/ C
  22. /* 每一个函数的结束都有一行破折号,破折号与下面的第一个函数之间留一行空白。*/  4 d% i: R1 \1 B0 l
  23. & T$ v2 a0 ]; S$ j
  24. /*-----------------------------------------------------------*/  
    - }0 _' ]3 s3 L  T
  25. / e+ K+ }; q1 S+ j6 h
  26. void vAFunction( void )  
    % e* Z! {1 K/ x2 R1 j9 |  O
  27. {  
    ; Z; J9 c3 B4 T& x4 P0 v) k, s
  28.      /* 函数体在此定义,注意要用大括号括住 */  
    . w6 h: T6 V8 [; u
  29. }  
    $ @* ]5 g/ M1 m) O: L7 D
  30. /*-----------------------------------------------------------*/  - n2 Z: h3 H& {. f6 f3 y

  31. 2 q; I  V7 u  W2 p
  32. static UBaseType_t prvNextFunction( void )  # W9 H  g6 q  z- l5 A
  33. {  
    & L+ J4 ~+ q9 x
  34.      /* 函数体在此定义. */    }/ L( v1 Y9 _$ W# `3 t2 L5 J
  35. }  
    7 ]' `& W6 B$ ?9 I, L
  36. /*-----------------------------------------------------------*/
    - U2 n( X8 z6 |  u

  37. 0 m8 _, M: o7 F- l1 w
  38. /*
    , K7 E5 B5 O, g
  39. * 函数名字总是占一行,包括返回类型。 左括号之前没有空格左括号之后有一个空格,
    ) T% F5 z+ o8 N; _5 E
  40. * 每个参数后面有一个空格参数的命名应该具有一定的描述性.
    0 w. l# a+ m( L0 I  y% `/ Y
  41. */  7 Q0 c# _: c% z8 @, P( i
  42. void vAnExampleFunction( long lParameter1, unsigned short usParameter2 )
    5 X! i8 `# `. O$ [% t: v
  43. {  
    4 o- e# t1 s8 u4 K+ D
  44. /* 变量声明没有缩进. */  0 W! r6 J9 `; w) i+ i7 ?
  45. uint8_t ucByte;  
    * M  @$ l0 ?. t6 D* f

  46. 6 d5 u& y& D8 V0 Z* }- u1 k- ~
  47.     /* 代码要对齐.  大括号占独自一行. */  7 I$ e* X& i: H  p5 @7 {- ]3 H/ o- [
  48.     for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ )  
    " _2 ]" P1 e3 W  k" A, c' s' [. l
  49.     {  
    ' p& v: R; I( M8 Z/ d0 W1 Z
  50.          /* 这里再次缩进. */  
    ! e( m6 t( x* R
  51.     }  $ `. ^3 t5 o1 H. C
  52. }  + C! M- J( c4 q$ ]! k

  53. 9 m: G) N) p. Q$ j' |. h9 {
  54. /*
    1 A! W; v0 A  a0 |
  55. * for、while、do、if结构具有相似的模式。这些关键字和左括号之间没有空格。. ?) x5 c$ G6 z" `. }1 J
  56. * 左括号之后有一个空格,右括号前面也有一个空格,每个分号后面有一个空格。/ b6 }% p9 s  k3 g( _# D' w
  57. * 每个运算符的前后各一个空格。使用圆括号明确运算符的优先级。不允许有0
    $ k" }& l4 `" g! _! o! A1 Y
  58. * 以外的数字(魔鬼数)出现,必要时将这些数字换成能表示出数字含义的常量或
    : I. l9 P$ ^  u( S9 z+ R  {8 V* O: @
  59. * 宏定义。5 p- W$ y1 E7 K7 S
  60. */  * e$ |  {/ J  q8 K3 o
  61. for( ucByte = 0U; ucByte < fileBUFFER_LENGTH; ucByte++ )  7 c& ?, Q0 q1 v6 d, D( W
  62. {  
    & O3 K+ R3 u; R# L
  63. }  & Y# c( S6 _7 P! m) t1 @' s

  64. & G3 M: d5 Y5 c+ Z2 H  T8 Y6 c" G2 z
  65. while( ucByte < fileBUFFER_LENGTH )  
    - Y2 z; @" F" u8 v3 ]3 E' X
  66. {  9 I: g' l! q# o
  67. }  
    ! N" g% @3 X8 D$ u1 q: E
  68. 3 a2 `1 ^0 `* I* A6 O
  69. /*
    / r8 b" x7 O8 e7 E
  70. * 由于运算符优先级的复杂性,我们不能相信自己对运算符优先级时刻保持警惕
    ) z/ T9 p0 S- l6 Y3 n3 k
  71. * 并能正确的使用,因此对于多个表达式运算时,使用括号明确优先级顺序
    . F0 _: c: a% ]0 L0 e& u
  72. */  ' [5 s/ u) `# ?3 F& ^/ e) Y- x' T
  73. if( ( ucByte < fileBUFFER_LENGTH ) && ( ucByte != 0U ) )  5 j( H5 G# e, D2 w1 I2 m
  74. {  + n2 L$ C! [, s  H( r4 P2 W
  75.     ulResult = ( ( ulValue1 + ulValue2 ) - ulValue3 ) * ulValue4;  
    - G. ~  i, B! o4 M" Z8 u7 e
  76. }  . r" W+ a- I* |* H  L$ O3 D1 H4 r

  77.   Z+ V# J8 s! n8 r# ?
  78. /* 条件表达式也要像其它代码那样对齐。 */  * |3 |1 \. G/ V
  79. #if( configUSE_TRACE_FACILITY == 1 )  
    ! W2 E+ ?$ P9 V- w9 m
  80. {  
    4 q" l: A( H/ f' I# M7 j
  81.      /* 向TCB增加一个用于跟踪的计数器. */  " f1 _: j( H0 j" z1 N
  82.      pxNewTCB->uxTCBNumber = uxTaskNumber;  
    + D2 D# @. i; v. S: k$ R6 |
  83. }  $ K; E/ h9 _8 W) Z9 ?; _) m
  84. #endif  , H8 K  y$ T- m8 ~
  85. ! M; b2 u, }4 A2 {4 b+ y3 m
  86. /*方括号前后各留一个空格*/  " [  Q! u& i0 R/ H; O  R
  87. ucBuffer[ 0 ] = 0U;  0 E' z& f$ E3 `( b# f
  88. ucBuffer[ fileBUFFER_LENGTH - 1U ] = 0U;
    5 D2 |, Q4 V5 q; R
复制代码

. s& k" X2 y9 y9 q* B8 C) G$ R  F* W( g/ E- W

, D' q, A) {; P
赞 收藏 评论0 发布时间:2022-6-17 14:14

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版