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

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

[复制链接]
STMCU小助手 发布时间:2022-5-16 11:34
1、源码准备) j/ ]" f% ~2 X6 x
       首先准备好我们下载好的FreeRTOS源码以及STM32F407的工程模板(这里以原子的F4跑马灯工程为例,可去原子的开源论坛自行下载),源码下载及参考请参考我的上一篇博客。
4 N7 P4 R6 }, U. _& o: c" T! u( p1 L5 n) y
2、创建FreeRTOS文件夹1 a/ n, I, a: Y, Y
在工程中创建FreeRTOS文件夹,将FreeRTOS源码全部复制到该文件夹下
$ ]. v6 b6 W; L2 h* e! n* |9 V1 z
9 f' R3 _( |- C% B J4VG7F(R0KA[1L[S_4RKHKF.png
6 e+ l+ I) n. ?5 u' J
$ y) y. R$ a! i2 }0 q打开portable文件夹,删除没用的文件,留下如下文件即可8 Y* Q) u" x+ i

8 M& D9 Y- t7 m+ r+ l. @ 20190816170452609.png $ U4 W; ?7 a/ e  w: m
, Y* }1 L8 J% v! _/ A
3、在工程中添加FreeRTOS源码: S# J" o2 E' R8 B) e
打开工程,在工程中新建FreeRTOS_CORE和FreeRTOS_PORTABLE,然后向着两个组中添加对应的文件,如下图所示:
' X8 ]& W* |8 L2 q* I: I3 }/ P" }( O$ x$ O# z: Z
20190816170518369.png
' z- t* _3 l3 v! p
! ]/ j5 H, h% ?       FreeRTOS_CORE的文件打开FreeRTOS就可看到,port.c是RVDS文件夹下的ARM_CM4F中的,因为STM32F407是Cortex-M4内核并且带FPU。Heap_4.c是MemMang文件夹中,这里有5个文件,是5个不同的内存管理方法,为什么选择第4个,因为FreeRTOS内存管理所决定。
8 e3 Y* ^* a& s- i% a8 e9 t4 ]$ w- N1 q2 `  M2 _; H+ n
4、添加对应的头文件路径- Y$ |+ W' ]  {8 F

1 u; f# ?% t7 `! O9 B
SU4[70TMSS9THQ_{YAT$)15.png   G2 }' `' m9 o

; u+ \, G4 Q) q3 j# w5、编译及错误解决

