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

【经验分享】STM32F407移植FreeRTOS步骤

[复制链接]
STMCU小助手 发布时间:2022-5-16 11:34
1、源码准备6 W8 H* ?: s. `6 f) r# f" a
       首先准备好我们下载好的FreeRTOS源码以及STM32F407的工程模板(这里以原子的F4跑马灯工程为例,可去原子的开源论坛自行下载),源码下载及参考请参考我的上一篇博客。+ f! w9 H+ o/ g( q

7 ~9 `3 O* E. F$ Y/ S2、创建FreeRTOS文件夹3 A5 m0 W+ b* @" o$ ~7 M5 n
在工程中创建FreeRTOS文件夹,将FreeRTOS源码全部复制到该文件夹下
8 C1 _/ r0 w& I* E1 Y- q2 P: P$ E+ ~8 ?
J4VG7F(R0KA[1L[S_4RKHKF.png
/ D7 D$ A+ D' m" {5 V, M4 @5 p% ]* k3 d# n5 ~
打开portable文件夹,删除没用的文件,留下如下文件即可* O6 |9 E( ~$ B+ G6 K
+ |( j9 \* m9 ~2 F
20190816170452609.png / z/ V6 T# P& @- l6 r
: T- b& a, X6 X$ O& Z6 x
3、在工程中添加FreeRTOS源码
8 }  D; B+ ]% f打开工程,在工程中新建FreeRTOS_CORE和FreeRTOS_PORTABLE,然后向着两个组中添加对应的文件,如下图所示:
; W2 |: t1 ?5 }% `- I* l
% S9 R6 N2 u1 C# C 20190816170518369.png
6 P. L8 w! U8 u
& D+ D+ m' p. b2 g       FreeRTOS_CORE的文件打开FreeRTOS就可看到,port.c是RVDS文件夹下的ARM_CM4F中的,因为STM32F407是Cortex-M4内核并且带FPU。Heap_4.c是MemMang文件夹中,这里有5个文件,是5个不同的内存管理方法,为什么选择第4个,因为FreeRTOS内存管理所决定。1 l4 J8 @& S) h9 G$ y

3 b# Q1 s2 x- W7 U# z4、添加对应的头文件路径3 y, v: }8 j$ I7 i. i8 h3 q; I

( ]; S: e0 D/ W: k' q
SU4[70TMSS9THQ_{YAT$)15.png
, }) ?/ A% [/ ~% v3 }7 }) I7 S' |7 H
5、编译及错误解决
$ z4 k: t' J# c
5.1 找不到FreeRTOSConfig.h文件
7 p9 ?8 |2 f8 m! `7 D4 ?完成后编译一下,会出现如下错误3 M9 }1 I& t/ C1 r6 f( T+ N

( g1 i! b3 b+ g9 g& q6 B- S 2019081617065397.png ; M, X7 s% r" F1 ]1 v3 G

+ q  o" A# ~1 }       很明显是没有FreeRTOSConfig.h这个文件,那我们就把它添加进去,具体位置在FreeRTOS的DEMO中找到CORTEX_M4F_STM32F407ZG-SK文件,如下图所示
7 b2 B9 b1 F7 r! T- _; Z$ d1 _1 C. a' Q. P" P( G
RB9(NYFTTB57AG]9}PD))0V.png - Q7 R" ?. s4 `1 l/ D

4 |4 _; b, H8 a      至于放到哪个位置自己随意,一般是放在FreeRTOS的include里面,而这个文件是FreeRTOS的配置文件,一般操作系统都有裁剪、配置功能,而这些都是通过一个文件内的宏定义来完成。: W  ^) L% q. ~$ Z9 a/ A3 I* |+ O

