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

基于STM32的FreeRTOS学习之FreeRTOS配置文件FreeRTOSConfig.h解读(三)

[复制链接]
STMCU小助手 发布时间:2022-11-17 17:20
1. FreeRTOSConfig.h文件; ?2 S0 n5 h. Q1 Q0 A3 g- _
1.1 "INCLUDE_"开始的宏

3 g. U7 {, P2 c/ t& ~* W6 Q4 V5 R使用"INCLUDE_"开头的宏用来使能或失能FreeRTOS中相应的API函数,如下图,INCLUDE_vTaskPrioritySet设置为1,表示使用vTaskPrioritySet函数。1 B: g+ t$ B+ v( x
20210311232441959.png 5 Q+ g6 Y8 z) e6 W! N0 i
  R2 B4 R" k* J6 h7 s, ^& D
其作用就是条件编译,这样可以根据实际需求减少系统占用的ROM和RAM大小。在移植的FreeRTOS_CORE分组中的task.c源文件里,有如下函数,这样就理解了吧。3 W" M" }/ B- X, h

5 e+ Z' E( _; z' u2 V+ p- Y6 @ 2021031123294987.png
% k: u! y/ }: I9 W* y
6 ^7 V; z% R$ {- _* w. [( q1.2 "config"开始的宏! b9 e* E# S" U3 |8 k$ L0 [
"config"开始的宏和"INCLUDE_"开头的宏作用一样,都是用来完成FreeRTOS的配置和裁剪。
* F/ d" B" j6 D  i8 W3 G6 H8 z4 N1 a- b# P" I' I, A
20210311233709613.png + E5 [9 ~, T' K/ S  C1 u
8 ~# o' l! V3 j, [# y" g; `* ~
接下来对"config"开始的宏进行简单解读
! P' {9 _5 N9 o) t7 F; v4 ]* M4 @# o0 t: l) `! ]8 b$ H7 Y6 T
1)configAPPLICATION_ALLOCATED_HEAP
: _2 K' Q) ?/ I: |8 m默认情况下FreeRTOS的堆内存是由编译器来分配的,将configAPPLICATION_ALLOCATED_HEAP定义为1可由用户自行设置,堆内存在heap_1.c、heap_2.c、heap_3.c、heap_4.c、heap_5.c有定义。在前章节移植时采用heap_4.c,如下图定义:
* Z9 h0 R% y( g8 j( p8 Q
3 ]! w! D- _( j% w4 u 20210312085947643.png ' F1 |0 A: J  l" J, u8 {

: v$ T; j9 }* J6 X/ z% x4 w如果configAPPLICATION_ALLOCATED_HEAP定义为1,那么堆内存由ucHeap决定,否则由编译器来分配。
8 U& @! |0 v# A% y* e' @: n- ^) |& O
2)configASSERT
+ a) k% D& Q; W( s3 g3 O5 N3 ~FreeRTOS内核中的关键点都会用configASSERT(x),当x为0时说明有错误发生,该函数一般在调试阶段使用,因为开销较大。* M' x3 w% f9 j' n# m! j+ _- n
使用举例:- A, Z& u  S1 N1 _3 ?

% I9 F8 m* z% }# p8 r
  1. #define vAssertCalled(char,int) printf("Error:%s,%d\r\n",char,int)
    + H' p2 O- }- v/ \+ C; g/ t
  2. #define configASSERT((x))  if((x)==0)  vAssertCalled(__FILE_,__LINE__);
复制代码
$ p- J9 a# J% C0 S& X$ X. I* O
一般vAssertCalled()函数有用户定义,当参数x错误时通过串口打印发送错误文件名和错误号。
4 X- N2 B$ a0 w# r4 S0 @5 j6 i
3 a! b$ \4 Z; A1 n; o/ ^3)configCHECK_FOR_STACK_OVERFLOW/ n/ j* d5 ^3 g; d) d* \; r
设置堆栈溢出检测,每个任务都有一个任务堆栈:9 ]2 F" g' {+ |: B# S$ m/ o! I
若使用函数xTaskCreate()创建一个任务的话那么这个任务的堆栈是自动从FreeRTOS的堆(ucHeap)中分配的,堆栈的大小是由函数xTaskCreate()的参数usStackDepth来决定的;- a2 [* f  ?7 g, T  Y! G7 i) x7 V" m
若使用xTaskCreateStatic()创建任务的话,其任务堆栈是由用户设置的,参数pxStackBuffer为任务堆栈,一般是一个数组。: D4 a% [7 i$ c! b6 i3 m; {
堆栈溢出会导致应用程序不稳定。& m" B. W; c- W) E" D: w& t. P
FreeRTOS提供两个机制来检测和调试堆栈溢出,即configCHECK_FOR_STACK_OVERFLOW不为0时,必须提供一个回调函数,当内核检测到堆栈溢出后就调用这个回调函数:
* z+ t1 e$ l/ X5 ?! b% w/ f' v& u8 n# _+ c  d& A
  1. void vApplicationStackOverflowHook(TaskHandle_t xTask, char*  pcTaskName);
复制代码
0 E/ o; D0 N5 }
参数xTask是任务句柄,pcTaskName是任务名字,查看变量pxCurrentTCB可确定哪个任务发生堆栈溢出。" n! f1 u% h+ y3 u8 c8 H: n* _

. u: k, }" P2 g6 O' R; J4)configCPU_CLOCK_HZ+ p( f& U* C0 ~9 `: }
设置CPU的频率
7 ]5 U2 L; C6 h/ \8 Y4 u3 s! K6 a3 v3 y# A8 a" @3 ^
5)configSUPPORT_DYNAMIC_ALLOCATION
5 J0 F! ~2 z% J/ T* P2 n1时,创建FreeRTOS内核对象时需要的RAM从FreeRTOS的堆中动态获取内存;0时需要用户自行提供。默认设1。; n. T& c% ^) _8 Q6 I
/ v; I! O) |/ Q1 t1 I
6)configENABLE_BACKWARD_COMPATIBILITY
& j$ g4 w8 D2 m7 H, D7 F& K默认1,保证代码从v8.0.0之前版本升级到最新版本后不需要修改。
. i7 P0 V( ^8 ?8 ?/ i
$ _- C; {! q1 y) }7)configGENERATE_RUN_TIME_STATS
8 C2 E/ l- B$ l设置为1开启时间统计功能,相应API函数会被编译,且还要定义如下的宏;为0时关闭统计功能。4 M2 l" y& L1 K. ~( {9 L- E

