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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 19:00
3.1   初学者重要提示3 ?( t) R0 L- {! X0 F0 @
1、  本章使用的ST专门为STM32H7提供的软件包, y5 r+ @, K7 J& @% Q

2 ?3 M6 C4 ^7 s7 r" g2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。' ~, `" [6 r0 b; ]. X4 z$ M( N" I
" d+ i+ O& y; W% T7 @5 S
3.2   USBX移植步骤1 v' U3 R2 {& d8 F
ThreadX USBX的移植步骤如下:
6 Z( r) k& \6 C. E2 P' x2 W
. `0 V* D% z' A6 {" S9 S, L# z; j3.2.1      第1步,了解整体设计框架$ r, l/ D; m) W% D/ D+ F
为了方便大家移植,需要大家先对移植好的工程有个整体认识:
0 c1 s! @: |9 V" O1 n( M9 u5 e/ V$ Z" Q
556edb9b3bb947f5b69aac84272def1d.png

# o: i6 h  p% Q! b9 E1 `; P9 ~, _8 N3 j( F) z+ O( i
& U! X# f4 `3 }- t* C
3.2.2      第2步,添加USBX和USB驱动到工程
& j& w3 T+ n3 U: n% [3 P这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。& p5 M. O2 `, V6 _, _$ C( H$ ?
7 r( R7 x  X8 M8 h& i
  模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。' U# T4 p$ |$ Q
配套例子是放在\User\usb文件。
( U: z% B( u6 S$ d5 ^/ \" L
9 c5 T! ~; G, |" C; S3 d2 Y  USB驱动文件stm32h7xx_hal_hcd.c,stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c。
2 y* Z! E; e6 V  G/ G这个是STM32H7的HAL库自带的。5 v( t& [# k8 y2 Y4 K* Z: r

5 A! q2 R9 ^9 r) P6 o2 e2 v. m  USBX相关源文件。
, X( D: h, D7 l; l& k* p大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在\USBX。2 a! o  @' U7 R0 X$ a1 t& S$ p
: x0 h! ]9 P0 M+ L
3.2.3      第3步,添加工程路径: ^- S! q! N+ T/ a  }. |7 U. D6 o
大家根据自己添加的源文件位置,添加相关路径即可:6 }6 m9 @/ d5 m- S$ E5 ~# A

8 I7 Z  q- H# \" _0 Q( Y' X
7d4292e15d424274b8e5aab1d6cd32a9.png

. S4 H" Q* B; y6 d7 S
, ?! C9 ~5 M1 s9 Y  j7 \& C2 P0 p! [2 i  |0 e) T5 Q& @
1 \# n' l: g; b$ M7 o
3.2.4      第4步,禁止掉添加进来一些文件

. L7 L. x2 E! Z4 J0 X之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。6 a: q& f( Z* L+ i
& g* J# d' {3 U% [
418a71e2dcbd48a199034bbf6765d9fc.png 4d161770a4734368b6881fe1ed982494.png
( f9 Y( ?6 m: I. K, }/ U! p+ w
3 a$ W1 ]: |# I" O
696837e6177b4f3caa286c6913cf4ea3.png f052ff2297b4462daa7186e7fc3b6ab8.png
% C& J" ?# G+ u% l# q  J$ e- n

# \7 S( N" x; w! Q; X" D2 _
0dadc8e05ea349beb4e04a737e86ed07.png

% Q; p) @7 I. M4 f0 K- C* {, P$ g& n( [8 T) D) z+ z
禁止的方法是右击此文件去掉如下对钩即可:
  b8 P- C) X( t3 z, ], T6 M* b$ n/ G% l; o9 x
4db1e499f0f7422f9e522bf1e7bcecfe.png

) \/ U: z& c- V1 [" t0 Y& e, Q& H4 S, y. v1 H( c

$ E3 o9 ]6 a; S# A( Z7 {; W, ?- J
6 q# ~! Z, B1 q# z0 f6 n% u' v3.2.5      第4步,配置GPIO和时钟- s- C6 v' u. y. m4 u  ~
USB时钟配置在bsp.c文件的函数SystemClock_Config里面:
$ G- E4 i2 x- C- G5 `' s; C7 L0 i4 s$ D0 |' C; A7 v# m
  1. {
    7 a& ^! K4 z9 v) _
  2.                 /*) y8 _! `7 ?+ y4 z7 l
  3.                 USB工作需要48MHz的时钟,可以由PLL1Q,PLL3Q和HSI48提供
    ) G/ z1 s1 v; t
  4.                         PLL1Q用于给SDMMC提供时钟1 C! G6 H- C1 a% G1 L
  5.                     PLL3Q给LTDC提供时钟,也可以跟USB共用,不过得更USB设置相同的频率才可一起用。+ e5 H# M5 h: E1 i
  6.                     HSI48可以供USB独享,就是精度不是很高。
    5 g2 H2 w4 b/ x' ~" u) D9 N+ w0 ]0 J  W
  7.                 */
    % [# |" O0 G, d9 v2 Y' ^' F
  8.                 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};1 N" e- d7 n. I0 `6 F4 B
  9. #if 04 v9 D  Y7 f2 a' n7 z3 c7 T5 A
  10.                 /* PLL3-Q for USB Clock = 48M */7 r, w" I9 W) L, ^; n. X! v
  11.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;9 O" ?. W3 y9 o
  12.                 PeriphClkInitStruct.PLL3.PLL3M = 5;
    + V& y/ b3 S8 I5 L
  13.                 PeriphClkInitStruct.PLL3.PLL3N = 48;
    3 ?( r! B6 x8 M6 c7 m
  14.                 PeriphClkInitStruct.PLL3.PLL3P = 2;4 X9 ]. e( O. R* W
  15.                 PeriphClkInitStruct.PLL3.PLL3Q = 5;  |  U7 i; A: z1 B" w/ t
  16.                 PeriphClkInitStruct.PLL3.PLL3R = 2;& |+ q0 o2 m$ @
  17.                 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;0 i& G3 h* r4 F7 P! W4 q- j+ r
  18.                 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;. d6 u# ?* q. `& c
  19.                 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;- K, `, x; X1 x' Q+ o
  20.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;
    8 x2 J6 W" D/ t7 k
  21.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK)' _9 v2 S" ]- f& a/ T
  22.                 {
      q( ?0 {+ Z: O
  23.                         Error_Handler(__FILE__, __LINE__);
    0 ]$ T, o# e. ?$ l2 L
  24.                 }        
    0 \0 s3 a; S8 ^' X" E$ y: ^0 g
  25. #else) p0 c- g- J9 q
  26.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    8 J! Y! m3 H; F
  27.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;! I5 i4 \9 X2 A4 z, P+ ~5 Q
  28.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
      ~. @7 ^6 t5 z
  29.                 {
    2 D" j" W$ g4 h& @% C( h) v
  30.                         Error_Handler(__FILE__, __LINE__);
    + ?) d& P2 ^# d6 Z2 {
  31.                 }
    9 K# D( b. D1 h/ h
  32.               HAL_PWREx_EnableUSBVoltageDetector();
    ; o. Z) p1 U7 Z" y3 ~9 t# w
  33. #endif- b( }+ H) Z* i
  34.         }        
复制代码

, ^9 K: A: w* N- E  P0 }4 F# cUSB的GPIO,NVIC初始化在demo_sd_usbx.c:) Z" j  U1 S) I+ y; U6 a4 F
' v1 l( Y  D. `8 x3 s6 _7 m
  1. /* 配置USB GPIO, NVIC */) Y' L. W! |' D0 d% P* N
  2.     {
    9 V+ g1 l8 S, n8 w; r2 T* I6 a
  3.         GPIO_InitTypeDef  GPIO_InitStruct = {0};: s, L# H# U! b! B' |2 r0 h
  4. 6 ]3 z7 e, h9 D2 v, Z' s5 F/ }
  5.         __HAL_RCC_GPIOA_CLK_ENABLE();
    1 w; Z3 L7 X0 `3 F' T

  6. - S# T* x, l1 y& Y* p+ Z
  7.         GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
    ' D/ a8 o, r* V9 L0 F3 a
  8.         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    , D( i8 H3 x  z5 C# B. {
  9.         GPIO_InitStruct.Pull = GPIO_NOPULL;3 y7 ~6 d: j% b9 {! E+ j0 }
  10.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;- I2 y; n$ d7 ]: U8 P3 R
  11.         GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;
    3 s  j! F% ]: w2 o+ `$ q  p
  12.         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);/ `* q- g/ X% Q. N) Q) a) Y
  13. # W5 A9 i% y: h" t6 M$ g
  14.         /* 使能USB FS时钟 */, U4 i" R3 `. m+ @
  15.         __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();
    3 L6 f) Z. \1 x" W" ^9 ]2 D* @& Y
  16. 9 ~" S: Z8 W1 W- F  E4 ^1 Z
  17.         /* 在睡眠模式下禁用USB时钟 */
    5 b" ]2 [/ e( }  A" I
  18.         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();
    + y- z5 O! J* ~, G1 ^6 {) c" v

  19. . L1 e! K7 ^4 r  D
  20.         /* 配置USB FS中断 */1 u- v1 }& L7 b; y5 g2 Z. R% I
  21.         HAL_NVIC_SetPriority(OTG_FS_IRQn, 0x2, 0);
      Q; `- j" S9 x& B; q
  22.         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);0 k! v+ J" n! z5 H0 A2 e& l
  23.     }& W) B5 t" G$ G4 f" D2 |

  24. , h2 O7 U) n7 L1 S7 n" g( A
  25.     /* 初始化USB */
    3 v! Q/ O& [' V3 t9 J) O9 ~- _
  26.     {
    1 C8 `6 _3 J) C; E, ~: D$ G* l
  27.         HAL_PWREx_EnableUSBVoltageDetector();
    ; _; l# B) S6 {9 p5 N  Z- Z& G9 Z

  28. ; M7 b6 b! I0 J
  29.         memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));* w" x% ?8 U0 |2 A9 L- W
  30.         hpcd_USB_OTG_FS.Instance = USB2_OTG_FS;
    * B' g/ \% o2 J# [
  31.         hpcd_USB_OTG_FS.Init.dev_endpoints = 8;
    ' ]' ^$ I1 [* V% _* P: G5 e
  32.         hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = 0;
    1 q5 y) L7 \1 e3 Q) _! i+ D; p* \
  33.         hpcd_USB_OTG_FS.Init.ep0_mps = 0x40;
    & y- b9 X  {. h
  34.         hpcd_USB_OTG_FS.Init.low_power_enable = 0;" t) z# C* n1 D& M1 B' ^- F
  35.         hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;" ?; c, U* x& x3 [
  36.         hpcd_USB_OTG_FS.Init.Sof_enable = 0;- O5 Z7 W8 F8 e6 d! K7 z
  37.         hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
    ! K# |9 K- z1 _$ L3 b
  38.         hpcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;
    - K2 R+ j) q1 K
  39.         hpcd_USB_OTG_FS.Init.lpm_enable = 0;9 q* U+ y+ }% w" E+ `- \* ?/ H/ s
  40. . U+ Z, U  [) e. Q5 e& F
  41.         /* 初始化USB  */: F) ~# g! W- u; a
  42.         HAL_PCD_Init(&hpcd_USB_OTG_FS);; f' G* K% V7 [2 M
  43. , K1 U/ X1 @: R
  44.         /* 设置TX FIFO和RX FIFO *// o2 j$ m1 K, _0 D% z; j+ O. e
  45.         HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 1024);
    ) x) \! x8 ~. q# S" l$ S2 Y
  46.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);; e- |  ]1 Q2 U: `. N7 V* H
  47.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 1024);+ p2 s& ~4 ?0 d' @1 S
  48. * h" L, c) T7 E8 N
  49.         /* 注册STM32到USBX协议栈并初始化 */+ |1 `! O% V! h" f/ c- L
  50.         status =  ux_dcd_stm32_initialize((ULONG)USB2_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);2 j" K$ _0 D' C8 {

  51. 4 ~( z* t  h0 p* u& j/ c. B
  52.         if (status != FX_SUCCESS)# p- O1 ^( e" q& U
  53.         {9 I) I8 g4 P) S/ M7 P' \2 B
  54.             return;9 @  F5 U( B- n# @/ F0 [4 D+ i
  55.         }& t8 G6 Z2 [  k( E2 i% f
  56. + f3 Y8 G1 A2 P& O' V7 ^$ P, g& M( q% E
  57.     }
复制代码
- w% V* Q) v. I& }2 R
3.2.6      第5步,MPU配置

