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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 19:00
3.1   初学者重要提示
- o8 e' l5 L& l8 z5 w1、  本章使用的ST专门为STM32H7提供的软件包: b# P6 H  `" a7 ]$ r( P

8 H& f8 E. Q+ c# F1 M  G0 t% R2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。
& s. s; k8 J4 F( a7 W
# \. m1 P$ K$ G" u3.2   USBX移植步骤
9 F% j1 O' P# V3 V  Y8 [# a+ YThreadX USBX的移植步骤如下:
! C# m* D2 n. c8 r: H/ v7 G
6 t2 p9 B# f! P! N* z3.2.1      第1步,了解整体设计框架
/ u- ]* C) ?+ ?为了方便大家移植,需要大家先对移植好的工程有个整体认识:' y9 {0 I; Y) x5 W
& x+ t0 |: x1 I) ]- O) \
556edb9b3bb947f5b69aac84272def1d.png

$ h* Y# C- M$ Q9 K8 \8 V7 b
6 Q+ s/ Q  F% V( m9 R0 N3 j9 q* [$ R$ G# B; Z" {
3.2.2      第2步,添加USBX和USB驱动到工程
3 W$ ?2 o" _5 k8 Q0 v/ p这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。# `" b; o: q) O3 o/ |: d+ t( x

( V. [8 w2 [- J1 u2 I: y- D: W" ]- k' a  模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。: P0 _. d2 [# I2 d" i
配套例子是放在\User\usb文件。6 X! S# G0 g9 g: ~& R, A

3 u. ?2 C( V9 C4 e  USB驱动文件stm32h7xx_hal_hcd.c,stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c。8 d3 j5 k/ i: g. C, X
这个是STM32H7的HAL库自带的。
, X) q1 H! o" Q' J* J5 o1 J4 W% d% u2 f: A0 E
  USBX相关源文件。
& d' F# ^; p" K大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在\USBX。
4 T9 p* [% K7 @( o
9 f" M1 X0 F8 R3.2.3      第3步,添加工程路径
* \, Y5 K/ q- W$ H大家根据自己添加的源文件位置,添加相关路径即可:4 H2 L5 a' z  V" @  ~
' m% A' Z2 P( B* ]6 h/ `3 V
7d4292e15d424274b8e5aab1d6cd32a9.png
  h2 z6 p0 ?; n9 K% f4 P# T0 @

& a( b' T$ B' K8 \: |9 b* [
5 G# D" r, W5 d2 F& S% r' ]  e4 o8 a$ U. V
3.2.4      第4步,禁止掉添加进来一些文件

" Z) o* w7 Z7 X  s/ x' y& c7 U之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。/ Q( ]" |/ m7 @" [1 c% t

4 k; g% T; z1 G0 p0 G- ^, T* h
418a71e2dcbd48a199034bbf6765d9fc.png 4d161770a4734368b6881fe1ed982494.png
7 D; q6 V  `  I9 Q. d& \( p
- ~: q8 V  l/ J
696837e6177b4f3caa286c6913cf4ea3.png f052ff2297b4462daa7186e7fc3b6ab8.png
. l3 ]  x1 v6 r" s
. O/ t. h) G" u( R% e
0dadc8e05ea349beb4e04a737e86ed07.png
: e; s: f: X1 K2 j+ m
& G2 {$ W2 d: T: U
禁止的方法是右击此文件去掉如下对钩即可:/ e. ^) g* Q/ e: R; g+ Q
3 i) S  `& B- H! K: k0 t
4db1e499f0f7422f9e522bf1e7bcecfe.png
- ?$ M& u: j+ l* f+ H  v/ d/ o
5 K: t1 F3 h% T, Z
6 t# \$ L) f3 l4 I
- N+ s" z) Z% I; _
3.2.5      第4步,配置GPIO和时钟$ Q" J8 z- ~) C2 e: V
USB时钟配置在bsp.c文件的函数SystemClock_Config里面:; A: d& @. v# O6 t

2 V. F. I* u! Z! s- Z& [( q; o
  1. {
    2 v: H1 j  s) s& ?* {) p3 ]4 b( S
  2.                 /*8 I- A) R8 w; R
  3.                 USB工作需要48MHz的时钟,可以由PLL1Q,PLL3Q和HSI48提供1 R* e5 f2 N$ x- q1 p. s& k0 a
  4.                         PLL1Q用于给SDMMC提供时钟
    8 @9 f6 X# Y7 u+ B" l' i
  5.                     PLL3Q给LTDC提供时钟,也可以跟USB共用,不过得更USB设置相同的频率才可一起用。5 |) f' H$ F; V  X; p( x% j! [% f
  6.                     HSI48可以供USB独享,就是精度不是很高。
    , U! V" P' D: j, E0 U+ d9 I
  7.                 */
    ( `7 i9 J5 l7 {- h+ G
  8.                 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};8 t, W9 v9 w- e1 M1 F5 B$ K
  9. #if 0
    $ |; G. F& u+ f) P  f, [, T
  10.                 /* PLL3-Q for USB Clock = 48M */
    4 I: r" S6 |& Y2 J
  11.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;* j$ P/ R, H: T. |6 ^- P2 C
  12.                 PeriphClkInitStruct.PLL3.PLL3M = 5;
    ) q/ V! b1 _$ N. u; V
  13.                 PeriphClkInitStruct.PLL3.PLL3N = 48;# P8 {) x+ L* o5 I! M1 T' d
  14.                 PeriphClkInitStruct.PLL3.PLL3P = 2;$ p# z. G, W4 N7 |  ~6 N9 E
  15.                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
    - e' |$ U( }' X9 X/ y
  16.                 PeriphClkInitStruct.PLL3.PLL3R = 2;& e) ]! M$ K, ?% r: D, K' B) Y8 X
  17.                 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;- x4 P; r# a% _
  18.                 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;, L3 w, V$ o2 T
  19.                 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;( I5 O$ `: r" I9 N9 F
  20.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;' q  K" j% [) t) j
  21.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK). ~' {! E2 Z3 ~% T9 N
  22.                 {: E, A6 ~$ d& R/ e2 [! m
  23.                         Error_Handler(__FILE__, __LINE__);
    " w0 K7 t8 |& N- B( b0 F* ?3 o
  24.                 }        
    , x* c& F  |/ O+ C; |% c( D: t
  25. #else
    . h" h4 X# E& V# K6 X
  26.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;  f% {3 [, u5 L% w
  27.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
    . y9 F$ I0 j) g" I3 u( i" L
  28.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK); h- B3 }0 G2 b8 e8 d+ h
  29.                 {3 R1 _+ @( w. u+ e: @/ u
  30.                         Error_Handler(__FILE__, __LINE__);
    0 @0 d7 B$ U6 X! {2 H7 H7 f- F0 K
  31.                 }: P0 [' k. }: }! X& W9 D
  32.               HAL_PWREx_EnableUSBVoltageDetector();: L) [2 k$ @- r( i
  33. #endif! h. A/ Z: Y/ n4 E
  34.         }        
复制代码

. E7 s# A1 k3 e3 X, m% P( UUSB的GPIO,NVIC初始化在demo_sd_usbx.c:
+ r- S9 b$ t) x  d. w1 \; N; q% J+ G5 r
  1. /* 配置USB GPIO, NVIC */8 _3 X2 L+ h6 s& t0 X4 K
  2.     {
    / O' Q/ J* q( f! q+ @, n
  3.         GPIO_InitTypeDef  GPIO_InitStruct = {0};# ~; R  L0 ]# W) |% C+ q

  4. 8 ^0 M5 B; `6 l. `/ ^
  5.         __HAL_RCC_GPIOA_CLK_ENABLE();% J7 |! c9 p; T" Z; d

  6. # I+ T* ~. D  c2 ~  G; g
  7.         GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);( S% a5 w& z8 W7 Y6 t
  8.         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;7 x8 ~7 P& N0 z, P) `
  9.         GPIO_InitStruct.Pull = GPIO_NOPULL;
    2 k1 T& V& L4 ~* E7 q
  10.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    ' v: K5 ?9 F' X1 a
  11.         GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;
    5 `7 {4 ~% ?; x! |& Y" A
  12.         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);' a3 O- e; l$ K, g0 [% S

  13. 3 H5 F, z) A( W* n4 o! Y
  14.         /* 使能USB FS时钟 */
    : Q4 ^$ }8 U4 Z( M6 y! A  k  W
  15.         __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();
    $ A% S1 |- L# p- }$ n4 t  s
  16. 0 U$ H; `9 Z9 F9 u( J! j6 {/ f
  17.         /* 在睡眠模式下禁用USB时钟 */5 ^. A8 X/ J9 j- p- Q, O! K( l
  18.         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();
    8 ?: c8 O+ {0 y2 W- X- d

  19. % }$ v; }7 O8 [! \) `
  20.         /* 配置USB FS中断 */
    - J+ I/ N) B6 i  s- i+ v
  21.         HAL_NVIC_SetPriority(OTG_FS_IRQn, 0x2, 0);
    : A, b5 {7 s0 w& i, i6 O5 ?
  22.         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);- W6 W$ B% c2 X4 e; I: v
  23.     }0 o7 `+ p! m; }, s9 u; l9 q$ a' k# q

  24. 1 N( b. e- B( C
  25.     /* 初始化USB */
    : w& C: b" y# d  O
  26.     {
    ; z1 n+ |. V! R0 _" a0 i1 o9 e
  27.         HAL_PWREx_EnableUSBVoltageDetector();, s$ A9 i  `, A5 G" p+ h2 y

  28. * S7 z+ W1 D! D, S; ~2 D
  29.         memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));- b5 N! e% C; Q2 X& ]5 y( D
  30.         hpcd_USB_OTG_FS.Instance = USB2_OTG_FS;
    ! ?/ \9 ~. W+ ~: f
  31.         hpcd_USB_OTG_FS.Init.dev_endpoints = 8;
    ) k+ E+ E2 B6 l0 O3 Y
  32.         hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = 0;6 B, o. b1 y  P
  33.         hpcd_USB_OTG_FS.Init.ep0_mps = 0x40;/ l) V. j% ]/ l8 \( ]
  34.         hpcd_USB_OTG_FS.Init.low_power_enable = 0;
    ! ?9 _* H: O3 Q, K
  35.         hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
    ) ~, j) m% N9 ~4 ]  c
  36.         hpcd_USB_OTG_FS.Init.Sof_enable = 0;$ z" @. Z6 [) g9 w9 X$ A0 F$ V) H, g
  37.         hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
    . I, W& P; e0 b4 x+ ]
  38.         hpcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;4 @' u5 a& J) w3 X
  39.         hpcd_USB_OTG_FS.Init.lpm_enable = 0;
    ' X# C* L: Z$ I; J8 B* q
  40. ; j) a6 @8 N+ [1 z, W
  41.         /* 初始化USB  */
    3 [+ K) z4 L! p0 W- J' h! c8 e" M
  42.         HAL_PCD_Init(&hpcd_USB_OTG_FS);
    $ N& }; i) [9 R1 Z

  43. 8 P* g' g7 r' t1 Q$ u
  44.         /* 设置TX FIFO和RX FIFO */
    ( n1 q& J5 u% U1 {
  45.         HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 1024);4 b3 y, f% K5 \4 I; s+ q
  46.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);1 e, O" `5 y! C3 n1 N0 v
  47.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 1024);" Y4 G  P  t$ _2 c. ?+ h$ m

  48. ; l& I' D- K2 I& F. [
  49.         /* 注册STM32到USBX协议栈并初始化 */
    * x' z3 Y! ]) B' [% t! V9 t
  50.         status =  ux_dcd_stm32_initialize((ULONG)USB2_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);5 n/ Z: Y: a7 f
  51. 2 @$ z: Q4 Y" j  s
  52.         if (status != FX_SUCCESS); @2 P( n, D* r8 Y2 @9 ?
  53.         {
    8 s& K' `! O' k# @1 t. _0 t5 F
  54.             return;4 l/ r- ]; x  e( l( B% g% ^
  55.         }
    ! L0 c5 }; h. j6 S( O& D: w
  56. * I1 x% g% _4 h) g) N+ q% D3 A
  57.     }
复制代码

- n" [% _8 g  Z9 ^3.2.6      第5步,MPU配置
9 n# i0 }+ S4 G' E
为了方便大家移植测试,我们这里直接关闭AXI SRAM的读Cache和写Cache(这样就跟使用STM32F1或者STM32F4系列里面的SRAM一样)。此配置是在bsp.c文件的MPU_Config函数里面实现:
7 q* y. A  b" t' G( L% w
9 `2 v3 y) A7 Y' e2 S
  1. /*
    % C5 h. D4 t7 y+ o8 T  D& G
  2. *********************************************************************************************************
    ( U' C6 h7 H! h( d* u3 _8 b
  3. *        函 数 名: MPU_Config4 |& Z+ F* z! p' |  B. ~
  4. *        功能说明: 配置MPU
    1 D! w$ U7 M  \* j2 l6 r; v$ }* n
  5. *        形    参: 无
    2 M' e, d3 y# m4 t& \
  6. *        返 回 值: 无
    7 g+ d9 P, W8 G. ~
  7. *********************************************************************************************************
    - z8 d9 r9 c# x% X2 _1 }- l
  8. */% S3 R% d! M5 u8 I% ?
  9. static void MPU_Config( void ); k: f* T1 }, k0 i* i# E
  10. {
    1 b5 f% o4 W4 J# [( ~
  11.         MPU_Region_InitTypeDef MPU_InitStruct;& N+ S5 {/ _5 g+ |' G

  12. 2 n; _9 w+ F6 Y7 P& W
  13.         /* 禁止 MPU */2 E& Z& @; U. G- L7 R  @7 u
  14.         HAL_MPU_Disable();
    # s$ Z+ {4 F( L/ Z0 r

  15. + {6 M/ T3 w( z' p/ N: Z5 E/ R
  16. #if 0
    ! B% j0 z# }7 H4 x5 w9 b0 a, r! y
  17.            /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
    + r+ c) i, G! b8 G* H/ `5 Y
  18.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;" x0 G6 B; c7 A$ d" R8 o
  19.         MPU_InitStruct.BaseAddress      = 0x24000000;& P* `! ?2 @4 U# o- _4 @" i# @. g
  20.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;$ }+ W" O1 W/ f1 Q& b$ i: @; F7 B
  21.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    $ D6 H* @' Z* C( H5 c+ L
  22.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    0 S* D' Q! o! G* i& e/ `
  23.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
      i! L1 L0 ~+ O5 e! l& }: a7 l
  24.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;9 C; M/ P/ A; O9 _, P" E
  25.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;4 r; z2 m4 ?# n
  26.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    & F7 ]: u; P! |2 O
  27.         MPU_InitStruct.SubRegionDisable = 0x00;
    % w1 l4 f) W5 r1 V" }
  28.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;9 K" K$ |5 W1 W1 ?

  29. 7 ~  F* y6 [; b0 |8 S
  30.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    2 T. y% x- ^) K6 c  c# S
  31. : E6 z: ?4 s3 `
  32. #else, e* [, j1 |+ y& O% H
  33.      /* 当前是采用下面的配置 */& o3 h1 t& }: W$ f; ?# q
  34.         /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */3 S. `- [# H8 ^7 H% _
  35.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;3 y) d. F( ]/ f% L' f
  36.         MPU_InitStruct.BaseAddress      = 0x24000000;- k" X4 C# J+ f+ U3 c7 v2 K
  37.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;, ?. V- X' d7 _" z( Y3 W$ [* o
  38.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    & L- T) Q# }" o1 g# Q
  39.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;3 O9 c+ X' t- [5 F0 Q4 P, Y
  40.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
    : |  Q% V1 U9 f3 x  y$ o& H
  41.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    % |& m9 [6 [4 x4 Y
  42.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    ) r" I% e/ y/ @: u+ ^% }6 F6 _
  43.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    - ?* v+ L6 C9 C3 J+ V( [
  44.         MPU_InitStruct.SubRegionDisable = 0x00;2 S' y' T* j5 d% ]: e. K% f
  45.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;3 t! }9 X, ~9 I* ^: J' O# z
  46. 4 a. _2 C5 [/ r' t
  47.         HAL_MPU_ConfigRegion(&MPU_InitStruct);: w! E2 i3 M! l7 s* e* w/ [
  48. #endif
    5 g; Q. ^7 I0 h' U  F2 B' o1 ~
  49.         /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */9 M1 q7 l% Z- `* v8 h% q
  50.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;" X! L/ f: j9 m8 H: ~
  51.         MPU_InitStruct.BaseAddress      = 0x60000000;( v$ I* [" J8 G. A4 U/ y3 _3 h: E
  52.         MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;        
    1 S3 [: u- T5 a) Y( f  R4 M
  53.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;/ b0 r; Q0 J7 P! c; j' _
  54.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    " O: N8 Y" Y9 V' ^% v: S
  55.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
    ! Z: T/ d1 e6 N, }& q
  56.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;; O, ^/ i% a" T# ]3 A
  57.         MPU_InitStruct.Number           = MPU_REGION_NUMBER1;6 L% Q$ ~* X# Z1 W5 `4 }
  58.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    1 \) I6 C4 K5 ^, u  @3 T% s) R
  59.         MPU_InitStruct.SubRegionDisable = 0x00;
    6 t8 a# q( n: }" p2 u" f2 A5 \9 \
  60.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    . g$ Z  F5 T2 j# R( W9 J, K) ~$ m8 h
  61.         
    ' t+ O$ M. Q$ Y3 P
  62.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    : s6 Q2 R# l2 @. h5 r3 U5 F: T" R1 `; {

  63. 9 ~) {6 P8 N, V/ @
  64.         /*使能 MPU */" ?+ t0 f' H: _$ h" [, g% i* v
  65.         HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    , t2 X7 Z( V( A$ H
  66. }
复制代码
: V9 K2 e$ W) P& {8 |
3.2.7      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)
  ?/ b" ~# [* E1 M
USB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可8 N* _2 X2 g6 d8 \. ?* a

. R3 o) i) V. n. |9 f- T3 o  U特别注意USB中断服务程序别忘了添加。
! A0 ?# H( o7 E0 T: n4 k, ?% z1 i/ j1 v! t# K$ C1 ~0 P& ?4 O
3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明; u& s5 m, H& K  \$ r! c3 z# G; x
这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。
9 A3 E' F, B7 p+ G, ?+ Q& ?' \
3.3.1  状态函数app_usb_device_thread_media_status
$ T, f8 M8 A, ^6 X1 G! v代码如下:
9 [, i5 A" W" x9 c' F4 q7 m, v
% j/ `' X& i% H- T5 p4 V# u
  1. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)" o3 P/ f7 T- h' E& j2 w
  2. {. Z& g- c, D4 C7 a! l
  3. 4 e2 Y3 I9 J& m( p( l1 {
  4.   /* The ATA drive never fails. This is just for app_usb_device only !!!! */8 p$ y' f4 A' g& h- Z
  5.   return (UX_SUCCESS);3 t& X/ G( C8 T) A
  6. }
复制代码

( E+ j4 c: g$ m* _, z此函数主要用于获取SD卡模拟U盘的状态。
" i% a# \. P. F8 n/ f- o9 u! p3 G" B$ o8 h6 u
3.3.2  读取函数app_usb_device_thread_media_read

1 P3 _3 t# K: z3 J. L) W代码如下:
2 t! P/ J! W3 ]& V' P  |+ _9 V. {' y9 t' h
  1. /**
    # E" ~3 }  [. z2 o: m5 }3 F
  2.   * @brief  Function implementing app_usb_device_thread_media_read.0 q. R. Q4 k2 E+ [# [1 d7 N, L
  3.   * @param  storage : Not used+ y. E* [% q: l4 L
  4.   * @param  lun: Logical unit number; N) ~- i' v: M. e! I+ ~& k8 q
  5.   * @param  lba: Logical block address6 r4 ^! B& b1 t/ I# V
  6.   * @param  number_blocks: Blocks number
    1 A* I0 r% A) s: i1 H
  7.   * @param  data_pointer: Data+ e* ]- \9 D  P
  8.   * @param  media_status: Not used0 K+ g/ ?' t2 m  P
  9.   * @retval Status (0 : OK / -1 : Error)  j$ f5 k: g) v2 j8 J" ?- V
  10.   */
    + M8 t* ]0 Y9 n3 ~$ M; ]
  11. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,& u3 X3 E) f6 V8 N8 o* s/ {
  12.                                        UCHAR *data_pointer,
    ) h4 z; n- t. I2 j9 u2 W0 Q# K
  13.                                        ULONG number_blocks,6 N0 ~. ]1 \0 k+ L7 {$ [
  14.                                        ULONG lba, ULONG *media_status)
    4 J! E, L) f  \' W
  15. {
    + R  z  h1 ?7 k* ~' d; C5 v+ ~7 |1 {
  16.     UINT status = 0U;
    * Q3 M* j/ T4 j2 a( K

  17. 3 h- C8 q" O$ P) l6 R  ?
  18.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                        
    & k  \' A% o2 O
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);- f! S9 R8 |/ p) b: I, {& I
  20.     status = check_sd_status(0);   
    1 w" v3 S1 j0 f$ M
  21.     return (status);
    1 J  Q! s$ g2 r+ K
  22. }
复制代码
# g/ r. Y3 V, ]. m1 U4 _
用于实现SD模拟U盘的读取功能。
& x2 }5 ?% {% m- Z2 g. `% Z
) j+ q6 Q, C5 z# P+ o$ b! p+ k: n3.3.3  写入函数app_usb_device_thread_media_write
: C0 i: u% g, ^$ T, u& a/ w代码如下:. n' o3 I3 ?2 P: v5 `" K
8 G, S) Y0 @6 s4 E5 ?. G
  1. /**
    ! j; r2 O# }/ }9 t$ }, ^& o
  2.   * @brief  Function implementing app_usb_device_thread_media_write.
    ' }+ r) X' G% m8 U& a  A
  3.   * @param  storage : Not used
    + a3 M5 }% {5 w4 L
  4.   * @param  lun: Logical unit number
      J& O% @/ r& q: r$ m( f4 a
  5.   * @param  lba: Logical block address
    & S9 F( M, x' V( J' f2 x* e
  6.   * @param  number_blocks: Blocks number7 ]9 n/ H" h5 l  q9 {1 h4 F
  7.   * @param  data_pointer: Data
    " L5 P) L0 Y" z3 H$ E
  8.   * @param  media_status: Not used
    9 Y" P5 g, h* ?7 h
  9.   * @retval Status (0 : OK / -1 : Error)' G/ a  K4 a% a, s( g3 }1 y4 _  L
  10.   */; W: g/ _* U6 O$ b+ b) M1 A$ `
  11. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,2 h! C6 [8 {' d/ ?
  12.                                         UCHAR *data_pointer,0 H9 k+ P+ Q  J3 P5 l9 e. ]! C& f# Y
  13.                                         ULONG number_blocks,
    3 M# t& @$ A$ n
  14.                                         ULONG lba, ULONG *media_status)
    ! [2 z* _* U9 [$ U& w: u% {
  15. {: v( I; C8 i) O% [
  16.     UINT status = 0U;3 _' [1 R, }4 L

  17. 2 S' B+ J& V% H& P# t7 J
  18.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);8 Y' E0 o0 b( ]
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
    - g, U  K0 g- Q+ C$ @: @
  20.     status = check_sd_status(0);
    + i% U8 |6 \% f  {  |
  21. 7 U8 G- C. D& n; l- l
  22.     return (status);9 ^; l0 D5 x! _+ x$ u
  23. }
复制代码

. o- o$ p* `( b用于实现SD模拟U盘的写入功能。) e  {  r; S% ~1 s
- Y5 }" y$ M6 t
3.3.4  接口函数注册
6 w: H; r) N+ K0 w$ M接口函数的注册是在文件demo_sd_usbx.c里面:
+ k: L5 d9 `; \  K, H! x3 M, ~  S2 ]  E* `% H. C/ p0 A4 G
  1. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;6 H) k" e' _! S1 u) G# s
  2. - j8 i& S7 V) G) h9 f4 H8 p
  3. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write; ( j0 o  y' I/ _8 |9 x' h* m
  4. . O* m: L+ v1 H% I( X2 @
  5. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;
复制代码

3 f7 `1 v; j$ p8 s  Q) N/ G, d3.4   使用的MicroUSB接口并注意跳线帽设置2 J% t, Q4 S9 `# J3 l' m
本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:7 a; ?7 ^! M+ k
1 Q+ k) G0 k( N$ z
a9cb882c39474dd9bd63b8c7e14cb451.png

$ U$ [- p* d7 T9 H5 M9 c% |5 T  k: C0 `/ i+ t" P0 _  T
注意使用的是MicroUSB接口:
9 @! Z! u, ?! c8 w
+ h4 g8 B( i1 q
f871e17a6a2d4c03a9413daf725670c4.png
. q+ t8 R4 {2 |8 n
; n  b, J4 A$ n+ ?, Z

( J1 }' z' }1 v5 j9 {" ^+ p注意板子左下角跳线帽的设置:- M5 i* X8 o  o3 v- \, b
% `5 @8 F' p. F" z3 T
41272c92c8c9483f9d5dc6a04cbf87b8.png

' t$ [3 J2 j4 r: g  C
3 Z; c$ v, w% x' @1 h% {, E5 I# Q6 x+ `5 [3 s. Q$ ~9 u8 w
这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。- P; V/ b2 o0 ?" y/ e7 o$ O& B
8 [1 I, F8 x5 M9 O
3.5   实验例程
6 _( n& r+ Z0 }& w% W  f0 A配套例子:
4 n) h6 H; H" w0 o; ?6 `% S
5 ?: u2 ~! c* TV7-2401_ThreadX USBX Template
* J( ^6 |' e6 E( ?+ R  ]% p7 o
5 w; J* A6 l) q+ O+ J0 |9 d# l实验目的:
6 a- u6 T) a1 r& @$ Y4 _  N0 J# N' W7 E( M% l
学习USBX模板,通过SD来模拟U盘。
/ F. |# O: u9 A6 n* n$ ^. E, o; @: u实验内容:
" j2 o( w6 O4 a+ T  c- u/ x- E, ~& z3 }4 R, G9 t% C
1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                 
. N+ I6 ?) F" @  Q2 j& z2 W& e6 g/ X. a) z* r& x# I6 ^/ `. K
  ========================================================! m* ?5 P" H  B. R
/ j' q9 Z; p% a" ~9 W3 D6 w. r& H
         CPU利用率 =  0.89%
% C% G% J/ Q% J  U" v$ c6 z
0 ^! u7 W; ]' X) \         任务执行时间 = 0.586484645s
( p1 c) f7 C- K% H
3 S6 j# @  A) @! u) L( r" N" h: R         空闲执行时间 = 85.504470575s
7 k$ T+ Q" j8 E. B; s/ T: V. x, D
) g9 D2 Q3 \7 U8 X  {         中断执行时间 = 0.173225395s
2 y  r- k3 K4 \4 i! \% w# u) }, v3 d7 h! I" r4 J
         系统总执行时间 = 86.264180615s              
7 Q4 l- M, r% r( T6 h
" i7 r( Y# O2 Z' I6 R* ]5 J' I6 w0 Z9 I=======================================================! k' h8 d# h" M' [
7 P* h9 _$ x* N6 f, w
        任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名! `" y% t6 ?9 C1 ^5 g1 d3 q; h+ o# d

9 e% H' F- s1 f          Prio     StackSize   CurStack    MaxStack   Taskname) D- M8 X* {9 C2 T  |6 t

8 `1 Y/ |. L+ }* }/ T  }) C          2         4092        303         459      App Task Start9 C6 U& M$ I0 V% a, l
8 `3 c$ ^% ~: Q
          5         4092        167         167      App Msp Pro
$ J- s  r( \7 l) K6 O0 V+ d4 k- t8 O# I* k
          4         4092        167         167      App Task UserIF
; K) u) @( r% c! B  A, f) X
, Z% z2 I; h& ^0 f: \           5         4092        167         167      App Task COM
, _  ~& P8 z; z% b2 W5 p4 R3 j
* Y3 n* |' M* j3 n$ }8 o# y           0         1020        191         191      System Timer Thread           
0 ^& n8 I4 I1 y- x6 I  m% Y& P# B# D4 o1 [' g+ [8 o
串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。
  _5 [3 A5 X2 A2 H; w
" d4 G5 u' Z; N7 RApp Task Start任务  :启动任务,这里用作BSP驱动包处理。+ a5 }/ w. @; V, h7 k- i, y" p

9 f* f! i1 T8 {$ q* X1 ~% h# p9 ?App Task MspPro任务 :消息处理。. o( d: u- J1 L( c7 {" A: i

( r8 R8 n4 i' d) P3 L1 \( kApp Task UserIF任务 :按键消息处理。2 b8 j2 b, x; r- i

" R; m, M; n: q7 l; }0 |# a) @App Task COM任务   :这里用作LED闪烁。
5 D1 w  _6 b- {: y: ]" y
/ \. E" r2 ~- J: @6 @2 q) vSystem Timer Thread任务:系统定时器任务
; S: Z) }$ Q; f- i6 L$ V  T; g3 ]9 U3 R$ D1 h0 i. R
2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。  B. k- L/ q; c) O! F/ Z
, a; p9 }( Q9 f' ~1 o' g. v2 h4 U
      (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
; K0 @2 e' ^# J' }1 z* ?
1 r' e- t  P) h" |: y+ E3、默认上电是通过串口打印信息,如果使用RTT打印信息) C7 K& F2 ^- l

5 Q& z+ C* D# o2 [(1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可
: }! k9 f6 X" l/ B" r/ ?
. k: R! Z8 S' v0 P& W, h#define Enable_RTTViewer  1- ]5 L7 s% a4 ~; _# `7 X8 I

