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

【经验分享】STM32H7 RTX5操作系统移植(MDK AC5)

[复制链接]
STMCU小助手 发布时间:2021-12-30 14:32
4.1   初学者重要提示
$ ^6 e5 f1 a# @8 h! ?: }  当前RTX5可以移植到GCC,MDK和IAR三大平台,考虑到仅MDK平台下有RTX5的调试组件,我们这里仅提供了MDK的移植说明。% o3 n5 Q% E+ b# t, {8 L
  STM32H7使用MDK RTE环境添加RTX5,需要强制运行一次STM32CubeMX,因为H7已经没有配套RTE经典添加方式,而STM32F4是支持经典方式的,所以无需运行STM32CubeMX,详情可以看我们STM32F4开发板对应的RTX5教程。! q/ O* E  U0 P8 S
4.2   移植RXT5内核整体说明, H: s- ^: L# d) }+ f7 b4 {" z9 N
移植之前,有必要对移植过程有个整体的认识:! S! ?( r3 G- n' c( D0 C
$ N8 V- h9 X: B
  第1步,准备一个工程模板。
; x! _& M' k0 f/ S/ b$ |  第2步,移植RTX5。
) f" W5 Y0 X1 ~  U  i5 R  移植RTX5是采用MDK的RTE环境直接添加。当前H7芯片使用RTX5强制运行STM32CubeMX,所以需要大家提前安装好STM32CubeMX V5.4或者以上版本。
7 ?! e9 x+ z1 C2 t4 G) r  第3步,处理HAL库时间基准,MPU配置等。* N/ f+ }3 ]7 m9 b
  第4步,创建应用。  s" u9 |( e7 W8 v* c9 |! d- ]
4 Y, y. f, G8 w+ d% p
总的来说,这4步就可以完成移植, 下面将STM32H7的移植步骤和注意事项为大家做个说明。! _. J8 B/ \) a* T# J# H8 B" r2 s# A
) @* f1 \8 z5 c6 H. g8 c
4.3   了解RTX5内核模板框架设计) u' O' ^) P3 j
移植RTX5前,我们优先了解下移植好的RTX5内核模板,方面大家后面移植:8 E$ W% {6 s* j7 R7 C- B0 A

) i! d; Z6 V$ m, X/ ]; X
ebf7bed4831890980f518eaeb842a943.png
: e' S% B+ @- ?" |2 x% d
" G8 N8 }5 o; y1 X3 j
框图如下:2 v$ K$ U$ h4 k6 h( ]& ~: h

! T  m: X. ~2 z' m) V; r* X
cc3f4f5af7e41dcb23a03a25e14d8ae7.png
8 F- S) V. b4 r
, K5 @- t$ b1 v0 `
4.4   第1步,安装指定的MDK软件包版本. t" E8 b8 l% P8 r, }; U6 K! w/ W5 q* m
移植新版RTX5需要大家下载当前最新的MDK软件包版本(如果有最新版,推荐大家用最新版):
. Q; j% y( K$ T( ?+ o- f
& c& L, H) [5 z! V4 O1 k$ K  CMSIS 软件包使用当前最新的:V5.7.0( T: Q! o, m' Y+ B
  STM32H7使用当前最新的:V2.6.0; `- V( i& [" O) i
  STM32F4使用当前最新的:V2.6.0
- j* ^# W7 G3 c! B5 l9 }, L  STM32CubeMX使用当前最新的:V6.0.x
3 r) w! M# w! |8 }4 `( T  ARM_Compiler使用当前最新的:V1.6.1
5 F. R  [8 ]6 w7 B  [  D( E
+ @8 J; O; \7 s" D不管以后MDK的软件包版本如何升级,当前的软件包版本和以后的新版是可以同时安装的,也就是说可以安装多个不同版本,在这里可以选择指定版本:% y& ?4 T: N8 ?0 N) [) G3 ]
; u: f2 Z1 W! w' L: m9 U. I8 z3 A
bbb84b8c4b3275b1026d2c95b5012294.png

$ y3 @8 k" I8 P. @$ }" \3 W6 P
, G  G6 _4 L* Q8 @1 e) s* i! `4.5   第2步,准备一个工程模板
, E. _3 f0 i8 S; \8 A首先准备好一个简单的裸机工程模板,已经为大家做好:V7-400_Base Template,准备好的工程模板如下图所示(大家也可以制作其它任意的工程模板,不限制):
: Y/ b8 Q% e! f7 N8 [" _
3 S+ o6 P% y- [& F( _5 d
5618d5a487ef825c0a75ce19685c4821.png

4 r; U: v) R4 b6 [8 n3 W4 E% M  b1 l+ v3 ]; U4 V9 {- _$ A
4.6   第3步,添加RTX5并配置, C- k/ j' m$ F: E) p
RTX5可以方便的通过MDK的RTE环境添加进来。对于H7版本,MDK会强制运行一次CubeMX,并添加很多H7的HAL库文件,这些库文件我们可以使用,也可以不使用。教程配套的工程文件是不使用这些,因为前面的工程模板里面已经添加了。所以要将这些文件全部隔离出来。3 X$ p. T% V' m! C( c9 P: x# u9 Q

5 x3 I, v3 y6 t1 f4.6.1      添加RTX5源码5 ~8 A2 m# w7 ~( X9 x

- c6 n" b2 {" e2 \! `
48f11b91f9fc45f3f04431047156434d.png
. u& Q6 O8 m8 f3 |
7 }; V1 E2 o/ ^* U1 @
点击OK按钮后,弹出如下界面:
0 a! R/ b6 S8 T) z7 r8 P/ R3 h, b. O
! t% y/ C4 ]/ o; h3 ~, o3 L. U- |
b430f5f7b2e1a16de73553adb9dd1f89.png