& L4 D7 v  L1 K" T. X9 A为了方便大家移植测试,我们这里直接关闭AXI SRAM的读Cache和写Cache(这样就跟使用STM32F1或者STM32F4系列里面的SRAM一样)。此配置是在bsp.c文件的MPU_Config函数里面实现:
6 Y9 w' A2 ]+ U! X) H  Z
$ z2 r/ e, t" X5 n6 d: m9 U: ?
  1. /*
    8 M! o; O( k) d' O
  2. *********************************************************************************************************: h. |7 n2 t1 f" \! z6 T
  3. *        函 数 名: MPU_Config- R7 M/ r5 O. |' g- k6 W9 x
  4. *        功能说明: 配置MPU2 F. C( W: T7 Q+ r
  5. *        形    参: 无
    % _  b) F# l# l9 v
  6. *        返 回 值: 无1 Q9 T, g& V- m0 ]' d/ i6 M
  7. *********************************************************************************************************9 n* R; D; V+ b! N! @8 z5 G/ F
  8. */
    " h& }, U2 @( P+ ?3 B! R
  9. static void MPU_Config( void )
    % h) ^+ \; a" s$ T
  10. {1 b" J& a" @8 @
  11.         MPU_Region_InitTypeDef MPU_InitStruct;
    . c2 C8 }6 [# k0 Y% U4 b8 d
  12. " N$ S; J+ I" e: t
  13.         /* 禁止 MPU */
    3 w- `& d8 F) N+ P: {
  14.         HAL_MPU_Disable();
    ) w% I# z- z( T- f
  15. 2 L$ W7 B/ Z/ R. T
  16. #if 0
    " V1 l; s% n+ ~! _3 `
  17.            /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
    ( x6 p! t# T) Q
  18.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;' {8 d  G7 C. J- Y( D
  19.         MPU_InitStruct.BaseAddress      = 0x24000000;$ d8 k; K/ F6 p2 v+ w
  20.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
      R; C3 Y. b1 }5 \+ l. j- N7 M
  21.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;# e5 }' k9 Z0 N' S+ @7 @
  22.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;( I: X  t) ?5 B% e: `
  23.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;) y1 j2 @, z4 K! |' F
  24.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;2 _# s3 N: T/ L! N' N
  25.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;# y$ K/ q; h& R8 F
  26.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;" r/ b" _3 Y2 u5 j+ Q
  27.         MPU_InitStruct.SubRegionDisable = 0x00;
    , @) A! Y6 F7 d( j( f3 ~
  28.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    / [) X1 Y9 _6 a+ p
  29. & K* Z8 N# i! H: p
  30.         HAL_MPU_ConfigRegion(&MPU_InitStruct);. p! d! S2 c0 u( V! t; q

  31. & Q: }* |5 e$ h) n- s$ S
  32. #else
    ! n0 ]: @% s  a8 _3 @' O6 O% P
  33.      /* 当前是采用下面的配置 */6 J( K; Y: t7 @5 ^( j' h
  34.         /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */: h$ m1 O2 I: l; u4 n2 f* H6 R$ h. Q
  35.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;) e. D' I4 L, b2 m4 q# j* L1 ~% v+ L
  36.         MPU_InitStruct.BaseAddress      = 0x24000000;- p) l, C% n8 j% S
  37.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    7 q6 t4 U* S* q1 ~
  38.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    / J3 v7 [9 q' Z  y5 Y
  39.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;
    7 K8 H3 ]; A% F0 g$ X# z3 t* t
  40.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
    , u6 n4 l" i7 x1 I. K( u5 f) ^5 G/ r
  41.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;! ^, _: W$ \& X" X' B# z
  42.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    ; b7 A: q# I* ?& A6 ~0 Q
  43.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    5 l4 S( ^5 a$ p7 m' v% b
  44.         MPU_InitStruct.SubRegionDisable = 0x00;
    0 c' y' b* c# K1 z
  45.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;" e) d2 U" M% F  u& T3 r

  46. & n  c! S4 X& b( b3 D' a
  47.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    5 r, O/ b/ Q' E7 Z
  48. #endif
    9 S- Q& ^5 h7 [1 T* z
  49.         /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */# u* S* Q2 b. v: n6 N% |& v5 K( |
  50.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;& b; R; v+ u7 Y2 h7 ?
  51.         MPU_InitStruct.BaseAddress      = 0x60000000;* f5 \( z3 l( C1 g1 z! S
  52.         MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;        
    5 [2 e% c; V" j1 ]# t* {( H& O
  53.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    , W1 X0 w7 |+ H& r6 @+ }, t% |
  54.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;' q7 `( E( L6 G! G) Q- U0 R
  55.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;. n3 g/ ]0 i  N
  56.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    ! P' \$ V8 }! N2 X8 h
  57.         MPU_InitStruct.Number           = MPU_REGION_NUMBER1;) D: d& i4 f2 C2 E2 B5 o
  58.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    5 d% }& s6 b" E: N* S3 J
  59.         MPU_InitStruct.SubRegionDisable = 0x00;1 E" B, m( b. M( z$ g
  60.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;" J3 J9 M# `& u; S% \" t
  61.         ) W2 Q' Y! o6 S) A/ @
  62.         HAL_MPU_ConfigRegion(&MPU_InitStruct);! r% i  E: a; y4 }

  63. / h/ |* @& f7 Q; v- A" |$ r; A
  64.         /*使能 MPU */& G3 I5 I* B& r& G6 k
  65.         HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);6 W4 T# d1 a6 C- ~* I6 }* N9 B. ^$ V
  66. }
