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

基于STM32的FreeRTOS学习之FreeRTOS移植(二)

[复制链接]
STMCU小助手 发布时间:2022-11-17 17:37
1. 准备工作
9 {/ Y; s/ p6 K: Q- i& J# ~1)FreeRTOS源码(选择所需要的即可)。
% u% E3 \! V, f7 v
- o5 O, w( ~" N. ?( N( q/ }2. FreeRTOS移植
: t8 {$ T3 E3 \. _+ w: Y* Z2.1 添加FreeRTOS源码) Z/ C: _7 ~9 n( t4 g( V
在案例文件夹中新建一个FreeRTOS文件夹,以后将FreeRTOS的源码添加至该文件夹里。根据前一章的知识点,portable文件夹里只需留下keil、MemMang和RVDS三个文件夹,其余都可以删除。
6 r! X( _# f0 y0 O1 n2 G$ t 20210311230409275.png $ H  D) i' T7 l& s- A+ I) s

  H0 `6 L( }2 n- {! P+ Y2.2 在工程分组中添加文件3 d" G  @: Y6 Z. y
打开案例工程,新建分组FreeRTOS_CORE和FreeRTOS_PORTABLE,然后添加文件。 FreeRTOS_PORTABLE分组中,port.c是RVDS文件夹下ARM_CM3中的文件;heap_4.c是MemMang文件夹里的。MemMang文件夹里有heap_1.c、heap_2.c、heap_3.c、heap_4.c和heap_5.c,表示五种不同的内存管理方法。
" o- W7 n- t& t, D- S
0 d9 u/ ~3 ~$ d) @1 n  c 20210311230557444.png
# k/ F9 R+ r( L5 ~3 W, |2 B" V. k  }$ k* W
2.3 添加头文件路径2 R0 v9 o- C4 i( Q0 `- I
如下图所示添加头文件路径:) o% @3 |3 j/ e2 @( |$ ]# X
  V+ B: ]. B: e
20210311230718207.png + ]3 @+ P2 s& K) _( _
+ V6 s! z7 r6 S* A2 I6 L
头文件路径添加完成后编译一下,有如下错误,提示打不开“FreeRTOSConfig.h”。
0 ?6 S5 v/ Z' A9 e- \) ?这个文件可以在FreeRTOSv9.0.0–>FreeRTOS–>Demo–>CORTEX_STM32F103_Keil文件里找到。
9 U. f8 Y- q/ O8 D: ]& k. ~
# @0 D. o& W( H/ `- f8 N' }" u4 R3. 修改SYSTEM文件夹里的文件0 @+ E4 ?9 M. H. V+ P5 Y3 ]3 K, }
SYSTEM文件夹里有三个文件:sys、delay和usart三个源文件和头文件,这是正点原子团队开发的,但不仅限于战舰v3开发板。
7 P# k( ]. e; O* V4 J$ e8 p6 N9 J! m; f. ]* K" x: W
3.1 修改sys.h文件
' m+ H+ U' K" @4 xsys.h文件里面用宏SYSTEM_SUPPORT_OS来定义是否使用OS,具体代码如下:
# ~( Q1 u2 `/ d* T$ G* w# U' P; i7 K  y- _  C& M
  1. #define SYSTEM_SUPPORT_OS   1 // 定义系统文件夹是否支持OS,0,不支持;1,支持
复制代码
& N- }6 Q. V+ ^
3.2 修改usart.c文件  ^7 l5 |! ~: j' E# P
usart.c文件有两个修改地方:6 M% K: a1 O4 Y) F! X4 m
一是添加FreeRTOS.h头文件:
) C$ u* s3 p9 Z; U6 J
% X9 a5 g- t& Q& r" k& [
  1. #if SYSTEM_SUPPORT_OS
    & I+ N; T! q# z& p* X( O0 A
  2. #include "FreeRTOS.h"3 T+ T7 M3 w! Z7 q) B$ S( F
  3. #endif