; n. ]; U3 K5 D: n7 }" d(2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。/ B0 h4 u" _2 m! g' D9 Q9 X% O
5 d7 W0 {/ m- t! v1 h3 |6 q) {
实验操作:
8 n& e) L- u! J3 |. H. H% b4 w+ s# a# x! ^$ U6 q
测试前务必将SD卡插入到开发板左上角的卡座中。' G9 W. m+ U+ u8 R
支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可* r4 V  p6 \, E9 R
printf("1 - 显示根目录下的文件列表\r\n");
  f* L7 ~# t' @printf("2 - 创建一个新文件armfly.txt\r\n");
! {/ W. R7 E* e) U4 z, q4 W: E+ ~printf("3 - 读armfly.txt文件的内容\r\n");
) s  v! p2 c! {+ kprintf("4 - 创建目录\r\n");
5 q* s7 Q) y' N0 V4 H0 rprintf("5 - 删除文件和目录\r\n");( V4 g, q$ B( I! H2 @
printf("6 - 读写文件速度测试\r\n");
7 O; Y: e0 n- ^) `printf("a - 打开SD卡模拟U盘\r\n");
5 Q9 \2 O% ?2 M/ V+ R' z+ Uprintf("b - 关闭SD卡模拟U盘\r\n");
* b7 j2 X8 N0 a# Q3 @2 _% {2 d串口打印的信息:
! O3 x4 Q3 ^  w7 E' W, K1 T" ~( w' E& n' M
波特率 115200,数据位 8,奇偶校验位无,停止位 12 Q8 Q9 k* E, Q  l

0 N4 n) a. F% P2 u8 V0 A4 L
74d954c9e7b649289184a7a4bd58d6e6.png
4 Y( J2 F& L! J( M( z/ S& P

5 }7 x2 y( }/ D0 N6 G% B2 l6 k! E
* b6 [' s3 w/ X: U' H! h: H
7 H+ _$ z* ]0 O1 I; X1 BRTT打印:
4 j0 u* V9 @& I5 Y4 b
+ n' ^, L! g' F& D) B5 G& H7 }
cdcab0e093ed468a912923050806de22.png
. b- ?3 B& d8 o' R( W. w+ @
' l- f6 {  m0 E3 W  i
# e6 e* g* r) ^2 Y2 Z, T9 k
$ m7 g0 Y5 s0 O# v4 V* T. t
3.6   总结4 a1 Y- J, f5 D! D. p9 c9 u% C+ x
本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。3 E7 c# k) e) I; S: P8 Q

* o% f; P" h. v4 F' K) c) k$ t, J! \7 [% ^5 O' S) b9 O! w

" F5 h. |/ i' }  f+ D1 t
收藏 评论0 发布时间:2022-1-1 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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