1 r8 Y* K% q9 I6 G( Z0 }1 I8 [/ w7 a, ^7 c/ S3 v
点击Start STM32CubeMX,这里需要大家电脑上已经安装了STM32CubeMX,并且为其安装了H7的软件包。0 f1 R6 i# s! }8 `/ W" C7 j

0 {$ n$ F% O0 a) P  u( h/ {
af4f52889e56b18313faf6baa5ed1281.png

& m0 A" {# Q0 L5 N7 {
# R% C  T2 T# z8 |打开后,用户仅需配置如下地方即可:
& r" j/ B0 ]# R$ p! J0 w9 K# p; z- ]7 f* q: J2 P$ t2 d% P1 k. l
7c8a9271ba3d0ccb045c81921fd97d0f.png
! D# ]. J9 b7 ]+ I

% ~! g' t; S; i5 D! y/ M然后点击右上角的GENERATE CODE:- I5 d* d3 Q$ C( f4 Z

! T/ P3 U: Z. o5 S/ r- s* f
62747d5251f02d427c05caf48fc46d77.png
  _$ T' S* I& j# K+ ?
! Q, F6 n2 |) J' Y- m
然后弹出如下对话框,点击Close即可,然后关闭STM32CubeMX。4 Y( ^1 ]8 n6 s0 p0 s2 @+ \% ?

9 W0 @' F( m+ X8 [$ f+ I, i5 m
1a4404327c06b66c217f46c74bd48db2.png

0 H% F) c8 C! c8 F3 S, `( ^' _4 Y% X4 m) q- O- c! y1 r
重新回到MDK,会有一个对话框,点击是即可:: u  }0 w6 u: ~8 s7 g1 W: p& y3 {

$ `1 P; M# w4 c
cdfb3b29fdf8c8b60f0d85f8aaa161ff.png

1 v" U& C8 Q3 S( o  Z/ a7 z
1 n9 J# I# e) T' x; l$ ]  i最后就可以看到RTX5源码已经添加到工程里面了:3 b* r/ V+ t2 _- I
$ R  U: R! a0 j9 ?
e49f340b4464ddd3afb5bf5082de0fdd.png

8 L4 h+ L  a8 }! b  k8 L
6 f5 e( w: c# u! {6 h3 t0 c/ D& A4.6.2      将自动添加的库文件隔离出来
! O% J3 [( o6 c$ c7 x5 J: c添加的所有文件中,仅RTX5和文件stm32h7xx_hal_msp.c留下,其它文件全部隔离出来,隔离方法也比较简单,比如隔离生成的main.c函数,鼠标右击此文件选择Options for file ‘main.c’
' i+ v. K$ ], v% Y
  z, c  v  N6 j$ S" o
3b989ad148a2ec7c0522490cd84fcf3c.png

) J! M$ _( g9 L3 f' I, p9 e" D) W& J3 K6 R
然后取消掉include Target Build前的对勾,点击OK:" P* L8 G+ p, c9 R) f( ]2 m8 i" W
9 }3 E+ }( W  c5 G" Z
6652eec0f1078d33b6c1508049d0c922.png

! m$ k' O6 h0 u" N5 t5 D# k! M. K6 |) N. b  r* P" w# x5 d  d7 e$ `
看到main.c文件上有个红色横杠,就表示已经隔离出来了:9 J$ J4 r( I5 s6 v

1 ^6 r6 M7 Z* L
cafbe4a03ab78632d36b9cf1b050250c.png
% ~. F. z$ p/ q, _, w5 Q
+ B) Q' q5 n, B* M# i) o( U
同样的方法,将stm32h7xx_it.c文件也隔离出来,文件stm32h7xx_it.h不用管。
) p! J# }# H2 r6 b/ }' e
) F9 a8 {6 |; n/ W" w. Q  }* k  N: hDevice下面的这些文件也是同样的隔离方法:
* q" X' w% M1 ^! `$ Y( Z1 j5 V( k" v
- z) A0 D% p$ _" D4 G4 N4 j
f46dbe6e1b27dd459e04cba9849d9ff9.png
( a" R: [: E7 t2 S' p. s
- N. J% M2 d" p! O: C6 s: {
只是鼠标右击弹出的界面有些不同:( i6 S. \4 P. I( y
: s% W( u! G' G- u6 l+ P+ }
aeccd1d366ee4da23ceff332ae2f84e5.png
* }% A/ g9 {0 W9 U. a

! W8 b# n7 i% y- [2 e+ R5 z( L; G$ I注意stm32h7xx_hal_msp.c无需隔离,其它所有的文件全部隔离,stm32h7xx_hal_msp.c对应的隔离配置是STM32CubeMX,如果也隔离了,编译会有问题:8 }. @! w3 Q( P* W% j
) J# x; V0 @+ f6 H% v
59f0e5e7d43f7ac7e983147c132a42ce.png

  u& ~. n* `% v- |2 e/ N: p# U4 t# p+ W& i) L
隔离后的效果如下:; d! r: k: d& X# Q
  |7 U; }4 s/ t# i) ]4 x( o+ M
573fb2c99aa8ef7ef6f577c106084913.png

( t! ^. R" [2 p) P3 i, K2 w, V% e2 y3 v3 @9 @+ M
4.6.3      RTX5配置
( H! K8 D# b$ W) Q剩下就是配置RTX5,设置RTX_Config.h文件即可,移植阶段先按照如下设置配置好,后面章节会专门为大家讲解每个参数的配置含义:
6 z  O" c' Z" |4 S+ K& l% Z/ F' k- t3 W& U2 z( a  X
576cda809f95be40653ff18b9682f906.png
! }2 h, O- o- f3 s% Y7 y! q: t
  G. M% u8 l( O/ v) T
4.7   第4步,MPU和Cache配置文件bsp.c$ ~2 w6 p* ?% q8 b, j3 ^
这个bsp.c文件也比较重要,移植阶段,直接将我们移植好的模板内容复制过去即可,这里把相关的内容为大家做个说明。6 b1 K5 M2 j( z3 J! o
5 @# b) Q* g7 K( Z8 ~+ o' V
4.7.1      函数System_Init

- _/ r) n5 B1 h9 ^+ y3 Q系统初始化,主要是MPU,Cache和系统时钟配置,需要在RTX5初始化之前调用。
4 e9 D# d0 {6 _" T7 E
0 q. `# h5 p+ Z1 b& n# j
  1. /*
    . \/ H$ w* O, s  t$ l  O
  2. *********************************************************************************************************5 ~6 ~( W& z$ z. o# P
  3. *    函 数 名: System_Init
    ! J3 Y9 i( f* E! v# h2 R
  4. *    功能说明: 系统初始化,主要是MPU,Cache和系统时钟配置! P8 c6 Z% V8 u" D( X% ]
  5. *    形    参:无8 ~9 j, |  r9 @* N3 z/ c
  6. *    返 回 值: 无6 Q) @5 x( O( S, y
  7. *********************************************************************************************************
    4 {& A' t9 }. }& g* b5 O4 ~
  8. */
    / z8 n8 J/ Q! K
  9. void System_Init(void)
    % m  m1 m7 N, N, U/ I; u
  10. {3 \" ]: V3 U. l

  11. $ I/ E5 [) ]! o( M
  12.     /* 配置MPU */
    2 Y! G* D: c2 t8 R2 }
  13.     MPU_Config();
    ' f' ^! s0 c  Y5 H/ r3 P+ B

  14. & o! j$ V' m/ P
  15.     /* 使能L1 Cache */
    0 M0 j1 j8 m( n& b4 G0 ~0 M# `
  16.     CPU_CACHE_Enable();. p7 A0 B5 B( R. b1 }. O
  17. 5 f. n9 @% M  g" v/ e: U
  18.     /*
    ( Q8 g3 g' r: r6 L' U5 T$ m
  19.        STM32H7xx HAL 库初始化,此时系统用的还是H7自带的64MHz,HSI时钟:  d3 [! q8 l  e, E/ @7 Y  q/ c& Z% d
  20.        - 调用函数HAL_InitTick,初始化滴答时钟中断1ms。: Y& a7 V) q* C  l1 p
  21.        - 设置NVIV优先级分组为4。: F5 Y* c9 g3 X0 r- n9 P- l
  22.      */
    2 Z$ Y# \; {( K1 R7 J' X. `
  23.     HAL_Init();
    : v) K/ o4 o/ b4 G& _3 H  i& Z
  24. 7 z8 }' C% d) H; M, [, b7 Q$ X$ R
  25.     /*
    . R! X; \# X8 d- x
  26.        配置系统时钟到400MHz7 q2 l5 ~' _# o3 S+ X
  27.        - 切换使用HSE。% y0 J3 i& `0 \0 ~
  28.        - 此函数会更新全局变量SystemCoreClock,并重新配置HAL_InitTick。
    1 \2 ^8 G, d/ L: a
  29.     */
    2 [  U5 O8 s) d* L8 N
  30.     SystemClock_Config();
    2 }; D7 G' ]( ]

  31. * Y5 w, B! g0 R% }7 X; S0 h
  32.     /* . B+ @0 A; T* C$ t: v
  33.        Event Recorder:8 S2 ^' o& ]4 n
  34.        - 可用于代码执行时间测量,MDK5.25及其以上版本才支持,IAR不支持。
    # N0 s, m  y: p
  35.        - 默认不开启,如果要使能此选项,务必看V7开发板用户手册第8章
    , o8 |' G$ j6 f! K1 e
  36.     */   
    ) @$ E4 h! g8 T
  37. #if Enable_EventRecorder == 1  , [. ^3 v" O8 ^7 y# _2 j! |# Z
  38.     /* 初始化EventRecorder并开启 */
    2 |* G% x5 t3 v; l/ P8 z" g
  39.     EventRecorderInitialize(EventRecordAll, 1U);
    ; T/ P( `  b) I4 I6 G
  40.     EventRecorderStart();
    9 E) z4 K0 m, L* u5 c
  41. #endif- |" P' N8 k( S- q& Y
  42. : m& M6 `  W2 x* Z
  43. }