8 w0 D2 _' q: F( y( K8 b5.1 找不到FreeRTOSConfig.h文件
! {1 P- F$ A  I* K/ {5 R% Q完成后编译一下,会出现如下错误
( C2 b2 s* W9 I5 G/ f# C, m
. O7 x9 \  ^$ V 2019081617065397.png
& d" z  @  W3 h8 J6 B) d- W
1 S9 c! {8 q4 D       很明显是没有FreeRTOSConfig.h这个文件,那我们就把它添加进去,具体位置在FreeRTOS的DEMO中找到CORTEX_M4F_STM32F407ZG-SK文件,如下图所示6 D" J/ B9 ?( V+ O; j" B* |( N
; X! K/ Q3 z( y1 u  S
RB9(NYFTTB57AG]9}PD))0V.png $ b, e4 |3 }' E' A0 x* \$ B

# E1 g0 n( J3 a$ l4 y" T+ @3 `      至于放到哪个位置自己随意,一般是放在FreeRTOS的include里面,而这个文件是FreeRTOS的配置文件,一般操作系统都有裁剪、配置功能,而这些都是通过一个文件内的宏定义来完成。% {; w' g* U/ [" L

( H7 q4 `: @+ \' P! R# A8 E" w( [5.2 SystemCoreClock未定义
9 o" C4 n# J2 ~4 {: A接着上面的步骤再编译一次,还会出现以下错误,意思是SystemCoreClock未定义$ w! \( c/ G( A( p- k) l4 E
20190816170815891.png
% V/ U) G! ~9 f" i  y5 Q4 y
( h& R. K* S+ Z解决办法:修改条件编译. Y7 O2 m' d+ N9 L

5 a! K  |- N; O9 Z% ` O({SZ$P%M[VB6]C}PA1WCJO.png
: }- K1 ~/ ]; Q/ w# X
  p" N# p$ y/ F2 @* {& |1 e9 w5.3 重复定义- ~& h! o0 h2 x! T
接着再编译一下,发现还有错误,这次的错误是重复定义6 _( M# Y; S4 V0 G& s. [

. Y- I7 j8 C6 W) [4 n 20190816170906281.png
1 q8 q! M/ U0 j& k
( o+ c2 n# X, M  ~解决办法:/ D0 G$ Z4 k# O
+ S+ d; K7 ]5 _  O
     屏蔽掉stm32f4xx_it.c中的PendSV_Handler(),SVC_Handler(),SysTick_Handler()这三个函数,& Y) g2 w. t" d( m& Q$ f

, i2 G) G) t/ |( Y2 ]5 n J1{J5FFPO6%)VS2$FL4RPO9.png 2 T: V! T; M( M
5 @+ i* q3 Z4 X, U1 _6 v
5.4 钩子函数未定义
! L7 R( L2 F9 f% N5 b     继续编译一次,还是会有错,这次的错是函数未定义,他们都是Hook结尾的,称为钩子函数。3 ]6 Y( r1 d0 C8 q: }3 I+ W  b
1 R0 Y1 @2 j9 P
20190816171003138.png + D  e# F( h9 @9 X. i* u

, X1 t6 _7 H$ G0 Q+ c8 @  ?解决办法:
2 [: T  P! G) v4 d+ D
6 D7 @7 G8 X" X% K, {9 k        去FreeRTOSConfig.h中关闭这些钩子函数,他们都是宏定义决定,这里将configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configUSE_MALLOC_FAILED_HOOK和configUSE_FOR_STACK_OVERFLOW定义为0.5 J* {" k" H! M9 [9 j; `
. h0 A- P, d7 D/ D# x6 O; `
AD3PLMJQC][R4G94VZUK8[O.png
& F" Q0 |1 r6 Q3 s8 J, K  l; E4 ~: z$ G! @8 e8 u; I$ P
再编译一下应该就没错了。
6 n! f+ [9 _( r0 y6 f2 v8 U- c. q8 k6 ?3 G2 [
6、修改SYSTEM文件
( M1 _$ J7 E  T( t$ \因为原子的SYSTEM文件夹是针对UCOS编写的,所以要进行对应的修改0 w% R3 A! H% m/ |" k2 u
6 d- `3 W# y1 d9 n( R
6.1 修改sys.h文件: \) k$ t. f5 D5 N8 N- T0 N4 c4 |
把宏定义改为1即可,要支持OS,UCOS也一样的' |" J9 S5 I  o
% E; t3 d% _2 r$ \+ O
20190816171410738.png 8 `' b' G, c* h  o5 u  u

; Z/ G' [& g) u, ]$ L8 c9 Z6.2 修改usart.c文件1 _  W" C+ m5 T3 X8 E+ T, i
修改头文件为$ L+ x8 D# o' x& A
$ f: c; q- N7 T. o' A
20190816171442265.png
& e0 \! b1 d  g! m) b  ^" J+ V
6 ]8 i& ?0 D# Z9 R修改串口中断服务函数为:/ w) V+ f* Y7 j# x  E$ c
$ L2 g+ }2 p7 ^. }9 H. O
}YRE3F87]$D8C8J4Z((9L5A.png 2 c5 z: e2 s8 I  o1 v# U5 H$ P! @8 G

& h% D' x' N, L5 i6.3 修改delay.c文件

  u( {6 D, i& z' x  L同样先修改宏定义的头文件# y* w0 S$ z8 s$ @- r8 r

! U( b9 y( V4 }/ z 20190816171540153.png
0 e1 X0 B3 n! a2 v% K1 W( U; c8 h  Y! X- I
接着修改systick中断服务函数为
' u5 a$ o2 G0 B  S1 h3 D+ N6 K
" l0 c) ^$ [6 `  ]  Z, C. @ 20190816171548315.png # W+ }1 ]  G/ L$ l

; V7 }8 x$ k. A, \9 J在滴答定时器中断服务函数中调用FreeRTOS的API函数xPortSysTickHandler();7 W$ m9 [# A+ F; i& a% N
* t7 r  u6 \; V% J% X+ ]3 R$ i
在修改delay_init()函数,如下:2 {8 m8 p; @6 ^) l: S$ ?, j

$ s1 B% G! t6 q& n5 x TF[2BS{SWY0__(HLC0YUP.png 1 y3 i! i: I) L, s" _8 ~; b  D0 b$ P& @
' f' v  G2 V( S' h
接下来就是延时函数的修改" [- l% a. _. I9 ?2 a
( \/ a" l, V1 W) a2 Q4 Y
TOZ(Y}6`9}UOCF))H}%(8_A.png
& B# j* t- s7 x! {' C# d  u) r0 e0 O1 M& U4 f( T
修改完后再编译一下,会出现重复定义的错误,如下图:
* F" {. o. T" B( [. d6 K! I' c; \/ S" I/ R; t
20190816171647173.png
. `1 |" A% X# |
- i) d7 z1 R5 q' P解决办法:屏蔽FreeRTOSConfig.h掉底部的#define xPortSysTickHandler SysTick_Handler7 |& _" c+ V5 m) I! l

; U, F" ]( F1 T* N7 a* s( i C}N@EYXV4Q8[OGMY[CB4[KJ.png 7 ^9 u9 p/ f( S$ @$ Z; D
$ v1 t; z( U( V
7、修改main.c进行功能验证
% c' W& c9 e7 R主函数主要是实现实时系统多任务的创建,具体如下
  U/ ^$ d& }/ e2 P
% K& q* P, V5 \
  1. #include "sys.h"5 f3 V; R) I: Y& O+ g& r1 n
  2. #include "delay.h"
    : v+ L2 I; P; |" F2 b
  3. #include "usart.h"
    ' [4 |# {  O: s0 A; @( b
  4. #include "led.h"' H1 K$ k' J3 p
  5. #include "FreeRTOS.h". y5 y$ o) M# c" a& ^$ u. I
  6. #include "task.h") p! }0 K4 G( M2 V/ ~! W7 M
  7. % X9 K$ T$ _! ^
  8. #define START_TASK_PRIO                        1
    ! K  S5 P7 h# L. ]: R) j" N8 r
  9. #define START_STK_SIZE                        120: f. r: M/ s7 K% {& t& w0 c! R
  10. void start_task(void * pvParameters);  //任务函数
      E4 D7 `% d* g- ^% Q5 s% f
  11. TaskHandle_t StartTask_Handler;                //任务句柄         : W% w( g7 _& w8 q! V
  12. ; Q1 t  w6 E+ _/ a

  13. . Q* l8 y! g2 _2 Z" s4 \# W
  14. #define TASK1_TASK_PRIO                        2
    2 d! a! `- s1 ^" c0 ?( J
  15. #define TASK1_STK_SIZE                        1205 `7 f9 W7 M3 @  |
  16. void task1_task(void * pvParameters);; j$ j2 G6 s8 G7 L! n
  17. TaskHandle_t Task1Task_Handler;                //任务句柄         
    # P, r8 G5 [5 p+ F: g: Y1 F% Y+ J, e
  18. 2 U& C2 c5 _. V2 U
  19. #define TASK2_TASK_PRIO                        3' H, A5 F, }; a9 M
  20. #define TASK2_STK_SIZE                        120
    , z( k9 ^" {0 B6 J. O) |
  21. void task2_task(void * pvParameters);
    0 }' c+ O; g% ~5 b' r
  22. TaskHandle_t Task2Task_Handler;                //任务句柄        
    7 K! }" r) L4 _, p  b7 |
  23. 1 S" K4 j+ F; F
  24. int main(void)
    ) @( `9 i9 k# |5 p# D9 n( Q, G# u
  25. {: ^3 Z+ p/ _# y* Y, x  P
  26.                 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);( `3 n5 U8 L9 t! R
  27.                 delay_init(168);                //初始化延时函数% S" T' T* P2 S. o
  28.     LED_Init();                     //初始化LED ( l- V! Z( K. Y2 Q$ S# |7 I. ~
  29.     uart_init(115200);              //初始化串口
    " w- w2 ~8 b* a# Y/ S, e
  30. 6 j5 G( N9 X) s8 M
  31.         xTaskCreate((TaskFunction_t        ) start_task,3 ^7 ~* h( D# j  q
  32.                                 (char*                        ) "start_task",
    ) }$ x. w9 ]: P0 N' H
  33.                                 (uint16_t                ) START_STK_SIZE,, W' N' Q3 a; w8 f9 i
  34.                                 (void *                 ) NULL,- P- n: v# Q0 [1 A% N$ ]
  35.                                 (UBaseType_t        ) START_TASK_PRIO,
    & k# Y/ N/ p& v/ b
  36.                                 (TaskHandle_t*        ) &StartTask_Handler);
    ( I9 U; \) n0 R3 t
  37.     vTaskStartScheduler();          //开启任务调度  E& |6 _+ |, A2 n. P
  38. }& e! z% R+ d6 |8 B) T

  39. - l4 ?  P* a) Y
  40. void start_task(void * pvParameters)9 |# Z! P; Q( k8 p/ O
  41. {* k7 K# d  }+ G" M; ~0 L7 b9 W
  42.         //创建Task1
    5 p: [2 [1 D* }
  43.         xTaskCreate((TaskFunction_t        ) task1_task,
    8 h" B/ S( |4 x- P4 B3 f3 A, e
  44.                                 (char*                        ) "task1_task",; \: E! X0 G" [% K, ~! N3 e
  45.                                 (uint16_t                ) TASK1_STK_SIZE,
    3 g% j% Z; Q0 K# J1 k% R
  46.                                 (void *                 ) NULL,+ l( W  u! _7 W! \$ t
  47.                                 (UBaseType_t        ) TASK1_TASK_PRIO,
    6 _# m, C8 l1 Q: n3 S+ r
  48.                                 (TaskHandle_t*        ) &Task1Task_Handler);
    9 O) w3 @2 a" F
  49.                                 * p  N2 B. v/ N2 ?  b
  50.         //创建Task2
    7 L5 ?) P& C5 U. m
  51.         xTaskCreate((TaskFunction_t        ) task2_task,
    ! g  i0 L0 F6 i! P9 F! v1 A8 M
  52.                                 (char*                        ) "task2_task",! o; O, m' l$ Z; D7 `  R+ W. `4 t
  53.                                 (uint16_t                ) TASK1_STK_SIZE,5 a( R( J5 A; l
  54.                                 (void *                 ) NULL,
    " e0 j" G: J' L  Z! n
  55.                                 (UBaseType_t        ) TASK2_TASK_PRIO,; E6 ~; _4 F3 R! G% Y" W1 j
  56.                                 (TaskHandle_t*        ) &Task2Task_Handler);
    - x2 x5 U' H8 ?
  57.         vTaskDelete(StartTask_Handler); //NULL
    9 [4 U8 N4 {/ u/ f2 e
  58. }
    " Y- E+ i: {; n. _, j

  59. - Y4 D+ X2 c% M( T
  60. void task1_task(void * pvParameters)
    ; S1 Z+ s: E6 V% T# L9 e
  61. {
    ' a2 ?, }- C8 I1 u2 u
  62.         char task1_num=0;/ g; `/ o8 m8 V1 t9 X5 q
  63.         ) K* A. q+ t( g( u  e  G* J- m. r' z
  64.         while(1)
    ; C% B$ j8 D7 u% O
  65.         {
    9 g" @% c7 I$ h% f, F: J' U- m
  66.                 task1_num++;
    ! t9 N; D; E* P  I0 O4 c
  67.                 - i1 n* z$ Y5 `$ Y
  68.                 LED0 = ~LED0;
    + b0 q) j% V; I) _
  69.                 printf("Task1 Runing %d !\r\n",task1_num);7 y0 P0 G5 f$ J9 i
  70.                
    & e$ F% _( O5 k- U0 q
  71.                 vTaskDelay(1000);
    5 @. O* d/ l# h) o9 c. M! B
  72.         }
    ) l; K/ J0 I7 ^  \. I& O4 i
  73. }' V# `: y; _) A7 `  }& s8 j

  74. ) `2 r& E4 N/ ^5 \
  75. void task2_task(void * pvParameters)$ }% a4 K; O* Z, x' k6 R6 ^
  76. {
    & u+ h/ b! O+ i% x$ E5 z
  77.         char task2_num=0;! ~0 g* x5 y$ B' X+ R
  78.         while(1)
    4 y# P, E9 B9 C+ s
  79.         {
    0 S/ g  Y. E' N3 n2 W
  80.                 task2_num++;
    . q. M. D9 c5 {9 M
  81.                
    0 y! g) ^" D0 q% G6 D/ c$ ?; b
  82.                 LED1 = ~LED1;- p! _0 c2 {. p( B0 J. {! u* j
  83.                 printf("Task2 Runing %d!\r\n",task2_num);+ d; P9 b( [6 Q: ]
  84.                 vTaskDelay(500);
    7 ?5 ^5 I7 c0 ^  `
  85.         }
    ; @2 R& p/ ~9 L  v; w4 v- C
  86. }
复制代码
) ^9 O' v/ a1 u
实验现象;
% D9 ?- p3 B( P3 w; a# b; j" h
1 O! s& P- Q1 ]& u% X      开发板上LED0和LED1进行不同状态的闪烁,串口也会打印任务执行次数,很明显任务二的速度是任务一的两倍。2 _6 |3 ?) k3 d

/ U. T  T  y7 }% s# D 1VM2{H5BDGWPZL[[W@NP2)D.png
- D' O, x0 c  L# {* ~2 n+ j4 @* ~% `* o( h7 {
20190816171854468.png 6 v% i+ h5 Y7 I* G6 V8 }

! `8 T/ T' e: H" E4 r我这里使用的是STM32F407VET6,原理都差不多,用那块板子都一样。至此,FreeRTOS移植和任务创建成功。: H7 M- w, b6 M/ }
$ [+ ]- J# y6 A' f) g2 l

- g( i2 [7 _  I) D9 B* e% Z% k& `: C' @
收藏 评论0 发布时间:2022-5-16 11:34

举报

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