复制代码
. S# F0 ~+ m/ [( i+ e. E8 F9 M
二是USART1的中断服务函数:8 A1 W3 k) v$ W* k  A) s
$ v) Z: t3 J+ G1 i
  1. void USART1_IRQHandler(void)
    & I% E9 Z* [5 W
  2. {) H) Y$ [+ [8 ?3 w' i; ?( H
  3.         u8 Res
    / Z/ q# g- U9 @; v2 Z! Y" y  q6 D
  4.         if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)* C/ F9 Z' f% c; s
  5.         {
    9 K4 N1 V. L+ p  y3 }2 l) V4 Q! p
  6.                 Res=USART_ReceiveData(USART1);
    8 v1 _" R" g5 W$ L/ O+ Q6 x
  7.                 if((USART_RX_STA&0x8000)==0)   // 接收未完成$ H' t3 q+ p$ o7 j6 i
  8.                 {
    ) F" v' I3 B' h  ], g
  9.                         if(USART_RX_STA&0x4000)    // 接收到 0x0d
    9 d; \# F# z! b# p/ x/ D* s
  10.                         {
    : X( a/ L* z0 k7 [+ U
  11.                                 if(Res!=0x0a) USART_RX_STA=0;
    1 O. `: N6 D* b2 ?: V
  12.                                 else USART_RX_STA |= 0x8000;  f6 t9 _4 V$ K
  13.                         }' ?) W0 g6 {  d0 k7 V7 t
  14.                         else // 还没接收到0x0d' n5 v& ^2 }$ P
  15.                         {
    0 u! O+ |& v2 v) M8 V5 y( g, k
  16.                                 if(Res==0x0d) USART_RX_STA |= 0x4000;, r; w8 d  \) w6 ]
  17.                                 else1 N; ?: F4 O  w! k% J
  18.                                 {7 O, K- g: z$ N" q% Q
  19.                                         USART_RX_BUF[USART_RX_STA&0x3FFF]=Res;! }  ~: V# y3 X8 K  w1 A
  20.                                         USART_RX_STA++;. d1 F  p6 Q0 z$ L3 {8 s% k+ [; Y
  21.                                         if(USART_RX_STA>(USART_REC_LEN-1)) USART_RX_STA=0;
    ' q6 z* e& T6 P5 {; A( H
  22.                                 }
    - |& Y- g; B; J6 W
  23.                         }& P" q: x; X) m0 y4 L0 p- `
  24.                 }
    9 h/ E/ _- J6 ~, e5 w* K
  25.         }9 G* J( ^( ~- J! }+ f1 h2 z
  26. }
复制代码
; f$ Q# g9 s) F7 J+ z0 b
3.3 修改delay.c文件
" Q8 K- N* E+ }9 u  pdelay.c文件修改地方比较多,因为涉及FreeRTOS系统时钟:1 a) N9 x* H/ q  d# p
1)SysTick_Handler()函数1 S, h: T( Y: i* }& K; R! R0 `

$ W" C+ a! b8 L2 n
  1. extern void xPortSysTickHandler(void); // systick 中断服务函数,使用OS时用到
    2 w) n( k2 ^/ J) ?& H6 b
  2. void SysTick_Handler(void)% x2 Z! d, V, P/ [. q
  3. {
    5 s# Q/ D! g9 C8 S
  4.         if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED) // 系统已经运行" |; i: p; D; q4 Z
  5.         {        xPortSysTickHandler();        }  ~6 r6 D7 ^! R- N; m- Z
  6. }
复制代码

* J% G: R( S5 a, KFreeRTOS的心跳是由滴答定时器产生的,根据FreeRTOS的系统时钟节拍设置好滴答定时器的周期,就会周期触发滴答定时器中断。其滴答定时器中断服务函数中调用FreeRTOS的API函数xPortSysTickHandler()。
( `$ o2 g- K* J2 s# J; V6 F9 r5 [" i, e% D0 W
2)delay_init()函数
; b, U2 R/ f. u' n) q
; K# u" I( o) J; f  F( O
  1. void delay_init()
    ; L3 a  u5 q% K. ^8 h1 K
  2. {$ k8 n; Y3 r" v8 ]4 k
  3.         u32 reload;
    1 R2 o) n2 x! d( q: q
  4.         SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);  // 选择外部时钟HCLK
    1 [) d/ X5 _7 P6 }
  5.         fac_us=SystemCoreClock/1000000; : ]+ o. v# M8 X" C5 w. e4 D7 D
  6.         reload=SystemCoreClock/1000000;      // 每秒钟的计数次数,单位M
    ) z7 p, W- ~2 V1 Q6 }* G
  7.         reload*=1000000/configTICK_RATE_HZ;  // 根据configTICK_RATE_HZ设定溢出时间reload为24位寄存器,( p# U  }5 e! E: ]: w4 S, Z9 T! r
  8.                                              // 最大值:16777216,在72M下,约0.233s左右
    8 o) ~9 T3 V' _
  9.         fac_ms=1000/configTICK_RATE_HZ;      // 代表OS可以延时的最少单位1 j* S, n* Z8 e
  10.         SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; // 开启SYSTICK中断 7 p% {7 u0 N3 W7 B
  11.         SysTick->LOAD=reload;                // 每1/configTICK_RATE_HZ秒中断一次
    " O* g  p5 l0 _2 M5 k) V6 b
  12.         SysTick->CTRL|=SysTick_CRTL_ENABLE_Msk;  // 开启SYSTICK: ?! i) o# e4 M, o
  13. }
复制代码

