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

【经验分享】ThreadX USBX协议栈移植到STM32H7

[复制链接]
STMCU小助手 发布时间:2022-1-1 19:00
3.1   初学者重要提示
7 o. x9 N6 J! d# B1、  本章使用的ST专门为STM32H7提供的软件包' S) [, d% g2 \2 j* K5 A, [: `& F" c& H
( v( U9 ~- J: i3 ]: i( n5 N: f( ?% M
2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。
% n, O3 t; Y  s' z8 Q* q3 {2 R  g* m0 C9 A. L; h/ n
3.2   USBX移植步骤
5 e8 h9 ?/ R# L, ZThreadX USBX的移植步骤如下:
1 \- {( H, B9 o; X  }
: }+ l+ ?) S; T, [/ L  z5 R3.2.1      第1步,了解整体设计框架) N- j- x% H0 H  \
为了方便大家移植,需要大家先对移植好的工程有个整体认识:
8 m, e- i5 O+ j& I* Q8 p$ t7 d5 |1 Z
556edb9b3bb947f5b69aac84272def1d.png

: S9 [; U6 F9 |1 }/ W, G) {1 A5 n2 Q, J% Z( d
7 E" e. Z% D/ }: s. a, I5 {
3.2.2      第2步,添加USBX和USB驱动到工程
! I4 A- |9 Y* }7 `4 a这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。" P& m2 v' T2 T

. }- \% F3 J$ \1 N6 e  模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。8 Y0 D/ J7 D- x2 Y  v+ x% X
配套例子是放在\User\usb文件。
" R. C( S% h- |; r! D% x2 b/ s! X9 X0 ~3 P$ g; v: l' Y
  USB驱动文件stm32h7xx_hal_hcd.c,stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c。) v2 S  Y  _& `) R' t
这个是STM32H7的HAL库自带的。
. p3 M; R4 F3 s( y1 I. n( e8 _# Z
  USBX相关源文件。
1 [) r; |. K5 Z  k$ F8 @, A- J" O大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在\USBX。
5 J' _( k5 X1 {/ L, ]
0 o+ G; R0 H$ _3 W) e* g/ o3.2.3      第3步,添加工程路径1 u% n7 a' J/ t% V2 M
大家根据自己添加的源文件位置,添加相关路径即可:
" G. s" \! P9 d+ w# G+ E6 {' r2 z5 C+ M) @9 X& _4 m) I
7d4292e15d424274b8e5aab1d6cd32a9.png
& G  G" v1 z( v' {- }  k

" X; j" V$ q$ v2 O2 ?, I* R, E
9 p7 F* k; N* j* n
% k& D8 F8 K% n8 j1 X) W6 @3.2.4      第4步,禁止掉添加进来一些文件

" h2 `9 U  `0 `8 [4 V3 R/ X; G* x之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。
  l! Z- F7 P, U) w2 S
, g+ S$ b6 D/ g/ q* j# ~6 m
418a71e2dcbd48a199034bbf6765d9fc.png 4d161770a4734368b6881fe1ed982494.png

2 Q+ n% l1 Y* Z+ t
* X4 S1 h# Y: r5 [
696837e6177b4f3caa286c6913cf4ea3.png f052ff2297b4462daa7186e7fc3b6ab8.png

8 I3 ~# d6 [0 @' v8 Q5 T# L3 t1 s! o4 d' C' h. [' |
0dadc8e05ea349beb4e04a737e86ed07.png
: T8 o* x5 S# O. d2 D/ A

& a2 D3 k2 u" t5 H# A) H% s禁止的方法是右击此文件去掉如下对钩即可:7 A) P& p5 _+ u. p! q# k. [

) A# V6 B& j% p
4db1e499f0f7422f9e522bf1e7bcecfe.png
) j" G+ C1 ~3 ~9 t' d! Z

' j  P' a* X! f7 q/ ]& p( E) P2 g  `6 p8 p9 `7 w" R# o

* a! Z/ |' S+ P4 c" s5 T" {& o3.2.5      第4步,配置GPIO和时钟: Q$ a6 `# i3 ?" ^; H/ B9 Q
USB时钟配置在bsp.c文件的函数SystemClock_Config里面:/ Y) T7 w# _" G8 A

