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

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

[复制链接]
STMCU小助手 发布时间:2022-5-16 11:34
1、源码准备. b' C0 f  F' D! Q; @/ |; U  m
       首先准备好我们下载好的FreeRTOS源码以及STM32F407的工程模板(这里以原子的F4跑马灯工程为例,可去原子的开源论坛自行下载),源码下载及参考请参考我的上一篇博客。9 ^6 Q8 B- E  l/ P# R' d) T$ p5 _

6 p9 f2 b0 M% @/ y3 Q2、创建FreeRTOS文件夹
( C) O" M% h0 w  m8 h% l在工程中创建FreeRTOS文件夹,将FreeRTOS源码全部复制到该文件夹下
6 D1 T0 B$ S# M  _' N+ X* |2 `. }
" U+ _3 Q5 W; Z J4VG7F(R0KA[1L[S_4RKHKF.png / M* c% l$ Q; g: U6 Z. B& \

7 s4 e/ o6 }; B! p# g2 i2 j打开portable文件夹,删除没用的文件,留下如下文件即可, H+ u( W$ z2 q' f  x" O

% N" ]' G7 L* m% Y7 ?  C; I 20190816170452609.png : d. D9 t" @6 T7 l. n. c0 r

' O' V2 y  l5 D6 S, M2 B# `  B3、在工程中添加FreeRTOS源码+ c  n! Z. l( u! k, u1 p* B+ s5 D) u
打开工程,在工程中新建FreeRTOS_CORE和FreeRTOS_PORTABLE,然后向着两个组中添加对应的文件,如下图所示:3 k4 J+ @4 M! p; R5 F! F( W( X
, L3 s2 a' I( b/ x( |
20190816170518369.png
* x5 K! S7 v9 W% j  `1 \6 E; t% b  d) n, u" i1 @
       FreeRTOS_CORE的文件打开FreeRTOS就可看到,port.c是RVDS文件夹下的ARM_CM4F中的,因为STM32F407是Cortex-M4内核并且带FPU。Heap_4.c是MemMang文件夹中,这里有5个文件,是5个不同的内存管理方法,为什么选择第4个,因为FreeRTOS内存管理所决定。" G6 S$ u  Q+ ^; V- U. J& q
2 I( ]% r8 w" u% y: P6 [! D
4、添加对应的头文件路径, e, @/ [. S' X, U" E
3 B" f. `7 ^1 Y6 m( [' w' x
SU4[70TMSS9THQ_{YAT$)15.png 4 M6 G4 r. q0 D
! F: e% n. E; x( O% \
5、编译及错误解决
! [) m# m2 D+ L3 J. u! f1 n
5.1 找不到FreeRTOSConfig.h文件
( N1 h! |: \0 s1 M5 E8 ^+ `3 Q$ a完成后编译一下,会出现如下错误
8 P1 K  f0 w1 n  @# l9 T( X4 e( m+ Z% u9 h
2019081617065397.png
! o* F: i: _& j6 z$ J: |: L1 E# N7 I* H. C( a9 c2 d; w$ S+ [
       很明显是没有FreeRTOSConfig.h这个文件,那我们就把它添加进去,具体位置在FreeRTOS的DEMO中找到CORTEX_M4F_STM32F407ZG-SK文件,如下图所示
- |% M( S; J1 E7 a, n' L. H8 ?5 C) W- ^
RB9(NYFTTB57AG]9}PD))0V.png
: B  k3 q0 X' I& C
! H# S$ V- {# i      至于放到哪个位置自己随意,一般是放在FreeRTOS的include里面,而这个文件是FreeRTOS的配置文件,一般操作系统都有裁剪、配置功能,而这些都是通过一个文件内的宏定义来完成。
7 r! t' k4 ~8 L, I+ n5 D) s8 O( b. Z2 B
5.2 SystemCoreClock未定义) x+ Z' _6 {- k
接着上面的步骤再编译一次,还会出现以下错误,意思是SystemCoreClock未定义
  q/ p8 p3 M9 q 20190816170815891.png
5 }, v7 v! ]3 h  f% M3 m7 Y" z
# ~2 |! W' f! l1 `解决办法:修改条件编译; l1 B4 b$ k6 L( D1 {" D0 K

# W. f6 W, P  Q( z: R: H O({SZ$P%M[VB6]C}PA1WCJO.png 9 Q8 e( G5 F$ y  |% A+ ^5 b, `8 ?- l

5 c! J! \# p  `0 K. O5.3 重复定义( H2 X* l3 l( k: F6 B9 |  B
接着再编译一下,发现还有错误,这次的错误是重复定义
; S6 e( h# e& D3 l4 r" U) `
- b2 c3 o& R! x" f& ~8 h 20190816170906281.png
1 X% I; q, n) ^0 |) w
0 O+ F% k# {- U6 X. P# }解决办法:
; m$ X6 B1 j( F" r$ s  m# K- v, K& w7 p7 N: s+ c1 a% k* R: |
     屏蔽掉stm32f4xx_it.c中的PendSV_Handler(),SVC_Handler(),SysTick_Handler()这三个函数,# y, i5 p1 w; w' B/ z

+ u$ `$ z6 A8 x4 q1 i; s J1{J5FFPO6%)VS2$FL4RPO9.png
; v! s6 f' Y; Y" ]( d" |0 z' M  }6 h7 [( f
5.4 钩子函数未定义
. s) K: a" H' y     继续编译一次,还是会有错,这次的错是函数未定义,他们都是Hook结尾的,称为钩子函数。; B' p: T' Y' A% V' n9 r

8 U2 c3 g  Q. f6 Q( [- ]9 L 20190816171003138.png
+ X7 ~5 U6 C" Y; w8 x  I
( y7 i3 m& V5 @: b3 A2 B解决办法:
- o% \. h: N3 [! o7 Y0 d* W7 h% ]/ D* l" \: k+ X' i
        去FreeRTOSConfig.h中关闭这些钩子函数,他们都是宏定义决定,这里将configUSE_IDLE_HOOK、configUSE_TICK_HOOK、configUSE_MALLOC_FAILED_HOOK和configUSE_FOR_STACK_OVERFLOW定义为0.
. b5 b3 J. T2 d4 G  l2 h! y7 m( N& T" E' x% h$ E3 w- ^/ o
AD3PLMJQC][R4G94VZUK8[O.png
* _# B  B9 Q6 i1 U( s% [- x6 r$ X* f; j, K5 s( m/ I( i$ D
再编译一下应该就没错了。
; R/ [, z2 N9 r) f5 T% {3 R5 X- F8 ?- e0 p# E# R' U
6、修改SYSTEM文件0 j6 Q$ X% j- @  p& H: ?) M. o! f
因为原子的SYSTEM文件夹是针对UCOS编写的,所以要进行对应的修改5 a" J8 o4 }9 l5 r8 |$ l# m

3 O7 p3 t  G, c  H6.1 修改sys.h文件9 F  _* n" ?/ B
把宏定义改为1即可,要支持OS,UCOS也一样的
  ~! }6 }! c. u# q1 z5 C
3 {+ F( Z+ o* o9 m3 Y1 ^, P 20190816171410738.png * F3 U# J1 J. I; u8 Y) D7 p( ?

& I6 c2 o7 X' b8 P- |- }, V6.2 修改usart.c文件
+ Z3 i+ j$ m  r  t, {$ Q修改头文件为- e! s" Q6 y  O% I8 q

: c: G- ^& @* h. n0 y2 R+ t: F  s 20190816171442265.png ( c1 d7 n. m0 e2 d- E2 ^+ v# T

. |. o8 Z. ]4 f) |1 e# V修改串口中断服务函数为:
* R; Q  d& U* K" y1 e; r& n6 B
}YRE3F87]$D8C8J4Z((9L5A.png + M( r6 l, E2 A

; n* a  L/ Q8 V) v6 w6.3 修改delay.c文件

9 I: k5 f& k4 u( \同样先修改宏定义的头文件0 A0 b# ]; p) c( j; P7 |" z. U

+ n2 n4 ]  [, W  P' j. B 20190816171540153.png
3 o; G) a( D( V- R, r" j; {2 V
/ z  _  E; g) R+ O' y) @接着修改systick中断服务函数为0 C# F- p) ~' X

( U1 X5 [' c/ Y+ o: J! G: B 20190816171548315.png
2 {0 X5 T: o3 \9 `; j3 O- x0 U/ N
8 G- Q7 `% f, C: ^2 N; @5 ~在滴答定时器中断服务函数中调用FreeRTOS的API函数xPortSysTickHandler();/ T) F# e" q4 ]' J; t% @

5 u: ^  B8 g7 \/ N; o$ I在修改delay_init()函数,如下:
: J( ?2 }& ?/ P/ |" F" \+ e9 Q2 m8 y, I* |/ y
TF[2BS{SWY0__(HLC0YUP.png " t! {9 k! S. t1 {: U# T6 m0 x

) R8 X5 s  z& d5 H5 V接下来就是延时函数的修改2 Z. ~2 ?- v% I3 M0 i

' p9 M5 E- ~' _' z$ x TOZ(Y}6`9}UOCF))H}%(8_A.png # j7 C& L! |2 l* {  n  Q6 D
9 w3 Z7 ?% c3 b9 }* f5 _
修改完后再编译一下,会出现重复定义的错误,如下图:( o* V9 E! i; X4 L, J
5 V3 T! b6 M- B" u8 A
20190816171647173.png
/ g2 |4 Z6 w* q4 I% m3 _5 U/ g; g, W6 [2 q* x! U" S( J! n$ l
解决办法:屏蔽FreeRTOSConfig.h掉底部的#define xPortSysTickHandler SysTick_Handler+ }1 Y. s6 ^+ w# S+ I  e, j! E

4 Z  ]6 `! P5 o1 q, O2 x) D8 a C}N@EYXV4Q8[OGMY[CB4[KJ.png
! K$ F( U9 h" |
+ g( h6 n; M6 V/ o0 S6 @+ _. Q+ U7、修改main.c进行功能验证( ?5 P" @1 X7 l# J$ j+ n
主函数主要是实现实时系统多任务的创建,具体如下+ f4 A9 Q  R: W' v/ |7 _

$ U0 D, c& b+ u. O" G. E) H
  1. #include "sys.h"
    & P. U1 E6 k' E) ?" K5 B) Y
  2. #include "delay.h"$ ~9 H; e! K7 D6 r
  3. #include "usart.h", C+ J* E: Y8 g: D  z/ d! ]
  4. #include "led.h"( y$ c) x8 E$ j" [7 h
  5. #include "FreeRTOS.h"
    , N! n0 |" [0 \, _0 d! `
  6. #include "task.h"
    1 r$ l! b; r9 P" \) Q

  7. * f& G  D* t4 M, H0 K" G" I0 Z6 s
  8. #define START_TASK_PRIO                        1$ x8 a$ [3 b* o3 p! ~0 }4 c+ s. `
  9. #define START_STK_SIZE                        120
    $ z) z/ p. c* O8 {/ ~
  10. void start_task(void * pvParameters);  //任务函数. C4 J( ]0 z( Y
  11. TaskHandle_t StartTask_Handler;                //任务句柄         
    ; M$ @' h2 T& c
  12. / C, ?" g& \0 F5 c, E" J

  13. 8 F4 {6 P; W  ~/ ^
  14. #define TASK1_TASK_PRIO                        2
    % {( j8 t0 u' s
  15. #define TASK1_STK_SIZE                        120# F& m9 |- \2 l3 C% Z
  16. void task1_task(void * pvParameters);- {( e7 R* g. o& d4 g3 w6 p
  17. TaskHandle_t Task1Task_Handler;                //任务句柄         
    5 b5 K; y' e- C- N

  18. 1 H4 Y5 ]3 Q+ Q. D, h
  19. #define TASK2_TASK_PRIO                        3- v: u& l  R( l! v
  20. #define TASK2_STK_SIZE                        120 8 b+ A9 g" [* Z. U- u. \: T3 J) p0 }
  21. void task2_task(void * pvParameters);; h2 |4 N* _9 |0 ^. {' ?2 i- K6 N
  22. TaskHandle_t Task2Task_Handler;                //任务句柄        - r$ {: [9 s+ m+ a7 X
  23. : F8 i: o* {/ V% g) }; Q; W
  24. int main(void)
    - _+ `! w/ [. g
  25. {) t0 d9 z, ?: x0 C7 R6 i  ~
  26.                 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    , i2 w$ J3 x' g& v' J0 H6 v
  27.                 delay_init(168);                //初始化延时函数  v* c5 a& u( s; R0 c0 R
  28.     LED_Init();                     //初始化LED
    # p# e9 F5 m9 u) m6 J5 B9 D
  29.     uart_init(115200);              //初始化串口) @0 Z+ [1 N, d% T% `

  30. 8 y8 R7 Q) e# l1 y. a
  31.         xTaskCreate((TaskFunction_t        ) start_task,
    - ?3 _2 A; p* u. \! B5 N7 V. g% T- I
  32.                                 (char*                        ) "start_task",
    - [' X# L+ e! O. o9 M
  33.                                 (uint16_t                ) START_STK_SIZE,
    4 B! O: Q, G9 l# q9 V" U. [/ _
  34.                                 (void *                 ) NULL,5 y& c6 Q* N! D& R, W0 P
  35.                                 (UBaseType_t        ) START_TASK_PRIO,
    " W( Z$ ^. l& H* u' T
  36.                                 (TaskHandle_t*        ) &StartTask_Handler);6 m: x" o" |9 p  |
  37.     vTaskStartScheduler();          //开启任务调度- m. w2 C" w# ~) w; V* i
  38. }
    4 @  r8 j$ Q- J
  39. . H9 [- p2 _) Y; S
  40. void start_task(void * pvParameters)
    % D) J% U( p) M
  41. {
    4 m- R& y, K: K
  42.         //创建Task1( s2 H7 U: e* |6 Z5 n# [9 h
  43.         xTaskCreate((TaskFunction_t        ) task1_task,( b) [* ?$ v$ W" {* p" ?# b, e
  44.                                 (char*                        ) "task1_task",
    9 P. Z% h2 O1 T5 g. ^" H$ Z
  45.                                 (uint16_t                ) TASK1_STK_SIZE,
    8 H- r& g! h% }  x# }0 M+ ?
  46.                                 (void *                 ) NULL,
    2 ]$ y3 b, Q9 T
  47.                                 (UBaseType_t        ) TASK1_TASK_PRIO,
    ; W% u: e$ x8 q2 a- z
  48.                                 (TaskHandle_t*        ) &Task1Task_Handler);
    8 o7 r  a8 w& l+ K+ q8 }! t
  49.                                 ; n% q8 f" D3 \/ G9 |6 ?  h8 m
  50.         //创建Task2, o" L# ]" n# |0 _' R" j/ f
  51.         xTaskCreate((TaskFunction_t        ) task2_task,% N- A! e4 x1 [1 o# Y. ^
  52.                                 (char*                        ) "task2_task",6 r# L, |1 g; D
  53.                                 (uint16_t                ) TASK1_STK_SIZE,/ \& `, X% u4 ~0 K
  54.                                 (void *                 ) NULL,# ^  i  _1 L1 t
  55.                                 (UBaseType_t        ) TASK2_TASK_PRIO,
    ' S; x' H3 a& a) F
  56.                                 (TaskHandle_t*        ) &Task2Task_Handler);" Y2 \" L  d/ X" _
  57.         vTaskDelete(StartTask_Handler); //NULL
    5 s. d, H$ a( g1 Q, H) v8 A$ `
  58. }$ G; t8 z; l# p- ^
  59. 3 z& p' e4 [" i
  60. void task1_task(void * pvParameters)
    * G+ a7 q4 p" e  ?2 u/ |! I& B! Y
  61. {
    6 X( I: i% Z. `, v
  62.         char task1_num=0;6 n" W. P2 D: ~8 o( p) P$ h( ?. ?" P. i
  63.         & ]5 a( S% o+ E* U6 I
  64.         while(1)) T% ~8 @1 V' q: }( B" `9 I$ }
  65.         {" i1 H& _* E! Y- @/ D
  66.                 task1_num++;
    2 x4 A2 l7 h5 I, g( q/ N+ v0 U
  67.                 4 a1 T# s  o) m2 ~
  68.                 LED0 = ~LED0;7 D% w7 }5 ^# L3 Q1 W6 Z
  69.                 printf("Task1 Runing %d !\r\n",task1_num);
    - w" ]( h& H* j8 I6 f# ^
  70.                 4 E( J$ c: ^9 V% Z4 t$ x: y5 U
  71.                 vTaskDelay(1000);. n7 d5 h' T$ g
  72.         }- U! G, K: c0 A2 F9 R" ]
  73. }4 K6 q* A! M1 E' ]/ f% v: X

  74. ' c$ V% e4 e- M# t9 m
  75. void task2_task(void * pvParameters)) b. b+ d8 E3 C  i9 O+ ~
  76. {
    0 `9 p; p; M: }+ J' T+ i0 a  z0 ~- }
  77.         char task2_num=0;
    ' ~. W  d' k. N2 z0 N
  78.         while(1)
    & Z, b- Z1 H  z6 O
  79.         {
    ( K& ?1 ]3 ?! ^6 Z) d
  80.                 task2_num++;3 L8 t3 }( p+ \5 M4 J4 y4 P
  81.                
    1 m$ K6 R: _) u1 Q
  82.                 LED1 = ~LED1;
    % X  Q1 Z" }' Z$ k* Y/ P" Q
  83.                 printf("Task2 Runing %d!\r\n",task2_num);% I% F* Z9 _7 l) S' q( }
  84.                 vTaskDelay(500);6 X4 v5 f# h! P7 t, G8 @
  85.         }
    1 P/ |+ V/ r+ L; I% L. _4 `0 r2 R  \
  86. }
复制代码
  g- o: D4 Q0 f8 o5 g, c3 z
实验现象;
- {, R6 h9 \2 V- c- q
! B9 S6 h0 j' v# c; y4 ^2 p      开发板上LED0和LED1进行不同状态的闪烁,串口也会打印任务执行次数,很明显任务二的速度是任务一的两倍。
2 m7 Y! w1 b; D4 G- ?; K( a
. a- ?) j8 C- W' m 1VM2{H5BDGWPZL[[W@NP2)D.png
9 c/ u) K# a1 a6 g3 s. n; D
4 C& ^; y5 z8 l, K 20190816171854468.png
- g/ h$ `  w+ _& ?3 b& {
$ G& Q) @3 R2 t! p' D" O9 i4 o我这里使用的是STM32F407VET6,原理都差不多,用那块板子都一样。至此,FreeRTOS移植和任务创建成功。
( K! w7 T" h  D- W9 b
( R7 l4 w+ Q- ?9 i% J& D: p! p5 ~! i
; b- a- g# `3 l! F* [' D! @! A, R1 j7 B* I! x$ g
赞 收藏 1 评论0 发布时间:2022-5-16 11:34

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版