% v  U3 N( s& d; z  n' B* D 20210312093138382.png
- Q5 |2 e# H* k( t' C0 D+ u+ q" k) l* ]6 L
8)configIDLE_SHOULD_YIELD
' E" H$ M7 N, ]5 S7 ]6 W& r! r定义了与空闲任务(idle Task)处同等优先级的其他用户任务的行为,为0时空闲任务不会为其他处于同等优先级的任务让出CPU使用权;为1时就让出使用权,除非没有就绪的用户任务,这样话费在空闲任务上的时间会很少,但也有副作用。# {- z. _! U- |
$ G6 l* x  p+ K9 I
20210312093517653.png
0 a8 R' m0 c. a! e+ B( X5 Q2 H4 B4 M& O
参考上图进一步说明,有三个用户任务:A、B、C,还有一个空闲任务I,用户任务和空闲任务处于同一优先级,任务切换发生在T0 ~ T7时刻。T0 ~ T1之间的时间为一个时间片。开始任务后,B、C执行了一个完整的时间片,T2时刻空闲任务I开始运行,运行一段时间后被A任务抢走CPU使用权,A任务运行到T3时刻发生任务切换,B任务开始运行。可以看出任务I和任务A一起使用了一个时间片,即A任务运行时间比其他任务少。
8 G% @/ I* ?6 }2 B一般建议关闭该功能。
# Q; d5 {1 {% h; D1 R/ D2 P" b) ~! j) f0 N/ d: `7 ^
9)configMAX_CO_ROUTINE_PRIORITIES& b2 ]5 q, n# |) Q( K3 f. ~
设置可以分配给协程的最大优先级,即协程的优先级数。优先级可以从0(最低优先级) ~ configMAX_CO_ROUTINE_PRIORITIES-1(最高优先级)。5 J5 d) q7 J/ _3 E* R/ C% I  a
- N: b* b7 S! u9 [) T! Q- d3 Q
10)configMAX_PRIORITIES
7 X+ d9 Q" j9 X. K" s设置任务的优先级数量,优先级从0(最低优先级) ~ configMAX_PRIORITIES-1(最高优先级)。
8 d  [: N7 ?* q% }# t& ^, {8 m) B5 _! u+ V/ b" b: h" \  t2 [
11)configMAX_TASK_NAME_LEN2 \/ k1 u" Z% }# c) |" }2 q! O
设置任务名最大长度。+ A. d* V2 t. t  u& T3 D

