4.1 初学者重要提示
; \, ^- d6 g! p1 |4 C3 m 学习RL-USB移植前,务必保证已经熟练掌握了RTX5内核的移植- H5 s% E3 o d( M$ J9 U$ }8 n; h: U
STM32H7使用MDK RTE环境添加RTX5和RL-USB,需要强制运行一次STM32CubeMX,因为H7已经没有配套RTE经典添加方式,而STM32F4是支持经典方式的,所以无需运行STM32CubeMX,详情可以看我们STM32F4开发板对应的RL-USB教程。
/ h" Z4 J2 n2 N, ^% A 本章配套例子使用STM32内部RAM模拟一个U盘,使用的MicroUSB接口。
; L' s8 t& L2 A' S) A7 E+ \3 V2 k4.2 移植RL-USB整体说明9 h/ U* O4 v- x) u
移植之前,有必要对移植过程有个整体的认识:
; a2 e9 ]5 l: S% \/ w: V, i
7 J" d7 R$ _% U5 o; z' V3 G 第1步,准备一个RTX5工程模板。% F7 {% k0 f3 o8 y* k' F
第2步,移植RL-USB。
$ h6 y, n# k9 r/ H 移植RL-USB是采用MDK的RTE环境直接添加。当前H7芯片使用RTX5强制运行STM32CubeMX,所以需要大家提前安装好STM32CubeMX V6.0或者以上版本。
1 I7 o) Z6 N, M& G v& Z& l 第3步,处理HAL库时间基准,MPU配置等。( o, a* G: }/ K6 S. { M
第4步,创建应用。
1 \. P y) b% t) L, C5 i总的来说,这4步就可以完成移植,下面将STM32H7的移植步骤和注意事项为大家做个说明。
" A$ `! ^1 z# a; D& {7 q3 J$ i) U) L( G5 H9 w
4.3 了解RL-USB模板框架设计
& Z* I6 r/ K. Z u4 ~移植RL-USB前,我们优先了解下移植好的RL-USB内核模板,方面大家后面移植:
" o2 E: ?6 n! ?
A. G: X' V2 p0 U0 M0 h7 q& \! ~
: |$ H* i4 H! V! Q; c3 m3 F
0 f; ]0 f1 ^$ l* ~% d8 o) S框图如下:
( Z8 G0 u5 z# T* C0 U! t, t5 C1 b: r( o. k* u, j) R9 _
# o' q- S' J! h7 R$ Y1 l; R
( G1 ~4 p1 f* y7 g$ X4.4 第1步,安装指定的MDK软件包+ s) j4 r( A! T
移植新版RL-USB需要大家下载当前最新的MDK软件包版本(如果有最新版,推荐大家用最新版):
# {7 t; W' E% |3 l$ U3 a G% F3 L8 t2 q5 v
CMSIS 软件包使用当前最新的:V5.7.0
& l3 H* l3 i1 r9 l$ z, y4 k$ T STM32H7使用当前最新的:V2.6.0
. P0 ~# I; u/ C' _: r% T: _1 x5 Q STM32F4使用当前最新的:V2.15.0
" l* z* l( Q/ }0 t) M) D% a' W+ C STM32CubeMX使用当前最新的:V6.0.x# V; ^# w; a2 e! r
ARM_Compiler使用当前最新的:V1.6.3- {8 K* |$ i. q" i
RTX5中间件使用当前最新的:V7.129 V0 t7 N8 d" i5 S! @$ S0 r4 _
& g) L3 E+ {) _% {9 h" v
; s: J4 X9 h$ m- Q
不管以后MDK的软件包版本如何升级,当前的软件包版本和以后的新版是可以同时安装的,也就是说可以安装多个不同版本,在这里可以选择指定版本:
, |: ?/ a1 A- h. z; H
( \, h+ w. v/ P. N0 c* h6 f1 J
* I8 W4 |: ?8 b/ }- |5 Y/ L5 D6 M' }9 \
4.5 第2步,准备一个工程模板
2 E0 p( t# M# n首先准备好一个简单的裸机工程模板,已经为大家做好:V7-4001_RTX5 Kernal Template,准备好的工程模板如下图所示(大家也可以制作其它任意的工程模板,不限制):
6 Z1 \$ m9 @5 { p1 Z. I
! f! K) o5 U1 ~
' p1 ^% L% w( }6 S2 H6 j( Z. v0 V5 @2 c! ~2 L1 Q. i) V% Q
4.6 第3步,添加RL-USB并配置
i! c! m, {- g看这部分内容前,务必保证已经熟练掌握了RTX5教程移植章节的添加方法。 p4 p& `4 P t1 [; M4 Z) m0 E
' x6 p. N; G0 [# `/ M4.6.1 RL-USB相关文件和驱动$ I4 ^7 ~3 M @
CMSIS-Driver分组中添加USB Device驱动:. ^5 B% d6 R% W+ o) R
1 i, ^* e' r* A5 O9 H# r0 E7 @' j6 d+ T' X0 p8 L
+ S- K; K% ?4 P
添加USB驱动:
2 @- u- r4 |5 P0 E% q* m: \* C3 Z0 B/ ?- ]! N& G( ?* G7 _; X
; z* }& d0 C# b1 I
& o2 E( H: G% S5 y* ~. o) U添加RL-USB并配置:+ Q1 h! I8 Z7 @) l$ x/ u- {6 d, G
2 |8 U. k" k* p1 I
5 A5 }& J; x4 Z# ]& c# w7 q) `& P9 A' O; g M- ?7 K* S7 |6 f
我们需要的都已经添加好,效果如下:
7 ?5 u; R1 b+ M; N/ X. u$ g, z4 F K. l
- s J' e q1 n& b- H" s! I, k
$ V5 ^( Y; T$ `1 W6 x红色方框里面驱动要隔离出来,隔离后的效果如下(隔离方法看RTX5教程移植章节):. i- w3 ? |* [) ]
; l5 i% M' Z. C5 b' T+ |5 a8 Z4 ]/ i+ P- J/ W
/ ]$ d3 p) p* G+ q" p/ Y4.6.2 重新添加被隔离的CMSIS-Driver文件- L2 N4 j4 w4 F+ O. |& \; y
将我们提供的程序模板中制作好的RL-ARM文件夹复制粘贴到大家准备好的工程模板中。( s2 V: \0 w0 c+ _
9 T0 y' c/ N; ~ y9 r' x3 Z1 R! g8 c: H& @; S
: { U: ]* ]/ m6 m6 n# T8 l# I3 V& n! eRL-ARM文件夹中有如下七个文件夹,其中只有RL-USB文件夹里面有文件+ X5 w5 t& }/ _7 O O
6 y9 M4 X P# Y/ ~5 S8 c% O
5 i7 j$ v* V+ Z/ \! k* E$ v
6 X) g" A5 Q$ v1 f% g4 s! a% m. g# g内容如下,这些文件是来自MDK安装目录:. y6 E3 v! t8 m0 B0 ~; ?1 n6 F4 p, p- K
' T. {* C% c% T5 B3 T2 ?* R% k& V# J0 e2 z7 H
6 V* K7 }( a; R* o" K然后将用到的两个文件添加进来:
- {5 H$ \) ], G0 K7 X! {2 F# Q0 C1 [) j3 W( i" K( S
7 Q" c7 a; W0 [
9 a* w' z B! r9 o
4.6.3 重新添加被隔离的HAL库USB文件
. N8 k& l3 p. ^" A4 P) \文件stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c被隔离出来了,我们单独在分组HAL_Driver里面添加。除了这三个文件,同时将两个pwr文件也添加进来:0 A" f$ C. J' i% S# x
# V3 @) Z9 w g2 @# G$ m) \
, K+ Z. R" ?" z- a5 G$ T5 I& [# F; \: Y; [0 \. z5 N% d; i+ G
4.6.4 RL-USB配置; w8 L1 H7 D, I/ T; G
添加完毕RL-USB所需的文件后,就是配置RL-USB,具体每个配置所代表的含义,会在后面章节专为大家讲解。* x- o- J3 r e7 Z+ B
: a) M5 ~4 O" [USBD_Config_0.c文件配置:4 }' E" T+ |2 u1 h5 P! A r
: x4 i4 ~$ \& F3 [, {' G3 K: t/ e l5 L6 L0 E5 m+ F/ _
0 x. `; l+ \# I8 o8 o注意这个文件里面还有一个RL-USB内核线程的优先级配置,当前是将其配置为:, L: s( @: Z2 x" V9 D$ `+ n5 G9 @
6 w9 y3 K# C& K# o' |! S4 fosPriorityAboveNormal:
3 D. T% Z/ h" J; T
& F, C' T% ~# O9 i
4 \9 T; L2 ]* [
! I0 Z2 K, k) r, dUSBD_Config_MSC_0.h文件的配置如下:
* O! c0 Q; T$ `0 c! L
/ J6 R U& x% \1 d
2 n: }1 t; K" p0 P; P" Y
8 C0 T; L5 P2 n3 _+ \$ }这个文件里面有一个USB MSC任务的优先级配置,当前是将其配置为:osPriorityAboveNormal。# z3 l3 n5 w+ d2 ?
# n/ Q. K+ r2 u+ G/ R5 O: ~. p
3 C- j! i) E. F0 [/ z5 c. g
2 k0 { G2 B. Z
4.7 第4步,强制运行一次CubeMX配置USB
+ n' y) y' s7 Z+ W3 s$ k我们这里要强行运行一次STM32CubeMX来自动使能RL-USB的相关宏定义,并配置USB接口使用到的两个引脚PA11和PA12。% p# z. T/ k; y* @6 n; f9 u& d
* p# N4 B. G0 I$ \$ g# y打开RTE环境,点击如下按钮:2 z( I9 A( _2 p) I8 X9 ^
8 e$ i. u* S" }" D2 H
0 }6 `5 f1 h K: x% c% C8 t2 _( a- X* v' c' R, V! f
弹出的STM32CubeMX配置如下:: j, z2 ^/ M$ @
! ^- k+ s1 N+ d' K+ ]
7 p. l5 j# Q% r! f3 L S$ F' q9 x6 p1 l& W$ d5 S
修改位置1:用于选择仅使用设备。
4 t" |' i. T$ j% n* k' E' x" Q) _4 b% V5 l0 @' B
修改位置2:用于使能USB FS中断。然后点击“GENERATE CODE”5 A9 s% a: r X; l5 f8 @% c
" ?4 `1 s7 q% o _
% T% |( J( c m: l( S0 U
, w" e* G( L% t+ L然后弹出如下对话框,点击Close即可,然后关闭STM32CubeMX。* I, B `3 ^, ]- G/ E
9 f; Q1 O U+ ]; {* D- q. u
% H, W, _* K1 l/ ~) r" y" X7 @
$ ~( m' o' T1 x4 u% v6 N9 k重新回到MDK,会有一个对话框,点击“是”即可:3 c. E2 [ h2 |* Y0 D5 S, Z
; i& l! [ y0 V/ m
. P9 D- r& Z+ Z: f$ e2 u5 v
8 r8 W& M- g' X& ]' ?( F; R+ ]配置后,就可以看到stm32h7xx_hal_msp.c文件里面对USB引脚做了配置。
* Y, L/ I; [3 f9 V5 Z& S. g
- l- \$ u. C, u9 e' m* o
5 o9 K, u& s2 ~# [' m2 }/ b8 Y* x8 e/ r" b7 B( W) O% x1 K ^( f. ]
4.8 第5步,修改文件USBD_STM32H7xx.C: w' Z" E8 N& x; f$ T
这个文件开头的头文件顺序要修改,否则编译会出错,原始的顺序如下:2 F; O& F4 e' m3 t r
' D0 q3 x6 R1 r2 A. I1 ]* S: {- #include "OTG_STM32H7xx.h"
' ?6 _3 @3 x9 G% X - #include "USBD_STM32H7xx.h"$ {# c. f8 ~# q0 F
" g/ ^8 E1 r& R- #include "stm32h7xx.h"
复制代码
3 ^8 l! G! c9 q& {8 k修改后的顺序如下:8 B: K8 A8 L3 K* x1 g6 ?; v1 ]
. B) @, H0 N& G8 Q- #include "stm32h7xx.h"
) U) L$ L' G# a: i: ^% A6 t - 3 b0 C' H7 ]6 z: Q. _6 u) E3 E
- #include "OTG_STM32H7xx.h", S1 H+ L* B2 ?' x" ^
- #include "USBD_STM32H7xx.h"
复制代码
: |, M% V8 U( R3 I4.9 第6步,修改文件stm32h7xx_hal_msp.c
$ p4 [. a4 u- k需要在这个文件开头添加一个变量PCD_HandleTypeDef hpcd_USB_OTG_FS,此贴变量会被USB的CMSIS Driver文件所调用。最好将其放在如下位置,防止重新调用STM32CubeMX时将清除掉:: q; Z/ z6 d$ z1 G, g S2 g
6 J& M/ K9 j) ~. c( q" z8 `) @" k: ^0 m
5 @0 q* Y2 R# V9 [
4.10 第7步,修改文件includes+ Z( d% {3 S/ |8 y) c
添加USB头文件:#include "rl_usb.h"8 C+ ?) }8 A8 ^ j, D$ Q) Q# K" y
4 p1 e. {6 W/ L3 Y
#ifndef __INCLUDES_H__$ a% `6 ]0 s d$ K+ e. Z6 c
#define __INCLUDES_H__
% \9 G. K3 q3 E: y$ B( ~
, w4 u% [$ G. D9 F \7 m/ c/ J/*/ H1 I* q- b+ P. j
*********************************************************************************************************
4 d# a# G v% K' t* 标准库7 W0 o1 E% p9 j/ v/ E3 I; d# S) U
*********************************************************************************************************8 @! [; M. {; q- [; Q
*/
) m9 Z% _0 D1 `; U& B2 Y#include <stdarg.h>
, F9 }7 f6 b/ S9 G, r#include <stdio.h>
+ V5 s$ }) }/ k# {, O; D4 P#include <stdlib.h>$ Y. }0 j% V. k' y
#include <math.h>3 N/ P. c: H" B, g8 _. N* o; t
2 V, t6 [. R; o& r
, V4 ?/ `% m8 x6 v# \$ m" F- G/*
: f5 f6 W2 I( K*********************************************************************************************************" Q5 s6 t1 G3 z p- i2 y- P
* 其它库
6 s9 }0 ?" I1 {; v' d*********************************************************************************************************
, q y& V8 G2 j" O*/# Q9 f* k* g+ W
2 {/ h% ]* n1 M/ @ q, i6 g
6 X/ h% V8 K7 p0 g4 D" f/*
9 K% D$ c: r. @; V! w*********************************************************************************************************
" r1 P9 S7 p% c5 \$ Q- |* OS和系统库 R& S# \; F* e8 O6 Y/ S
*********************************************************************************************************9 l4 P$ y+ j n# L4 o0 O/ {
*/
+ i4 P# u& q3 M#include "cmsis_os2.h"
3 O b8 Q) j, v* _3 a#include "rl_usb.h"8 b7 m3 v, S( O' T/ M9 V
! G. k( f) a' _& U/*4 ]; G# O$ f) Z# s: D3 D* |1 a- a7 E, E! }
*********************************************************************************************************' \% s/ i% k! Q) R
* 宏定义
) a6 f1 I0 e& Q/ o*********************************************************************************************************
# n+ p% r" m/ y*/5 H' B5 a z1 I0 D2 { K; G3 [
+ b* W, E! w$ r' A
" t0 _1 @! P% j: B9 I* O
$ U- R+ M- M4 g5 h {$ a/*) y; w, {% b% S- r& Y8 A
*********************************************************************************************************0 d5 c- _! f% V9 R) `0 d
* APP / BSP
, H: z- B( p+ Q0 H# Q& l0 h*********************************************************************************************************8 F M {+ r, _6 I
*/9 P4 v3 r: F: \7 L0 f5 ?
#include "bsp.h"
6 ?: k* f+ ~: E8 q: {3 I5 s. @/ p$ y3 Q% P* {
l1 K( v* o3 E% K; k# ~& X* s8 F! x {# Q. Y
/*/ M2 L7 e! c! J! H6 @ B
*********************************************************************************************************
1 w7 _% X- ?0 Y' l3 v9 L: T2 m* 变量和函数$ L6 h+ m8 Y* v/ y* m
*********************************************************************************************************
7 R2 x# d0 J4 s*/; ^/ {2 |, _ L7 m; F# Z
/* 方便RTOS里面使用 */8 b \* t9 A, a; |
extern void SysTick_ISR(void);, X9 }! v& }6 X3 u0 r, r. E% `4 \
# ~* y) W ~. @/ {* f, H2 F
#define bsp_ProPer1ms SysTick_ISR# [( v' q" ^+ P: n" V" M6 E5 g2 J& i
# a% E4 u5 O- B- i0 }9 k( ~/ N, u#endif( F- E" ~! c( }
2 I3 k, D$ P8 T* n! m/***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
: D8 b$ h3 A. b& M2 z* x+ Q4 @- P4.11 第8步,添加两个应用文件
6 K' r) b j6 n7 T/ o: H为了验证移植的USB是否成功,我们这里使用内部RAM模拟一个U盘。需要添加的两个文件在MDK安装目录里面。方便起见,大家可以直接从本章配套例子里面复制粘贴(这两个文件位于User文件夹),添加后的效果如下:
1 o' o7 O* B. Y0 }/ x8 X7 ?7 r8 z; T; t; Y
! O! B- j, U' H, ]( K0 O" ^7 _
& R' T: B7 l A# W* p4.12 第9步,添加头文件路径
" |, p1 k9 y; R& G" c添加头文件路径:- F6 ~+ h* T% \& r) y
. B: ]/ H2 J/ U+ u$ }! V# d3 S) f6 ^. V$ q# ?" b, Z* f
4 P: J! u4 Q& X p+ k9 ~
4.13 第10步,创建应用任务(重要,注意启动任务)
) S) i: [9 g# O) w* C! H8 ^% P s应用程序比较简单,大家可以直接复制本章教程配置例子的main.c文件中的内容到自己工程里面测试。主要创建了如下几个任务:8 S# f0 I: _( Q0 k3 @: Y
! c: s- W3 n+ H
AppTaskUserIF任务 : 按键消息处理。0 [0 {! P5 X( W2 y
! z* P5 ^5 _. |4 V% sAppTaskLED任务 : LED闪烁。
0 X. Z: E( b' t& G% ^: E4 w3 Q$ `
- }' l7 n' ]! z4 R: xAppTaskMsgPro任务 : 消息处理,暂未使用。
- D& I7 @' Z" F& E4 ]0 t1 { C& m6 F; |1 Z$ E3 T* M$ M+ X. ]
AppTaskStart任务 : 启动任务,也是最高优先级任务,这里实现按键扫描。
$ e& q; Q. A* l, g4 b' K1 E+ Z2 u8 W, y$ D B+ K ~% w
osRtxTimerThread任务: 定时器任务,暂未使用。
7 J+ N7 R/ B9 e" ~
: a- y1 t4 J1 ?9 g. f任务栈大小和任务控制块定义如下:7 Y) h/ U/ ?; v# r. K/ Y4 Q
, k1 N" W+ l5 f3 V$ n5 N
- /*
5 Z* h: `+ l0 T' @ - **********************************************************************************************************! k+ e2 p5 x: \2 B
- 变量, A; t+ E$ ^9 c* o
- **********************************************************************************************************
8 H/ T2 [1 c9 ~0 { - */
7 g( S" h) n; n0 Q* r - /* 任务的属性设置 */
: d# d! m: g1 r5 q - const osThreadAttr_t ThreadStart_Attr = + w0 U# d6 g2 r7 S2 O- u. h" a
- {
+ J+ a( B7 B, R9 d e9 o( Z* g - /* 未使用 */- W) S6 Y& n+ q9 I$ ]8 O9 s" V+ c
- // .cb_mem = &worker_thread_tcb_1,' B" l/ ]' i' Q" k/ S6 X
- // .cb_size = sizeof(worker_thread_tcb_1),# w4 Q- e; C3 l
- // .stack_mem = &worker_thread_stk_1[0],' z% k" @6 e; B
- // .stack_size = sizeof(worker_thread_stk_1),2 c" I- u; ]7 X7 z& S3 h2 |( _! L
- // .priority = osPriorityAboveNormal,& R9 Q+ F: g* i
- // .tz_module = 0
% ?! l8 _- j1 v. N7 Q N
# P9 {$ |; |; p/ e( L- .name = "osRtxStartThread",
P9 {4 D# }/ ? - .attr_bits = osThreadDetached,
4 b7 D% m4 j N/ H' \ n: p - .priority = osPriorityNormal4,
9 r/ E; b; |" D1 ` - .stack_size = 2048,$ n6 N- C4 E8 N0 B" M5 g, w
- };
4 e& ]) h3 e: J( P3 u
! R! I5 i$ Y" ?$ ?% f! w- const osThreadAttr_t ThreadMsgPro_Attr =
! m9 }$ o8 v7 x7 c+ Y" x5 j3 ~ - {
! G( w2 S; M9 R6 G# }' Z - .name = "osRtxMsgProThread",# q0 i/ q E# j2 n4 j& i& ~* I. \
- .attr_bits = osThreadDetached,
& A9 Q# c8 f2 J4 H7 i- s6 l - .priority = osPriorityNormal3,1 R4 r) I! ~: n, b
- .stack_size = 1024,
4 F1 a6 e$ b7 _& j$ Z3 f$ |* O - };" m5 @$ U1 h( K! U
6 p# X* C7 o8 P; z$ [% L- const osThreadAttr_t ThreadLED_Attr =
& N3 C8 T* U: C8 x5 o2 @ - {
* t8 n* I4 a- j0 V - .name = "osRtxLEDThread",+ n" {$ z: d6 D, v
- .attr_bits = osThreadDetached, 0 H, `$ D8 {) C0 J) L1 H
- .priority = osPriorityNormal2,6 t2 d7 K3 e% L; q+ ?
- .stack_size = 512,
9 M) Q8 u6 a0 A) ]0 v0 n# v# T - };$ z# Q- O. L4 l- V
- " S3 ]( Q. e6 ^, C* X
- const osThreadAttr_t ThreadUserIF_Attr = 6 A' B" q8 {! k) W, P# G0 R: R
- {
2 K8 |2 z! n5 u% D) \, G - .name = "osRtxThreadUserIF",+ a0 j$ {" `! \7 K3 k2 g1 |
- .attr_bits = osThreadDetached, 0 [. k. L+ c/ d: t; \
- .priority = osPriorityNormal1,
! M8 f! O3 z. h5 m/ r5 |* \ S: U - .stack_size = 1024,
0 f" T& G8 U' X0 v# A - };
复制代码 6 m. R/ o+ G2 \. `% o$ h
任务创建:
. b z9 M/ G/ p- @$ T9 b* V3 U# ^
4 ^# v% b1 T. Z$ C& w& y- /*
3 U& e# e, B3 p8 i+ p% I& ^ - *********************************************************************************************************
I# {0 e, E& j* A; J; \( z/ Z - * 函 数 名: main
1 w$ ]& w' U- ]8 U - * 功能说明: 标准c程序入口。
4 f3 }2 B' ^9 [( I3 ?) O - * 形 参: 无! ]8 N- o/ F7 W2 A
- * 返 回 值: 无0 ]5 c7 Z: P+ a! Q2 i6 @3 I C
- *********************************************************************************************************
* W4 W- n* b7 |! a - */
0 e: {+ v1 i6 G' A0 f - int main (void) / F0 E- v' J' n: P- _+ v8 J
- {
, X3 l2 ]7 i4 c2 [# f; b1 G - /* HAL库,MPU,Cache,时钟等系统初始化 */
% l* Q5 C4 C8 d1 i L! X0 ~, } - System_Init();
9 @5 R/ K' [3 k3 b, Z I
" M; v( J+ q: D- D- /* 内核开启前关闭HAL的时间基准 */
; t8 x) |6 B2 b `( f - HAL_SuspendTick();
' D# c8 J7 F) H0 h; H
6 h3 l( d" U* E) R$ n! k* G# `- /* 内核初始化 */9 }- x$ T$ M+ k! d7 y) E+ D2 v
- osKernelInitialize();
- T3 l2 l+ C, n! F" T. j5 B - 8 |- Y( p% A# v4 f' i _( A v
- /* 创建启动任务 */
! p% G$ _+ I3 i y+ h. m" S8 Q - ThreadIdStart = osThreadNew(AppTaskStart, NULL, &ThreadStart_Attr);
( m3 q+ D; L0 Q# r1 m
! w# @# @) D, ~6 H3 ?- /* 开启多任务 */
. U3 T' {( ?/ \0 R) V) [; D" t- | - osKernelStart();
- x2 O3 H d4 F3 L; s7 F# X
; P/ A L) O! k9 u- while(1);
" c1 R( x* I% }5 O- \0 w3 Q: \0 `/ q - }/ ^7 e: A2 i! K5 K! ^2 T" T
- P" W$ Q" G, p( b- /*; U5 }6 @! p A+ X1 d, C3 m
- *********************************************************************************************************
; q& A6 W9 o$ Y. n7 L8 I/ } - * 函 数 名: AppTaskCreate
; \8 H: g5 W* j* M& q - * 功能说明: 创建应用任务
1 c/ w I# c. A1 u% b - * 形 参: 无9 Y% v9 b' |- j: u
- * 返 回 值: 无
! R" }' \1 O a9 e( |1 S2 @( I - *********************************************************************************************************
: n9 l) O6 r( B5 p+ X - */! @1 f& j/ m5 u: E" I, c' ^
- static void AppTaskCreate (void)4 g5 r( u. n& J+ I* {2 C
- {1 ]- l3 I# |6 w& j$ a$ A+ E# G
- ThreadIdTaskMsgPro = osThreadNew(AppTaskMsgPro, NULL, &ThreadMsgPro_Attr);
. U1 i: k: P z" i - ThreadIdTaskLED = osThreadNew(AppTaskLED, NULL, &ThreadLED_Attr); ' Z9 n2 Q% x6 A8 w2 v& n
- ThreadIdTaskUserIF = osThreadNew(AppTaskUserIF, NULL, &ThreadUserIF_Attr); % e0 r. O* K+ A( m" Y8 D
- }
复制代码 4 a- A1 ]5 H! F6 I Z' v
这里我们重点看下启动任务,主要做了五个工作:0 [' i) `7 a7 x: k" P( {
8 A: r+ s4 m% t% k3 G 外设初始化bsp_Init。( _& B3 h6 P$ m2 _
任务创建AppTaskCreate。
& s3 x+ L$ R6 W7 W" m# }. E 初始化USB并连接电脑。, s! i' O l H9 {2 _8 g; `& ~% K
需要周期性处理的程序bsp_ProPer1ms,对应裸机工程调用的SysTick_ISR。这个的实现非常重要,这样之前裸机里面使用的API,就可以直接在RTX5里面直接调用。0 q) N) ]5 }3 ~0 Y. Y! k1 j. [7 ?
- /*6 T+ U, O1 u/ D
- *********************************************************************************************************
: D+ m! @+ r7 r F - * 函 数 名: AppTaskStart9 F' N0 t- f; H& T' L* B
- * 功能说明: 启动任务,这里用作BSP驱动包处理。
. H, j# k( g4 `3 w - * 形 参: 无- n! h4 i; U/ t3 F( z0 l, r# h
- * 返 回 值: 无
{6 F7 b* w% I4 ? - * 优 先 级: osPriorityHigh4 , o0 q. p0 `1 P- |4 P# W
- *********************************************************************************************************) s% g2 s% K" i4 {
- */
( E/ A6 z1 h, u8 b' T$ W - void AppTaskStart(void *argument); S; l. x( w1 D. p/ u7 h+ G
- {
$ m8 p* l' k' N9 ^: { - const uint16_t usFrequency = 1; /* 延迟周期 */
& a. o0 ?/ b% | - uint32_t tick;- P( s8 E, U. t! M: k
- # \1 l, w' [& j/ S; F
- /* 初始化外设 */
6 l& D1 j- M7 P' Y% i: ~ - HAL_ResumeTick();, r/ ]$ g5 K2 x$ N' \6 D! I
- bsp_Init();1 H/ F9 v! p2 }4 K& C
- 3 }5 B4 z! G6 i [
- /* 创建任务 */
' i/ t$ h8 Z W - AppTaskCreate();
2 z' \ N7 w7 Z0 @5 m. L
9 m; ]5 L1 M, k: k1 L, x- USBD_Initialize(0U); /* 初始化USB设备 */5 m9 k9 _' W' X) J4 L& o2 K. s6 M
- USBD_Connect (0U); /* USB设备连接 */& F& e7 a" r9 l; h* t. ?
- 3 a7 {0 p, N! g, j5 e
- /* 获取当前时间 */( d2 D- Y' w( g4 C/ w7 [0 X
- tick = osKernelGetTickCount();
- X' K' _ V. V" K8 D3 d; b4 x
+ `# e( `0 J3 K$ i- while(1)3 r) W2 z) ?5 `7 c
- {% V% ]2 P& z0 `! Q# y% c" v& ]( H
- /* 需要周期性处理的程序,对应裸机工程调用的SysTick_ISR */
/ u; \5 T, e2 _- ~0 i" x3 W- [ - bsp_ProPer1ms();
( N" w2 [) b8 l1 S; @ - 4 m: q5 r% q$ z
- /* 相对延迟 */
/ z3 \6 A! s8 y5 f7 x3 @ - tick += usFrequency;
5 _" F w- C+ r l' I7 \7 b - osDelayUntil(tick);
( V) n# G! T1 \/ a2 Y6 ?4 p! z - }) O; q* a" b( Q& m
- }
复制代码
3 y8 f+ g0 o$ I+ N4.14 常见移植错误总结: t% g9 B7 R" W! _) p; W9 J
编译后提示如下错误:
0 b7 U$ V# i: _6 ^1 Jerror: 'Driver_USBD.h' file not found
3 a2 g9 |. s- j% s/ n9 f0 g1 B
* W! l8 ~ F9 I解决办法是将新版 CMSIS 软件包里面 Driver 文件夹全部复制到自己所创建工程里面的 CMSIS文件夹下,并添加路径:
& D3 V0 U6 A3 J, V0 h! g2 i/ ^$ a4 j8 Z+ X( E
& |0 ^2 l5 {% N
G: P, c0 u4 A+ [6 B$ p 提示如下错误
1 X7 |2 m4 F) T/ j, L& sunknown type name 'HAL_StatusTypeDef': d6 ` a0 t, r' w
D/ _& L& h9 g H( N6 k: r" X解决办法:本章4.8小节。& Y1 K7 W. x) B+ u3 y5 C y7 A; s$ D
. @! M* [ x0 c9 n; c3 M! W4.15 使用的MicroUSB接口并注意跳线帽设置6 ]# R' ~1 i! }4 N7 m7 S9 H
本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:+ F7 G5 i( I5 x
6 f. D/ G/ @ A7 j0 f
7 g5 S1 ~' R. e' l- u
1 e$ m0 D3 H. r, I) J1 [注意使用的是MicroUSB接口:
( D' l* o) r; A* f& O2 x3 I9 b+ M/ K% X/ _7 y
: [; `/ H3 u, ]. ?& L7 p
0 ^6 {4 k* {* m# F. H; ^
注意板子左下角跳线帽的设置:& \9 Y2 L/ Z1 L6 B1 g* P6 D
# v, ?/ V, W) E/ V' P. J b/ g
4 k% K& J0 ^2 \/ m. M7 u
7 ~" n7 b8 U; a( u1 X r# C这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。: N+ x9 E% H/ `; `# a3 t4 B
4 j; E, e# D0 e7 W+ i
4.16 实验例程8 @. j& y' r# n4 a- Y. K
本章节配套了如下几个例子供大家移植参考:6 {+ P! d$ J, [1 i1 i6 S" j3 O0 V! j
9 ]) P$ `0 z9 b# I0 u, z V7-4001_RTX5 Kernal Template
$ Z0 |8 w- y7 f. g2 _0 v# _5 P: }6 Y8 N0 o0 p0 W9 ]- o
RTX5内核模板。
* q$ p1 v0 f% G. N9 G- ]* P8 x7 Y5 Q$ D/ C, P2 L
V7-4002_RL-USB Template
" a8 R" n# n( }9 Y, C0 o
- H0 c$ p) y/ c- e. q) E/ E4 |( WRL-USB工程内核模板,使用内部RAM模拟了一个U盘。2 O/ A- x3 @0 d* {2 _2 u
, [0 c# t: o/ S6 F/ y
MDK进入调试状态后,选择周期更新:/ ]' |* [6 Y; ~8 Z$ I
3 c2 J& W7 z8 }( K' h$ D% \* _6 i) _1 v. \/ [5 E. z
+ b+ W% k; W$ I7 s2 f
然后打开调试组件,注意和RTX4的调试组件位置不同:
q) L- L4 z1 h1 h/ \1 ~% |4 j- H1 g3 x1 \9 h
) ?8 k) r0 c) z7 F
# @( ]/ G3 Z' y4 }; A7 ^然后点击MDK的全速运行,8 C0 x$ K8 P3 b f: K# @* S0 `
0 l! i4 U2 e: Y
/ u' G" G! K; w n2 z% s# B3 m+ @* \
至此,就可以动态实时查看RL-USB的运行状态:) z6 D: k. ^, d
$ t8 @, d6 S. }! s, K7 C
) M; `+ Q+ z. N: ?
8 Z% l# A a+ N$ p5 L2 z2 ^4.17 总结2 @# m0 f2 _' L+ i r# ^5 Y
本章节为大家讲解了RL-USB 在MDK AC5上的移植方法,移植涉及到的知识点比较多,初学的话,建议实际动手操作一遍。
. B8 @/ e* {3 w& K* L6 h6 t& p1 |/ C
% S7 K# K% A7 r% ]
2 }; ~. I* e$ q/ D7 L9 R
$ z5 k! {% o; _
0 Q) [: v/ W$ V( P$ V5 f, U6 O |
好好学习