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

【经验分享】STM32使用HAL库手动移植FreeRTOS10.4.1

[复制链接]
STMCU小助手 发布时间:2022-4-10 19:56
(一)裸机工程创建. a& p! d' ?0 E) R6 v8 A& r- I
使用STM32CubeMX创建裸机工程:
6 P/ b' F. D$ E2 T4 ]; Z4 T) z$ h
这里我是用的芯片是STM32F103RBT6,时钟主频为72MHz,配置时钟树:
+ n! {* X$ q9 |& l6 V6 a8 L/ `; s( Z5 A- u% x* P+ T% H
[HJAIVR6Y8OGG98AS[H.png 8 T* f6 P  S8 i: @- ^. n" B5 ~8 ?
5 h# y4 Z; I5 [2 W* h7 e0 s( K
配置调试串口1:, n6 @! @3 G6 g

1 ?- h, `; F$ x+ w) p" ]8 n: w M8_G2}7WA8CT@ZUVG}0@R`0.png
& n3 w* o* M# f" y8 N! M6 `7 q( b% I3 [1 K
配置两个LED灯:
' Q* i- X1 ~7 P" a* F1 h5 J9 J- ^
20201010162500610.png & K: R5 Z1 G" m  W2 X
8 ]3 H! {4 ]/ ]" v# ~+ V
由于FreeRTOS使用系统嘀嗒定时器当作心跳,HAL库也使用了这个定时器当作超时计数用,FreeRTOS和HAL库不能同时使用SysTick定时器,所在在这里将HAL库的定时器改为其他的定时器,我改成了定时器4:; p) S! v6 D2 l( a
- d8 j( Y  C; G
ZW]AZRZ6{KK3FJ9V~Y{}D~Q.png 3 M- b6 ]/ ]. D! q" c; Y
4 B1 x# _; l  u
配置中断,注意这里一定要选择组4,也就是全部为抢占优先级:; F; d* n& n. _$ v& Q8 G% t

& O# d4 G; ^7 ~, f: l ANO~JLI_}E$E1]8B6U78I[X.png
( T) q" ^! F+ Y, q: t8 a
4 ]2 |1 w1 T$ O; u2 {输出工程:7 g+ s  t; x; X# d

3 w  H2 {$ p  T5 p 20201010162753196.png
+ e% D( I4 d% q# Z% ~0 V% A% F 20201010162833214.png
- Q- @1 w* a2 j# o% `' @, I* Z3 N2 R, Z( O) C( v% k8 h3 d+ Y

, z  ]7 U8 K7 x+ }9 m& q(二)移植FreeRTOS, ~: ^1 _+ X8 u3 t: u9 b
5 O( _5 r* ^- k( w1 t4 i
解压FreeRTOS源码包有如下文件结构:0 O  p1 B- X, A; e$ ?8 E- E- o2 Z) }( t
" |( K/ N: |" t2 X0 }
7L$%8]J0YCQ2N2IE`HG1PJN.png # V' I! _" H/ J1 w! Y
+ j& M( \. m' {( C. w9 g5 ?
在Keil工程目录下新建FreeRTOS文件夹用于存放freertos的源码。
* m/ g7 @+ R3 B; r6 U: Y$ h0 x- u* L# c4 A0 |7 }2 I
拷贝FreeRTOS/Source/文件夹内的以下文件,放入keil工程目录FreeRTOS文件夹内,效果如下图:/ N* b9 h# Z! r

5 z) I' G9 U& g 2~65A5@GXSM$QGGM2S885GU.png / q. E4 Q  i* l! V4 `

3 |2 y+ F, g; V% D& d, t; I在Keil中将FreeRTOS源码加入到工程内:# S+ d1 M% a9 ?: }
3 W: Z0 e- X2 B4 Z% P
0]DPJOU3QX3U0ZAN46OSQ04.png
7 z% g4 m: d5 M+ F4 s2 g$ n* i' l- ^3 M5 `. w) K; o5 ~6 G
打开stm32f1xx_it.c文件,在头部添加FreeRTOS的三个函数导入:
  1. extern void xPortPendSVHandler(void);
    9 \7 j" _$ Q" N8 c
  2. extern void xPortSysTickHandler(void);6 w. c5 r  Q' n3 i* X6 ?
  3. extern void vPortSVCHandler(void);
复制代码