& y4 Y( X& g* A+ x3 k12)configMINIMAL_STACK_SIZE
" F# T9 _% _/ O! I设置空闲任务的最小任务堆栈大小,以字为单位,不是字节。如设为100的话,则堆栈大小是100*4=400字节。
! @" O9 x- n. f6 f# x
# \4 N+ X% @6 P13)configNUM_THREAD_LOCAL_STORAGE_POINTERS
$ p1 G' [( i! V' V设置每个任务的本地存储指针数组大小,任务控制块中有本地存储数组指针,用户应用程序可以在这些本地存储中存入一些数据。
+ L+ _+ Y6 l. x5 s) @
2 y# a- w5 \6 T! Z4 B2 O14)configQUEUE_REGISTRY_SIZE. k. d( _# t, l: ^' C6 E
设置可以注册队列和信号量的最大数量,在使用内核调试器查看信号量和队列的时候需要设置此宏,且要先将消息队列和信号量进行注册,只有注册了队列和信号量才会再内核调试器中看到。+ Y; v% c2 p6 y+ `7 o

  Z, z* q+ r5 U, J  C: H15)configSUPPORT_STATIC_ALLOCATION
: ^' a3 c  A2 H4 [' K$ }4 L* J) ~当此宏定义为1,在创建一些内核对象时需要用户指定RAM,为0时使用heap.c中的动态内存管理函数来自动申请RAM。
% J1 k5 b* r/ ^" [6 }
6 @5 n# q0 B" f9 \% H16)configTICK_RATE_HZ
, D1 B  H4 [' X# k6 n: C设置FreeRTOS的系统时钟节拍频率,单位Hz,此频率就是滴答定时器的中断频率。
- c- v0 F, _+ @& h4 n4 x+ [, _: L8 c# {
17)configTIMER_QUEUE_LENGTH3 x  |. ]) P. }
配置FreeRTOS软件定时器的命令队列长度,软件定时器API函数会通过命令队列向软件定时器任务发送消息。
$ U$ z% j+ i) V& T9 _) _% F5 M
7 b: A! r: Z' M18)configTIMER_TASK_PRIORITY, o" i0 B: F8 a: Y* N
设置软件定时器任务的优先级。5 M( E6 i( ?! M& N; {
& X* ~0 \# j& [" b; q
19)configTIMER_TASK_STACK_DEPTH
4 O8 s, e* D9 S  J/ V( u" O' ~设置定时器服务任务的任务堆栈大小。
- o4 E! ]+ X; x3 [  {2 T" i7 z/ w. y1 @
20)configTOTAL_HEAP_SIZE
  Z7 D% G* h7 `设置堆大小,如果使用了动态内存管理的话,FreeRTOS在创建任务、信号量、队列等时候会使用heap.c中的内存申请函数来申请内存。这些内存是从堆ucHeap[configTOTAL_HEAP_SIZE]中申请的,堆的大小由configTOTAL_HEAP_SIZE定义。