复制代码

7 g. U3 o/ h( X; Y# ~- t* w" |& ?4.7.2      函数bsp_Init
- L7 t# c* U& h硬件外设的初始化,这个函数在RTX5的启动任务里面调用。
- {% ^1 _2 j2 Y  ?5 b
' f$ [6 F9 |' e7 j5 ?% U$ ~- W7 @
  1. /*+ H' V: [  `& F6 b$ @, D
  2. *********************************************************************************************************) N1 j% f( _5 ^8 I- \% M
  3. *    函 数 名: bsp_Init
    5 q, i8 l! |. p1 t
  4. *    功能说明: 初始化所有的硬件设备。该函数配置CPU寄存器和外设的寄存器并初始化一些全局变量。只需要调用一次! C' Z& o/ F! X3 U* y+ a# Y4 m
  5. *    形    参: 无
    $ w0 w' @- o' r% @
  6. *    返 回 值: 无
    ) X' J6 a2 k1 W' T  ^
  7. *********************************************************************************************************
    2 [! f; u- H4 d
  8. */
    2 {. E1 ]4 x- t8 k, F
  9. void bsp_Init(void)
    1 B, m9 Y6 K) k/ q
  10. {
    4 ?" {5 R! {/ @3 q
  11.     bsp_InitDWT();     /* 初始化DWT时钟周期计数器 */      
    2 S5 G2 ?2 X# Z( m
  12.     bsp_InitKey();        /* 按键初始化,要放在滴答定时器之前,因为按钮检测是通过滴答定时器扫描 */
    ! O/ i% k# s6 z$ W! @4 D6 j  n
  13.     bsp_InitUart();    /* 初始化串口 */3 H7 O$ C; R$ t5 P0 J5 {
  14.     bsp_InitExtIO();    /* 初始化FMC总线74HC574扩展IO. 必须在 bsp_InitLed()前执行 */   
    , m  Y5 C$ f# @5 p; N
  15.     bsp_InitLed();        /* 初始化LED */    0 R- s: k  i% x
  16.     bsp_InitTimer();      /* 初始化滴答定时器 */
    - M& S, w* i; F2 {+ ~
  17. }
复制代码

( R# P! e' ], H" T4.7.3      函数SystemClock_Config4 x1 D3 x# z8 H& }+ P
这个函数主要是完成系统时钟配置。2 g& I! K. l  |# F
. R. P: x- J1 {/ [2 G" r+ D
  1. /*
    & G( `' k; y9 |9 F5 _1 T
  2. *********************************************************************************************************
    + g$ ^' E( n  n1 w- ^& w
  3. *    函 数 名: SystemClock_Config
      V* x9 I% _& f* ^
  4. *    功能说明: 初始化系统时钟
    : H$ L1 X5 E, Y" h6 L
  5. *                System Clock source            = PLL (HSE)
    ; C+ y8 v/ @0 E. ]- f
  6. *                SYSCLK(Hz)                     = 400000000 (CPU Clock)
    2 o) \! r& S! J( f: d+ \" e
  7. *               HCLK(Hz)                       = 200000000 (AXI and AHBs Clock)2 V: Z$ |4 p. e9 g
  8. *                AHB Prescaler                  = 23 K- y$ u$ I' J3 Y* G
  9. *                D1 APB3 Prescaler              = 2 (APB3 Clock  100MHz)( G+ T& Z3 }2 K: y' g6 T0 N6 F
  10. *                D2 APB1 Prescaler              = 2 (APB1 Clock  100MHz)( U- Y! ?4 b9 I# j- b- v
  11. *                D2 APB2 Prescaler              = 2 (APB2 Clock  100MHz)
    7 v6 L7 u: ^  H+ t! {7 N
  12. *                D3 APB4 Prescaler              = 2 (APB4 Clock  100MHz)$ X6 U: F; U" l4 x& u: e3 X, g2 P1 N
  13. *                HSE Frequency(Hz)              = 25000000
    ; }/ [% @4 v9 S) p; t- B( `
  14. *               PLL_M                          = 5/ f; @. X4 ]$ M- W7 ~# J
  15. *                PLL_N                          = 160
    9 j: a/ p& ?+ R: E! X2 _
  16. *                PLL_P                          = 2, l- t" J& T& l& B
  17. *                PLL_Q                          = 4
    & d$ }, d* J0 v+ _9 @1 ^
  18. *                PLL_R                          = 2
    : ?: W* M$ @) w: v# ]
  19. *                VDD(V)                         = 3.3( R2 L( t7 Z' I5 Q  W- [4 ]; b4 L
  20. *                Flash Latency(WS)              = 4
    0 I" n( a: u7 C2 K8 l* e9 {/ }+ r; z
  21. *    形    参: 无, _" o* j6 N7 @% x) v1 X1 q3 j
  22. *    返 回 值: 无0 M/ p, Y7 j" H0 R, ?  b' k
  23. *********************************************************************************************************
    . Z3 p3 }* n: Q2 v
  24. */- K4 E* W, y- A/ i: A) E. Y1 \
  25. static void SystemClock_Config(void)4 O1 _4 x7 W- [/ Q7 ^
  26. {
    ' M/ U7 P7 a0 }$ L5 K
  27.    省略未写
    8 z( K; _  E, g/ y4 K8 C: ^9 `

  28. ( p/ U) d# X) p# O* X3 l/ T: P
  29.    /* AXI SRAM的时钟是上电自动使能的,而D2域的SRAM1,SRAM2和SRAM3要单独使能 */   
    0 v4 M& T  E6 z; ^- M
  30. #if 1
    ( }$ V8 u  ^! I! j9 T
  31.     __HAL_RCC_D2SRAM1_CLK_ENABLE();) S3 u# M" j7 C& x* O2 z
  32.     __HAL_RCC_D2SRAM2_CLK_ENABLE();9 v6 h' U6 a# A9 _1 q& `. D# X5 @
  33.     __HAL_RCC_D2SRAM3_CLK_ENABLE();
    ( W4 |; t3 [4 V" r1 r

  34. # K8 |3 c/ z; T; ?" H) v
  35.     __HAL_RCC_BKPRAM_CLKAM_ENABLE();       2 \4 ~9 O% V' J8 p/ q
  36.     __HAL_RCC_D3SRAM1_CLKAM_ENABLE();
      u' j% t: k6 h0 h3 q9 w
  37. #endif, B9 f0 a  l  ?8 K5 A& s8 b5 z
  38. }
复制代码

  k; A2 _4 K7 {这里的RAM时钟初始化比较重要,这几个RAM的时钟都要单独使能。9 l  \9 x  `* o5 B2 f

- _* S4 b" v8 Z% G% Q: f% h4.7.4      函数MPU_Config2 u( \* r0 `3 _- E* Y& L
RTX5例子默认采用AXI SRAM作为主RAM空间,因为空间比较大,方便我们后制作综合例子使用:
2 e  `6 F% [+ k( w9 s3 v8 X) F! _. ]( M
  1. /*
    ' \0 o# P/ H6 V
  2. ********************************************************************************************************** b; S# i. F- F% X3 `
  3. *    函 数 名: MPU_Config: n( g* _0 V! j' p3 O1 p# l
  4. *    功能说明: 配置MPU, h/ [; l) y. ^- b( o  r
  5. *    形    参: 无" P+ w8 t" Q/ T9 l& t9 r
  6. *    返 回 值: 无! t# D! j' Z8 T, X+ V
  7. *********************************************************************************************************( `' K* ^6 `3 [+ R
  8. */
    7 {* b; H3 ?, |# O/ [4 ^
  9. static void MPU_Config( void )2 A( K! h) M% T+ u2 S* K
  10. {9 C1 A7 l% t1 N
  11.     MPU_Region_InitTypeDef MPU_InitStruct;' {% b" G+ t# }! q' O$ T

  12. " _; A. a8 P5 }) p4 K0 g
  13.     /* 禁止 MPU */& e/ Y  ^0 L  B/ W
  14.     HAL_MPU_Disable();
    4 B; l3 g1 u* b) o6 M! I
  15. # R% U% F2 m2 o/ K7 r
  16. /* 最高性能,读Cache和写Cache都开启 */    2 G$ E6 `" x% C, F
  17. #if 1
    4 R7 F: q! z! O) j! g
  18.        /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
    0 q+ ~8 j( @4 W4 ]% |
  19.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;# Z  C& O, |7 @' V- I8 \
  20.     MPU_InitStruct.BaseAddress      = 0x24000000;
    9 Z  K4 M( E( @
  21.     MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;3 Y6 e* }& T, s) d) ?% ~
  22.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;; l4 Q( Y3 Q; s: @/ C" r2 K
  23.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;! M3 g9 V; ~6 y3 d6 U
  24.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;% W2 ^/ _& d# ~" d. `
  25.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;3 j, Y  N3 c: d/ L
  26.     MPU_InitStruct.Number           = MPU_REGION_NUMBER0;) D5 z6 E3 i: ]' a2 r5 V$ s
  27.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
      |) p% q) s5 f
  28.     MPU_InitStruct.SubRegionDisable = 0x00;% P1 K# T' ~% r/ f# ~( Q. q
  29.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    9 K# m; Q  e3 ~( G' H# W6 R2 C
  30. / \/ N% [( f4 U
  31.     HAL_MPU_ConfigRegion(&MPU_InitStruct);
    - x# e1 |4 k) W# M1 h# C

  32. ' P1 J2 _1 O' m7 j5 M9 {, P: a
  33. /* 最低性能,读Cache和写Cache都关闭 */% }  S( {  k4 Z, e
  34. #else9 i1 J; A& L4 @
  35.     /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate *// q- I7 k2 j3 h% E, U
  36.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    * n, r2 a% c0 w1 K/ M  L
  37.     MPU_InitStruct.BaseAddress      = 0x24000000;
      Q/ h4 O: t3 y6 w+ h- D
  38.     MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;5 R/ y! }6 l1 [  r) j$ @' R
  39.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    8 D2 S) O) l3 x
  40.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;9 D' [1 ]# m9 `2 m0 u
  41.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
    3 T. t* n2 I# o( D. V8 @: u
  42.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    0 l( M& {4 o5 {" [7 s# T
  43.     MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    1 O' S% [0 S  P" V5 v6 r) S' Y$ H6 Z0 @
  44.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    2 |' m' M! |% ~3 F( J4 N
  45.     MPU_InitStruct.SubRegionDisable = 0x00;
    7 Z8 ?& J' W' D3 c# D
  46.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    , ^! D; r8 m% b+ V$ K
  47. * r& u; T. A2 W/ w
  48.     HAL_MPU_ConfigRegion(&MPU_InitStruct);+ f' P* _/ K% Y9 x% @3 ]4 C
  49. #endif
    6 }9 I/ P6 @/ R) ]( E

  50. ! }) O( z/ n. ?, R6 E
  51.     /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */
    1 @$ w# P! ^/ r$ ?9 @
  52.     MPU_InitStruct.Enable           = MPU_REGION_ENABLE;) d7 w# }1 {' v5 R' Y  `, j' Q5 H
  53.     MPU_InitStruct.BaseAddress      = 0x60000000;" O( o. Z& N% r: K6 h( q4 R
  54.     MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;   
    ; r9 l. J& }, s$ I7 L0 x9 ~
  55.     MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;" g+ e9 J# {8 X3 `/ o7 f/ m
  56.     MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;" r! U" w* h6 e) c9 i8 F, S
  57.     MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;   
    . F: o% W- I4 d
  58.     MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;3 m) Z* R: m1 O2 H9 o, w7 f1 u
  59.     MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
    # `: i& D6 A% k; |$ h& i
  60.     MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    $ s% k, x7 Q" u
  61.     MPU_InitStruct.SubRegionDisable = 0x00;
    + f, O4 M- X* W" l3 n( `* F! j
  62.     MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;1 r, T! h" d% Q# U/ }
  63. 2 r$ F8 X/ ^) ?: \) `
  64.     HAL_MPU_ConfigRegion(&MPU_InitStruct);+ b$ i2 C1 Z9 E' r1 Y

  65. + y6 B6 X, z( `1 |4 M
  66.     /* 使能 MPU */
    8 P) c8 q. r: F$ `- k+ X$ i
  67.     HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);, l3 q1 t+ N! @) `
  68. }
复制代码
2 f" Y9 j9 F5 L* j9 Q& t( e+ }
4.7.5      函数bsp_RunPer10ms; f; {$ h: R) {$ A
这个函数里面默认有个按键扫描,如果大家移植的程序里面没有按键初始化,务必要把这个按键扫描函数注释掉。
8 b; k6 M2 ?. Z. K
. q1 t7 }6 {6 n% q
  1. /** p4 w: E- w/ @4 R, U; o% M, \
  2. *********************************************************************************************************
    ( Y6 g5 A; y) Y# ~5 n. E
  3. *    函 数 名: bsp_RunPer10ms
    ( h& P- T' l; L$ r$ ?
  4. *    功能说明: 该函数每隔10ms被Systick中断调用1次。详见 bsp_timer.c的定时中断服务程序。一些处理时间要求& \  b0 v& \% I
  5. *             不严格的任务可以放在此函数。比如:按键扫描、蜂鸣器鸣叫控制等。
    ; u7 U2 [7 T# K* z) `' E
  6. *    形    参: 无
    ' H, e6 C( J$ Y: m% D- S' S+ j2 v, L
  7. *    返 回 值: 无
    9 o( k7 V4 I' V0 d2 X
  8. *********************************************************************************************************& Y8 g; z  A: ~  R" ^
  9. */& b0 {% r/ b  V/ ?% P3 P
  10. void bsp_RunPer10ms(void)
    7 L8 Q- j  ?6 T
  11. {
    ; N  h; _. l# V" s
  12.     bsp_KeyScan10ms();
    " r/ n; C+ z' c0 L. r; y( M
  13. }
复制代码

# A! g$ ?  P  c# X! y4.8   第5步,更新bsp_timer.c和bsp.h文件
& W) O, A2 R. e! I, C; X更新bsp_timer.c文件是因为此文件跟RTX5都要使用滴答定时器,有冲突。所以大家直接将我们工程模板里面此文件覆盖移植的这个文件即可。0 M9 g1 U, Y7 F# X1 l- L

& Z2 _0 g. O. J% X3 T4 z" ^bsp.h文件里面要添加一个宏定义,因为bsp_timer.c文件里面做了些条件编译:  K1 j/ H6 H8 s  ~
6 d+ s% {& j) e8 h$ k% E
#define  USE_RTX    1* N* s: d- E( d7 x7 `- a- ]
5 z% a0 }/ {2 G# H. C+ V
另外,bsp.h文件将大部分头文件都添加进来了,大家可以根据需要,用到那些头文件,使能那些,用不到的,可以注释掉。当然,不注释也是没问题的:5 h2 C8 _8 z; m! T, C
8 [+ g5 M5 m, E: _" a2 O
  1. /* 通过取消注释或者添加注释的方式控制是否包含底层驱动模块 */$ K( R9 I0 S. o7 c# s3 x
  2. //#include "bsp_msg.h"
    / G; `4 H8 O0 i. U2 R1 i$ H8 q
  3. //#include "bsp_user_lib.h"4 X9 b7 |5 B1 O$ Q) p3 `
  4. #include "bsp_timer.h": r1 m1 ~; h; V6 z# r
  5. #include "bsp_led.h"
    8 D$ f+ x# p  Q2 w
  6. #include "bsp_key.h"& h# h) V) |# _3 \
  7. #include "bsp_dwt.h"' d% |! Z; k' U

  8. 8 e+ g! F2 F5 o7 D+ v
  9. //#include "bsp_cpu_rtc.h"
    , ]* K6 B8 p5 U1 _
  10. //#include "bsp_cpu_adc.h"
    ! |, `4 X) z6 e
  11. //#include "bsp_cpu_dac.h"
    6 d: H7 W1 T0 p* ~0 ~
  12. #include "bsp_uart_fifo.h"
    : S! n7 c: p3 ]9 E
  13. //#include "bsp_uart_gps.h"3 u% F8 P* ~4 a( L  B! R* m2 q
  14. //#include "bsp_uart_esp8266.h"
    8 V' S: M$ E/ X* Z
  15. //#include "bsp_uart_sim800.h"+ g6 z# S# n9 D3 |! N

  16. & S  s% S$ {! o& I5 o- C5 i
  17. //#include "bsp_spi_bus.h"- C+ y7 l/ }7 s; P- w! ^
  18. //#include "bsp_spi_ad9833.h") J" x* R8 _( B7 ~  J$ Q: R
  19. //#include "bsp_spi_ads1256.h"5 h2 o$ Z5 E, z+ _
  20. //#include "bsp_spi_dac8501.h"1 Y  K- n7 \$ F
  21. //#include "bsp_spi_dac8562.h"
    2 R( v/ B: [4 {$ l
  22. //#include "bsp_spi_flash.h"
    / C# W4 H) j) F9 S: M
  23. //#include "bsp_spi_tm7705.h"
    / R, A* A3 P% w, A1 _
  24. //#include "bsp_spi_vs1053b.h") @. H8 |$ o- v# b7 T  p/ A

  25. 1 |6 C" W1 M1 m0 p
  26. //#include "bsp_fmc_sdram.h"
    4 H& e5 W' p4 j, X# W( {
  27. //#include "bsp_fmc_nand_flash.h"
    - j1 R% R; A4 Z6 S+ m- d* x
  28. //#include "bsp_fmc_ad7606.h"7 P) M" M" e: |6 [
  29. //#include "bsp_fmc_oled.h"6 d  T. Z4 M/ B# q0 F' Z, l
  30. #include "bsp_fmc_io.h"0 f  a8 T! ?* r' w9 o' E
  31. 0 l9 G; u/ H% J7 @4 p. {# ^
  32. //#include "bsp_i2c_gpio.h"
    9 q/ P& K0 m5 G9 d. b" I5 Z
  33. //#include "bsp_i2c_bh1750.h"0 S: z% T2 s! |1 P4 W
  34. //#include "bsp_i2c_bmp085.h"
    % s( Y( t+ E, I: X% l! Z
  35. //#include "bsp_i2c_eeprom_24xx.h"6 }# g7 O$ [  s- }' n
  36. //#include "bsp_i2c_hmc5883l.h"! X( A% S/ F" l+ ]8 o. U$ ?
  37. //#include "bsp_i2c_mpu6050.h"! D( ?1 q' M2 c* _" G0 Z; t6 ^
  38. //#include "bsp_i2c_si4730.h"
    - h& N/ q  {9 L; ^3 c' l4 [4 O
  39. //#include "bsp_i2c_wm8978.h"
    9 k1 U6 n, y9 N

  40. ' @3 i( w9 o& t2 ~- v( V
  41. //#include "bsp_tft_h7.h"/ K8 e% D# d* a( ^' ~
  42. //#include "bsp_tft_429.h"4 t4 E% u5 M7 K: ^3 W. i
  43. //#include "bsp_tft_lcd.h"7 H1 s& ]6 V- _& Z$ b  m
  44. //#include "bsp_ts_touch.h"
    + Y5 a; v+ u. ]: H/ O$ F/ X$ V
  45. //#include "bsp_ts_ft5x06.h"/ e3 V0 A3 w% b5 {
  46. //#include "bsp_ts_gt811.h"* ?; C; R5 p0 c8 l# Z
  47. //#include "bsp_ts_gt911.h"
    : p7 J/ i" D; c( X7 K3 V3 k
  48. //#include "bsp_ts_stmpe811.h"5 o! n+ T/ U: e' ^

  49. - Y, t! X" {3 L
  50. #include "bsp_beep.h"
    # q5 A7 {0 q: a# T( f. |3 |; I" k
  51. #include "bsp_tim_pwm.h": \2 q1 ~! I4 b4 X9 [3 Z
  52. //#include "bsp_sdio_sd.h"
    ) O6 k7 R% G/ q; {$ A; Y
  53. //#include "bsp_dht11.h"
    : i/ U# Z+ h2 C/ R3 O2 J: g2 z
  54. //#include "bsp_ds18b20.h"
    * P* T9 w$ C' t' J% o$ O
  55. //#include "bsp_ps2.h". C& g& l( t8 C% j& O: m
  56. //#include "bsp_ir_decode.h"
    " {2 t5 e+ ^& a  \6 ^3 }2 r
  57. //#include "bsp_camera.h"8 G' R% e8 S7 J9 N3 S" C1 F
  58. //#include "bsp_rs485_led.h"
    . K; C7 a! o/ Z& z  L
  59. //#include "bsp_can.h"
复制代码

$ i1 W2 e# A7 q/ X6 W4.9   第6步,修改文件stm32h7xx_it.c( p$ `9 B0 `) z0 |) j
删除此文件里面带的如下函数,RTX5要使用,冲突了。
2 P3 k% S% l/ q4 }. ?9 B% ~7 k
  w* x" S: h/ e% z
  1. /**: F: A4 L% i2 h/ Q  I0 l2 m
  2.   * @brief  This function handles SVCall exception.1 |4 d' a" _, x' {% j+ b# G  K
  3.   * @param  None6 F3 s  {. I% \. Q0 u, L
  4.   * @retval None
    / S& T+ Y' b' ^- S2 u
  5.   */
    ! ]* P. V1 Y6 x" P5 l% s6 r
  6. void SVC_Handler(void)
    ( C% G' z7 C4 ]  E4 Z# m
  7. {
    3 e& i# C4 Y4 A# s0 C& k) J
  8. }9 v" g9 J" y1 E% T6 _
  9. 1 O" |9 x4 G' P; N; Q7 {2 g
  10. /**
    % I  T, h& l1 X! x
  11.   * @brief  This function handles PendSVC exception.
    & r4 h) E1 n9 T) H% ]) H8 r' Z
  12.   * @param  None
    $ z, h7 `7 y" T6 R- M4 ?1 Z( E
  13.   * @retval None
    - q$ @/ m0 l$ ^# Y$ X) w6 \0 \. h
  14.   */( J5 I* m% X) n6 Z* ]
  15. void PendSV_Handler(void)* A5 U! d/ F6 F! i1 J
  16. {# ~) a% B. D, \. y
  17. }
复制代码

1 P6 H# |+ }4 Y- _  R4.10 第7步,添加头文件的汇总文件includes.h
# D) Q  Z# M! b% \1 L4 |: L1 A  F在User文件夹下添加文件incudes.h,直接从本章节教程配套例子的User文件夹复制即可。此文件主要用于RTX5的各种头文件汇总。2 Q: t/ r6 ^& ?# D! D1 r9 J% ]

& o$ i: |  C& l
63fafbc927e6b911f6f3b81c4acb6af1.png
# M0 z* Q! u  H
* E2 R' x8 Y* {) A3 p
4.11 第8步,HAL库时间基准stm32h7xx_hal_timebase_tim.c

. t% D6 }# M$ g4 `$ `/ B. h" b由于RTX5和HAL库需要一个时间基准,而且默认都是用的滴答定时器,所有要有一个选用其它的时间基准。当前的处理方案是为HAL库提供一个时间基准文件stm32h7xx_hal_timbase_tim.c。此文件
5 F: S6 x6 d- v" \. t5 T
8 N3 G9 }% a! w( `, @- o里面做了两套方案,一个是使用TIM7做时间基准,另一个是使用RTX5的API做时间基准,通过条件编译做选择。默认是采用RTX5的API做时间基准。" \) Z5 U  F/ m- u8 k" j

6 b0 T1 {  d! U' K4 _
  1. /*
    " U0 N+ R, u2 _+ m. }, o: U  |
  2. *********************************************************************************************************
    . T6 G$ G' o3 j" h
  3. *    函 数 名: HAL_Delay
    + R% }9 v: F' w
  4. *    功能说明: 重定向毫秒延迟函数。替换HAL中的函数。因为HAL中的缺省函数依赖于Systick中断,如果在USB、SD
    ) H3 \2 F8 H2 j  p
  5. *             卡中断中有延迟函数,则会锁死。也可以通过函数HAL_NVIC_SetPriority提升Systick中断2 M3 C' [2 |+ w- M$ t. c
  6. *    形    参: 无- Z1 \( v+ J; ]: }2 Z
  7. *    返 回 值: 无/ O5 `) R0 n" A6 N" J0 c+ l
  8. *********************************************************************************************************+ Q/ D8 v% R* ]5 L
  9. */8 s8 s+ s$ p" s9 d
  10. void HAL_Delay(uint32_t Delay)$ b7 k1 W2 R# ^! y
  11. {% Y, P9 s3 A& z; O& D" R2 P6 I$ _, u
  12.     bsp_DelayMS(Delay);
    , E& M+ m3 Z( M8 v
  13. }$ G$ F( e2 j/ s0 Q! p

  14. 4 E6 w9 ?. D5 Q3 H" [' K8 u
  15. HAL_StatusTypeDef HAL_InitTick (uint32_t TickPriority)9 w5 ]  Y5 Y2 F
  16. {
    * e; U* V' _  u: J! a' I
  17.     return HAL_OK;
    ( k0 L6 D+ Z: O4 b
  18. }
    $ ^8 \: E; S* P9 J+ x3 j, k
  19. + b+ R3 c' ^% x" x
  20. uint32_t HAL_GetTick (void) : M# \3 G0 |! Z9 g
  21. {4 p7 E3 j" h+ X
  22.     static uint32_t ticks = 0U;1 t! h' h* z  ]. D: @/ F
  23.     uint32_t i;- F! I0 ^. ]; U5 c. o/ R
  24. 8 M5 }8 a1 |+ f$ Z
  25.     if (osKernelGetState () == osKernelRunning)
    7 C* N2 u" N' b
  26.     {9 e0 J- L6 D/ z6 B2 `9 t
  27.         return ((uint32_t)osKernelGetTickCount ());% `0 x% H9 B% N0 F" k4 o
  28.     }" G+ [% V3 l" q, G: C9 i) o8 i, b3 v4 V
  29. ! i( H2 Y9 Q; U- d  J  A$ U
  30.     /* 如果RTX5还没有运行,采用下面方式 */
    4 ^6 I4 h* s& E
  31.     for (i = (SystemCoreClock >> 14U); i > 0U; i--)
    & U8 H6 R/ H. e5 h1 P, i$ ]; ^
  32.     {2 V$ L( C2 f' D, k" x" R! M
  33.         __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
    # V2 ~1 z' _$ k! e  W& u$ f. C
  34.         __NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();; J- E" E% T8 r8 I( \$ @
  35.     }
    ; E4 N! d5 g7 Z& e# O# e- q

  36. 4 E4 O/ I3 [# I  ?, d7 s# j
  37.     return ++ticks;" G4 b- @% z1 X+ a, S" W
  38. }
复制代码

5 S5 ]% i" E+ H5 \4.12 第9步,添加BSP驱动文件bsp_dwt.c
' {+ _+ X$ }: }- e7 n
添加bsp_dwt.c文件和bsp_dwt.h文件主要是因为第8步中的stm32h7xx_hal_timebase_tim.c文件里面的函数bsp_DelayMS要使用,此函数是基于DWT系统时钟周期计数器实现。/ u& N0 k  f& ?! B: ?9 B$ T

- n: U! `7 e5 C( v/ d
f0d85f2002a553fa31c8f67b30e2db76.png
7 c, A7 o4 n! B

6 w7 f( n3 b2 i4 T; |9 h: I4.13 第10步,创建应用任务(重要,注意启动任务)

: C' {. u' _6 ?& W, y0 J5 a6 C应用程序比较简单,大家可以直接复制本章教程配置例子的main.c文件中的内容到自己工程里面测试。主要创建了如下几个任务:
; {( O4 z8 M9 N. y# k, j( y% L: q4 w8 ^: Q$ [4 Z) X7 w% M4 [
AppTaskUserIF任务   : 按键消息处理。( L- Z7 r* G- R$ E: d0 ^! X

6 ^) O5 A5 N' {AppTaskLED任务      : LED闪烁。
# i/ o$ o! N5 g* `% X" C- j8 j$ w3 N" W5 q
AppTaskMsgPro任务   : 消息处理,暂未使用。
3 t6 b  h; _4 [5 }- ~0 ^5 C9 I6 f* M* f. V; ?% ^# k2 _
AppTaskStart任务    : 启动任务,也是最高优先级任务,这里实现按键扫描。
- h# v6 H+ i% O3 g3 E2 K% Y: f1 R% f: p5 ?8 n' O! s& g" L( W3 ?
osRtxTimerThread任务: 定时器任务,暂未使用。' J& c- ^1 U6 U9 [& a3 c' Y
2 S: G* ?( Z" E3 y
任务栈大小和任务控制块定义如下:. [% ~0 E; k, Y! U+ d8 j) g
6 h8 W  Q: E- ]! V7 K
  1. /*
    + Y4 T$ Q. m4 [5 R1 y1 `
  2. **********************************************************************************************************. j# q' [4 e7 V! M; f/ h
  3.                                              变量. I; u  p! @% E, w7 F
  4. **********************************************************************************************************
    ; ?% S5 {0 d1 C( v: Y, {% j
  5. */) w' ]! g6 ?' `; A! u: {
  6. /* 任务的属性设置 */. ?. {' L# X- Y" c# N1 W
  7. const osThreadAttr_t ThreadStart_Attr =
    2 r  R/ D& F- K
  8. {5 V* k" g9 X& p  f4 D
  9.     /* 未使用 */
    : k4 H& s! Q/ q6 B
  10. //    .cb_mem = &worker_thread_tcb_1,
    + Y% ~6 o2 n' C# U; i1 S, o; C
  11. //    .cb_size = sizeof(worker_thread_tcb_1),
    + D; f+ F8 a+ V: Y3 Z
  12. //    .stack_mem = &worker_thread_stk_1[0],
    % k) Z8 i' |% R- j% D: _/ M4 d4 j
  13. //    .stack_size = sizeof(worker_thread_stk_1),
    7 o# w" e9 v8 H4 c: c- _6 S- O
  14. //    .priority = osPriorityAboveNormal,
    * {: s& b/ [4 R
  15. //    .tz_module = 0
    % d% m7 }! L! ?" y% F- v

  16. % G, N. L! N- v% u3 [: [* Z
  17.     .name = "osRtxStartThread",
    2 v7 j6 L: Y1 J! y
  18.     .attr_bits = osThreadDetached,
    + q; E; I! d/ D& h
  19.     .priority = osPriorityHigh4,; @8 H" K% j' q
  20.     .stack_size = 2048,
    1 u( u7 m$ P' @4 w. G
  21. };
      z; }0 W' U4 E9 ~6 U1 `; J1 |
  22. 8 r# g( M0 T7 k: s
  23. const osThreadAttr_t ThreadMsgPro_Attr =
    . G0 }4 A; t& t+ V0 L0 x, A
  24. {
    / D1 K0 F& |% Z3 }# X& x1 p. x3 r
  25.     .name = "osRtxMsgProThread",
    - Q+ @8 I, C+ v, u4 P/ Q2 v
  26.     .attr_bits = osThreadDetached, 4 U# \# l% S4 i; A$ s7 J2 N
  27.     .priority = osPriorityHigh3,
    % f- q$ M3 E$ o
  28.     .stack_size = 1024,' v" w  G( D. u- z
  29. };
    + v2 t- k3 i! o% O) ~
  30. ) G$ Q1 X$ P. g
  31. const osThreadAttr_t ThreadLED_Attr =
    + O7 t7 ?, H% c. a$ b2 `
  32. {) d; R1 l- i; ~, J6 P4 u' Z7 m- M* R
  33.     .name = "osRtxLEDThread",' x7 ?* e  M; v9 @
  34.     .attr_bits = osThreadDetached,
    ! m) R$ R, h" ^6 r. K- z
  35.     .priority = osPriorityHigh2,$ c9 \# g7 E0 Z. _5 w4 b5 ]2 v6 Q
  36.     .stack_size = 512,4 m. r% _( |9 b# I. x
  37. };
    ( F! @. E7 w/ x) i$ L$ O/ h
  38. ! V, z. r& x: f6 G+ q! _& p
  39. const osThreadAttr_t ThreadUserIF_Attr = 3 A1 m% k: X8 P1 e2 X( {: _- }# F! _
  40. {" ~! X, X! o; P2 q
  41.     .name = "osRtxThreadUserIF",  `& U( i& y2 L1 S+ A! _* X
  42.     .attr_bits = osThreadDetached, # j8 N& g2 ~6 Q1 _% Z7 x
  43.     .priority = osPriorityHigh1,
    * w3 K) O% `  o. R7 }) e$ p
  44.     .stack_size = 1024,
    , p* {4 o4 l0 S4 Z
  45. };
复制代码

% K4 N  ]- w5 E1 H4 l% S任务创建:' p- W/ t; L7 {

) W) b, Z% A1 p# E: V
  1. /*4 @4 `( @1 E2 u  w$ f! d7 w1 ]
  2. *********************************************************************************************************7 R- h/ E: y" z. z. d
  3. *    函 数 名: main3 @, c* w+ {3 ?
  4. *    功能说明: 标准c程序入口。& {2 |" A" D5 M
  5. *    形    参: 无7 ^) f. ]# {/ i8 p0 h
  6. *    返 回 值: 无
    7 l( ]) W: ]4 ^' l; }5 O$ Y" p! z
  7. *********************************************************************************************************
    ) @  i" [* m4 m& U2 }
  8. */
    % d4 ]. a" i. z+ J* t& b
  9. int main (void) - D1 m' N, Y# j. B9 F! y2 k3 n5 ]
  10. {      c6 Z5 U% W! o
  11.     /* HAL库,MPU,Cache,时钟等系统初始化 */* p2 b$ ?) k/ |  A; k! a6 c
  12.     System_Init();  }; ?" @3 W5 A- Z8 h+ F! |* s

  13. 7 {6 y2 ]/ x& O  A
  14.     /* 内核开启前关闭HAL的时间基准 */
    4 Z" e- l, t; D. v
  15.     HAL_SuspendTick();! c) y4 B- N# J5 [. d/ X% M
  16. 2 a" B* V: g' O9 ]% B4 ^
  17.     /* 内核初始化 */  m8 |% h) D# q9 [, `% S5 C/ k' q
  18.     osKernelInitialize();                                    ]" K0 R/ g# b) q3 B4 P

  19.   g8 {* F( `* H6 V% q, p8 `
  20.     /* 创建启动任务 */% h( c9 u$ W$ ?' A1 h6 U
  21.     ThreadIdStart = osThreadNew(AppTaskStart, NULL, &ThreadStart_Attr);  
    6 r0 h6 b( l/ m" \3 c
  22. " _( _: ^8 f/ G) i# F' E2 M
  23.     /* 开启多任务 */
    - D1 Q7 z! e7 H9 E* a% }
  24.     osKernelStart();8 Y7 D& n. x$ }3 m7 n" ^

  25. & W& }7 _$ d* I6 W1 n9 R' T) o
  26.     while(1);
    : f  ]  r: [( w1 O+ [; T
  27. }. ?* H/ j/ ]* p  [" U9 f/ g9 x$ h+ y

  28. ) K2 O0 |( L4 `
  29. /*
    1 a) I! O# x0 t4 y" W2 N9 w( |
  30. *********************************************************************************************************
    * g# ?& K, E+ j3 P  y
  31. *    函 数 名: AppTaskCreate
    " f  ]" c" w5 H) A) x
  32. *    功能说明: 创建应用任务3 u, y: L4 L/ j& L6 D
  33. *    形    参: 无$ m& x5 q. U! Y# J- P6 l8 M
  34. *    返 回 值: 无
    7 R5 A, l4 d( e% t$ Q- ]; \& K: S
  35. *********************************************************************************************************' C+ F, d4 [! _) H
  36. */
    . y; P" K2 R8 t7 R; h
  37. static void AppTaskCreate (void)
    / L: A- G% V& y3 D6 s) O
  38. {
    ; u3 B* T3 l( k6 e- ]) T
  39.     ThreadIdTaskMsgPro = osThreadNew(AppTaskMsgPro, NULL, &ThreadMsgPro_Attr);  . {( J. [8 @5 v% Z* r2 J- A) B
  40.     ThreadIdTaskLED = osThreadNew(AppTaskLED, NULL, &ThreadLED_Attr);  7 |( Y& T9 k- Z( u
  41.     ThreadIdTaskUserIF = osThreadNew(AppTaskUserIF, NULL, &ThreadUserIF_Attr);  
    / r; h% R- m1 N4 J
  42. }
复制代码

, I, S! V3 V2 f1 V这里我们重点看下启动任务,主要做了四个工作:5 i$ B8 A7 _8 b) C4 x

$ j3 ?3 h( z. _) t6 G+ U  外设初始化bsp_Init。
" H5 N. U# C( Q, g4 n  任务创建AppTaskCreate。, l$ d# r) h2 F3 s+ D* z
  需要周期性处理的程序bsp_ProPer1ms,对应裸机工程调用的SysTick_ISR。这个的实现非常重要,这样之前裸机里面使用的API,就可以直接在RTX5里面直接调用。
& e* f* j6 y2 x8 h) H
  1. /*  d5 t6 Q2 v% \; C* [. E
  2. *********************************************************************************************************; a/ M( C6 {% P& q
  3. *    函 数 名: AppTaskStart6 Q* G" W" W  `7 b9 ^% s
  4. *    功能说明: 启动任务,这里用作BSP驱动包处理。
    7 I; K1 Z9 g' I  @1 B
  5. *    形    参: 无: e# {% |5 g7 C' F5 B0 Y3 ]
  6. *    返 回 值: 无
    / O6 z7 ]# a9 r, d7 R3 P4 U
  7. *   优 先 级: osPriorityHigh4  
    * ]5 F" B' D1 t% @: J  F+ t
  8. *********************************************************************************************************& y, W, B% ~9 e: S9 F
  9. */3 }4 t3 V2 ~! e- G6 ]7 a4 e' k
  10. void AppTaskStart(void *argument)$ n$ l4 v8 t* e0 G: [
  11. {7 L) T- d; q/ B3 `
  12.     const uint16_t usFrequency = 1; /* 延迟周期 */' f9 f1 |. J) C
  13.     uint32_t tick;& k" u, t9 w+ i% L- [- A9 b7 n

  14. + ^+ I% x% a8 J( R+ v6 V
  15.     /* 初始化外设 */6 e' }% O6 i: X; E; c2 G& {
  16.     HAL_ResumeTick();. T5 I. R7 H& E
  17.     bsp_Init();" B* {# h8 X+ W7 @/ V( L7 t% o

  18. ; o0 z* I. v2 s& H
  19.     /* 创建任务 */
      D, ^+ h" G& J( n3 [% [/ ^4 {
  20.     AppTaskCreate();% E; H0 E. \$ H8 }

  21. 8 E( y& v: U9 @6 W
  22.     /* 获取当前时间 */
    & y' h" v: s- Q) [" A! w
  23.     tick = osKernelGetTickCount();   r; h+ |, e7 {: V' ]$ W
  24. 1 f. `- w2 a) i( n$ `6 t
  25.     while(1)& m2 P  e  |8 T8 g! V8 y
  26.     {
    * Q7 D3 i% n* d" y
  27.         /* 需要周期性处理的程序,对应裸机工程调用的SysTick_ISR */
    ! C" i3 W: ^/ J0 r
  28.         bsp_ProPer1ms();7 L) p7 J/ `1 R# M4 Q( R, [2 J& B
  29. $ E" b% K& r- Z/ F& U' u/ H* T
  30.         /* 相对延迟 */
    4 E( N) G' w( T1 U+ R
  31.         tick += usFrequency;                          
    ( Z( ?4 X" |, r! c: T( l6 B" c
  32.         osDelayUntil(tick);% g) m# s0 T8 p. E* c
  33.     }) v# c' n+ m& Z+ g& Y# g
  34. }
