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

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

[复制链接]
STMCU小助手 发布时间:2022-11-17 17:37
1. 准备工作
7 N0 V4 ~6 i4 h% b0 i1)FreeRTOS源码(选择所需要的即可)。2 o4 V7 I/ G5 T3 l4 R6 V

6 a6 [" \+ L3 a$ c2. FreeRTOS移植# I: c0 E  Y6 |3 q- x6 |
2.1 添加FreeRTOS源码1 y3 M' M$ N& Y8 R/ C
在案例文件夹中新建一个FreeRTOS文件夹,以后将FreeRTOS的源码添加至该文件夹里。根据前一章的知识点,portable文件夹里只需留下keil、MemMang和RVDS三个文件夹,其余都可以删除。
6 L, S8 a( \+ P( |3 i, z 20210311230409275.png / v  ~" n  ?: t
* S" c0 C- E- L/ c0 G! i
2.2 在工程分组中添加文件- z" w: E" O+ c/ L. L! P, s
打开案例工程,新建分组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,表示五种不同的内存管理方法。
5 y0 X; Z& ^) @2 p, |4 h' K6 v- }% @
20210311230557444.png
8 i2 ]% Q1 h$ t3 V4 H
3 h4 ^' f5 Z2 E# J2.3 添加头文件路径
9 e1 L6 R: R) @( O; Z" G. t如下图所示添加头文件路径:
. p& I2 l" s8 _; N1 {( i* o! W
8 T2 E$ v+ I0 y! k 20210311230718207.png
1 s& n1 n, E4 n: y% U% M- E
' }  E; z4 l/ s头文件路径添加完成后编译一下,有如下错误,提示打不开“FreeRTOSConfig.h”。& P9 h2 X' ~$ c4 L- X
这个文件可以在FreeRTOSv9.0.0–>FreeRTOS–>Demo–>CORTEX_STM32F103_Keil文件里找到。# X, h; @5 ~( f- \
3 l( V9 E/ q2 x7 h. Q5 D. ~5 U
3. 修改SYSTEM文件夹里的文件% _, I( K, a' n5 N/ J: e8 V2 m
SYSTEM文件夹里有三个文件:sys、delay和usart三个源文件和头文件,这是正点原子团队开发的,但不仅限于战舰v3开发板。2 y# O* [7 [' R5 w

2 u+ `( @1 M1 l5 @% ^; z3.1 修改sys.h文件5 N1 k( S, d5 G1 n# X4 {  c0 r
sys.h文件里面用宏SYSTEM_SUPPORT_OS来定义是否使用OS,具体代码如下:
% a8 c- u) u/ s; f  ^
) q3 U  Z; N+ N% x; e
  1. #define SYSTEM_SUPPORT_OS   1 // 定义系统文件夹是否支持OS,0,不支持;1,支持
复制代码

' o% k) ?0 x& c6 w3.2 修改usart.c文件
% U& ^+ X' h$ lusart.c文件有两个修改地方:9 V7 B8 v2 E( n9 X: I- K
一是添加FreeRTOS.h头文件:
/ |: C6 s4 g3 @* C$ u8 K! S9 n+ l# g, K4 h2 p( A, ?/ m4 ~# `( u) I
  1. #if SYSTEM_SUPPORT_OS
    / @" `) o/ q" q
  2. #include "FreeRTOS.h"
    ' i, Q- E9 B; Q# o; w+ T- h
  3. #endif
复制代码

* i# A( O8 G* Q$ M二是USART1的中断服务函数:6 y+ M8 f9 g2 i0 K% `$ |& b, o

) c) @# ~7 V6 Y* H; @! Y. A2 T
  1. void USART1_IRQHandler(void), K4 ?$ B) H+ \5 R. A0 }
  2. {
    ! B  S2 t3 S; A6 W* l& W
  3.         u8 Res
    6 ]& x/ S0 F; B) e& X
  4.         if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)2 \$ {; ]' X. `. f" e# ^1 s
  5.         {+ z& Q9 E: k' I* h
  6.                 Res=USART_ReceiveData(USART1);8 ?1 i6 M% Z3 Z5 ?* A
  7.                 if((USART_RX_STA&0x8000)==0)   // 接收未完成
    5 W. K3 j  F; T- S. r
  8.                 {7 }+ l: h; B/ T5 Y' K2 r$ Q
  9.                         if(USART_RX_STA&0x4000)    // 接收到 0x0d
    5 O# g: ^1 J- }0 q3 k* y* a. [
  10.                         {
    9 K: ]' D8 z- x
  11.                                 if(Res!=0x0a) USART_RX_STA=0;
    9 Z5 ?4 m# d; b1 _) P
  12.                                 else USART_RX_STA |= 0x8000;1 w9 f& k( g% R
  13.                         }
    ) B1 D) a0 r& R2 v1 p6 N! v% a
  14.                         else // 还没接收到0x0d
    " s: W8 o$ m( c' F
  15.                         {7 ~2 o# @  ?, F0 r: P' c" j
  16.                                 if(Res==0x0d) USART_RX_STA |= 0x4000;) I) ~4 S& I. O' R+ y& ~  C
  17.                                 else/ I. Y4 R: W5 U+ o' W2 ~$ S0 Y/ o
  18.                                 {& b) z& F7 A0 Q6 v8 b
  19.                                         USART_RX_BUF[USART_RX_STA&0x3FFF]=Res;+ k3 ]$ u+ f- Q- }; M) d# {0 d  H
  20.                                         USART_RX_STA++;
    0 u* j5 o* b/ R! g' t) k: S
  21.                                         if(USART_RX_STA>(USART_REC_LEN-1)) USART_RX_STA=0;
    3 k0 _8 {; i0 d3 T+ m) r2 x( S
  22.                                 }- Y9 F. o1 x* Y0 R
  23.                         }
    $ a' c$ P. T$ U  w6 c
  24.                 }
    5 L" _/ E/ s: k- P- {5 z
  25.         }/ @( S! ^/ Y5 H" t* Y3 T$ g! O
  26. }