2 S. q' G  P# p+ f1 K5 W6 w
  1. {
      Z$ H' y# ?  \+ ]0 M
  2.                 /*/ k' g& V7 K8 g6 b
  3.                 USB工作需要48MHz的时钟,可以由PLL1Q,PLL3Q和HSI48提供
    % Z2 f" D; F0 W" q, Q
  4.                         PLL1Q用于给SDMMC提供时钟8 h- J6 s& ^6 o) N
  5.                     PLL3Q给LTDC提供时钟,也可以跟USB共用,不过得更USB设置相同的频率才可一起用。1 N) G& X6 T3 E9 }) D* g5 k- s1 C2 o! T
  6.                     HSI48可以供USB独享,就是精度不是很高。
    ) p3 l6 ^* Q- X( y
  7.                 */
    5 _: A5 X% \% h
  8.                 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};* H: [4 d, ?* D- ^" W/ s
  9. #if 09 J; `; ?& S; Y% q9 S# @" C
  10.                 /* PLL3-Q for USB Clock = 48M */' f2 q& r  {/ z# V
  11.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    - ?; \( y, J( L9 F
  12.                 PeriphClkInitStruct.PLL3.PLL3M = 5;* d; F, \7 |) U5 v+ C. f
  13.                 PeriphClkInitStruct.PLL3.PLL3N = 48;8 G/ X1 ?/ O2 O- ~0 O, Y
  14.                 PeriphClkInitStruct.PLL3.PLL3P = 2;
    # Z' K  c" T( @9 ~& @0 ?; I
  15.                 PeriphClkInitStruct.PLL3.PLL3Q = 5;- j: Z2 Y. O1 c% V1 K
  16.                 PeriphClkInitStruct.PLL3.PLL3R = 2;
    % m1 ^$ Y  O' y( j' F* b9 v7 N- V  ~
  17.                 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
    2 J2 [, T) ?4 B$ ^& ?0 C
  18.                 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;- Z0 _% j8 I' g# b
  19.                 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    0 d% E- P- R$ I% d) {  U. d
  20.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;0 d! a. |4 j9 O5 V! O
  21.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK)' x& n+ `9 n8 [1 i& u
  22.                 {- x) G. {$ W0 @" g1 G
  23.                         Error_Handler(__FILE__, __LINE__);( d6 w6 t0 a' W
  24.                 }        / h3 L' M: A: ?
  25. #else$ a1 j$ a4 |* T, G7 F
  26.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    + i! m/ X3 m. K  z: p$ |) e
  27.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
    , R0 l1 ^( A  Q& F& e8 e1 C: @( G
  28.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    ! Z! V5 i4 {$ U# m- P; u; I
  29.                 {' d. q! L1 Q  Y2 |8 W3 M5 F, _* h
  30.                         Error_Handler(__FILE__, __LINE__);) d0 K1 s; ^8 N3 I
  31.                 }4 f2 e, @% h; L+ ]) n3 L
  32.               HAL_PWREx_EnableUSBVoltageDetector();  p" O$ O0 d- s" Q8 f/ ^
  33. #endif
    8 e' Z5 P# x7 \, k& |& i- j' M. Z
  34.         }        
