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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 19:00
3.1   初学者重要提示) H" t! o" j1 J  j- `
1、  本章使用的ST专门为STM32H7提供的软件包
& g5 V& A  n# V6 p/ d$ E) P) k; e, d5 Y4 r8 D/ e/ q
2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。. O1 Y- t2 P5 e5 `4 {
: H9 [2 ?" D0 z- ]+ u
3.2   USBX移植步骤
8 B' p( ?4 J( I# n0 m; S4 SThreadX USBX的移植步骤如下:% ?2 u, l  z: w
9 y( y: J# ~# k# ]
3.2.1      第1步,了解整体设计框架
4 E7 L; C+ o2 X( w( i. N4 X为了方便大家移植,需要大家先对移植好的工程有个整体认识:
3 S% Q# g0 d/ G6 k2 U+ m4 _9 v
556edb9b3bb947f5b69aac84272def1d.png

* e) v  b" f: ?3 _. }) @. @1 S; R6 @; n( O7 r% p. `
+ X! [& k* `) l0 Z: ?
3.2.2      第2步,添加USBX和USB驱动到工程
( K9 ?8 c1 N, T8 h( E/ A4 P这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。
5 F0 ]8 f: E) F# `9 J
3 @/ [- \) D8 [6 m. m  模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。/ S: Z2 T# t+ w+ w5 u
配套例子是放在\User\usb文件。" A- ?: h9 p& K4 [7 @. S

. F( q& Q4 q0 G: s/ T  USB驱动文件stm32h7xx_hal_hcd.c,stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c。
! u# `; n. a4 ~  k这个是STM32H7的HAL库自带的。
: P8 d: O# P  u' c
0 Y' ]7 t0 [0 P$ H- y  USBX相关源文件。
& t( J/ a& r4 V" w大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在\USBX。) K# Z2 M) q6 G) x

' z' e" H8 W! T% q2 T; m3.2.3      第3步,添加工程路径& x, D& b" W$ X( a" K# |& ]
大家根据自己添加的源文件位置,添加相关路径即可:  M2 ^2 P4 v! l( h, x

# m( ^* [& F5 {* p- Q! f- ^! V
7d4292e15d424274b8e5aab1d6cd32a9.png

. G" Y' h, g* u/ R( w9 z" j, A( h+ Z% `
! @2 l) v9 C/ G7 n5 E  G

6 n. F- i7 J. {3.2.4      第4步,禁止掉添加进来一些文件

# A4 t8 C$ `- z6 O/ C8 R之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。. W7 n3 u' {% M9 j' w
4 B, ^7 U  Y- e6 M
418a71e2dcbd48a199034bbf6765d9fc.png 4d161770a4734368b6881fe1ed982494.png
! Q4 M/ j3 u6 j* L( n4 a
% u. N6 G2 \+ d! V; v: `( U5 {
696837e6177b4f3caa286c6913cf4ea3.png f052ff2297b4462daa7186e7fc3b6ab8.png

1 |4 R* U2 C. q
( ~: Q; _! R3 S2 a7 O& ]* a
0dadc8e05ea349beb4e04a737e86ed07.png
7 ]! h2 {4 E4 M% W" j  m

) b* S- A; c4 _$ c9 ^禁止的方法是右击此文件去掉如下对钩即可:% v; {; t. `& l0 P  K6 f3 k

1 ^# y+ l9 D# O
4db1e499f0f7422f9e522bf1e7bcecfe.png
3 X; e7 E6 k8 u+ N5 k' `

4 C& T0 G7 `1 T! S, ]& B5 I
2 ]% b" u' Y( ~7 N8 I5 }* k% _3 }6 C! w
" ?1 W1 k% U6 q/ |% |" m& ?3.2.5      第4步,配置GPIO和时钟
; r& m" Q6 S* n  l2 u1 QUSB时钟配置在bsp.c文件的函数SystemClock_Config里面:
: S: D$ K) t3 ]9 G: `
' l' ^/ B1 p  w' e; G4 q4 X
  1. {: F% N( ~9 L  J, X8 N
  2.                 /*& W0 K! K/ X  U
  3.                 USB工作需要48MHz的时钟,可以由PLL1Q,PLL3Q和HSI48提供4 e4 s6 G! b6 z' a* N, }
  4.                         PLL1Q用于给SDMMC提供时钟
    : T' |/ Z. w' {' \
  5.                     PLL3Q给LTDC提供时钟,也可以跟USB共用,不过得更USB设置相同的频率才可一起用。
    ! U: i7 o; ], E4 ]) h2 @$ ~) k
  6.                     HSI48可以供USB独享,就是精度不是很高。
    2 O! M0 X$ B/ ~; W$ k1 s. [6 \4 `: x! X' D  ?
  7.                 */2 @" K1 r; f* d: a
  8.                 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
    + h' K$ O" [, b; v1 i4 W
  9. #if 03 P$ l  C5 _6 {6 Z: ?3 F1 p  {8 F
  10.                 /* PLL3-Q for USB Clock = 48M */
    + ~& Y% a( a2 c0 i0 b8 M
  11.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;7 B/ ]2 k) x" U4 g2 i, D' S: x
  12.                 PeriphClkInitStruct.PLL3.PLL3M = 5;, P# _' E. K" @; e$ E
  13.                 PeriphClkInitStruct.PLL3.PLL3N = 48;
    + g- l% h4 G! z9 G1 V! _' l# n
  14.                 PeriphClkInitStruct.PLL3.PLL3P = 2;
    , h: o0 N8 M" A  J( _. p4 o
  15.                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
    8 D0 N8 |1 a; T9 e5 t, v) n% H
  16.                 PeriphClkInitStruct.PLL3.PLL3R = 2;
    + I8 ]7 h' c& ]/ J( E7 t5 w3 `
  17.                 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;0 H1 p6 a8 R& O1 F
  18.                 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
    6 P# M# n* h3 C# ^
  19.                 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    7 A; E$ @. Q% F+ U# v
  20.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;
    5 n: I; Q6 _/ \* l: P& k6 M+ `. j
  21.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK)
    5 V) A1 W5 b& Z+ l" l& c+ q, k! B$ U' z
  22.                 {
    4 ~, `- `+ s. j6 v
  23.                         Error_Handler(__FILE__, __LINE__);$ s) f" s8 @) @# s6 G6 t9 ~
  24.                 }        
    # t4 n/ m+ u* t) ^  f
  25. #else! [! |2 f& z# I0 v- b' I0 o
  26.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    7 J3 y: t; M1 O7 W! ~
  27.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;* g8 [3 |6 e6 D/ M' M' c& T
  28.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    ! U$ B( d6 J5 v; s
  29.                 {
    8 h7 }. O, {  N
  30.                         Error_Handler(__FILE__, __LINE__);
    $ i- \& d/ b2 p4 |
  31.                 }" R$ |: H1 t, _4 o
  32.               HAL_PWREx_EnableUSBVoltageDetector();
    & t, b2 @# p% e+ ^4 I& W
  33. #endif
    * v7 \3 W# k: Q. U  M& X
  34.         }        
复制代码
$ v. c, [5 Z& f6 V1 E
USB的GPIO,NVIC初始化在demo_sd_usbx.c:
' n7 q0 ~0 [- n5 g" E& u* M% m/ O) _
; `" R* ?/ E% D
  1. /* 配置USB GPIO, NVIC */
    7 y9 g' E0 D/ V& S0 A/ L3 L' y
  2.     {
    2 S$ t6 w. P  d) u( ~
  3.         GPIO_InitTypeDef  GPIO_InitStruct = {0};
    7 f9 `# v. d9 Z

  4. 0 i! x. \$ t5 v: D
  5.         __HAL_RCC_GPIOA_CLK_ENABLE();
    ) {/ V8 W& a1 ^' M

  6. ( ]# i& N5 `8 V" k; u% C, c
  7.         GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
    , `/ E0 X, \2 e% R' p; I7 N
  8.         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;8 h  j* x9 [. h7 o, k" X% r# I
  9.         GPIO_InitStruct.Pull = GPIO_NOPULL;
    ( S( ^1 ]" }/ y# h
  10.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    # e$ w: e* b: \6 M- w# [" @
  11.         GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;
    : E* @% N9 ]4 i5 |/ Z" B# g
  12.         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    7 K# `. q. i1 ~# h8 ~, L
  13. $ U' F* ^* l0 T* m3 [5 f
  14.         /* 使能USB FS时钟 */
    2 `( d- R+ g. ?# i( C
  15.         __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();
    & z$ i* E6 K" p* Y9 L
  16. 0 `4 D9 D+ l2 h8 c. D0 s
  17.         /* 在睡眠模式下禁用USB时钟 */
    * Y. x( f( G5 h9 r$ Y4 ?" n; z
  18.         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();* C: U9 m9 ]2 `

  19. ' f6 X; \( D& g( f* B
  20.         /* 配置USB FS中断 */# o$ e. f0 c) t' S* Q3 ?3 z
  21.         HAL_NVIC_SetPriority(OTG_FS_IRQn, 0x2, 0); 0 Q9 i! a7 R% C; ?: F! X
  22.         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);" P. P0 b/ V$ s+ W
  23.     }  R! e3 }5 c- E0 m9 K  s

  24. 2 J# w) l; \; m( L7 r
  25.     /* 初始化USB */
    $ B  p' k) L( V( L
  26.     {" P1 D! L3 S6 p6 ^: |+ q8 c8 j
  27.         HAL_PWREx_EnableUSBVoltageDetector();
    # i2 |4 o( W( Y

  28. * X2 I) W5 E2 ~. U% y5 O/ b' Z  ]
  29.         memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));5 ~: P2 z- z: N) @# F
  30.         hpcd_USB_OTG_FS.Instance = USB2_OTG_FS;& S. I: X9 i  ?4 C5 ^3 U
  31.         hpcd_USB_OTG_FS.Init.dev_endpoints = 8;2 K, p7 D7 r5 K- ?8 V0 K
  32.         hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = 0;$ J: ]5 k, t+ ?+ C# W
  33.         hpcd_USB_OTG_FS.Init.ep0_mps = 0x40;
    % |5 o6 X% F$ ]/ s5 s
  34.         hpcd_USB_OTG_FS.Init.low_power_enable = 0;9 p' }. |) i3 e% `5 X; S! L) A1 B- a
  35.         hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;  {  X/ o) m+ y
  36.         hpcd_USB_OTG_FS.Init.Sof_enable = 0;
    8 e& Z- e# Q2 y5 {  A- I
  37.         hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;! I2 h) x6 L9 l, J4 E* C( s3 [9 M
  38.         hpcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;, C& J: M! ^' k0 b% k/ G
  39.         hpcd_USB_OTG_FS.Init.lpm_enable = 0;
    4 A9 q2 z+ Z' j6 l. q) L. D, l+ k

  40. 0 w1 R; R$ S% N& ^: v0 f
  41.         /* 初始化USB  */
    + e: S9 {( H3 g
  42.         HAL_PCD_Init(&hpcd_USB_OTG_FS);7 `/ Q0 G- K  Q* {/ B' `

  43. 7 D- [9 X; o4 p* [/ w! K( S
  44.         /* 设置TX FIFO和RX FIFO */: p( Z( o9 V: v! Z' R; @
  45.         HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 1024);$ k8 `/ t+ j' _8 j. v/ S* E. |0 z
  46.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);
    $ c5 U6 o6 |; j3 M8 f2 L
  47.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 1024);1 ?6 [5 F  P. P) [7 l
  48. + i& Q* _- R' Q9 H0 I
  49.         /* 注册STM32到USBX协议栈并初始化 */" ^- L' x+ J7 a6 ^: h! Y+ _
  50.         status =  ux_dcd_stm32_initialize((ULONG)USB2_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);
    ( M) L+ C5 H0 h/ n6 P0 r  O; q9 H
  51. ) Y5 s& y; a' S0 n+ D$ x
  52.         if (status != FX_SUCCESS)
    , G& W4 n3 i9 `& P! T
  53.         {  e; d) h7 ]- O& H5 K* H" e" H8 R
  54.             return;
    : P4 d2 v) H& y
  55.         }# a% B' R  Q7 G4 F, s% b
  56. 3 J# W! ]3 j5 A7 e
  57.     }
复制代码
# b( A! F9 u  s% T- q
3.2.6      第5步,MPU配置

$ |" ^! E3 i5 o  X+ @$ U) z( M# e为了方便大家移植测试,我们这里直接关闭AXI SRAM的读Cache和写Cache(这样就跟使用STM32F1或者STM32F4系列里面的SRAM一样)。此配置是在bsp.c文件的MPU_Config函数里面实现:9 w$ ^  o# F7 b
5 d4 a- l; F6 s7 ?
  1. /*
      O; L/ x* _! r/ a
  2. ********************************************************************************************************** Q/ X) S& F% c; q7 R
  3. *        函 数 名: MPU_Config4 a1 c+ h. \; [& H
  4. *        功能说明: 配置MPU( y, U/ F: D7 R3 l, Z/ z# S
  5. *        形    参: 无
    " v( t% L) x5 X  V: |, {$ F
  6. *        返 回 值: 无
    ' a9 m1 v5 h0 u! Z  \( r; A
  7. *********************************************************************************************************
      \. W' A1 a' L1 T7 p
  8. */
    6 A* F8 Y/ F: O) o  m) Y8 R( L
  9. static void MPU_Config( void )( m+ o# Y% {6 L* R; n  c/ a
  10. {" ?$ y& \& |6 x2 i
  11.         MPU_Region_InitTypeDef MPU_InitStruct;
    1 T7 ~9 J9 }7 ~1 a, [
  12. 8 R7 F6 |  P7 |; r; ^; J+ K
  13.         /* 禁止 MPU */
    - N+ e: y, R) e2 F
  14.         HAL_MPU_Disable();
    " Z8 w& [$ c# K0 o4 h

  15. , M4 f8 k, j$ c) s( D- S: N
  16. #if 08 |+ r9 M! `3 R$ [2 m3 i# s
  17.            /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */' Y  h  P! _* r) Z8 _5 n
  18.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    ! y5 J# b4 D6 T: D
  19.         MPU_InitStruct.BaseAddress      = 0x24000000;
    : X3 N% U0 }3 C. [
  20.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;) L. o) L. m& Y* [+ t5 t  s4 Q
  21.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;6 _8 c; m! e1 A8 R
  22.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    9 v& }9 r6 y% g
  23.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;/ H" D4 e0 c4 H# j
  24.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    ) J/ o5 ^' i6 g. Q
  25.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    & O2 }) c' T8 N: U) F; b1 u
  26.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;& X+ k8 [/ }8 m- h2 k2 ^
  27.         MPU_InitStruct.SubRegionDisable = 0x00;
    % e% G, @+ p9 D# A0 |0 Z6 x
  28.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;5 v( O- ^( `" ~2 q) b% \# u

  29. + I$ _. b2 n3 X) \$ m8 `2 a
  30.         HAL_MPU_ConfigRegion(&MPU_InitStruct);2 _  _9 a7 T  T5 k; t1 A4 t, b* f

  31. . _0 Z# Q5 G4 U! [9 y$ B" a1 k1 T4 g
  32. #else
    ! Y) D$ q$ q; c0 @3 |
  33.      /* 当前是采用下面的配置 */! i: G: S; [2 k& T' L
  34.         /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */
    + ~3 u3 V  u/ d2 |( w; R1 I
  35.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;  H3 Q' a1 x" j0 ]$ d2 q: E  a  b
  36.         MPU_InitStruct.BaseAddress      = 0x24000000;* Y# @3 i' ~6 l
  37.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;% J& @# g) |  s. A! w$ |
  38.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;+ O, n; w# \8 Y
  39.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;3 Y& T  `; Q/ E
  40.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;* N) V8 Z  Z: U  t+ _
  41.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;& \) g& X4 X) H* [
  42.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;2 h: S  c$ [4 F* e9 \. B
  43.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;" M! i( C" b- k; A2 U
  44.         MPU_InitStruct.SubRegionDisable = 0x00;! k% _/ X! F* T# B7 W  r
  45.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;( s. [) T1 N- R

  46. 7 {' w( {5 E. R; |% g& }# f5 U
  47.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    2 w& r3 p9 T5 b4 c
  48. #endif' `. X" V/ Z6 S3 i( X( n
  49.         /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */
    / t; i( x, c; U+ E8 y
  50.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;2 n1 ^9 Q. V- ^2 C) B% X! Y5 \7 u
  51.         MPU_InitStruct.BaseAddress      = 0x60000000;
    " X0 m9 q! X: i. d' u& W
  52.         MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;        - W0 u6 P: U8 X+ m% n
  53.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;3 O5 P: F2 f! ?/ n+ o$ n; N
  54.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;! N( R2 O# g) y
  55.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
    7 R$ ?$ q6 a: t. D/ |0 d( k0 r
  56.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;3 U- O8 D4 l% Y& [, R
  57.         MPU_InitStruct.Number           = MPU_REGION_NUMBER1;3 q/ F- N1 U9 G+ ]' A% q: s7 r# W
  58.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    " t. _, K0 e6 p( z2 [" ^
  59.         MPU_InitStruct.SubRegionDisable = 0x00;
      z3 i% i2 w! M% q/ G
  60.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    9 Y+ Q) H6 c8 q6 P% v
  61.         
    , U  s" l- I' ~+ N( F% `8 v: ]
  62.         HAL_MPU_ConfigRegion(&MPU_InitStruct);0 ^3 f  l1 b7 V+ k, s/ [
  63. 5 |+ I4 X( n7 [
  64.         /*使能 MPU */6 g' w( T, A( G9 U8 C) O- c
  65.         HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    3 q4 t5 h- R' q' A+ {' ?* k
  66. }
复制代码
5 d3 S" F& y5 |' m( V- [
3.2.7      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)

0 i6 p- X$ O0 v% XUSB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可+ x" [5 e2 h3 t8 d) F* e

5 I: D8 i- i6 v( Z. c3 t特别注意USB中断服务程序别忘了添加。
3 x$ N0 ^/ W% n
2 g/ M  }# d. E7 M2 r. V; i3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明
: x4 B$ g# d- r4 q0 }这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。' B0 k, j5 x1 q& \4 T1 |

0 k2 ^  C9 D  p5 `& B: _3.3.1  状态函数app_usb_device_thread_media_status+ `- ]+ P- v2 h$ Q( {/ l* h
代码如下:
2 c" u1 U, b* L& B/ Z
1 ^) f- U3 \" u: N: A
  1. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
    5 L& f, t- Q8 m5 V
  2. {
    5 t  J6 `6 O9 f4 `- ^

  3. : Q& v' z- f' C! E& j
  4.   /* The ATA drive never fails. This is just for app_usb_device only !!!! */
    9 w: Z/ |! ^: O7 \  n( P) \4 A
  5.   return (UX_SUCCESS);5 j1 e7 R7 c- E$ G. N
  6. }
复制代码
* Y, q8 D! \5 I0 N" y# v0 z
此函数主要用于获取SD卡模拟U盘的状态。) U! N  \1 E) C' }
+ K. ^& \0 w) z
3.3.2  读取函数app_usb_device_thread_media_read

; S" i+ @: r9 R! `% T, T代码如下:
  c% O, [1 E% B6 H9 L  C% o9 M6 H
, x% p; D* \3 T+ \7 \
  1. /**: B: ]2 p4 p/ w' u# X' p
  2.   * @brief  Function implementing app_usb_device_thread_media_read.
      D- {0 Q8 `% a
  3.   * @param  storage : Not used2 i5 W4 G0 I! i* _: h1 ~- @) q  Y
  4.   * @param  lun: Logical unit number
    - ^; G  J, S% x, d/ }5 `
  5.   * @param  lba: Logical block address
    % Q/ m+ @$ z- e
  6.   * @param  number_blocks: Blocks number# B0 e1 p( z/ q9 I: ~- D! B" k
  7.   * @param  data_pointer: Data
    & x; ]% q& B0 Y% X& x2 q7 M; b8 i
  8.   * @param  media_status: Not used" j  x! U% D4 B- w4 o3 B/ o1 k
  9.   * @retval Status (0 : OK / -1 : Error)
    ( q( K- A" o+ G5 {$ c- q3 g
  10.   */
    9 `2 V% K8 w7 k- U! z7 o
  11. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,
    5 `! s. L( c5 E* q5 v' h
  12.                                        UCHAR *data_pointer,0 F1 b, P( a; L( V
  13.                                        ULONG number_blocks,
    : W; C: \8 Y0 ]
  14.                                        ULONG lba, ULONG *media_status)
    1 V8 v/ X5 K% L- }& u2 e
  15. {
    : q& T( L3 L: ]3 Y; t; N6 s- y3 K0 D
  16.     UINT status = 0U;& _0 z4 X9 _" e' y- ?
  17. ( I  V) f9 n+ l& R& Q/ B
  18.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                        ! a3 H8 t. k( D. V' Q
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
    / B: _0 E6 ^  v& \6 u4 x& H
  20.     status = check_sd_status(0);   
    , D# n, e5 n- r3 i8 ?* y% Z  N2 R
  21.     return (status);9 U9 d+ b! G# p8 g7 O( w4 x
  22. }
复制代码
7 O0 U8 j8 J) p- r0 d, s% q* G/ H
用于实现SD模拟U盘的读取功能。
7 d1 T8 ~8 L- ?* w: r1 p
% B( C1 R: p- X( D; I8 c- a3.3.3  写入函数app_usb_device_thread_media_write
& G, e1 c+ C1 p- B/ ~6 ~代码如下:
) Z- ]7 |, H" x# X3 u  W" {; [( `6 j, y; O9 w8 Q4 M- ^& [# y
  1. /**0 B6 w% y$ O' W/ A+ Z& C( o
  2.   * @brief  Function implementing app_usb_device_thread_media_write.+ X, c- p6 h- d5 v
  3.   * @param  storage : Not used
    & _4 ]+ v: E0 S% d" e) X% U
  4.   * @param  lun: Logical unit number- u1 D( }9 w; Z; I; f. T6 j' d
  5.   * @param  lba: Logical block address8 g8 }( C! N& G/ o6 Y
  6.   * @param  number_blocks: Blocks number
    1 y1 I( t" t4 d; P$ S. m3 y) w/ Y
  7.   * @param  data_pointer: Data
    6 ?" F+ l6 y% O  k- R' x. i5 y  E
  8.   * @param  media_status: Not used2 J. }. @( o$ R$ y6 f, C
  9.   * @retval Status (0 : OK / -1 : Error): q& O% ^8 L; i' l" _$ Q
  10.   */
    ' o5 z- D! r$ G
  11. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,
      V' H8 ~9 s0 k7 G% f9 W
  12.                                         UCHAR *data_pointer,: Y0 f, h: J5 O- a
  13.                                         ULONG number_blocks,
    % ~4 y- q6 C; U, W3 E
  14.                                         ULONG lba, ULONG *media_status)3 _7 D$ Z3 Y% J
  15. {* I: w2 D0 u( ?6 l7 X% T  R
  16.     UINT status = 0U;* p3 f3 s; F$ a# L! @

  17. ; x( |% Q; V3 V+ a3 I$ R7 S2 w
  18.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);  O7 H4 ]' `- q9 k
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
    $ Z" }: Q" E- B- H& ~3 b& z
  20.     status = check_sd_status(0);
    : g6 r4 M( ~2 B* x- M0 L$ w3 C/ n

  21. 3 N8 @+ f& r# ~# E5 a/ F% _
  22.     return (status);. |. x. X1 ^! @3 f
  23. }
复制代码
8 N6 G- @% }( _( T; r. x" d3 D
用于实现SD模拟U盘的写入功能。
9 j% x& |  e+ b. o' n; C' m5 ?) y: Y
3.3.4  接口函数注册* V; J3 X) G! N
接口函数的注册是在文件demo_sd_usbx.c里面:
+ A7 ~' V# y/ j' }! J; L- Z6 L- u$ W' {5 d  N% e
  1. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;; \& f  t% \- a* J' _5 ]

  2. 6 w/ Z+ ~' ]" N9 e
  3. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write; ' |9 w, t) V& _8 L) ?
  4. & r8 B% Q! ~7 |% b, b# J! o
  5. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;
复制代码

0 ?" x: s/ k8 P( L  J1 d8 [3.4   使用的MicroUSB接口并注意跳线帽设置" A8 @6 E" s. a; u/ c
本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:
; L/ E* c# s# n/ ^- N$ ^; E8 H8 ?$ j( |
a9cb882c39474dd9bd63b8c7e14cb451.png

! B8 t: N  \; m5 C8 e- ~! m- L' j/ p) m- j' [, [' o
注意使用的是MicroUSB接口:
  D9 Y- f/ x9 n. [0 j3 J1 Q5 T, o7 r# N8 w$ ^/ C" d) c7 }
f871e17a6a2d4c03a9413daf725670c4.png
' y6 x/ e3 |4 r

, p) ?* H+ V$ M- Y4 O1 O
, }7 t+ F4 s. G2 M. r9 k$ N0 ^注意板子左下角跳线帽的设置:
; U7 o& s% V6 P5 m/ @' d
7 b. a: [' j- n4 ~
41272c92c8c9483f9d5dc6a04cbf87b8.png
( V1 ?3 y1 {: i  X. ?

: s- u2 z8 c% F: N& ]5 v8 N
1 J$ H- m: i! P6 [3 k+ ?( J' ]这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。3 c8 A* {7 A/ @8 n; M) `* M

. K& x6 i! t9 N. f# b3.5   实验例程
1 l0 l/ i% h7 K3 n配套例子:) e/ Z3 S5 }" K& V$ t/ K( K. K# y

) A5 g& b/ @' X, `  oV7-2401_ThreadX USBX Template
% L9 n* ?8 T. K; A) Z* J9 \- W& v2 a
实验目的:; E7 G; ~( d( g5 a7 v6 |2 e) f, B
, o+ t: x9 z! s
学习USBX模板,通过SD来模拟U盘。& f7 v2 }/ F. i$ _9 I, L& f8 X
实验内容:/ M1 [0 V9 E4 h! N4 M. e0 f

# V# x0 m% w( V* X1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                 
  ^: o8 g3 b8 d! m' Q# M1 v2 n! K7 A3 d) Z% i* P8 y
  ========================================================
  Z) j* F& `) C3 r% g' H8 `- T( R+ q4 X/ R8 |
         CPU利用率 =  0.89%
% R* I0 N( E% M, L7 G5 f9 H; {) v! C+ k5 W, s8 r
         任务执行时间 = 0.586484645s
( J& F: h4 ~3 @- o  M; V8 ^! ]' `* Q+ y- A9 O$ w
         空闲执行时间 = 85.504470575s
! `9 Y' B/ W, ~3 \
1 ~  m. ~; @+ G- K         中断执行时间 = 0.173225395s
; u0 W$ B% m- p4 ?4 {0 c7 h( S" ?' P$ _" x, ?1 y
         系统总执行时间 = 86.264180615s              ( D* {$ [" ]  `6 t* j, i# \

2 _, c1 j+ B5 ]2 `# h/ v=======================================================
: y9 A! f3 R! ^1 i  Q
% `4 {( N, k) g2 c7 i        任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名2 M- T! Y6 K7 t/ o  \# a% J

7 x6 T+ `2 V: l, w          Prio     StackSize   CurStack    MaxStack   Taskname& _5 X8 |/ c) j6 U

. S" m2 T% a# `: b' m2 H          2         4092        303         459      App Task Start
0 T: m& r; t. g/ `0 j
; l/ `. j" R  G+ e          5         4092        167         167      App Msp Pro
' w$ N1 E- i4 d
* s% Y4 L0 g+ D- N9 i. [  |          4         4092        167         167      App Task UserIF" |. O8 O9 I- b% x

* G' E1 ]% d6 [- O  T           5         4092        167         167      App Task COM  ]: {( [9 Y8 M# E2 r3 \, @' A$ u. S

$ ?% u6 z# Z: K* b  ~           0         1020        191         191      System Timer Thread           " `; B1 u" u9 a5 c: ]& \, |
+ _; o! K" b$ H6 `  d& ~% Y
串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。) q0 r2 k7 E4 b5 |# i

1 S, u% [6 x& U9 X2 d- U( t1 o% dApp Task Start任务  :启动任务,这里用作BSP驱动包处理。
7 @' r* e7 ~4 r% P2 d$ G3 J) w6 Q) K
App Task MspPro任务 :消息处理。
  z* K1 Q+ `$ v: B) a  ]' e; r/ n
% d  U5 k1 X0 _' _- v. b7 [App Task UserIF任务 :按键消息处理。$ [& E' R0 m; P& o2 I0 f

; K6 c. T9 H9 O. lApp Task COM任务   :这里用作LED闪烁。
+ _, R$ e7 P9 V2 y, k
7 m+ _+ L6 [" X! [* ISystem Timer Thread任务:系统定时器任务
% D4 ^( i+ M. L" h+ H4 i8 E
, f2 R& Y9 _. \2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。
3 p, S4 }8 z4 l" S1 S
7 S- d) V; V' X7 Y3 P; b      (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
- D) r4 n7 r5 y) B0 v3 m1 G$ o/ r- p
3、默认上电是通过串口打印信息,如果使用RTT打印信息
- i: A; X# _" V) }( @( \: H! K) j! r
(1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可- t' P2 J: A3 k; q9 D6 J, V, T

  k  Y0 C6 P0 e6 Y#define Enable_RTTViewer  1% A4 v6 d# H8 }- h$ H% o

2 g5 S" ?  D% h" t- s+ x+ v7 b9 e+ X(2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。
+ ^: [: U  V2 d, c3 t
7 l' ]0 ~' h) V, t! i& p; [实验操作:' C% }# g) t$ H5 e* `3 p( }. S3 H
, y6 C; d5 U; L* U3 a" h5 F2 u
测试前务必将SD卡插入到开发板左上角的卡座中。
% x1 Z# |0 i2 I5 C0 `0 A/ ^支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可$ q( k5 I, m7 i5 Y# s8 V
printf("1 - 显示根目录下的文件列表\r\n");
  D3 I0 a. W. |& j1 O( c* y' T: sprintf("2 - 创建一个新文件armfly.txt\r\n");
8 V  F2 M1 L" s% E. e# K8 }printf("3 - 读armfly.txt文件的内容\r\n");
! ~" L# T1 K' x3 w9 L2 Vprintf("4 - 创建目录\r\n");# D8 f+ o, }* |+ ^. n
printf("5 - 删除文件和目录\r\n");
* A" ^, Z8 o7 r" c% g2 o% Mprintf("6 - 读写文件速度测试\r\n");
1 T0 n: |3 j+ f! y" P% p0 Zprintf("a - 打开SD卡模拟U盘\r\n");
; }! t& }, T- R6 _; wprintf("b - 关闭SD卡模拟U盘\r\n");4 s+ o$ H$ q8 }7 `7 W
串口打印的信息:
, W% n6 \& D) C  v' j# F9 R% c: y. y' T
波特率 115200,数据位 8,奇偶校验位无,停止位 1
/ W& N- @. Q! _7 i6 A, q6 S9 d& b6 z# \$ X: B
74d954c9e7b649289184a7a4bd58d6e6.png

% n8 V* p. a0 U  j% S" j
/ {1 U: v2 N2 U/ D$ s8 L) ?9 y. [
$ k" t2 i/ v- Q" m$ J* n1 T, W& ?+ o6 U5 I' Q2 x  ^" o
RTT打印:
0 C$ _) C5 X2 `3 s% c9 V- ?( B- h3 n5 U$ F5 \
cdcab0e093ed468a912923050806de22.png
  B' [2 w! \7 C$ z9 M- }% l
$ A, g5 B! Z$ w. X( R7 \# J

+ C1 Q" X4 N9 Q, v
, A4 ]0 N+ G$ f" [3.6   总结, M- d2 C# d* Q  f7 p
本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。  a1 a! Z/ l( q$ i

5 m* o$ s, M3 H! g: y1 E- h& O
1 T+ _- Q. C; v# {+ D; ~" A  ?" i" F8 ^* V
收藏 评论0 发布时间:2022-1-1 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

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