复制代码

+ ]; A/ E: a' v. D" u( |$ \2 w- _* H( J3.3 修改delay.c文件
' f- w0 u1 B3 p4 e' Z9 Adelay.c文件修改地方比较多,因为涉及FreeRTOS系统时钟:5 e0 w  W! ~2 y0 O; p$ \; u
1)SysTick_Handler()函数/ ]' m7 C# S9 ?+ q. S' [

2 k. G: g, F4 x$ U; M. z
  1. extern void xPortSysTickHandler(void); // systick 中断服务函数,使用OS时用到
    4 r+ ~; Y+ a( i1 |0 B8 X- A
  2. void SysTick_Handler(void). N0 _( ?. A4 v7 t0 Q
  3. {
    $ @; P5 l) t/ I+ G' V
  4.         if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED) // 系统已经运行
    / A# G& I: V# c7 m) `3 w
  5.         {        xPortSysTickHandler();        }
    5 O4 ]- l9 b' X  k0 J0 Y0 H& T
  6. }
复制代码
; X' [# c( U6 C. H
FreeRTOS的心跳是由滴答定时器产生的,根据FreeRTOS的系统时钟节拍设置好滴答定时器的周期,就会周期触发滴答定时器中断。其滴答定时器中断服务函数中调用FreeRTOS的API函数xPortSysTickHandler()。9 U6 v& K3 E& h7 i& I