* k# C! L# E9 w" _" e. Ndelay_init()用来初始化滴答定时器和延时函数,根据FreeRTOS的系统时钟节拍初始化滴答定时器,其节拍由configTICK_RATE_HZ来设置,其值可自由设置。4 A- U( I2 P, z* G" f( [* X
接来下是三个延迟函数:1 ?$ v( b* p) _2 ?* n. J3 F
9 u' w( A4 K' [3 y' i7 x
  1. void delay_us(u32 nus)7 }% u  o4 X% v5 p* }8 X
  2. {
    1 z, A3 l. [6 r9 z9 N% c
  3.         u32 ticks;/ I5 x; f- x) b, S% h
  4.         u32 told,tnow,tcnt=0;4 ^/ V7 w' V% [( P6 |! _* c
  5.         u32 reload=SysTick->LOAD;   // LOAD的值  O% ~3 a& l: e# ~: U6 R* ]
  6.         ticks=nus*fac_us;/ b& N0 D4 s- C4 y/ G- |% ?; j
  7.         told=SysTick->VAL;          // 刚进入时的计数器值4 [) J. V) G+ D
  8.         while(1)
    6 P) O: Y7 e1 E1 n
  9.         {
    / ]! v8 h* f, N
  10.                 tnow=SysTick->VAL;) G4 i3 p8 X$ J" t# I
  11.                 if(tnow!=told)
    + V) V" s# ^" X" m
  12.                 {        // 这里注意SYSTICK是一个递减的计数器$ p+ e, j1 M5 |4 T# N. Y) I+ [
  13.                         if(tnow<told) tcnt+=told-tnow;
    6 W( ~2 s! K& S  X! n( K/ V: F
  14.                         else tcnt+=reload-tnow+old;( E( Z4 `2 |1 O
  15.                         told=tnow;
    + F: z+ a- k! b2 t( }
  16.                         if(tcnt>=ticks) break;  // 超时
    2 K9 q# i) ^) E; A
  17.                 }9 M/ @, d0 K* y- n
  18.         };( _3 H+ z* ~: C7 m1 S
  19. }
    . G9 X* q- _7 U$ [
  20. ; T! Q* J& T) C9 ?  @! v
  21. void delay_ms(u32 nms)
    - f: s! g0 a2 k/ V
  22. {
    9 v1 u" x4 f& h. i8 ]
  23.         if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)  // 系统已经运行& i6 B* g7 Y  D/ G: ~( w6 p
  24.         {7 `8 t- W1 f# X9 |9 g- w7 Y" \
  25.                 if(nms>=fac_ms)        {  vTaskDelay(nms/fac_ms);        }. C: K) [2 ^+ ?6 u
  26.                 nms%=fac_ms;   // OS已经无法提供这么小的延时了,采用普通方式延时! N  T; H. u7 A9 l" U: M) l$ o8 n
  27.         }# J, ?' E! {' D6 t' [
  28.         delay_us((u32)(nms*1000));! t) p1 K) [; ^) o7 i
  29. }! f  q) x9 E; f/ e6 Z& E" p
  30. ( c' v* [) B8 D, f4 D
  31. void delay_xms(u32 nms)3 c1 b* Q5 A2 N, v  _" t7 @
  32. {, j) ^+ {' w7 }* w+ @
  33.         u32 i;
    2 g$ t- P1 w: P% z7 X% y* [. Y1 ]
  34.         for(i=0;i<nms;i++) delay_us(1000);6 K: }0 B( _& T" m. u
  35. }
复制代码

: P5 q% K4 ^5 O! D  M3 Y  Z* edelay_us()和delay_xms()不会导致任务切换。delay_ms()是对FreeRTOS中延时函数vTaskDelay()的简单封装,所以在使用delay_ms()时会导致任务切换。2 A  x# }' C- P. D" U
delay.c修改后编译一下,如有错误提示在port.c、delay.c和stm32f10x_it.c中三个重复定义的函数:SysTick_Handler()、SVC_Handler()和PendSV_Handler(),这三个函数分别为滴答定时器中断服务函数、SVC中断服务函数和PendSV中断服务函数。可在stm32f10x_it.c中将这三个函数注释掉。
5 B9 i6 D+ |- c" N
7 C  @! W. o# W. } 20210311231109847.png & ^  h, ]: }# w% w) H8 b) t

) _; Z- a8 U4 Q至此,SYSTEM文件夹修改完成。* t. c" o7 ~: n4 E5 T7 ?+ _
————————————————
) d- i4 M; U! q% ?版权声明:天亮继续睡
1 W0 x- c. R! C$ l  E
0 O9 r! v9 X0 }* A# B7 r+ X7 k9 Y8 A" ?& w9 d% p* b
赞 收藏 评论0 发布时间:2022-11-17 17:37

举报

0个回答

所属标签

相似技术帖

官网相关资源

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