复制代码
" u: y  d- A% g* K& p
3.2.7      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)

0 G/ w" d6 ?/ Q6 F7 v! h/ `USB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可# k4 A; i0 }* Y
- Q- g9 d7 ]  K- C2 H, D3 Y; `4 L: H0 d
特别注意USB中断服务程序别忘了添加。. C, T- ~- ]3 ?9 k* _7 B
: {% ]# M1 F! I$ [9 G0 n& O3 |
3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明
( }8 p6 f/ v" }# j这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。
; _' O/ x* X! B7 r* O2 J0 B; q( \+ j' W3 |- y; ^0 q$ S$ f/ B
3.3.1  状态函数app_usb_device_thread_media_status3 w2 d- `, ?8 V! ?" D. U* s7 F4 W/ z; F/ \
代码如下:1 A: p9 g: H- ~
* a* F- c5 y8 X' H4 w
  1. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)( M+ u- B. C) H6 G" Q' [
  2. {1 V! K* z3 E# `

  3. : ^$ N1 O4 f' |( e. ]
  4.   /* The ATA drive never fails. This is just for app_usb_device only !!!! */$ C) T  m- Y8 a. h
  5.   return (UX_SUCCESS);$ m7 k/ i6 H$ P
  6. }
复制代码

4 I6 s! m5 L0 a" t! f; a此函数主要用于获取SD卡模拟U盘的状态。
' Y% B3 h1 j. B0 S
5 n/ I" F  A& Z0 k7 @# \4 Z6 A3.3.2  读取函数app_usb_device_thread_media_read