, g% f- I0 H- O( i2)delay_init()函数
* l+ ]& c! D; u( `7 x, Y. n
4 [& B, Z# M( a6 ~- N* ]  B
  1. void delay_init()
    $ l  n0 j% X8 r4 D5 G
  2. {' ]) R* Z& f4 B0 d* K
  3.         u32 reload;/ h" J: h3 S2 \
  4.         SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);  // 选择外部时钟HCLK  i6 p: n( x" V6 t
  5.         fac_us=SystemCoreClock/1000000; " {* y' Y2 i( e& t
  6.         reload=SystemCoreClock/1000000;      // 每秒钟的计数次数,单位M6 V# q9 A/ Z3 O# q& T0 b" u
  7.         reload*=1000000/configTICK_RATE_HZ;  // 根据configTICK_RATE_HZ设定溢出时间reload为24位寄存器,
    * a, c! ^1 S2 h! _$ V# g
  8.                                              // 最大值:16777216,在72M下,约0.233s左右) Q; g8 r) H: ~" x0 |/ H" d
  9.         fac_ms=1000/configTICK_RATE_HZ;      // 代表OS可以延时的最少单位; i3 B  G" ?9 Q4 ]  u3 u
  10.         SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk; // 开启SYSTICK中断 9 v! l4 b. X! k" w0 y8 `7 x
  11.         SysTick->LOAD=reload;                // 每1/configTICK_RATE_HZ秒中断一次
    ( z' t! t4 I, W8 ], N. H
  12.         SysTick->CTRL|=SysTick_CRTL_ENABLE_Msk;  // 开启SYSTICK, a% U5 G0 e2 F. K4 {7 z
  13. }
复制代码
3 F/ u7 C$ k4 S& O
delay_init()用来初始化滴答定时器和延时函数,根据FreeRTOS的系统时钟节拍初始化滴答定时器,其节拍由configTICK_RATE_HZ来设置,其值可自由设置。
1 W4 x& `, [2 x0 y3 M2 `$ X) S接来下是三个延迟函数:7 y5 z$ c! {+ q  a2 Q
6 W" B. ^2 P1 W: B/ R
  1. void delay_us(u32 nus)3 x( T$ ?/ V8 u  f' Y1 P4 i1 S
  2. {
    4 ?/ @: R4 J" d& ~9 S, h2 w# s4 T
  3.         u32 ticks;% N) H7 }* t& r, q3 H) M
  4.         u32 told,tnow,tcnt=0;" m! x9 f7 _. c8 x/ \
  5.         u32 reload=SysTick->LOAD;   // LOAD的值5 f$ \# H+ x( o+ Y( @5 D
  6.         ticks=nus*fac_us;
    ; ?& r1 }. m+ Z8 S
  7.         told=SysTick->VAL;          // 刚进入时的计数器值
    2 [% |9 \  ]6 o7 {: B* ^; X3 b$ H
  8.         while(1)
    % ]$ T5 b* T& n( f2 ]) _( {6 O; A
  9.         {! q; a2 ~. q" ~+ i! @' I% l
  10.                 tnow=SysTick->VAL;
    + X  ?" G" |+ m! x% b
  11.                 if(tnow!=told)
      w  F0 d. k$ }! D% L
  12.                 {        // 这里注意SYSTICK是一个递减的计数器
    7 V. a0 R4 L3 \( {" p. y
  13.                         if(tnow<told) tcnt+=told-tnow;; e0 s- }3 l8 W) `# m
  14.                         else tcnt+=reload-tnow+old;: O# F+ L$ W/ C( V
  15.                         told=tnow;! j8 l: c6 u+ r  N  ]" I) t
  16.                         if(tcnt>=ticks) break;  // 超时
    4 g# C; g/ [% x: |7 a# c; H
  17.                 }6 y* p# ?; H1 R# q0 X! S& Z
  18.         };/ E4 `; R- i: ^& ?
  19. }
    1 P3 H' p: j" L% h% G
  20. 8 B: F/ W9 e, k' p
  21. void delay_ms(u32 nms), R" [, G8 F" ?# ?- f- c7 C
  22. {
    # L+ W$ B: ]* L1 d; S* z
  23.         if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)  // 系统已经运行+ E% Q" W) W: {
  24.         {
    / j$ n$ H; N+ l$ `, ?+ D' q
  25.                 if(nms>=fac_ms)        {  vTaskDelay(nms/fac_ms);        }  x' Q5 u9 r$ B- r' C
  26.                 nms%=fac_ms;   // OS已经无法提供这么小的延时了,采用普通方式延时; Z! J8 m5 }) m; _
  27.         }1 D! Z4 K; g" b  a
  28.         delay_us((u32)(nms*1000));$ Y4 g& Q3 u: C9 N& M+ p3 {
  29. }
    5 }! [' W; h/ B- I

  30. ; B+ f- q/ F9 S- W  B* r
  31. void delay_xms(u32 nms)
    $ n# ?: c% p/ U! l; q
  32. {: |% D( M& U* T9 d: B  B  _. _
  33.         u32 i;
    & s/ R' _6 j" w
  34.         for(i=0;i<nms;i++) delay_us(1000);3 R6 v; B5 \1 U7 ]8 J
  35. }
复制代码
. K9 F9 Y, T' S. T$ N
delay_us()和delay_xms()不会导致任务切换。delay_ms()是对FreeRTOS中延时函数vTaskDelay()的简单封装,所以在使用delay_ms()时会导致任务切换。
4 n. C8 C% O% n6 Z$ Z6 O3 o" y7 ?delay.c修改后编译一下,如有错误提示在port.c、delay.c和stm32f10x_it.c中三个重复定义的函数:SysTick_Handler()、SVC_Handler()和PendSV_Handler(),这三个函数分别为滴答定时器中断服务函数、SVC中断服务函数和PendSV中断服务函数。可在stm32f10x_it.c中将这三个函数注释掉。% d; Y! c+ |& P4 z) Y5 V
* R$ o* z! F% K4 L' K5 m* ~4 B
20210311231109847.png $ ]# y9 k  l( T8 i

5 e  b( t, l, K8 [" N至此,SYSTEM文件夹修改完成。
6 Y$ K7 d' w4 i; M; @/ k/ q————————————————+ U. F3 N/ _- b' w
版权声明:天亮继续睡
9 P1 ]2 B* g; Q" v( o# B, N1 ~4 x; z/ t2 Q) K- D
' I- I1 K( A& z3 g' u- Q( N
收藏 评论0 发布时间:2022-11-17 17:37

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版