复制代码
# a: [7 y6 C: O* w7 z7 g$ j4 V
USB的GPIO,NVIC初始化在demo_sd_usbx.c:
, N) |. u2 S( k* B: \. }6 t& e0 k% A1 _$ c. t% `
  1. /* 配置USB GPIO, NVIC */- l5 w8 I+ E* B7 d* b
  2.     {
    ; F% ~; _8 i8 ]. D, i* I
  3.         GPIO_InitTypeDef  GPIO_InitStruct = {0};
    / O4 b0 g& O9 A, ?
  4. : B( W& A, d1 C1 y
  5.         __HAL_RCC_GPIOA_CLK_ENABLE();
    / V8 n3 n4 {6 J3 C( H
  6. 9 v( U4 B; L# @& y7 k6 o
  7.         GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);! f2 |. _; D8 o; O" X! N
  8.         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    ) P$ \% c" o9 D4 Q
  9.         GPIO_InitStruct.Pull = GPIO_NOPULL;
    ' y' w0 M, q5 M$ v+ K- j
  10.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    / y3 l* x) ?# o% F
  11.         GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;" Q9 P  M6 [. G. z; H! s) E6 V3 E
  12.         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);8 L9 o2 W( P* m- G: B0 v

  13. ) }' O3 d* I  b: \( u' Q' M
  14.         /* 使能USB FS时钟 */. P. w6 O, j3 e8 E
  15.         __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();
    5 a+ i1 F" Z# O) G9 X3 j5 C

  16. # g$ S$ l  E# A1 b$ l5 {$ M
  17.         /* 在睡眠模式下禁用USB时钟 */
    1 \7 a' ]. E8 @0 w1 P
  18.         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();
    6 p) |- g* i- @2 ^" h

  19. : Y; ?  @: m7 L; ~- V/ Z7 I
  20.         /* 配置USB FS中断 */
      h8 M2 s' v' _, ?
  21.         HAL_NVIC_SetPriority(OTG_FS_IRQn, 0x2, 0); * l5 F; T/ t9 ^4 l) P
  22.         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);6 r8 E. g, _3 h1 L: r$ ]
  23.     }' [3 M- C. P4 p9 a) f! F
  24. + V; h, b( F6 F! T
  25.     /* 初始化USB */
    5 \, @6 d% w% `& p; i/ b
  26.     {8 R! L# w( j" o$ P" A
  27.         HAL_PWREx_EnableUSBVoltageDetector();8 x) m6 f# `8 I' A, q( o1 i
  28. ) H+ W" |3 Z3 ^6 Q$ [2 U
  29.         memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));; t* d3 Y, m. M! r# k
  30.         hpcd_USB_OTG_FS.Instance = USB2_OTG_FS;# I5 p$ T0 U. D; D8 V% W
  31.         hpcd_USB_OTG_FS.Init.dev_endpoints = 8;
    9 ?# d/ {& a& E5 Z
  32.         hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = 0;
    ; {- O1 l# F, i$ j( P- D
  33.         hpcd_USB_OTG_FS.Init.ep0_mps = 0x40;' |! y/ r+ X2 N4 O2 _
  34.         hpcd_USB_OTG_FS.Init.low_power_enable = 0;. p4 q, A& l: J: }% A
  35.         hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
    8 V  J1 N4 r( M
  36.         hpcd_USB_OTG_FS.Init.Sof_enable = 0;: M" z- P3 b% g
  37.         hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;( M8 c* \! ~$ C8 Z6 K
  38.         hpcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;8 w+ e7 S8 H8 [1 p1 h4 p" W
  39.         hpcd_USB_OTG_FS.Init.lpm_enable = 0;6 R. n& N& p/ C; t/ k0 ^
  40. ' _# q; r& L% R
  41.         /* 初始化USB  */
    , C, p& f- e* W" C
  42.         HAL_PCD_Init(&hpcd_USB_OTG_FS);. W6 F2 z* z: i3 \

  43. ) p! k5 e; V5 v- b* m0 D
  44.         /* 设置TX FIFO和RX FIFO */
    0 n( u1 G- M' P( e1 ?7 u
  45.         HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 1024);( X4 l/ y( j3 L& Y0 j  j$ Y' @
  46.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);6 k/ M3 N4 y9 W) a- e* R3 q, d
  47.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 1024);
    $ l0 W. h( L6 V

  48. . x; W4 a2 V7 u7 j
  49.         /* 注册STM32到USBX协议栈并初始化 */1 K3 g- i4 a% t" O9 p" n1 s2 w
  50.         status =  ux_dcd_stm32_initialize((ULONG)USB2_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);: H! V5 d2 e& b7 u: z4 U
  51. 1 w2 C- K4 f+ B$ b% l
  52.         if (status != FX_SUCCESS)
    # R% s2 B( L2 L. F4 f, ]
  53.         {1 e( o' |+ A' f7 z2 b: W9 x
  54.             return;2 U5 r( e, I6 E' x+ s6 U4 }
  55.         }
    % I& }/ f  V# r, e& q

  56. " ?" y) ^* X/ o# H% I3 c
  57.     }
复制代码

, k/ Z8 J% N" Z9 C3.2.6      第5步,MPU配置
( V8 _, u% X& g6 @+ I! k1 C8 Q
为了方便大家移植测试,我们这里直接关闭AXI SRAM的读Cache和写Cache(这样就跟使用STM32F1或者STM32F4系列里面的SRAM一样)。此配置是在bsp.c文件的MPU_Config函数里面实现:
. |: y6 {5 Z; q  `2 Z; O4 W5 X( \' w3 W+ {% n4 ?" k1 n
  1. /*
    % f- B) {' ^6 k! w; L
  2. *********************************************************************************************************
    ' _# i% Y/ H6 o$ h& Q6 x% ?
  3. *        函 数 名: MPU_Config( }2 U- T1 b. L) C
  4. *        功能说明: 配置MPU5 I6 j. O9 r) O0 r' Q. ^9 J3 D
  5. *        形    参: 无
    6 y" G6 y% x$ u# \5 N+ ^
  6. *        返 回 值: 无
      Y* ?  \9 C2 B0 \9 e
  7. *********************************************************************************************************
    0 N$ W; C8 `9 z6 `
  8. */, y) W9 ]- Q: J
  9. static void MPU_Config( void )
    . W1 f$ v8 v0 [. e. N* x1 e
  10. {$ a: ^& t8 \; z# e) a) B
  11.         MPU_Region_InitTypeDef MPU_InitStruct;3 g* Q; Q0 ^) F6 C9 o
  12. " m' h7 X! r' \8 S: ]! t
  13.         /* 禁止 MPU */& w0 e* Q1 r. L) s. s, |/ ^5 X
  14.         HAL_MPU_Disable();( d7 G) j6 `# ~8 t' c& \2 a

  15. 0 u9 t* L% t1 u( F5 _- D) r% `
  16. #if 07 _9 Q# t: Y! q7 H; X
  17.            /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */4 ?* r  a- l# ]  k" d: \' r
  18.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    & y7 l3 x0 P  V3 W# _" R
  19.         MPU_InitStruct.BaseAddress      = 0x24000000;8 y& {1 I9 _1 l5 w- f$ M' y
  20.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    , K- G2 I" f" x7 \6 ^, D
  21.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    $ Q( K6 T  R, a4 N, G3 e
  22.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    ; ]) E9 m4 i* p
  23.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;) x* P5 ], e! {" ~/ J
  24.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;# y5 j8 o0 e9 A+ c  G
  25.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    / N- D2 V, R/ T5 z* U
  26.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    " N5 ~) X3 c3 e$ @" B
  27.         MPU_InitStruct.SubRegionDisable = 0x00;
    : o# I$ `) Q8 ?! |) `
  28.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;5 w" x* \6 W6 i2 M1 W) L! q

  29. . f: O0 {2 _7 B; R9 b
  30.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    8 t& q: A  i. B" M, T
  31. ! u5 Q+ E- I2 |' ]
  32. #else  E+ u* U* y! y4 t- B
  33.      /* 当前是采用下面的配置 */% B. p5 w: v+ l5 i+ {$ v2 ]8 [
  34.         /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */
    8 U, Q1 ^* ]3 {: D/ O
  35.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;: ?' C% q" f! B$ Y
  36.         MPU_InitStruct.BaseAddress      = 0x24000000;0 U$ i- O5 l; O) J! V0 r) X
  37.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;" W' G. C; h/ v$ [+ I) e
  38.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    $ Y7 L  p- n& {  x- q# W0 S) A
  39.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;" h& E0 y/ d; l3 L! b
  40.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;* d! \# S1 X, F- D5 p3 f/ H
  41.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    , ~8 b- s% [" U. F, P! }
  42.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    . |* u( X5 L1 V3 I3 T4 @
  43.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;! h, r- n- H% U, |: [2 w2 n1 \
  44.         MPU_InitStruct.SubRegionDisable = 0x00;
    & E( ?$ x: v# F( Y: a8 Y3 K' J% g( E9 ?
  45.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;! [* W* j0 V% e, b

  46. $ a8 N+ }: `( x& y4 j, d! q
  47.         HAL_MPU_ConfigRegion(&MPU_InitStruct);* X# a: i& [% e: Z
  48. #endif; S# W  `. w8 P
  49.         /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */
    + z4 |* ]* C  a% p
  50.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    7 B& M4 \; ~% S. |; s1 ~7 v/ A
  51.         MPU_InitStruct.BaseAddress      = 0x60000000;
    7 v# E5 C4 d" G7 o2 G
  52.         MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;        4 }; O, m( H- b5 l' E! w! q: m
  53.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    2 @: h5 ^3 f' H2 ~
  54.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;+ T4 E; X! [9 c4 X, W4 e
  55.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;/ u+ Z3 Y  U4 J
  56.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;, {0 P! ?8 C( m" o+ t9 r
  57.         MPU_InitStruct.Number           = MPU_REGION_NUMBER1;- h6 _. z( o+ V. Z4 H8 u
  58.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
      [! ~0 B9 m, m) T
  59.         MPU_InitStruct.SubRegionDisable = 0x00;
    ) g5 n9 B4 A" P% e2 i& X
  60.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    ) O5 M2 C' o# d  J. ^9 T. N3 d
  61.         
    / y* l  H  E# L% H( E( l1 E% V
  62.         HAL_MPU_ConfigRegion(&MPU_InitStruct);% R1 u) U0 Q* M3 S- {1 p2 [
  63. : e! x6 a, V/ ?" [( q
  64.         /*使能 MPU */( i$ |  P$ Z2 k; ^. i/ ~5 v  o
  65.         HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    # ?# o7 `; x" E' b6 v
  66. }
复制代码
& s' v; c, c( \* ]& n
3.2.7      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)

! G% C  J, z, }! H) c5 W) G& `2 E# P% MUSB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可% i: ]: K0 p6 H9 g8 w8 U
7 l0 f9 U: t& J( t
特别注意USB中断服务程序别忘了添加。# m& {4 H$ I$ L5 N

( {) p8 V+ n  e, e* F, w3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明* D, ~: |% E- }
这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。
; |0 H6 l6 }6 f, f, L) l( c% _8 t; J# U$ p, @4 @
3.3.1  状态函数app_usb_device_thread_media_status* s! q/ V6 D  n( E& B% L. }9 W) `+ ]- ~
代码如下:
8 Q! r/ E' Z6 t0 C8 G  o- P2 y6 e8 s8 m! M: v. S# P1 c
  1. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
    ( P- R- f( q1 S  k' H
  2. {* T  Z7 Z- Z5 X# j3 k+ ^
  3.   D  `. p3 S& o
  4.   /* The ATA drive never fails. This is just for app_usb_device only !!!! */8 ~4 G# s, T1 U, s6 B, J1 P
  5.   return (UX_SUCCESS);
    . l, z; p, o, a* J9 f  Z# {% l8 [
  6. }
复制代码

. J; i! p( d4 {此函数主要用于获取SD卡模拟U盘的状态。7 `) w. t9 \* ?; N- I+ ~
- @# \+ H' C" D5 h) d: g) E3 R
3.3.2  读取函数app_usb_device_thread_media_read
1 y" V8 ~; o  o: [  t
代码如下:
( f9 G3 I; F. s8 l: O8 c! }
6 H- [& ]' P7 I% X7 ^
  1. /**
    $ C) x' D$ W  e) @
  2.   * @brief  Function implementing app_usb_device_thread_media_read.1 q' A! _4 J. A+ Z& \8 k& k# w% I
  3.   * @param  storage : Not used2 }6 w; m3 c% V
  4.   * @param  lun: Logical unit number9 N+ y8 d2 q" I4 K
  5.   * @param  lba: Logical block address
    % u8 B3 T! h8 c; p8 f) _
  6.   * @param  number_blocks: Blocks number: D+ G( }* _' b6 ^$ \) C
  7.   * @param  data_pointer: Data9 |0 s, O7 s/ G; Z# W4 f$ d
  8.   * @param  media_status: Not used
    7 p' Y8 M9 |# e$ |! A$ m( g0 [# n
  9.   * @retval Status (0 : OK / -1 : Error)
    " ^+ `' }# m. ^7 J$ D
  10.   */8 c6 X% F1 k; Y8 ]1 H( u# N, P
  11. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,
    6 Q! z, e# n, }! S& r
  12.                                        UCHAR *data_pointer,* L: l) `: D8 j3 {) H  ?
  13.                                        ULONG number_blocks,) C; g  e, l  S0 d
  14.                                        ULONG lba, ULONG *media_status)
    0 M1 u8 v' {# C! |& n  C
  15. {
    ) Q( B* D0 Z% C
  16.     UINT status = 0U;
    $ o2 S+ Z1 w" M, |$ B

  17. 2 b. ]' j& ]( V( \! S
  18.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                        4 u0 N" s+ Z- R5 V! }' s/ P+ v
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);' O, R8 E, ~, Q# U9 f
  20.     status = check_sd_status(0);   
    # g+ S9 O7 s8 c+ i9 x+ @/ j
  21.     return (status);
      l  Q- E- N& P0 J# J
  22. }
复制代码
* n  q# o6 R9 G: \6 ^. M7 Y' u
用于实现SD模拟U盘的读取功能。+ \2 z+ Z1 q8 z& U. x
' v- E6 [! |: Y% R+ U, R5 R
3.3.3  写入函数app_usb_device_thread_media_write
$ C- g# Z( Y3 ?  F+ x代码如下:
$ B3 g  W, D  U6 x
& ~0 }2 Z% o5 F( C/ y* W
  1. /**
    8 r) h0 \& T8 M; u6 P. |" z" k2 c
  2.   * @brief  Function implementing app_usb_device_thread_media_write.
    ) q0 P( v# n# d+ d
  3.   * @param  storage : Not used# U3 R/ {$ ]$ z& n/ L# E
  4.   * @param  lun: Logical unit number
    ! c& d) B! R- R( S1 ?$ N! k
  5.   * @param  lba: Logical block address
    % J9 g3 \/ K+ w0 z- R
  6.   * @param  number_blocks: Blocks number, R: `! m& D6 a7 m0 i
  7.   * @param  data_pointer: Data
    9 G2 u5 W6 W& _2 c) y: L
  8.   * @param  media_status: Not used: G3 `, J8 b+ r# h4 T4 k! k$ W1 [$ p
  9.   * @retval Status (0 : OK / -1 : Error)
    7 x. F5 z. Y# A! W
  10.   */; U2 i6 W4 _; ?$ o7 [
  11. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,
    + Z/ p# u6 F/ |+ x3 P
  12.                                         UCHAR *data_pointer,
    ( m2 p! w4 d& R3 o; A6 O
  13.                                         ULONG number_blocks,  h! z3 @8 f( E9 J
  14.                                         ULONG lba, ULONG *media_status)+ w2 C5 |* u! z1 R" o* q
  15. {
      A; j- V7 Q3 ]) O/ Q9 q, C& A; [) V
  16.     UINT status = 0U;
    8 R' g* b9 _' I

  17. % R; K( Z  m1 S. q2 x2 Y9 B) e- x
  18.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);
    ; [  c# L$ Y! ?
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
    % y/ s- r. {0 u/ N/ \" g5 G
  20.     status = check_sd_status(0);
    . @) x* i* K4 C' F4 N$ {* ~
  21. $ e: k& l3 X. V) M$ \* g! C7 x
  22.     return (status);
    ' Q, m' m6 m" Q5 q
  23. }
复制代码

- J+ Y& I: \/ |( n2 L& z0 l用于实现SD模拟U盘的写入功能。0 R: F/ y  X5 {" O7 X; ~
# X  Y" y+ [1 E* O  }
3.3.4  接口函数注册
& r  x- S' b( m9 t' Z, K) @" w$ J) F接口函数的注册是在文件demo_sd_usbx.c里面:% H: Z% X4 {: |; o/ ^& m7 f5 q" \, K2 z
" Y3 I& ~0 y5 E; e
  1. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;' c2 n) @2 N1 R1 D; s  R3 z3 u
  2. 8 X* y/ u& W' `+ I6 t: Q
  3. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write; 1 V  j2 m, n: v- w, y

  4. - @7 I* e9 x1 [
  5. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;
复制代码
3 D$ W+ P5 n) S$ R4 s7 ^: s8 a: e7 c( d
3.4   使用的MicroUSB接口并注意跳线帽设置
1 q8 T' E( l# M( @/ t- J本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:
8 D8 L) b. @9 }5 L. j. t. S9 k' W$ N; a- T# F
a9cb882c39474dd9bd63b8c7e14cb451.png
1 [, Z: R( E& y4 ^1 D

& E# N6 L5 Z7 c) j' C6 a注意使用的是MicroUSB接口:5 B8 @/ g( u3 B: v, ?7 ?+ @/ {  d
0 p; C) n) F. G: T% d
f871e17a6a2d4c03a9413daf725670c4.png