0 L' Q- x4 d3 b% c" u  h- p) B& G! E+ h' ^" B2 v4 G# e% e
21)configUSE_16_BIT_TICKS6 k  s/ h" A5 V. j* @
设置系统节拍计数器变量数据类型,1时为16位,0时为32位。
" @* L$ F7 l+ H1 [& u; ]6 X# |+ U0 e0 Q$ y( U7 F4 }
22)configUSE_APPLICATION_TASK_TAG
0 {/ {. C# }* |* v% [7 L1时,configUSE_APPLICATION_TASK_TAGF()和xTaskCallApplicationTaskHook()会被编译。
; |  u$ J9 `9 ?/ S# S
1 g' K& a+ `# V8 h2 I4 p5 c23)configUSE_CO_ROUTINES
; N$ K- Q. a/ W; q$ l1时启动协程,协程可以节省开销,但功能有限。建议关闭。
* M, j5 w8 `4 _1 x  V
2 W2 r( g# L, T1 I24)configUSE_COUNTING_SEMAPHORES
( g7 I8 m8 }, l1时开启计算型信号量。2 v8 o6 H; w6 w$ C" h4 L
& @! W5 ~: b5 j2 q& L2 c/ d3 y
25)configUSE_DAEMON_TASK_STARTUP_HOOK* u: Z+ O* o' ~  p" i# _8 [' F
当宏configUSE_TIMERS和configUSE_DAEMON_TASK_STARTUP_HOOK都为1时,定义vApplicationDaemonTaskStartupHook()函数。/ T; h, L+ V0 [7 N# {+ S% M
( m& j( `- e, v: a+ V7 H
26)configUSE_IDLE_HOOK7 W* S  W0 r9 n4 d+ t
1时使用空闲任务回调函数(钩子函数)。7 K: {. q) A2 w+ V* W5 O  _4 ^

. H& x- I1 \8 i/ C27)configUSE_MALLOC_FAILED_HOOK
% u) ^4 U1 ^$ B7 W0 x! M% P1时使用内存分配失败回调函数。5 j1 r' q( F+ x( p$ K$ [7 l0 p
/ r5 T+ _5 u/ Z
28)configUSE_MUTEXES+ J6 ]9 @, e$ y3 \$ L) L
1时使用互斥信号量。
8 H4 a, o: p# m& O) s+ A+ p, A9 k( I( P: T
29)configUSE_PORT_OPTIMISED_TASK_SELECTION
4 G+ e$ y3 b; y- pFreeRTOS有两种方法选择下一个要运行的任务:2 H# h- f! `- x* ^
一是通用方法,特点如下:* T% w9 H' f" J0 p4 n! L
1)当宏configUSE_PORT_OPTIMISED_TASK_SELECTION为0,或硬件不支持时;' }& w# p. U1 m+ \3 W8 }
2)希望所有硬件通用;
7 ^7 T% d& @: @# {3 W% a/ [# d( h3)全部用C语言实现,但效率比特殊方法低;
+ y/ _  G2 j2 a6 |# h/ q' |5 Q  Q4)不限制最大优先级数目的时候。
9 b) d4 i. Q. D0 M二是特殊方法(硬件方法),用MCU自带硬件指令实现,特点如下:" |' @! p( {  V
1)不是所有的硬件都支持;, s) `, g- @( w0 y
2)当宏configUSE_PORT_OPTIMISED_TASK_SELECTION为1时;# \4 B8 H# w( W& H  x; O
3)硬件拥有特殊指令,如计算前导零(CLZ)指令;
7 f0 P6 b. ]% P2 e9 \. v4)比通用方法效率高;
4 ?% u5 E$ E: |5 a5)会限制优先级数目,一般是32个。
6 R( d4 |8 Z: ~. W& H* ^3 U/ {- [+ Y+ N9 d7 }. ?; ~/ t$ z
30)configUSE_PREEMPTION% K: t. W! W& {* u2 ?- H
1时使用抢占式调度器,0时使用协程。
3 B  ?- t1 y: i, z: d使用抢占式调度器时,内核会每个时钟节拍中断进行任务切换;
5 W6 y9 E- T( h+ l使用协程时,在如下地方进行任务切换:
! L  M' z6 B7 f  o1)一个任务调用了函数taskYIELD();2 G  Q! {5 [2 c1 P& D9 G+ w
2)一个任务调用了可以使任务进入阻塞态的API函数;
- z1 z; M( m- ]9 X+ d. f" z& o' J! t3)应用程序明确定义了在中断中执行上下文切换。
* W" z0 z7 h; b0 b8 }+ o* N/ r# E; L1 }# P5 E
31)configUSE_QUEUE_SETS- o% N2 M# B+ M- k4 G- _9 f6 Q
1时启用队列集功能。4 u6 n! N" i# l9 @4 T
% B/ }( K7 e" c0 Z
32)configUSE_RECURSIVE_MUTEXES
% u, ?* h; l& o1时使用递归互斥信号量。
  ~3 V6 N+ Q, m9 L, }: X  B* C1 O# ~' s# k. x% \' T, F
33)configUSE_STATS_FORMATTING_FUNCTIONS
/ t2 e6 q( q/ E  g" y) ^+ e宏configUSE_TRACE_FACILITY和configUSE_STATS_FORMATTING_FUNCTIONS都为1时,函数vTaskList()和vTaskGetRunTimeStats()会被编译。
& ]" m3 B2 P9 P& D/ T7 F$ n
: X) T% w& K8 j) B* V# N34)configUSE_TASK_NOTIFICATIONS8 l( Q4 B; D1 Z( M
1时使用任务通知功能,开启后每个任务会多消耗8个字节。
# _4 l4 q# ^4 [
, ~( Z3 C; {/ }& @) b35)configUSE_TICK_HOOK
+ v+ J$ Y7 n! @7 K8 {% R, Y! M1时使能时间片回调函数。; V9 c$ n% ~) N" g: m; W+ F
1 C# y, T$ D8 u# B( b
36)configUSE_TICKLESS_IDEL
, D& [2 E3 t3 D! X( t1时使能低功耗tickless模式。
5 R8 G% ]% ]7 R- O, x
$ H6 K- u1 m2 q) M2 q% n* J37)configUSE_TIMERS
" f$ I) A/ v: Z% n5 r; o1时使用软件定时器。当configUSE_TIMERS为1时,configTIMER_TASK_PRIORITY、configTIMER_QUEUE_LENGTH和configTIMER_TASK_STACK_DEPTH必须定义。; J% y) |" o7 b$ T& ?, S5 @

+ s3 r9 g, v6 i0 a$ W38)configUSE_TIME_SLICING
# A8 b  @# f7 \默认情况,FreeRTOS使用抢占式调度器,这意味调度器永远都在执行已经就绪了的最高优先级任务,优先级相同的任务在时钟节拍中断中进行切换,当宏configUSE_TIME_SLICING为0时不会在时钟节拍中断中执行相同优先级任务的任务切换。默认设1。
4 |7 N) _( p/ d- \0 S1 N6 ~0 l& T9 t* a
39)configUSE_TRACE_FACILITY# g! B# U( G3 v& ~% f
1时启用可视化跟踪调式。! k0 Z5 a: F. e
————————————————2 i, i& H- t9 k) f8 z( N
版权声明:天亮继续睡
0 A" K* s2 Y0 ^+ ^+ ?
! q% r7 F9 D' U+ w% a! f; P* [7 \9 \6 _; _
收藏 评论0 发布时间:2022-11-17 17:20

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版