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