% ]+ \( K* {9 Q1 h" y6 Y8 r' ~" Z
- o- [( v, C8 W, d& q# I& c9 a  ^4 Z7 `3 C
注意板子左下角跳线帽的设置:/ S" `1 K7 b/ O: z0 J4 V% X" f
% i# n; i  v. l; ]1 i) ^- n
41272c92c8c9483f9d5dc6a04cbf87b8.png
# f9 x- _" }; w8 p. U
& n9 a1 i2 y# c' h# f
, D  f0 v( o) o: P" A
这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。! y4 X8 x3 E9 i- K

) P, d7 M/ c5 B, C' ^+ v; c3.5   实验例程
$ M% o: ?0 }5 E, ~6 R配套例子:
5 u. e; \# s( T9 i
+ Y0 z, L$ U  c0 q: DV7-2401_ThreadX USBX Template- E) F/ T" K; B( r2 s5 q- P$ G
5 i/ Z5 a1 p' L$ @1 L. d3 A
实验目的:
9 [. s/ h* x' ~, r
9 U/ L. d) g* b1 r4 p# R学习USBX模板,通过SD来模拟U盘。8 N7 c* j8 v# C: P* I- U
实验内容:5 w& }7 y2 x4 [) f+ e" |; G
7 T7 u' z  s" y
1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                 
/ B1 \/ p4 Y4 D) t' e& g( s& H  c8 W
  ========================================================