3 R' f. L( w0 E代码如下:
. X" ~5 `7 F5 N( z- h! T0 Y0 W  E- O; {2 f) w
  1. /**0 ^" {5 I/ Z8 T
  2.   * @brief  Function implementing app_usb_device_thread_media_read.
    * w. s* {4 I- r; e  I5 p
  3.   * @param  storage : Not used
    % c, y+ U  ?4 C7 W* R, R
  4.   * @param  lun: Logical unit number
    & n- V$ u4 c/ U# E
  5.   * @param  lba: Logical block address
    " `! o% \; z  D+ _1 W
  6.   * @param  number_blocks: Blocks number) l$ J( T5 d0 N
  7.   * @param  data_pointer: Data
    / E7 @" s& T. l# z5 e& \
  8.   * @param  media_status: Not used
    & O4 ]8 S* @9 H7 C% W8 D
  9.   * @retval Status (0 : OK / -1 : Error)# j# o+ Q" p9 `: x! K% Y8 J
  10.   */' n$ w& m( D7 {8 b
  11. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,, Q. ^, [- a' m6 a- `
  12.                                        UCHAR *data_pointer,$ Z  X* G6 ~% U6 d3 O
  13.                                        ULONG number_blocks,  V( q. V9 G! \7 g
  14.                                        ULONG lba, ULONG *media_status)7 N# |8 j! k0 {, m! @' s9 w
  15. {
    5 ?" y1 k6 j; {/ |& k
  16.     UINT status = 0U;; p. [9 \9 }, S: g4 L4 Y
  17. , s" H! e( Q& q. q
  18.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                        
    % k. E& b' k8 [7 }
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);9 x9 \% a9 f  o+ |) u5 y! W( H
  20.     status = check_sd_status(0);    , @2 E! g( V, e# {
  21.     return (status);& p( S0 n" D, f8 W- r9 t6 g
  22. }
复制代码

9 ^5 ]5 ?; r1 u) Y1 j用于实现SD模拟U盘的读取功能。
8 v/ g7 [6 L+ w. k# F8 A* ~, A' p; q. X
3.3.3  写入函数app_usb_device_thread_media_write
5 b/ X; V2 ?. z. w, [8 r代码如下:6 z. Y: J0 Z4 I! b0 L" }$ n
/ p2 p2 o( w1 _( f+ @
  1. /**$ @9 N) u  |% W/ I* ?
  2.   * @brief  Function implementing app_usb_device_thread_media_write./ a7 W* C4 P% M1 Z! e
  3.   * @param  storage : Not used, u" a3 J( y9 m/ b  i* v4 y! ]" Y
  4.   * @param  lun: Logical unit number+ y; q2 R& Z; _
  5.   * @param  lba: Logical block address. X6 I2 |2 Y" b9 n% k0 \! u& M; t
  6.   * @param  number_blocks: Blocks number
    ; I; H6 @" w9 d" ?4 ^
  7.   * @param  data_pointer: Data! H9 p1 T2 h! o0 h9 h
  8.   * @param  media_status: Not used
    7 m  {0 c- m, i2 W
  9.   * @retval Status (0 : OK / -1 : Error)
    0 r4 L1 d5 S" Z3 t# _! G4 G* a! n$ G
  10.   */
    4 d8 O5 P7 O- g7 d- H( K# T
  11. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,
    1 O  E& s" X4 @0 ]9 i
  12.                                         UCHAR *data_pointer,
    6 U/ u1 G' j/ z
  13.                                         ULONG number_blocks,
    ( }) y/ p* Y  ]- ^
  14.                                         ULONG lba, ULONG *media_status)
    " R/ S8 x  S8 m+ [/ C$ u1 z7 ?
  15. {
    - ~: r" J. Q0 p4 L7 Z1 o
  16.     UINT status = 0U;
    , _! u5 C: D! U, ?
  17. 8 Z* s+ n: t2 W) |% v* V* G
  18.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);
    3 y( N) E/ x6 \/ h) e0 t
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);  [. Y6 Q* k( S& t# a1 G3 I( l
  20.     status = check_sd_status(0);
    / ]9 w8 K# C9 s9 i9 L3 I
  21. / x% ~  N! B6 T1 v
  22.     return (status);
      n, `7 p. w, S1 F
  23. }
复制代码
1 H0 {# p# ?& B/ R6 I
用于实现SD模拟U盘的写入功能。
2 T$ J& X: x5 _# f# g' i! }! Y) L& T# h. {0 W
3.3.4  接口函数注册7 f* E6 ?- r* Q6 ~7 a" I
接口函数的注册是在文件demo_sd_usbx.c里面:
& z* i9 y: z; {4 U) b9 z* O0 L- ^7 b. o
  1. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;
    , M+ c; k' ?* k; h2 O6 s& y

  2. 3 h: M- A6 d# f8 N1 w' I% m+ S  N
  3. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write; & _2 K1 s4 ?& s) {' k- x
  4. , P5 F& {- D9 Z7 j& v' P
  5. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;
复制代码
0 j* d! o/ c/ G$ N1 ^$ p& d6 ~
3.4   使用的MicroUSB接口并注意跳线帽设置/ ^3 q8 Z5 p7 V8 P
本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:
% y1 R8 U% ^6 f$ u( v- r. L( x) y( x0 D6 H
a9cb882c39474dd9bd63b8c7e14cb451.png

# t  B5 g0 D9 z3 U+ q, E7 I; `4 f: L" J- k$ X& z! C  m
注意使用的是MicroUSB接口:
; A# X  k. B, J2 ]- ], R. q% g
# c& i2 ^8 M/ ^
f871e17a6a2d4c03a9413daf725670c4.png

0 Q$ p) {" M" t- D% u6 H+ {/ j0 o+ T* o  I3 S4 e

2 Q: @! a  k! Z2 X( N  h" [; b注意板子左下角跳线帽的设置:
& F2 Z% r# w4 s' B! Z( ~& h
+ x6 v% ^' D7 X) T! q( T5 Y
41272c92c8c9483f9d5dc6a04cbf87b8.png

  w& \5 Q* J+ x+ k4 q6 n2 P8 P; S6 A5 q* I6 |- r/ }
' m: s3 S# ], h" ]6 s
这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。# |" Q- A0 V+ c( U1 h* @

) @% b) ]' V$ F' V6 h# d3.5   实验例程
* Q1 y) k5 c3 d3 ], V% I- S配套例子:
/ D+ w' `9 d0 p
! a* H; p. a, dV7-2401_ThreadX USBX Template+ U! I3 p& D, _. O