复制代码
9 b- A) G- w- Y: L5 ~% j/ H5 g
4.14 常见移植错误总结

, Y* ~, ~& y' B6 X9 O0 L1 V常见的移植错误主要有下面几种情况:6 q5 V2 t: r* z9 x
+ Q: m- J2 u: o8 {9 H. ~( ^/ \
  编译后提示如下两种错误:
. a9 _; N3 U1 mError: L6200E: Symbol PendSV_Handler multiply defined (by irq_cm4f.o and stm32h7xx_it.o).
4 P% f1 }* K; e) e3 I, h2 U, q. v- Z- P) r
Error: L6200E: Symbol SVC_Handler multiply defined (by irq_cm4f.o and stm32h7xx_it.o).: O; P; l& X* w0 ?5 o& i: O

9 i: z0 O. t' c: |, K解决办法:这是函数重定义了,直接将stm32h7xx_it.c文件里面的PendSV_Handler和SVC_Handler删掉。3 @# |! ?/ |* |  w
5 |, r) u# E) L8 [7 Q" a
  提示如下错误
$ P1 y2 f% s: |# C. {8 j/ G2 o3 HError: L6218E: Undefined symbol bsp_DelayMS (referred from bsp_fmc_io.o).
7 M1 U( [# U1 c$ \7 P3 U5 o* E$ Q1 R+ v# Q* X  F
解决办法:打开bsp_dwt.C文件中的条件编译。" E, V3 J) l/ u$ i+ y3 _3 c: M

9 A& G5 M0 e( [( E3 G/ X/ T4.15 实验例程
/ Y. x# H% j- g; P本章节配套了如下几个例子供大家移植参考:1 K! B" I; b: b/ {* n

/ X1 _! y  _0 v( ?( \6 Z+ a  V7-400_Base Template" X' G1 \: r9 `' z, q/ o, A' t
裸机模板,方便大家添加RTX5内核源码。
+ T8 b% K2 ?: K6 b7 }( j4 @7 Y
* v4 n+ C1 e8 p; E1 a  V7-401_Threadx Kernel Template1 G$ @  y/ ]% X; t) s

0 D( I( X! U' T* wThreadX内核模板。' r% f' Z& ^+ J1 V2 H9 I

% U2 p! n1 Z1 ], W; H0 u/ }MDK进入调试状态后,选择周期更新:
2 N* E3 V9 x" ?. m+ R: u" N9 q9 G* D, k! M% ?
fdce9fac9944ad56faa0dd13307f6ebb.png

3 j$ D. ]6 D% R( w+ |
8 Y& g! J) G9 S5 c, E# P. T然后打开调试组件,注意和RTX4的调试组件位置不同:0 u6 @0 Z8 c  l
: e2 q$ T' U- X0 B0 Z
9482ce7367ba4d7cf08c73a56db28f75.png

1 m2 i) x2 P. y; `7 T' W/ K- v0 ^; i% X& a. z
然后点击MDK的全速运行,
+ N+ d5 n% \6 `( s) o0 d
" k. [) d3 T) X* D7 E
e3038a01781216611f96ae37d5bccb17.png

5 j  a- X5 g" {6 `1 X3 p; G( }: y+ n) p6 s$ U
至此,就可以动态实时查看RTX5的运行状态:; ?2 [$ z5 Z! Z
0 H- Q. l  I; e/ t! l
797f68ea76bd699fe11ce441076df4ec.png
" F0 M- [; W$ t0 W  t- y
5 l8 C* X# L. w9 W5 C
4.16 总结$ O% l! w' M- |( O' @$ H( ^
本章节为大家讲解了RTX5 在MDK AC5上的移植方法,移植涉及到的知识点比较多,初学的话,建议实际动手操作一遍。# _4 J# U5 I# S0 w4 G$ o

9 B' U6 [+ I6 D
1 ~6 b! ?! s/ L$ h/ ^. S) P6 K8 ~# e0 b9 r# Q8 Z
收藏 评论1 发布时间:2021-12-30 14:32

举报

1个回答
STMWoodData 回答时间:2021-12-30 15:31:46

好好学习

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版