9 h! k. t( Q' k6 M$ L 3DC746)588]2)A%~F[L%ERS.png
* Y- F9 A6 U. \4 p, j1 V9 k" I
. H+ }% f* j( p9 p7 E* D在函数SVC_Handler中添加函数调用:) s& R. ~& t0 R1 e, ^0 Z
! N# A# P# q& e) R5 P& J( p8 c
20201010165147723.png 5 S& T. W7 @$ d8 q! I
! F( q* s& Y  f/ r+ o2 v+ ~" f/ v
在函数PendSV_Handler中添加函数调用:
3 m5 f8 Q1 [3 ^; C$ D, e5 }( L2 x. `8 B6 V
20201010165237842.png
  {2 X2 F6 T# P5 x# l& M3 t# M8 @1 M5 G
在函数SysTick_Handler中添加函数调用:
: g) U5 }) \) o% B; m- k4 X
/ s" L* ]8 D* V O[VQ{YF9{KZOLWVE[9O(OGN.png
) z. _/ n+ {0 p! ^/ I3 X( V5 X0 T! M% H7 |! x% [, c& N  p
新建一个名为FreeRTOSConfig.h的文件,这是FreeRTOS的配置文件,这里我贴一个我配置的:
* q1 s$ Q* ]" A& w! v$ l# u! X
+ B1 J$ y* j6 G; J( V) _
  1. #ifndef FREERTOS_CONFIG_H__
    ) m: o7 J" l& F
  2. #define FREERTOS_CONFIG_H__, \6 w; A- D! p! O

  3. % [# G% m* x" K5 O
  4. /*/ {- H6 N* Z3 T/ O* j
  5. & f7 `6 ]; t0 Q
  6. */
      m" L* o! @+ H
  7. ( F1 T) u3 y( J) o. R$ A; |
  8. // 设置为1使用抢占式,为0使用时间片轮转调度。) X& ]  P1 q! ]- R
  9. #define configUSE_PREEMPTION                    1" l7 Y2 ~1 f8 D/ `
  10. / y. m- V8 l$ A: j1 [
  11. // 设置为1使能低功耗tickless模式,为0保持系统节拍(tick)中断一直运行。
    3 l* \' E+ ~/ z$ c7 q, `
  12. #define configUSE_TICKLESS_IDLE                 07 u9 H& I9 B* J/ r- y5 q) o
  13. ! I& ?2 \3 D/ _& S6 \
  14. // 系统时钟主频7 i; x% s) k, f0 _8 U/ F: f
  15. #define configCPU_CLOCK_HZ                      72000000
    : A0 R. _6 G# r% L
  16. + |9 ~1 r, S5 R# P7 J! X3 Q
  17. // 系统节拍中断的频率,即1s进中断的次数,配置为1000就是一秒进1000次中断,系统节拍就是1s。8 I; V  k. z, ]5 K7 ]3 V# Q
  18. #define configTICK_RATE_HZ                      1000% n$ O+ R( E, B& n, \, G
  19. & m2 t  s# J( X. \8 R/ y
  20. // 任务最大优先级,对于STM32来说最大不要超过32
    3 `" I, J9 D2 B: c; {* R
  21. #define configMAX_PRIORITIES                    32" S0 t$ N$ c' Q
  22. : @+ u0 C+ u3 Z8 H& u/ \
  23. // 任务最小栈大小6 r, _- r* q1 `% M" m% Q
  24. #define configMINIMAL_STACK_SIZE                64
    9 d) R4 Y5 H5 q$ W' q$ Y6 \4 M

  25. 5 V, ~" s* i& q1 V
  26. // FreeRTOR堆空间大小
    2 S* D4 g2 z* i, R
  27. #define configTOTAL_HEAP_SIZE                   8192: [2 x3 A( B2 V" A0 v

  28. * _; Q5 ?/ w  w8 J  Y" h; }& U
  29. // 任务名称最大长度6 w+ K/ ]. I+ B1 H% u
  30. #define configMAX_TASK_NAME_LEN                 164 |, O: h. ]; ]$ H5 O4 p

  31. ' F+ J. e. E6 f% F
  32. // 系统节拍计数器的变量类型,即定义portTickType是表示16位变量还是32位变量。: A+ U) k) V( B$ \9 o2 s, g8 ^
  33. #define configUSE_16_BIT_TICKS                  0
    & \8 S7 d: e0 p) U7 `5 E
  34. 3 ], M+ Y0 Z7 {
  35. // 设置为1允许任务调度,为0不允许(时间片耗尽才让出CPU使用权),该参数抢占式方式下才生效
    * ^7 h2 R6 {; L! }) [
  36. #define configIDLE_SHOULD_YIELD                 12 ]: ]+ u2 F5 v. h3 G5 R
  37. 0 D, \* Q8 A. Z! Y9 s4 b
  38. // 设置是否使用互斥量
      Y: U" Y& U4 b% ?
  39. #define configUSE_MUTEXES                       1
    ; A( r! N# k: f$ Q0 i( @/ V
  40. ) b0 u; z* H# O
  41. // 设置是否使用递归互斥量
    ) n  i2 A3 A/ y- \0 Z# G
  42. #define configUSE_RECURSIVE_MUTEXES             0+ z, e: p. F5 O6 s3 B  c& c* {
  43. % X( O) F1 @. y5 j  s% h
  44. // 设置是否使用计数信号量
    * {  P: \! Y+ q" K4 S
  45. #define configUSE_COUNTING_SEMAPHORES           06 l+ Y5 }% m0 @* x- j
  46. 9 {7 x2 ?3 M: c
  47. // 设置可以记录的队列和信号量的最大数目
    1 Q( w/ v- r: z( T- ]' F9 s
  48. #define configQUEUE_REGISTRY_SIZE               10
    * z( A5 h8 `1 k# e* F9 x+ E8 J4 E

  49. : F7 A- H' d7 Q) ^' f( y* K( s/ I
  50. // 是否使用空闲钩子函数
    9 E5 N, L4 f6 @, K
  51. #define configUSE_IDLE_HOOK                     0! x0 h' w( N! B7 F6 X

  52. # Q9 ]! g# m6 M. F: g4 P
  53. // 是否使用TICK嘀嗒钩子函数! ?) D4 j" n- O9 G
  54. #define configUSE_TICK_HOOK                     0
    " ?0 a3 I  o" K9 V

  55. 6 t2 u0 i& j+ W* N" r/ J5 n
  56. // 是否使用栈溢出检查
    ) a5 q$ U* C- C: V. M9 ]/ I5 v
  57. #define configCHECK_FOR_STACK_OVERFLOW          0
    $ k" v" x# \8 M
  58. " w9 p" u/ I' O' M2 X1 M4 P6 W
  59. // 是否使用内存申请失败钩子函数# j& b6 H; P7 M
  60. #define configUSE_MALLOC_FAILED_HOOK            00 Q( P. w3 W: {. s4 w, d
  61.   x/ a6 \! k2 X: j
  62. // 是否使用软件定时器# T6 U3 O& r* d& l. W" ^" h9 t1 n
  63. #define configUSE_TIMERS                        1
    5 k! R$ W# o0 ~$ U. e
  64. . |2 d9 m6 t( b4 `
  65. // 设置软件定时器服务/守护进程的优先级3 M3 V4 l$ m' f3 V; M4 i
  66. #define configTIMER_TASK_PRIORITY               3
    5 d) L9 U" U6 U. n# W
  67. & I) k9 J+ @: T: m
  68. // 设置软件定时器命令队列的长度
    8 J* s$ i% _7 ^, d" W
  69. #define configTIMER_QUEUE_LENGTH                105 y6 i5 {/ Q" k( L- s" f0 U" L

  70.   r8 ]0 n/ ~) d/ V
  71. // 设置软件定时器服务/守护进程任务的堆栈深度9 q. q" x! R" m6 V
  72. #define configTIMER_TASK_STACK_DEPTH            configMINIMAL_STACK_SIZE5 z" N9 `3 A3 x$ M6 K/ c+ M/ `& e
  73. + m$ v6 W! Q0 h# P5 _) v4 J
  74. // STM32的最低优先级
    7 F6 u: n( g- b( y
  75. #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY   15) v; G( H9 f% j2 L
  76. 6 V% ?; I) Z2 ], Q4 T
  77. // 能够在中断服务函数中安全调用FreeRTOS API的中断最低优先级
    & o  ?4 p' z+ D2 E$ P: g
  78. #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 17 H7 U# N5 ~4 R; @) N# ~

  79. 9 o/ B9 @( b" m+ _3 u9 O
  80. #define configKERNEL_INTERRUPT_PRIORITY                 ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << 4 )% O$ A* l; r& ?% @% Y0 D
  81. #define configMAX_SYSCALL_INTERRUPT_PRIORITY         ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << 4 )
    # d$ A& ?- E# P8 d1 @1 U
  82. 0 w( M' x: |" ^, H: E; e* `
  83. # _; c* S9 H5 n6 F
  84. // 将以下定义设置为1以包含API函数,或设置为0排除API函数
    8 l6 d4 ^/ d! f  v( P4 F$ ]
  85. #define INCLUDE_vTaskPrioritySet                1
    : @; r8 M! I# r# n1 W1 H! e# ]) N
  86. #define INCLUDE_uxTaskPriorityGet               1
    3 ^% h0 w1 N) I4 r
  87. #define INCLUDE_vTaskDelete                     1, D, {0 z5 p" g7 l( c
  88. #define INCLUDE_vTaskSuspend                    1
      F4 Q/ X& v9 O3 R# Q- p7 h9 G; \
  89. #define INCLUDE_xResumeFromISR                  13 g" B: A- Z8 e( e0 Z- z
  90. #define INCLUDE_vTaskDelayUntil                 1
    2 b( {5 ~' k& Q6 @
  91. #define INCLUDE_vTaskDelay                      1
    $ Z) M0 N* S! ~1 O3 W6 b8 Z
  92. #define INCLUDE_xTaskGetSchedulerState          19 H: P; Z) O- `6 Y1 B
  93. #define INCLUDE_xTaskGetCurrentTaskHandle       10 c, C: B9 q: r8 @6 |5 G/ \' s" P
  94. #define INCLUDE_uxTaskGetStackHighWaterMark     0
    7 c4 d, m1 o  b# G/ j0 b; {4 D
  95. #define INCLUDE_xTaskGetIdleTaskHandle          09 r  p; {! M; E% ]: X: @8 E& L$ V
  96. #define INCLUDE_xTimerGetTimerDaemonTaskHandle  0
    ; b& Y0 I7 Q% K' P
  97. #define INCLUDE_pcTaskGetTaskName               07 W6 o" q+ c. G3 d3 V7 q5 a% }: L* W$ j
  98. #define INCLUDE_eTaskGetState                   0
    9 N* A* ?' I$ L. P8 h' l% J9 [
  99. #define INCLUDE_xEventGroupSetBitFromISR        11 T: R/ f9 V$ h: N3 [
  100. #define INCLUDE_xTimerPendFunctionCall          0
    3 i/ k* D! V0 X1 l% |# x: z3 p

  101. # s  ?8 m0 Z. v* n
  102. #endif  /* FREERTOS_CONFIG_H__ */
    & r/ f8 i7 w0 X3 I& d2 D! q9 z
复制代码
& z3 {$ P* f7 U) c# p
修改main.c文件,添加头文件:; {8 E" K& q+ h

7 P6 w/ G7 f, h. v/ s3 ?9 i* f
  1. #include "FreeRTOSConfig.h"
    " v$ ^! v9 G# D  a/ }- U
  2. #include "FreeRTOS.h"3 w1 ~( p8 L0 J; ]% I
  3. #include "task.h"
复制代码

4 L9 ?) O# Q1 c这里我创建了三个任务,任务一为led1灯每间隔500ms闪烁一次,任务二led2每间隔300ms闪烁一次,任务三为串口每隔1s打印一次helloworld。
1 b4 F' t4 L& o3 t5 A. m* @% h6 Y  _1 o" v  |% q

. E4 k2 r" l& G+ l. x# {
  1. void led1_task(void* arg)3 h% W- T2 B. k4 F
  2. {
    9 [5 y1 q2 w  x+ M) k
  3.     while(1)
    / ^' h2 O4 N9 Z6 E7 p
  4.     {
    0 R- z: ~& x8 l4 F
  5.         HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_8);+ r9 B  H/ ]) X0 l
  6.         vTaskDelay(500);
    9 S8 l& e5 Y( @) L2 T; b
  7.     }5 D  Z- M! K) ^
  8. }
    . ^" V" Y) U4 w5 o, f
  9. / }) [3 Q+ i, g! m5 |; R( c
  10. void led2_task(void* arg)+ w0 t2 R7 @, {# i
  11. {
    # J1 ~3 V% x7 m" N* X
  12.     while(1)7 J) q5 P. S/ L7 O
  13.     {7 R4 h- V& h" L3 ^
  14.         HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_2);
    ! {/ _$ \% O! \2 T
  15.         vTaskDelay(300);$ f' z! E6 Z, x9 V7 H
  16.     }% P# s0 M. @0 k
  17. }; G: j( K+ U+ O  E- ]) C
  18. 3 f2 H' S8 ~9 ]) k
  19. void print_task(void* arg)
    - @2 L' k! \0 X6 G7 |. F
  20. {: g- f; V( C) G" ]
  21.     while(1)" k, {& u' j; G/ g7 j$ A
  22.     {) {2 J! u7 j" R. I- ~" ?/ r
  23.         HAL_UART_Transmit(&huart1, (uint8_t *)"HelloWorld\r\n", 12, 100);# S* n, d& `* H
  24.         vTaskDelay(1000);
    ' @. v' V6 B2 p- q" a& _
  25.     }; s: _2 f; }4 a) J
  26. }
    ) X+ z$ ]* c0 C, n2 a8 A* c
  27. + {9 A7 G% U" r) n# w) r# X1 `
  28. int main(void)
    " N2 ]4 E  F: z$ L7 Z) W0 o8 H( Y
  29. {5 t$ o6 l. [/ @4 w4 n' q* y0 @
  30.     HAL_Init();4 A2 _! X, z% @) `2 Y7 A( A- _/ q
  31.     SystemClock_Config();3 a8 V, }* @/ B$ W! I5 _7 H
  32.     MX_GPIO_Init();
      P" H" I; t: f
  33.     MX_USART1_UART_Init();
    ) X& d1 `& L3 ?6 E+ i
  34. / u7 l  y3 P3 J. q. J) b/ Z
  35.         // xTaskCreate函数参数说明:
    - C9 w2 @; L8 Y% r1 U" H
  36.         // 1、任务入口函数) H2 K9 B  F9 J- W4 n
  37.         // 2、任务名称2 B& v4 h7 q8 b
  38.         // 3、堆栈大小,单位word
    3 x, i* h) {4 }& O; L
  39.         // 4、传递给任务的参数
    4 \% v5 j/ P2 `, y
  40.         // 5、任务优先级' e! F1 p) M* o; M5 c5 {
  41.         // 6、任务句柄( f6 I! S* w$ U( X" p
  42.         
    8 a. y; k, [2 m6 Q6 X  U  M! q  Q
  43.         // 创建任务led1灯任务
    % E4 {) ~; s9 t4 i
  44.     xTaskCreate(led1_task, "led1_task", 64, NULL, 3, NULL);
    ! e4 _# w: Z/ o
  45.         ' [( b  y- o$ a5 i6 s  y/ c
  46.         // 创建任务led2灯任务% G9 }3 N. W$ |( N
  47.         xTaskCreate(led2_task, "led2_task", 64, NULL, 4, NULL);
      T0 P* C1 m' j
  48.           f9 d% e' ~- ?' i
  49.         // 创建串口打印任务
    # T9 ]2 E' D) i' B
  50.     xTaskCreate(print_task, "print_task", 128, NULL, 5, NULL);4 Q+ m5 V, l, V+ V* Y7 c3 P3 w
  51. 2 c" D/ ^8 k0 v: d# i+ R' T
  52.         // 启动任务调度4 u0 `2 A0 V# c# R3 _
  53.     vTaskStartScheduler();( f; r& c1 z: r5 `: d4 o9 T" l2 Z
  54. * N' n8 l* y6 `* N2 {0 Y
  55.     while (1)
    8 l% v0 a& Z9 P8 E0 F8 z/ y
  56.     {2 U  y& Q) i9 P
  57.     }; |; D% s- ?& K4 T( T. Z
  58. }
复制代码
3 P$ E" G" T- K* [
到此,移植完毕!/ c$ s+ _9 I# I

& ?$ [9 [6 K0 b3 @9 m) Q总结:移植FreeRTOS还是相对简单的,主要是配置文件FreeRTOSConfig.h的配置,每个宏定义所代表的意思需要好好查阅!' s2 K  I% \" R3 @' D4 z+ R
/ ?# Y- l+ O. a8 a/ {, i3 b7 P# D) Y1 O! w/ m

& P$ C. I/ x' N- h2 S
$ f- P: T' {. @" W. D, ~
收藏 评论0 发布时间:2022-4-10 19:56

举报

0个回答

所属标签

相似分享

官网相关资源

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