请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
STMCU小助手 发布时间:2022-5-16 11:34
1、源码准备1 `# w* o3 N) y4 H% Q1 D
       首先准备好我们下载好的FreeRTOS源码以及STM32F407的工程模板(这里以原子的F4跑马灯工程为例,可去原子的开源论坛自行下载),源码下载及参考请参考我的上一篇博客。
; |9 @6 H1 g- F' |6 l) v( M! L6 l* F0 x: ?2 j
2、创建FreeRTOS文件夹( t' i/ K/ T2 |' Q+ Z) d0 f
在工程中创建FreeRTOS文件夹,将FreeRTOS源码全部复制到该文件夹下: D/ x6 y6 Q) k0 v3 w# a! O

+ F" k7 ~7 L3 ]% R7 } J4VG7F(R0KA[1L[S_4RKHKF.png
; t# n- T! B% v' S9 h/ U+ g& ]5 N& ~( M
( e5 A2 n5 _5 a) q! i打开portable文件夹,删除没用的文件,留下如下文件即可& d+ ?  V) o7 D$ I% K% x7 I- M
( U  }/ d0 o- q( s, x' L
20190816170452609.png $ W  }. w3 C5 @1 S0 M6 |0 v6 T
, G8 `+ N' {1 j  n  Z6 y; f
3、在工程中添加FreeRTOS源码
4 [4 n# g6 K: a$ K打开工程,在工程中新建FreeRTOS_CORE和FreeRTOS_PORTABLE,然后向着两个组中添加对应的文件,如下图所示:
0 G" t- A" m7 C; W- O8 P. A
0 |8 \4 O9 Q" k/ t2 J: g 20190816170518369.png , V7 A! e+ i0 p2 I/ a. n5 x4 b

* ^  T7 u5 Q! k& E& t8 L, \( a6 W$ S       FreeRTOS_CORE的文件打开FreeRTOS就可看到,port.c是RVDS文件夹下的ARM_CM4F中的,因为STM32F407是Cortex-M4内核并且带FPU。Heap_4.c是MemMang文件夹中,这里有5个文件,是5个不同的内存管理方法,为什么选择第4个,因为FreeRTOS内存管理所决定。
) i5 r  q! I0 |: ^3 C
4 y& Q) M5 J* }) I% ^2 {4、添加对应的头文件路径
$ w5 A, p2 r4 I! p: H/ M$ l* t2 H' b& ]
SU4[70TMSS9THQ_{YAT$)15.png / ?( ~" q0 y8 y. |. a* y5 H; V
5 ]5 P! q" r' `" o' q
5、编译及错误解决

* x4 i% d3 m/ P3 C5.1 找不到FreeRTOSConfig.h文件4 o( C& H, C& ~1 K, ]. `
完成后编译一下,会出现如下错误& P& q, Y" L' K; i: a8 ?3 k' S0 r& _
9 o9 o, T6 Y3 Z2 Q1 t3 X/ y' R
2019081617065397.png
  E9 S7 B: R, T2 [; x/ h5 k7 R& ]3 f% j
       很明显是没有FreeRTOSConfig.h这个文件,那我们就把它添加进去,具体位置在FreeRTOS的DEMO中找到CORTEX_M4F_STM32F407ZG-SK文件,如下图所示& U- E; m5 s# H7 n7 f

# T, I! W2 ~: i( I RB9(NYFTTB57AG]9}PD))0V.png 1 m. k1 {% b; G. ^

# ]/ e6 e2 D9 m, I8 a      至于放到哪个位置自己随意,一般是放在FreeRTOS的include里面,而这个文件是FreeRTOS的配置文件,一般操作系统都有裁剪、配置功能,而这些都是通过一个文件内的宏定义来完成。
+ V- l( R- D8 ]& e6 p* s  o; ^* z/ Z: \7 m1 F; C* Z$ b
5.2 SystemCoreClock未定义
  I- d, w5 b2 }* \接着上面的步骤再编译一次,还会出现以下错误,意思是SystemCoreClock未定义
$ D0 U% G, D- n3 K$ v 20190816170815891.png
! ]! s+ `1 O* M0 }( A$ H8 _% H1 v/ r$ S" W: Y5 k5 Q/ I
解决办法:修改条件编译' ]3 ^! J+ a2 ?+ z
  b& p2 H" c7 E8 n
O({SZ$P%M[VB6]C}PA1WCJO.png + {( B) q1 i& [, h6 Y

  q$ D/ h+ P" m& b5.3 重复定义
. j9 W$ Q, }- I( L- e( h+ w& Y1 I3 ?& Z接着再编译一下,发现还有错误,这次的错误是重复定义& U6 G9 K% V/ |' e& S
0 W  W2 v! ~; J4 a
20190816170906281.png . A( ~( }$ c( N( \) x

4 v4 t* c& L+ n, c" V% ^& D! P解决办法:
$ L# h5 e# b8 Z! ^3 h) C* W$ T* ~1 P/ X. x, V1 U, n6 @
     屏蔽掉stm32f4xx_it.c中的PendSV_Handler(),SVC_Handler(),SysTick_Handler()这三个函数,
/ \" M$ k' O! B' L& J! q) ?
$ ~. |" X/ p, T1 l- B J1{J5FFPO6%)VS2$FL4RPO9.png : ]  g7 @, M' j5 H* _
' [4 @( C1 t+ A
5.4 钩子函数未定义3 `) c' w+ a5 U$ K, q% ^( z
     继续编译一次,还是会有错,这次的错是函数未定义,他们都是Hook结尾的,称为钩子函数。
& Z+ o# r* A' X+ J$ y+ L3 z
6 }" Y7 f' f! Y3 M# i( q 20190816171003138.png & H! k# I6 Z9 S5 r0 U

$ |8 K# U8 y1 e2 p解决办法:
$ B; }  ?7 _* x9 D5 g: G: [) k- O7 V* {, m
        去FreeRTOSConfig.h中关闭这些钩子函数,他们都是宏定义决定,这里将configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configUSE_MALLOC_FAILED_HOOK和configUSE_FOR_STACK_OVERFLOW定义为0.
" c' ^0 T" ], P! L( E; [7 M; c% L) h( J: q, Q! T* L+ Z. G  E
AD3PLMJQC][R4G94VZUK8[O.png $ i% s. g% D1 u: N

" w+ k  f( F9 _! F8 p再编译一下应该就没错了。
2 X. S1 W3 ?; I& V6 @5 X7 Z7 @
6 J% ~, Q& \! O( ]* n* D$ L, u6、修改SYSTEM文件
3 P1 t" Z2 ]2 _因为原子的SYSTEM文件夹是针对UCOS编写的,所以要进行对应的修改
/ o2 u* S/ m; U, b  Q& ]* a# E1 A+ O' h2 D( @
6.1 修改sys.h文件
2 |" G; p; Q1 Y8 A+ r把宏定义改为1即可,要支持OS,UCOS也一样的) ]. K% e  S0 T: P$ O" E

  n/ y7 L1 J' r! G3 B2 t 20190816171410738.png
& `' j) O/ x' T
/ c" V9 [0 }" }: a; V/ d6.2 修改usart.c文件2 n( L* z+ I$ \& G
修改头文件为1 \' Y0 t/ k' z7 ~* B
3 T. |$ k! X/ g; m0 _
20190816171442265.png
1 E* ~  h( V3 H+ ]3 |' j8 J4 b8 O& ~  H8 m* x3 p6 n4 e. z5 O
修改串口中断服务函数为:
! ^/ f& s& `2 _( z7 h8 ~$ D3 c: D' b. a% l; h2 u* M
}YRE3F87]$D8C8J4Z((9L5A.png
) V% n. C4 s$ U0 V  p! ^
4 o4 }0 C+ y8 {. U8 K6.3 修改delay.c文件

) ~+ P2 t. K6 d! U' C1 {同样先修改宏定义的头文件9 q; z% q2 R2 @- d
  G+ G( M- h4 N- N
20190816171540153.png
# `/ S+ B5 d2 J$ F' ^* m7 h, [4 q+ A/ \& \
接着修改systick中断服务函数为, r# f4 L. i2 A- A5 U. R

7 k! x8 r) r$ E# d! W 20190816171548315.png
5 ?, c8 r4 p) X. }. Y  p9 e( s! [: h6 P) L* Q+ [; J5 D2 o
在滴答定时器中断服务函数中调用FreeRTOS的API函数xPortSysTickHandler();
$ h) k, a) m  n. r6 s# s
( i6 c3 A5 A6 N1 B# F在修改delay_init()函数,如下:
# t) [( ?2 Z2 _& b( D$ l
' a* T: v/ @: L8 w$ l$ d8 k TF[2BS{SWY0__(HLC0YUP.png 7 z) a& r' h; x0 J0 _/ F& i% v. G
  T8 D# l6 [$ b3 v/ v  k
接下来就是延时函数的修改: Q3 g9 e0 a1 \/ W

' v4 c9 \9 g: T8 q TOZ(Y}6`9}UOCF))H}%(8_A.png
# ]* c+ S. B; a' {6 u+ ]
3 \8 e6 V% J  f$ ^( l修改完后再编译一下,会出现重复定义的错误,如下图:- F& M( T; f" j4 q6 }: `

2 B% X9 K8 Q7 U- S4 N0 D 20190816171647173.png + G/ s1 ]& n# q, n

$ f7 T* @* W3 Y/ i% j* e# H解决办法:屏蔽FreeRTOSConfig.h掉底部的#define xPortSysTickHandler SysTick_Handler
9 A+ U3 V, @: q$ A- r( `9 y1 H" c
2 @; x6 `6 p2 c) G4 l C}N@EYXV4Q8[OGMY[CB4[KJ.png
0 v' H  n$ A. z% G
: q& Y3 |% |4 ?7、修改main.c进行功能验证) ?. t1 G0 ~. ?6 }! u
主函数主要是实现实时系统多任务的创建,具体如下
3 |8 Q/ i3 O2 f3 n4 ~  }2 @. X5 m4 d% m
  1. #include "sys.h"- d- t; {8 g& l/ v
  2. #include "delay.h"
    7 N# t8 _" Q! i9 L+ ?  p, B; C1 {
  3. #include "usart.h"
    # [1 ~" }" r4 r* [3 N" G& u; [# E* J
  4. #include "led.h"
    # d3 B8 N5 x, W6 Y# U0 |6 n/ D  m
  5. #include "FreeRTOS.h"# O! A5 u' A; C3 G) x" \( r9 C; n5 {8 M
  6. #include "task.h"
    ' o/ Z7 |- F; C/ ^' `! D' f4 a& U
  7. / {0 A3 A! ~+ t; H- Q* ^
  8. #define START_TASK_PRIO                        18 p- _/ Y$ j2 G' e# Z& }3 A3 Q$ _  U8 j1 F& ~
  9. #define START_STK_SIZE                        120" G) o/ v' I: h8 A" R1 }
  10. void start_task(void * pvParameters);  //任务函数  p+ o; u8 b% E  {
  11. TaskHandle_t StartTask_Handler;                //任务句柄         ( `2 O9 b9 J- I7 W- {
  12. ) [. r; p4 X! o* f# P$ q' C& X
  13. : f4 b4 p2 ^7 c3 N4 Z1 d
  14. #define TASK1_TASK_PRIO                        2" e; v5 O2 n9 W0 ~2 M( u# `
  15. #define TASK1_STK_SIZE                        120! O, J# W6 u/ _' W
  16. void task1_task(void * pvParameters);* ?7 n: E1 ~/ r- |
  17. TaskHandle_t Task1Task_Handler;                //任务句柄         ! F. @5 G( Z2 I; _  t6 U
  18. 2 h/ S' V, e8 I: |* d( M+ k
  19. #define TASK2_TASK_PRIO                        36 J, b3 ?0 }9 |, N' ~8 H7 ^
  20. #define TASK2_STK_SIZE                        120 # I) b- B" o* E2 n# u
  21. void task2_task(void * pvParameters);
    - @" z% a4 x% ^+ C
  22. TaskHandle_t Task2Task_Handler;                //任务句柄        & n/ ]7 ?) G4 h  L, C! P5 Q
  23. , P. q* A) Y$ H) q( ]. Z1 w
  24. int main(void)
    2 z5 Q% K3 f- j! D" i+ z# e7 G, |$ X
  25. {% r! d9 D$ [, C7 l# j" x% Z; x% |9 c
  26.                 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    , f  m- x: B* _; S3 m
  27.                 delay_init(168);                //初始化延时函数
    / W: r" J6 Q% C) {) e4 [0 P: ]$ Z
  28.     LED_Init();                     //初始化LED % I& C, z# p! W' Z  b7 ]: @
  29.     uart_init(115200);              //初始化串口8 U6 W9 A4 T; T$ A1 v+ _
  30. 4 U# j8 T1 c* r  l) g0 w9 E8 ]/ T
  31.         xTaskCreate((TaskFunction_t        ) start_task,
    , _, p6 m9 O, f8 b# B
  32.                                 (char*                        ) "start_task",
    . t# H( c* d0 Z: Z
  33.                                 (uint16_t                ) START_STK_SIZE,# h+ _  j; H& a) p* A, Z3 i/ H
  34.                                 (void *                 ) NULL,1 J, t5 K  H6 r3 X# ^! U6 j4 d% y8 Z
  35.                                 (UBaseType_t        ) START_TASK_PRIO,0 l- p% j" l; p0 m# z
  36.                                 (TaskHandle_t*        ) &StartTask_Handler);
    - V6 T( T; z; r0 E
  37.     vTaskStartScheduler();          //开启任务调度" _( i: L/ y& X0 O. O. f
  38. }
    9 y7 P0 k; {8 [) q% E
  39. 6 e* e9 p; A: e1 a* w; a- q, ]% O* {
  40. void start_task(void * pvParameters)
    8 Z$ C, `( @& H( S  K: A' \# g# L' b
  41. {2 O- l; [$ h; `! h0 _* j, h
  42.         //创建Task1* W3 v: W, M( x4 P, D1 C
  43.         xTaskCreate((TaskFunction_t        ) task1_task,
    5 g) v8 F" y: L2 H
  44.                                 (char*                        ) "task1_task",% ?8 h& H6 H6 `; l
  45.                                 (uint16_t                ) TASK1_STK_SIZE,
    8 b" M2 j3 p) v3 f; C
  46.                                 (void *                 ) NULL,  j& E3 W! Q* o' K, {! E
  47.                                 (UBaseType_t        ) TASK1_TASK_PRIO,
      l8 l1 z7 b. }. v
  48.                                 (TaskHandle_t*        ) &Task1Task_Handler);! {& y' s$ P' g! Y. ]& L( L
  49.                                 : l3 g1 M6 u; Z7 T! O4 M6 h6 J
  50.         //创建Task2
    0 C. u; Y+ E4 {: Y' Z1 |3 J$ a
  51.         xTaskCreate((TaskFunction_t        ) task2_task,
    2 ^& ?2 X" M+ f* ]& F! r: Z
  52.                                 (char*                        ) "task2_task",
    ' S* |- s& U4 `6 g
  53.                                 (uint16_t                ) TASK1_STK_SIZE,
    + V2 P# p( h3 v1 h7 A1 D5 ]
  54.                                 (void *                 ) NULL,1 W% t0 j1 l7 E- _8 |0 Q  P
  55.                                 (UBaseType_t        ) TASK2_TASK_PRIO,. a0 U" @4 _" H4 W4 s; }
  56.                                 (TaskHandle_t*        ) &Task2Task_Handler);, U* ?! q! ?- p( L" n! W+ H
  57.         vTaskDelete(StartTask_Handler); //NULL
    : i3 Q( K8 Q4 v8 P2 B. f
  58. }
    ) O9 g/ _# b8 W8 ?+ ?. h5 h
  59.   V  ]% q; U: U7 A0 ~- v6 T
  60. void task1_task(void * pvParameters)
    7 p/ S/ O0 U% n  u8 j. C# |, j
  61. {
    9 E& O" X- }. |& i
  62.         char task1_num=0;
    6 B9 e3 W8 `; M5 F9 X
  63.         1 ?3 l: \6 i% X4 j( ]" X
  64.         while(1)7 }* p4 G) O: m' _+ j, L
  65.         {0 \4 L! F  N$ Z( Q( m) s4 e) W
  66.                 task1_num++;
    ( G) h+ \! u" F' F! h5 y& y1 }
  67.                 + p6 A- v( V2 N  B: V1 s( A/ ?
  68.                 LED0 = ~LED0;
    & ^' a) E6 \, }
  69.                 printf("Task1 Runing %d !\r\n",task1_num);
    " t; S- d- t) r
  70.                 / V& h: J7 s- h
  71.                 vTaskDelay(1000);
    , g+ I" x% v3 o% n- Z1 F. }+ ^
  72.         }' ~4 _8 s, n. H- _2 i
  73. }
    9 E; ^; r  u7 p9 O2 b
  74.   Q2 y6 g+ y: W+ t
  75. void task2_task(void * pvParameters)
    ! {. b! E' i. z( o$ Y3 C
  76. {1 M; G+ Z; A7 p
  77.         char task2_num=0;3 C7 |* B) w% M
  78.         while(1)3 Z; [3 \) F; Y
  79.         {
    ' W$ J$ k9 f: B5 C5 `
  80.                 task2_num++;: q+ ?2 n3 b( n' e6 M) w7 T- \
  81.                 - @" w( l; h+ o% u7 t' N' D! A
  82.                 LED1 = ~LED1;
    : ~1 W% M% G0 _: u2 F
  83.                 printf("Task2 Runing %d!\r\n",task2_num);
    " Q  H$ E$ r7 ]) S) Y) [' n3 Z
  84.                 vTaskDelay(500);1 K' [+ O. v! {# p# W# K: X
  85.         }
      H, q1 J: c  F* d
  86. }
复制代码
( W6 J' K; `) ?7 [& W
实验现象;
5 f4 e; `" t) z/ _2 _* P0 J, I1 x
2 u9 h* r2 B& y* `2 {' B      开发板上LED0和LED1进行不同状态的闪烁,串口也会打印任务执行次数,很明显任务二的速度是任务一的两倍。/ q9 R) v6 J. E: f- ^5 I& I3 v

8 i7 ?( a  {, K0 q" Q1 ~0 p! n1 b! f 1VM2{H5BDGWPZL[[W@NP2)D.png 6 T! ^9 x  O! W9 A

0 k4 t3 ^+ D$ x6 k 20190816171854468.png * j. {4 G8 `/ D7 n5 ^8 x
2 X7 o5 x/ a! i8 x( g) J
我这里使用的是STM32F407VET6,原理都差不多,用那块板子都一样。至此,FreeRTOS移植和任务创建成功。$ r3 a" W- i: a
7 A/ I0 |1 D+ g$ K/ b. n: ]
& Y' W/ [4 u0 m$ Z4 I
5 L0 o. ^* V2 ?4 G/ H
收藏 评论0 发布时间:2022-5-16 11:34

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版