; H0 z+ L& d" P实验目的:
1 @" v5 X2 _: ?5 c7 y( \; ?' h0 L2 z; Q  a" U+ d: `
学习USBX模板,通过SD来模拟U盘。
. i& f% z* _; G实验内容:
8 L) G% V( D2 P0 O$ z4 b4 `
! K6 E' M8 |2 o: N, R1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                 4 L6 D# A& E7 e3 T# B0 p

, V# P* M' C, Z. v8 K  ========================================================
. j( F( `4 N4 [# m3 |8 O0 N1 B! f# M4 ?$ I5 x0 w
         CPU利用率 =  0.89%
/ k4 I( |4 G" O( ^, g0 |/ M
+ G/ r+ S% }7 v' j         任务执行时间 = 0.586484645s, ^$ W: c- @$ {7 T' p2 o% p

. t% @$ s; y% r. a' j/ E         空闲执行时间 = 85.504470575s
! |7 g* N1 B* L3 v* @, v# Y3 l- L! w$ c& e5 q/ p
         中断执行时间 = 0.173225395s' x: G' w( c3 L- U3 }2 s: g; ~
( o1 m3 s5 x+ b7 ~% P* b
         系统总执行时间 = 86.264180615s              7 S- F9 F% y5 O4 _" f2 Y7 ~1 b

3 B4 C( o4 t+ T8 G, x=======================================================
5 n) P1 L9 {% X* a+ H
: c2 S) j( M- r' e: b" ^$ ^        任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名+ i: r) ?, R$ f2 I( G: w

/ ^* n8 V5 f  ^) h  I6 n8 X          Prio     StackSize   CurStack    MaxStack   Taskname' c  d. q( [7 k' G
" ~. d0 W, D0 A
          2         4092        303         459      App Task Start
, Z0 l1 o3 b: c$ G4 A+ B5 o* @9 a5 M! z7 w; |0 Q
          5         4092        167         167      App Msp Pro" z, S2 Z" e0 d  j( ]

0 G# L6 S6 R: m$ H: U8 i+ Q1 S5 }8 O          4         4092        167         167      App Task UserIF
# A; S6 Y5 P* r  @
& J0 ^) D8 p, t- k: D3 \2 X           5         4092        167         167      App Task COM) n6 I& L  o, L% K' ~6 {

  h7 S' [) I3 ?4 Y6 F           0         1020        191         191      System Timer Thread           
) R9 g6 g' G# j4 b/ ]) z7 e/ k; D, p: u
串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。2 ?0 J; K$ Z6 D/ q0 h

2 {& L+ l3 ?( ^1 b7 P; nApp Task Start任务  :启动任务,这里用作BSP驱动包处理。4 N  g/ ]8 k* [8 u% c7 u1 }
; ~; j) l. q7 ]* Q% O! U7 b9 t
App Task MspPro任务 :消息处理。7 l& y# [' @5 f4 C- j& k5 a
4 {* z( s% M  ~! v$ q- ?3 z/ V
App Task UserIF任务 :按键消息处理。% M/ |4 H. K3 o5 ^) o
( y6 g5 }( o* C: t! r; |
App Task COM任务   :这里用作LED闪烁。
( U5 W0 U1 B$ f4 H. G: T
. O; b/ a& V6 g/ m3 x& g- S5 {System Timer Thread任务:系统定时器任务/ b# P2 Y* Y2 R: L+ ^
9 v8 A& C" p' X4 B# [* _
2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。" s1 V# B3 @8 N) N& _
1 g3 {/ r+ u. E  _4 B
      (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
8 n8 l, a  K# O& X8 o  K- X6 s: r/ B  z  Z
3、默认上电是通过串口打印信息,如果使用RTT打印信息
+ s/ R4 W% L3 Q& e& I9 v: d9 Y( k8 G  u/ p1 [/ a, q$ ?$ s
(1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可
* P  \  G: O3 I6 @% ^$ K% @0 P
#define Enable_RTTViewer  10 q7 E$ g0 H  _  G- [& M: T

% a1 W8 f5 r( p5 j, L/ H) N(2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。$ X0 e. A5 }% D- D

& z8 U. Q( |& o' H+ e( n. P实验操作:
5 e. J  ]: \% j* n8 L7 P
0 o' L8 ?5 Z- |" u6 A5 U2 Q9 Z测试前务必将SD卡插入到开发板左上角的卡座中。8 J, t: Y0 K* d! C7 B5 N0 O
支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可7 A$ @% K! X+ U5 T. I% t
printf("1 - 显示根目录下的文件列表\r\n");
: I3 I1 ~; t  J3 R2 `$ D% uprintf("2 - 创建一个新文件armfly.txt\r\n");4 E) Z" Y9 c" M1 S2 c
printf("3 - 读armfly.txt文件的内容\r\n");
* P8 D6 l' U. ^8 [9 [8 `9 kprintf("4 - 创建目录\r\n");
7 E) W7 U6 e9 H0 u8 s: c8 @  y8 ]printf("5 - 删除文件和目录\r\n");1 B# s1 i3 [4 v7 T2 O' g4 a5 I1 c: ?
printf("6 - 读写文件速度测试\r\n");
# O7 M4 _4 V% A0 B4 Yprintf("a - 打开SD卡模拟U盘\r\n");- ~8 @" Y  A' F5 i
printf("b - 关闭SD卡模拟U盘\r\n");" c% J0 s: e" X. N! ~
串口打印的信息:0 H$ g: S/ U+ o9 y: j. X

  u3 W# [7 |  v: B- s波特率 115200,数据位 8,奇偶校验位无,停止位 1/ A4 L6 h: K6 |9 I) c
" ], z) K6 |& y
74d954c9e7b649289184a7a4bd58d6e6.png
+ K5 I7 {* F. \! U+ J- {/ ^3 l
  P& b4 `% B8 a0 N9 q8 ?3 s
+ O& K5 w- }+ V0 M; W3 C

, G2 ]9 e5 |' nRTT打印:1 p8 o# I* [1 w' e& \6 m
3 \4 k/ e" p! c- v. g% N
cdcab0e093ed468a912923050806de22.png

3 ^0 I" |' ]2 ?& j' D% V; {3 }5 J, L7 [& z( }7 S

: L4 U% L+ [9 g' h
: x) A9 N* h  v' H3.6   总结
7 W$ |8 X8 q3 Q) Z本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。/ j$ y. g7 i$ Z) m4 ]" B

  O# ]. U. S- z6 o7 \' w/ J
6 x' s3 L) Z) C& J# X  g9 K) r" l) T# W/ N& `6 T, }/ S, y
赞 收藏 评论0 发布时间:2022-1-1 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版