& _3 u% N2 M3 P( Y" x8 T9 {) p' }6 y& S. H" J. q
         CPU利用率 =  0.89%% x9 `; J9 H$ `% L; E
- O/ ]2 e' M- Z  }6 _4 d
         任务执行时间 = 0.586484645s
% M8 M. B: X' @9 [( e& T/ x0 T0 u# H; w& F! D
         空闲执行时间 = 85.504470575s
+ K! g; E+ `/ M0 C2 m, y4 I5 V+ r' q" h1 X
         中断执行时间 = 0.173225395s9 X  ~5 T: ~/ |" |3 u
& ^5 y: U4 Q% O
         系统总执行时间 = 86.264180615s              
$ F3 |& y: Q, @' m5 h) x, b, j9 I2 l9 I
=======================================================
, x7 J, V# N$ L4 g1 y
; o% |  s' J' r        任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名; E% m6 H( p7 j! W( @6 Q) ]7 M

3 I! b7 E# l/ P# X7 v          Prio     StackSize   CurStack    MaxStack   Taskname+ T* X. J% f/ C( |
( V6 j6 `4 t, ^, I7 R4 m8 v1 E
          2         4092        303         459      App Task Start
5 ~* X: M$ c2 Y( G, {# H4 d) ~' w+ p$ @  w& p
          5         4092        167         167      App Msp Pro0 Q; C% I& o# ]/ r: y
1 I  n- c% i, w8 w& V( w! |  m
          4         4092        167         167      App Task UserIF
9 k1 v. I1 E6 l0 C  l3 i* X3 S, M, e
           5         4092        167         167      App Task COM- ~8 a" O: J4 l* q0 X

. ]: D/ B4 g2 i, }' }, X) J           0         1020        191         191      System Timer Thread           5 @3 p( d* u4 f/ ]

! m& a5 O7 w' ^/ h; l+ F串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。$ ^; n# }1 g( R, z, F
; D  E: ~, v" P- b
App Task Start任务  :启动任务,这里用作BSP驱动包处理。
* g& Q8 T3 z/ Z$ C* a7 r  g; m" e  u
App Task MspPro任务 :消息处理。
4 n* h3 }% `  k+ |! K7 }! B! R8 \/ g9 o- x& O
App Task UserIF任务 :按键消息处理。! b" T# c/ i; Q  Q( u6 T& X8 M( ]
7 U9 R9 A* p4 S7 X3 m- J! l( A) w  {3 z
App Task COM任务   :这里用作LED闪烁。
% j, G6 x; X  T. K& M4 Q: Z, j8 q3 D, |# I7 D( B
System Timer Thread任务:系统定时器任务4 @+ B7 |# X0 R# X; M

9 ^& c" }. s" C& a; o9 \) o! Q0 [2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。
; T' ~7 H3 z9 Q1 w1 O  ?
- Z/ i5 @4 t' X* s8 ^9 h% s      (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
2 d" L& a/ z/ u' m1 L/ j6 G
% H5 X$ v8 W! Z9 ?3、默认上电是通过串口打印信息,如果使用RTT打印信息
3 a; K, h8 b# e7 L5 r0 v( T$ A( V- E6 F7 T2 x+ L% p
(1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可
5 E5 w% ?. O/ C% C7 c
( ~: ^8 W4 _6 `; j7 ?, q$ `, ^#define Enable_RTTViewer  18 O# W6 p9 W) p2 f6 m; H
/ U1 }. y" |  p8 Z! W! @( O+ f
(2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。8 [" l. k/ K5 o( m8 O( j8 m. j
6 {# D) O" D0 G( m! u+ D
实验操作:0 n$ \, D7 `3 |( d6 A
( g' A- R9 q5 G; w( _6 ~' I' Q$ F
测试前务必将SD卡插入到开发板左上角的卡座中。
, g7 c% O) z' l# O$ Y% o支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可
; e# a2 b5 J  I# y7 Lprintf("1 - 显示根目录下的文件列表\r\n");3 @% K& [% ?6 {- ?) h
printf("2 - 创建一个新文件armfly.txt\r\n");' j# B' ?8 B2 |
printf("3 - 读armfly.txt文件的内容\r\n");
/ K7 c& _: }9 p$ qprintf("4 - 创建目录\r\n");
2 D2 M- V2 `. m( h) w2 oprintf("5 - 删除文件和目录\r\n");' \, W6 C5 |" u0 X' j# \7 Q' P: t
printf("6 - 读写文件速度测试\r\n");
! y5 o1 k% L/ E" e+ w4 d1 Rprintf("a - 打开SD卡模拟U盘\r\n");5 q$ _" _9 V0 z9 M
printf("b - 关闭SD卡模拟U盘\r\n");
, I/ ^7 ~) L( }. l串口打印的信息:
: k: E% Z3 K2 B) ?/ B4 B; g% Q% ~0 v9 z& \. w) i
波特率 115200,数据位 8,奇偶校验位无,停止位 1
; U* ~! W" Y" x5 V/ c6 k
9 K* \2 A- z( S3 D9 ]- u3 f
74d954c9e7b649289184a7a4bd58d6e6.png

6 N9 V$ p9 H8 }8 I$ y% x9 j0 ~2 G$ S" i' C

$ {. A: B: a$ r: l- G) h+ N/ C
& t( _4 e/ v- O9 m, ^8 Q! zRTT打印:
. L1 D5 l2 E5 g6 o2 n. S
4 h$ J. {6 r# A% O  ^5 {, u  S4 C' ~
cdcab0e093ed468a912923050806de22.png

2 ^7 v4 H1 H2 F) [# Z# q; L* ]5 d6 ~. w' |! Y8 Y* q; r* b

5 E7 H- I2 c/ G1 {' J! A6 c. ~/ i, q' e6 `7 w* z
3.6   总结
- v: t+ b) L% a( t) K' n2 M本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。1 ]! M2 Z9 t2 J5 i
5 d7 g" Z1 ]/ [4 D& N1 z- Z1 O

- J1 s& o( p8 r8 o7 a' f1 }4 }) l$ Z: i! x% v$ Y; C% _
收藏 评论0 发布时间:2022-1-1 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

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