2 x; n+ s" O1 J& N5.2 SystemCoreClock未定义3 K( W: r* R& d7 `/ S7 K
接着上面的步骤再编译一次,还会出现以下错误,意思是SystemCoreClock未定义
+ s8 j* O/ O: d; g1 i 20190816170815891.png
9 H7 Q( q; D, H" p! E( S
1 ?8 H7 v5 ^+ h+ |+ j  t; T2 k解决办法:修改条件编译
5 g* f& A  M: n2 v8 r  T( V" D& E6 ]' E8 y
O({SZ$P%M[VB6]C}PA1WCJO.png
6 A" g. W, ?% G# Y. ?, d, B7 E3 ^9 ?& `: f+ P6 S% o6 g
5.3 重复定义  W6 w; v0 w* c& T! r
接着再编译一下,发现还有错误,这次的错误是重复定义1 ^+ N! h8 M; M) a. |+ m: d

4 o8 B+ J; h$ U6 |7 b4 n- A 20190816170906281.png
' e9 E( f" p+ Y) w: p" W  t( o0 Z$ g/ h. }2 w; W- b
解决办法:
% x! c# t  o& n3 B* H  z  G7 C# q8 s2 I" Y
     屏蔽掉stm32f4xx_it.c中的PendSV_Handler(),SVC_Handler(),SysTick_Handler()这三个函数,4 r, q' ~0 G' p8 N: d. F  F
( f4 Z6 ^1 M7 q% O% J6 a
J1{J5FFPO6%)VS2$FL4RPO9.png
" [  s& K, S' e: n/ j  ]  I. |. v+ P, Q* E0 J
5.4 钩子函数未定义
* [3 y. e* m" T; @4 k     继续编译一次,还是会有错,这次的错是函数未定义,他们都是Hook结尾的,称为钩子函数。4 ~6 ?) C7 P! _1 m

+ E/ j! G; i0 B) D" B4 x9 V# I 20190816171003138.png 3 s2 G( D8 v# Y8 J

+ ?. P5 y" x4 ^9 F( Z" r( W) G解决办法:4 r# J2 v4 o) r8 u2 U2 F( i

5 @" z1 {7 M# l        去FreeRTOSConfig.h中关闭这些钩子函数,他们都是宏定义决定,这里将configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configUSE_MALLOC_FAILED_HOOK和configUSE_FOR_STACK_OVERFLOW定义为0.
" u. v. x5 b9 `* l, ~
8 n7 d/ T  {: D, D; ^$ y AD3PLMJQC][R4G94VZUK8[O.png
2 H5 m$ B4 F0 c5 J* c- ?8 C6 Y5 U! \. A& p5 _& |3 k. J, Z
再编译一下应该就没错了。( E3 w, s+ o) p; q
7 g- Q" _/ ~- m' s% J5 s
6、修改SYSTEM文件4 j1 {. |7 s$ t& |# R6 p. x' a
因为原子的SYSTEM文件夹是针对UCOS编写的,所以要进行对应的修改
4 M( ~, Q. k3 P- b  D" A8 V" s: D, N1 B9 S" F( _
6.1 修改sys.h文件8 a4 N0 y# i, Q' O
把宏定义改为1即可,要支持OS,UCOS也一样的4 [; e/ s' a, l+ V# G) T

3 I% `' K. i- y0 B 20190816171410738.png / c1 `+ _4 C' O2 k5 B0 d

; }, {( S( S& h! t) U1 R6.2 修改usart.c文件. q) o7 p$ H* R! E  I
修改头文件为& s, J5 w2 k5 u7 x; F/ W( B& q

! n- h$ j" n, j 20190816171442265.png / ~! P8 \; k3 C/ @7 p

* f; h0 {' A& u4 J9 P修改串口中断服务函数为:7 d- E  `6 F; p$ m* C
, Y. W8 T7 m4 o+ G' l/ a, U; ~
}YRE3F87]$D8C8J4Z((9L5A.png $ `  x3 |* m, k

4 d) C$ {' c" G7 A6.3 修改delay.c文件

1 C8 A' t5 F) `( A$ N同样先修改宏定义的头文件
# q- o1 b" G7 c# w9 A( e# x5 G/ z+ j& r
20190816171540153.png * k2 o. g- S) B0 z5 A

6 J% a. ]$ f! R( u5 A, i接着修改systick中断服务函数为
, o& M, @- H+ e( T! P# o: c/ h/ [& }! j6 P9 C
20190816171548315.png
! O3 e$ w7 r/ P- x% \. j' m$ u- }) ]3 {7 J0 o) Q, `5 h% d0 D, }
在滴答定时器中断服务函数中调用FreeRTOS的API函数xPortSysTickHandler();( b/ I+ I2 m  p  }( C% m+ d

( _/ i" q% I" h8 ]7 ^/ j( l/ E在修改delay_init()函数,如下:) c" a  @, w: M8 x. p5 z/ y" b0 R

5 y% }" [# k, m- B) q, ?0 Z4 ? TF[2BS{SWY0__(HLC0YUP.png 5 h* v# k& ~' T! H& j
" N' X- U0 v+ B: H3 f; o+ G
接下来就是延时函数的修改
5 s+ j% v+ c5 Y; I
# B) S8 D0 i/ ^  i" [3 k TOZ(Y}6`9}UOCF))H}%(8_A.png
1 R, G4 n  d, B# n9 r8 N) q1 \$ |2 y
9 [! x- b( u; \8 l1 i; U修改完后再编译一下,会出现重复定义的错误,如下图:
* ^2 H& J. W- C$ |9 l  ?! j& l1 v" o
. e. [" d# S3 C% N/ T7 _ 20190816171647173.png / k. G3 b* ?% ?# _

. }; n6 i5 C, r) x解决办法:屏蔽FreeRTOSConfig.h掉底部的#define xPortSysTickHandler SysTick_Handler
9 O( T( q3 j8 G: `  l9 a% u; ?. H
; m4 |* K) v6 C& J2 S, Q C}N@EYXV4Q8[OGMY[CB4[KJ.png # s1 G( c" T: _% v
: h2 V; M: R- Y# ~& i- p
7、修改main.c进行功能验证
/ [; e% N: u" g主函数主要是实现实时系统多任务的创建,具体如下
! V: k: {9 a1 B% M  Y
: M5 I  Q+ w! y! n" m% w% |  O
  1. #include "sys.h"0 c" g( o6 J$ j" C! b( S
  2. #include "delay.h". M3 n% J: i  b4 I
  3. #include "usart.h". p) [6 |4 c9 E6 R7 D
  4. #include "led.h"
    : L8 T# r+ c  [* i' C
  5. #include "FreeRTOS.h"6 u( o$ a* v: F$ o- i1 p
  6. #include "task.h"
    2 v' ^# c" ^9 m/ I" L
  7. " ?: }$ X0 q* H9 A3 @
  8. #define START_TASK_PRIO                        1& [1 B( ?' F5 S
  9. #define START_STK_SIZE                        120& `  b. z$ k' H
  10. void start_task(void * pvParameters);  //任务函数
    4 m$ P/ M  j  h3 f, J% ?) A
  11. TaskHandle_t StartTask_Handler;                //任务句柄         
    2 Y* E9 _$ P1 U+ ?+ t
  12. 4 S  v/ O, a6 d' c9 V3 I8 I

  13. ( g3 C) g3 O1 R& u8 Y' V
  14. #define TASK1_TASK_PRIO                        2
    # b9 q. ^3 E) R( _: X: f
  15. #define TASK1_STK_SIZE                        120
    : C% s1 ^3 y5 E+ F( j
  16. void task1_task(void * pvParameters);
    6 @/ ~1 I, {- x8 ~. Z0 [
  17. TaskHandle_t Task1Task_Handler;                //任务句柄         . `( V4 n# O6 ?2 A

  18. 9 ~. F, U- T, y* t9 G5 s7 D% s, Z6 w
  19. #define TASK2_TASK_PRIO                        3
    1 C+ c! k& ?+ H5 [8 j/ W1 |2 X
  20. #define TASK2_STK_SIZE                        120 8 G9 {6 K0 J0 l
  21. void task2_task(void * pvParameters);
    * F# `& K  c' R. U2 a0 P
  22. TaskHandle_t Task2Task_Handler;                //任务句柄        + s! j' @! b* t/ R4 L# [. D' j

  23. ( [& x0 e) o1 M) x; b' [
  24. int main(void)
    ; ?/ X# n  X) _4 D$ Y
  25. {; {+ S$ a. u+ n: M6 h! O
  26.                 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    4 j  {5 R: I+ V3 I5 Y# _$ d" j
  27.                 delay_init(168);                //初始化延时函数
    0 H4 u! Y- z0 v# H# `
  28.     LED_Init();                     //初始化LED " s& a5 h9 ~' K) c8 I: i" K# U+ C
  29.     uart_init(115200);              //初始化串口& Q9 U6 `# Y- ]
  30. 1 `& H& a2 \" \$ U; O
  31.         xTaskCreate((TaskFunction_t        ) start_task,
    9 s2 y6 |8 ~8 |
  32.                                 (char*                        ) "start_task",* |& h  P. m( R0 I6 @- u
  33.                                 (uint16_t                ) START_STK_SIZE,2 `* z7 [1 ^4 f7 H  a: E8 F& a3 B
  34.                                 (void *                 ) NULL,. C+ O% Q  n( S, g) ~& C: A" ?% f
  35.                                 (UBaseType_t        ) START_TASK_PRIO,, \. g, j+ Y# p" [/ e. C5 w/ H* c
  36.                                 (TaskHandle_t*        ) &StartTask_Handler);3 R; o/ i! S' g. t) d
  37.     vTaskStartScheduler();          //开启任务调度. j7 W- f+ D( T
  38. }  W1 t2 W# y2 [; D' [6 J5 z

  39. 2 u% j$ m; r" F& V) A) }
  40. void start_task(void * pvParameters)0 C0 ~9 s( V1 k" L8 f  X; a" T8 ?! H
  41. {* x8 [$ U" K' E
  42.         //创建Task1+ @) ^/ u4 T8 C( n1 r7 _
  43.         xTaskCreate((TaskFunction_t        ) task1_task,
    0 A4 U. n/ f- L
  44.                                 (char*                        ) "task1_task",
    9 s6 Z3 N3 }7 c5 Q) E* Z. S
  45.                                 (uint16_t                ) TASK1_STK_SIZE,/ h/ h( g* k2 F# C; k9 l
  46.                                 (void *                 ) NULL,
    1 u9 F3 X! w; E! S/ p# _# _
  47.                                 (UBaseType_t        ) TASK1_TASK_PRIO,6 S8 ~1 A! J& t$ V8 x
  48.                                 (TaskHandle_t*        ) &Task1Task_Handler);/ u9 V9 I( ~) S
  49.                                 
    # T$ I" V, U! @' ]& V8 ~- m1 b
  50.         //创建Task2; X, F1 a9 z3 L' O7 ^/ X: U7 q
  51.         xTaskCreate((TaskFunction_t        ) task2_task,
    0 [; h. x' G) ?4 a
  52.                                 (char*                        ) "task2_task",
    3 a+ a+ T& Z0 F) D  [6 R) q" ~
  53.                                 (uint16_t                ) TASK1_STK_SIZE," e! `; |4 I9 r% e: z# c. A
  54.                                 (void *                 ) NULL,
    . r/ Z4 u5 G1 D1 k1 j% T( j7 W2 f
  55.                                 (UBaseType_t        ) TASK2_TASK_PRIO,4 P" d9 B& `' n
  56.                                 (TaskHandle_t*        ) &Task2Task_Handler);
    ) m: i* j& W7 X' b" _" O
  57.         vTaskDelete(StartTask_Handler); //NULL1 K9 Z0 h% Z& q+ L9 m+ g( R# a
  58. }
    - c- R) C/ G1 q1 \: M

  59. $ @, |7 x+ a+ P
  60. void task1_task(void * pvParameters)2 n  ?' v, x8 r5 h; F7 F* d  i
  61. {$ s, n) x, m# Z% m+ Q0 B. S$ T" {
  62.         char task1_num=0;
    8 {2 A, C# B/ a; G+ b* p3 P
  63.         . C) z) ?! b1 u3 i- l4 ]; v
  64.         while(1)1 h/ g7 ?/ k" w, s4 ?9 Y
  65.         {0 d+ p/ `9 |  Q/ E
  66.                 task1_num++;
    ! H6 K6 [2 {4 T4 y1 j5 |
  67.                 ' e/ ?5 ^% m5 x5 T, P( N
  68.                 LED0 = ~LED0;
    , r. D& c+ F6 U0 H6 E$ a" a' _0 Z, F
  69.                 printf("Task1 Runing %d !\r\n",task1_num);1 d2 a9 G0 K% n4 R2 i% i9 U
  70.                
    & w1 M+ a2 X/ A; }
  71.                 vTaskDelay(1000);+ ^+ `0 n) D8 Y8 m, F1 t% G
  72.         }2 N9 g5 b# ^1 z% A. O5 ]
  73. }9 a1 m4 N, ~2 C/ r7 u5 ]& O/ a
  74. # X) d& o4 E' F/ p
  75. void task2_task(void * pvParameters)0 z1 T( [4 l6 P# J% ~, F
  76. {' z' n) Y  c3 k% x$ D/ w* n5 k/ w
  77.         char task2_num=0;
    : ~% V7 {9 ~4 D
  78.         while(1); O& B% v' T- c% w
  79.         {
    : N5 K1 E8 q1 \& R( B7 C
  80.                 task2_num++;" h6 M1 ^( o) I- }- L8 `
  81.                
    ; n1 N: I; e  j" y: F
  82.                 LED1 = ~LED1;) ?# H- a/ X9 w
  83.                 printf("Task2 Runing %d!\r\n",task2_num);
    4 w6 o7 @0 W& Z% Z& N3 l
  84.                 vTaskDelay(500);
    + _$ b: }1 e7 f3 _
  85.         }
    9 _7 i0 Q, G/ Q2 C$ P% E0 T2 S; M2 c
  86. }
复制代码
, Z) E! e) F8 z5 U! H4 S- @
实验现象;
( f$ E" M  G$ p5 L8 V! b! v8 d. q. a& l7 h! z2 Q/ I$ C2 e7 u% {
      开发板上LED0和LED1进行不同状态的闪烁,串口也会打印任务执行次数,很明显任务二的速度是任务一的两倍。
# A. {: M; {# f; A; f8 h3 `6 M& C/ e1 |. I# u5 A
1VM2{H5BDGWPZL[[W@NP2)D.png
) Q, Q" E( P- I1 `) ]! I0 |
0 @; w/ o9 @: [$ V 20190816171854468.png 5 p; g8 ^8 ^% p* H
. `6 q  S- b$ {  J: \5 e
我这里使用的是STM32F407VET6,原理都差不多,用那块板子都一样。至此,FreeRTOS移植和任务创建成功。5 z& K. {1 K  Q2 u
5 t) G" r! I; r" F5 ^' N
: I' i9 n! ~" h2 T) i
% E& V' C7 {/ _" w
收藏 1 评论0 发布时间:2022-5-16 11:34

举报

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