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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 19:00
3.1   初学者重要提示" u9 B' I4 ^3 M6 x) c
1、  本章使用的ST专门为STM32H7提供的软件包
  h! ]( v$ e3 H; X: V# U; a7 l" [  a' b) t5 J' H* i
2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。
8 v9 m# I. ?: l
- ]$ ]# ?! l2 `  N) e2 c% S3.2   USBX移植步骤
' @5 L* ]5 n5 H2 m9 @! v( [+ Z# S! PThreadX USBX的移植步骤如下:
0 A' A$ C2 p: U8 W* x
9 {0 P. \" e& o8 w* n* D3.2.1      第1步,了解整体设计框架) @5 ?; D& a8 f2 b+ e+ K1 q
为了方便大家移植,需要大家先对移植好的工程有个整体认识:8 n, Q; F1 e. S
6 Q. E& C. ?' E6 P$ Z0 A1 x
556edb9b3bb947f5b69aac84272def1d.png

6 P- T3 k! Q, ^. k
' q+ L6 t" Y5 T" d
, m9 t2 L$ T/ W0 T; V3 s) U# L3.2.2      第2步,添加USBX和USB驱动到工程
+ e1 p$ O8 w# Z这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。, v$ H* ]6 q4 m3 K

/ [, S2 H5 T0 O8 _- G* _# A  模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。
  s6 s+ X0 N  K& G配套例子是放在\User\usb文件。
+ V- `9 \) c# \0 }2 A( x
' g+ C$ v5 g6 \7 l0 |  USB驱动文件stm32h7xx_hal_hcd.c,stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c。
) B: k  y- O% T$ ~% w& V这个是STM32H7的HAL库自带的。) m3 a7 ]3 h$ k) ]8 T
* [" c1 B. g# }7 L- x+ V. D
  USBX相关源文件。
( l, l4 l' b; f% ^8 L5 D/ `大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在\USBX。
; i& ]* d/ g3 B
  Y2 L+ s. k/ ?+ W% H" C3.2.3      第3步,添加工程路径% q0 ]4 @8 e! F8 D$ w# Z, ?6 x
大家根据自己添加的源文件位置,添加相关路径即可:/ Y4 }* V0 F( ~- x& j' J

* c3 ^  ?" [+ w4 w2 b
7d4292e15d424274b8e5aab1d6cd32a9.png
  `1 i' u1 u' c6 ?/ V+ A, A
# P: r! \4 K/ H/ X" f9 a

& g) J3 y. M- K) W9 N% B* T, O3 G) M
3.2.4      第4步,禁止掉添加进来一些文件

& v' T& x: l6 c8 F' J8 T之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。* E: _# z! H9 T# c1 g5 Y5 `3 O
; Y8 C; c4 Z. F5 U# Q9 _. x
418a71e2dcbd48a199034bbf6765d9fc.png 4d161770a4734368b6881fe1ed982494.png
" k% M$ Z2 E. o3 j* _7 i! U
3 K; u" @/ Q4 Q3 Q6 a* ^; k: ~
696837e6177b4f3caa286c6913cf4ea3.png f052ff2297b4462daa7186e7fc3b6ab8.png

& k+ p! _8 E% y1 B- ]# N3 `  a; g" J, M3 ~3 w* x3 W# Y$ A
0dadc8e05ea349beb4e04a737e86ed07.png
* A6 J- B) \4 ~

4 [6 r/ N2 v1 ^+ s! D# o3 C禁止的方法是右击此文件去掉如下对钩即可:
$ h% i& p4 F% W/ X+ O8 ~# ?9 K! D4 ]' B
4db1e499f0f7422f9e522bf1e7bcecfe.png
( `- h' G" M/ d. s$ O9 n9 P

# {. V6 V  {* h8 R3 O, d3 x+ r. x8 W5 s3 e# q
5 B$ b, x7 m0 f* }6 J
3.2.5      第4步,配置GPIO和时钟
- |( g3 V/ X1 a; I: @/ n* s2 aUSB时钟配置在bsp.c文件的函数SystemClock_Config里面:3 g- _6 _' t+ b4 `. r+ v# p: Y3 Z
$ \3 D- A9 e* @8 X4 P
  1. {
    ; g4 t- X. P7 p1 X
  2.                 /*/ @! y5 {% M6 \" Q% y6 L( D% F
  3.                 USB工作需要48MHz的时钟,可以由PLL1Q,PLL3Q和HSI48提供' L; c! g1 D! I/ [% i& K1 Y' B: d
  4.                         PLL1Q用于给SDMMC提供时钟
    5 J( X$ s" W' h3 N7 Z# m  U+ i
  5.                     PLL3Q给LTDC提供时钟,也可以跟USB共用,不过得更USB设置相同的频率才可一起用。
    . ^& ^2 O$ ~. a& o; W
  6.                     HSI48可以供USB独享,就是精度不是很高。, W- l8 `" }+ [' \' K4 l: B* X
  7.                 */* j" U4 [- F* I
  8.                 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
    * O. U: B! `/ _$ I( D2 @: l- ~. w$ \7 x5 @3 o
  9. #if 0, J* O( A$ V; C/ F) g- c
  10.                 /* PLL3-Q for USB Clock = 48M */
    $ Q4 I. o' B5 @( Z1 B( n! L
  11.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;( E! A! Q; l( m) G- p2 n
  12.                 PeriphClkInitStruct.PLL3.PLL3M = 5;
    4 B  E7 E7 \) x2 S( ~1 E- s6 b
  13.                 PeriphClkInitStruct.PLL3.PLL3N = 48;$ d, b0 [# @# l: G6 S5 Y
  14.                 PeriphClkInitStruct.PLL3.PLL3P = 2;
    6 x* W/ V( Q6 p: O
  15.                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
    / Q; E. A* V% j: x5 v/ K
  16.                 PeriphClkInitStruct.PLL3.PLL3R = 2;
    , X& W! e; D  o/ w
  17.                 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
    * s1 y6 Y. m, ^1 m% {- @
  18.                 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;3 K. p7 P" V6 X# o. s# f' E
  19.                 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    3 P- q( Q' I! t
  20.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;5 g$ N9 q+ q1 |& t9 R! B/ O
  21.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK)
    9 i$ ?1 B, e' m: R5 M
  22.                 {9 W' x- g# x! c) t& Z6 ]+ L( {
  23.                         Error_Handler(__FILE__, __LINE__);9 O5 q9 j+ I) E1 ^, M4 |% z
  24.                 }        5 w1 w6 k7 _6 }- H1 m) K
  25. #else2 m/ R" T0 c( B& i- t
  26.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    ) k' |4 \" X( D* L
  27.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;; N; V& ^, Z% D  H8 O2 K7 E
  28.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    1 a& M1 N- W8 P/ o! @% O9 c
  29.                 {
    7 v3 v/ R6 i! Z# s) o1 e5 z( d
  30.                         Error_Handler(__FILE__, __LINE__);% ?  A" o' J" {: y$ W
  31.                 }
    5 u7 Z0 S* K2 T0 i* n& g  E+ I! n$ {! N, k
  32.               HAL_PWREx_EnableUSBVoltageDetector();
    4 d& |; C! f7 M7 j" Y9 ]' }& h$ \
  33. #endif" e# a! ~1 z7 ]1 s& k4 J
  34.         }        
复制代码
' F. I) C: }! V; |; A' Y3 |0 Z
USB的GPIO,NVIC初始化在demo_sd_usbx.c:
4 a6 n6 Z3 F# R9 i$ x/ y. t, i% x' P! |! k5 s" y: }  S
  1. /* 配置USB GPIO, NVIC */
    / c( S5 {' w8 x4 ^
  2.     {
    + r. |+ _7 a' m& W2 [
  3.         GPIO_InitTypeDef  GPIO_InitStruct = {0};6 l. ~* s4 h" R% S% T
  4. 5 D, k3 A  T- Z& I, |% j# m, \5 z
  5.         __HAL_RCC_GPIOA_CLK_ENABLE();% A$ i4 Y3 X7 J) D4 a% ?! Q6 A

  6. 8 x9 Y7 t* j2 L* J: _; k# K
  7.         GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
    " c9 _( G  l- M" {5 }6 E
  8.         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    ! t0 ?4 q) T: M) k/ Q$ I
  9.         GPIO_InitStruct.Pull = GPIO_NOPULL;1 {) q& T$ s0 o$ R/ S, s# l! d
  10.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    : C7 X6 ^) R- B3 T9 v, z! E
  11.         GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;
    0 V6 y# j  u3 P" L
  12.         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);0 j6 j+ D, A6 f9 m! O+ J! L
  13. 4 c+ t/ P7 p. C/ G1 _) E4 ?
  14.         /* 使能USB FS时钟 */( K; X* j! a3 P. _
  15.         __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();9 x4 F) O# ^* |! D: Z/ I
  16. 2 Q) _. E! e2 c
  17.         /* 在睡眠模式下禁用USB时钟 */
    ; r7 X, ~. o! G0 u- {! h1 ^
  18.         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();
    ; @6 n  \  w7 v% s2 J$ ?2 Q' n

  19. 2 r9 E; o8 @8 x. x: [
  20.         /* 配置USB FS中断 */1 L( w3 c, `7 N
  21.         HAL_NVIC_SetPriority(OTG_FS_IRQn, 0x2, 0); : G% U# w9 g3 e5 ~1 f8 Q2 K
  22.         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);4 R; ^3 p* d' ]% l5 l% ]
  23.     }& f8 O, y7 g/ @' K& B5 s1 C# B1 \
  24. ' C: Q0 Y. ^5 e0 R2 {+ I. Q
  25.     /* 初始化USB */
    : [) B! n3 L3 H2 T
  26.     {
    & M3 r0 z+ ~! Y6 e
  27.         HAL_PWREx_EnableUSBVoltageDetector();
    * i7 @& E4 s# |  M! ?. o

  28. & K; z  t7 {3 Q6 W* F8 s$ U% O- s
  29.         memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));
    ) [" f' ^/ R" i) P
  30.         hpcd_USB_OTG_FS.Instance = USB2_OTG_FS;7 ]0 m+ ~$ u% l1 l
  31.         hpcd_USB_OTG_FS.Init.dev_endpoints = 8;
    % V: d# S$ y& ?" y6 Y) m( }
  32.         hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = 0;# ]# J5 `. E' k1 c4 F4 J* T" }
  33.         hpcd_USB_OTG_FS.Init.ep0_mps = 0x40;8 O8 L$ Z% d% N5 R! Y! n  [& _
  34.         hpcd_USB_OTG_FS.Init.low_power_enable = 0;
    2 W* W# o, d( g$ V% r4 E0 R
  35.         hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;& z9 ^) i3 p( O( W
  36.         hpcd_USB_OTG_FS.Init.Sof_enable = 0;- N( R" _9 V& N4 ]" H% R$ N
  37.         hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;9 H, X7 p/ \1 R# d! u9 d" [; h5 w
  38.         hpcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;
    + J3 p1 `* J- t3 f9 w3 u, z
  39.         hpcd_USB_OTG_FS.Init.lpm_enable = 0;
    ) M) ^# y6 A: k
  40. ' W, o) k- K8 D& ^
  41.         /* 初始化USB  */9 Q, j- @, M3 x  I
  42.         HAL_PCD_Init(&hpcd_USB_OTG_FS);7 H/ M- g* ~! X# ~8 M: i3 H
  43. # M1 q. F' a4 J9 ?
  44.         /* 设置TX FIFO和RX FIFO */
    % ~* z: v- N" @, k0 c3 f* x
  45.         HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 1024);
    ( Z. |  v5 Q2 t. {  Y% Q/ Z) W
  46.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);
    ; V& S0 W' H% b7 q
  47.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 1024);
    * c8 S8 P* j7 S- ]; Q7 p0 d

  48. 8 S- \8 M$ r6 O& B8 o
  49.         /* 注册STM32到USBX协议栈并初始化 */, Y# _# x; B, z$ X
  50.         status =  ux_dcd_stm32_initialize((ULONG)USB2_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);
    7 @9 ?; {  z2 ]" M7 ?/ c3 Q

  51. 5 k: o) t& R2 t( o: `5 C
  52.         if (status != FX_SUCCESS)2 ?* X( x3 C1 K1 ]: Q% C% x
  53.         {! I: X0 C4 Z! x; B+ B7 j
  54.             return;3 N6 B* ]( b! u; M0 _
  55.         }5 }0 `0 t4 i# E7 q1 ~
  56. + l, Q9 B# g' a0 G' p
  57.     }
复制代码
+ X1 S2 M+ O( K8 L2 B
3.2.6      第5步,MPU配置

" o" H  v* R: {3 |: D为了方便大家移植测试,我们这里直接关闭AXI SRAM的读Cache和写Cache(这样就跟使用STM32F1或者STM32F4系列里面的SRAM一样)。此配置是在bsp.c文件的MPU_Config函数里面实现:4 p) F: Z/ K8 R

" w$ A: N" L% S4 X7 W
  1. /*
    8 Q* U( j& V4 f4 R3 O
  2. *********************************************************************************************************
    ( v7 D, k7 y) W6 u8 |
  3. *        函 数 名: MPU_Config
    7 w5 n0 o& S7 Y: b9 V" f- F
  4. *        功能说明: 配置MPU! L7 {: D0 [5 g: D* X% U' c
  5. *        形    参: 无: ~+ U3 T7 W7 J0 Z5 o
  6. *        返 回 值: 无7 M$ j! L2 S! H* v+ |' z- ~+ F
  7. *********************************************************************************************************
    ) {! ?+ _* U# u+ X/ u$ c0 ?+ \
  8. */
    ( \6 y, w! X" h0 {# L
  9. static void MPU_Config( void )
    3 T' M5 Z! A" m3 m# ^- a
  10. {
      ]  L& u6 Z$ E/ z' Z' L
  11.         MPU_Region_InitTypeDef MPU_InitStruct;. T- k4 G5 d5 [5 Q* J5 q

  12. . k" Y6 C5 p8 g( Y' _8 _  o3 x! R
  13.         /* 禁止 MPU */5 Z1 v; |% T7 D9 f5 L9 J
  14.         HAL_MPU_Disable();
    8 z7 |4 Z, x' F2 a
  15. " J" C3 b9 Z9 k5 t3 ^
  16. #if 01 D6 m/ _8 T8 d+ C* E) v4 u- |
  17.            /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
    3 F" \4 S' V  }  r9 q
  18.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;6 y3 |- M/ o3 E0 O
  19.         MPU_InitStruct.BaseAddress      = 0x24000000;
      |6 U1 ~: p. i* g: T
  20.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;; g* v  g' }  R5 T! @
  21.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    7 n& j2 w' u( h" i: y- V, T
  22.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    - t7 z% C$ Y7 d4 W8 t& |* _
  23.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;( O2 M' g" m# z. ]" R5 g+ n- T
  24.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;$ I9 y3 o7 u+ A( q. j5 V6 N
  25.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;  Y' s; z/ O; i
  26.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    9 l$ C7 |$ w9 e) X
  27.         MPU_InitStruct.SubRegionDisable = 0x00;" U. H5 x8 x$ \: s
  28.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
      i+ J! ^* m! x+ ]5 K0 q
  29. 7 A% L0 \3 X# J8 n$ b3 E! o
  30.         HAL_MPU_ConfigRegion(&MPU_InitStruct);% F8 e  |$ l9 X' I
  31. 8 h  U1 b; Z5 O1 J+ a2 w
  32. #else
    - g- I( N9 |" f3 ~4 t
  33.      /* 当前是采用下面的配置 */
    9 _' P5 ^3 f9 n/ T) C- A
  34.         /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */& {) t4 R5 P: i& g& F$ A
  35.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    ; W( ~3 w& \8 ~  {& \4 m8 s& m
  36.         MPU_InitStruct.BaseAddress      = 0x24000000;: X& r" x# \0 _: e+ C  b2 }- |0 v/ N
  37.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;. j5 m, l; U1 J% _+ f0 t0 y7 K1 E0 [
  38.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    . M9 a, L0 d  ], Z' d) |
  39.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;& F' `- z+ H: A& G' i9 u
  40.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;; J9 G  V  k, @$ s+ T
  41.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;, D" h9 N8 f  Q+ E& a
  42.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    8 A/ B, r* d% W, q8 ]5 |
  43.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    ) p6 @/ C8 l; S- p4 ?# q
  44.         MPU_InitStruct.SubRegionDisable = 0x00;
      F+ t# y, h+ ?( o- d- y
  45.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;8 V0 |1 k) _& [

  46. , w" ~; N) \' c) {7 \; I' |
  47.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    - ~9 d- b! G; m; m
  48. #endif
    ( z7 J+ B) g, F0 X# m! s6 V6 H
  49.         /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */
    3 H1 ?6 \+ a( `$ f9 r! n
  50.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;) k+ x7 R  b9 y3 Z3 |% H
  51.         MPU_InitStruct.BaseAddress      = 0x60000000;7 R; x9 |/ P5 T% j' P& n  T
  52.         MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;        - Q% c- M6 A8 n* [9 e: E
  53.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;1 R/ z( y3 ~5 `' ]; p
  54.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    4 f1 H! {; N! a! ~) t! y2 I
  55.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;3 ]0 M" X: T+ O' G* ~, y
  56.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;2 O6 U  v9 |" A6 {4 v+ `9 y
  57.         MPU_InitStruct.Number           = MPU_REGION_NUMBER1;6 F. h  K$ c2 p3 J) H3 F: ^7 V; k
  58.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;) c, R$ e/ C$ i. l/ [1 B
  59.         MPU_InitStruct.SubRegionDisable = 0x00;
    % o. u* K5 S! n4 Y
  60.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;- w( A1 q+ T% n3 F
  61.         & w* \, l% ^: G- Q/ d
  62.         HAL_MPU_ConfigRegion(&MPU_InitStruct);8 Q7 m1 i8 P, I. c, o; z9 t
  63. ' g" L2 W  q" Q! i; I
  64.         /*使能 MPU */
    6 p0 D! n1 A, l, _5 P
  65.         HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    - m# I, }. D& L/ f
  66. }
复制代码

; I- x% T0 X- c4 w3.2.7      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)
- n' p3 M: m% r4 b1 X/ P
USB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可
8 Q- S+ v: m. x# W1 z0 k' r( y3 @: a: O" T& c4 G% L& K( |
特别注意USB中断服务程序别忘了添加。
! p% Z8 J2 p! V& h, Q
* V2 Q# O5 O! y: ^  N+ n5 \6 p3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明2 @3 }5 I5 C2 {
这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。
5 n( F" X  E  X# G" f( w) P$ f9 E1 u. R% _  @
3.3.1  状态函数app_usb_device_thread_media_status' R, H  C) v3 o2 e& j2 ]/ [
代码如下:1 c6 ?; d) ~, r3 [; ~+ G. ^8 e
& b; q& n5 K% o, O; K
  1. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
    3 t( y( Q  j9 B
  2. {' x! S8 n! M$ q) f/ b9 h

  3. / N3 V' E1 o7 Q
  4.   /* The ATA drive never fails. This is just for app_usb_device only !!!! */
    $ Z5 A9 U0 N1 @
  5.   return (UX_SUCCESS);6 K7 Q* U" {5 P1 _: u7 Z3 m
  6. }
复制代码

& u! w8 h8 K4 {1 ?0 e; }9 y" D此函数主要用于获取SD卡模拟U盘的状态。
9 f* ~7 u2 S; R, R; ~* u+ K9 `
/ x' c. v$ V2 k* {/ u3.3.2  读取函数app_usb_device_thread_media_read

5 k- A7 T7 \3 H' A1 M  w' _+ S代码如下:. i# U5 r  A3 E  u8 z7 b  ~& [

; J. }; o0 ~, G+ i, f- u6 l
  1. /**
    . W) V# \' v9 I- E' u
  2.   * @brief  Function implementing app_usb_device_thread_media_read.
    * {2 p6 A. l2 l& W( d3 `+ ?3 y
  3.   * @param  storage : Not used
    : Z; L8 L( r2 a2 x/ F) A- R% l
  4.   * @param  lun: Logical unit number
      m8 j7 y5 ], M" t/ K# ~3 `
  5.   * @param  lba: Logical block address! `2 d8 i; U7 Z" U/ I
  6.   * @param  number_blocks: Blocks number
    5 `5 M. V' j" k" g/ k4 m
  7.   * @param  data_pointer: Data
    ; V9 s" y0 E- [: d9 o
  8.   * @param  media_status: Not used
    $ F4 i) @7 J- y: _5 k
  9.   * @retval Status (0 : OK / -1 : Error)
    : x4 W* n" N* w; n
  10.   */3 u0 E0 ~8 Z$ o7 R( r# ~6 v+ z
  11. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,' l1 [" d: P8 A& b  j' _7 V
  12.                                        UCHAR *data_pointer,
    ! G$ }0 a; S' b
  13.                                        ULONG number_blocks,
    8 n: m6 z/ D4 E
  14.                                        ULONG lba, ULONG *media_status)
    : l, ~/ x, ^2 g
  15. {
    ' W4 f* R- i2 e% s: i4 N
  16.     UINT status = 0U;
    $ J2 i+ @9 y& @6 H6 f: o

  17. 4 C, l" Z' ?8 R) F
  18.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                        5 l% |7 P; [; m, U, L8 P
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
    / n7 T3 |3 K2 _1 u0 f9 G5 g+ L) c
  20.     status = check_sd_status(0);   
    * S$ K4 d1 W, l! o! H0 a/ Q1 ~
  21.     return (status);
    ' y2 r9 [5 Z3 K
  22. }
复制代码
. Q- Q3 A5 ?+ Q5 B7 [' p
用于实现SD模拟U盘的读取功能。
9 t/ [# ^+ p6 W( V5 E7 p) Y
3 L1 J2 E. x& _7 Y1 l& O- J3.3.3  写入函数app_usb_device_thread_media_write
! M" X( W4 i2 b# `1 z代码如下:
  }( K  |: @; ^  B& t/ b( j
0 q" P( b5 h" k" V* L) p$ }0 m% c
  1. /**
    / p, [2 S) V# I% e
  2.   * @brief  Function implementing app_usb_device_thread_media_write.; _- o" Y5 K2 v* O1 X" W
  3.   * @param  storage : Not used: o8 H! _0 y& g! Z6 y
  4.   * @param  lun: Logical unit number- g0 z. ~  q0 l0 n1 i& ^
  5.   * @param  lba: Logical block address6 Q6 Y2 I2 k! U0 F
  6.   * @param  number_blocks: Blocks number
    $ `& t- z# O9 ?7 }! E5 K) r4 H
  7.   * @param  data_pointer: Data* ?) d* M3 @* ]7 C4 [
  8.   * @param  media_status: Not used2 R, U+ y5 b1 s( }" {
  9.   * @retval Status (0 : OK / -1 : Error)
    & H% ~/ C; a9 u- x$ G3 ^
  10.   */' d9 v/ I7 Y; Z+ H
  11. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,
    ; p. Q" D4 V) \
  12.                                         UCHAR *data_pointer,
    ! {2 @- `- C0 u% I; b" O
  13.                                         ULONG number_blocks,
    ( |) I# G7 w& Q
  14.                                         ULONG lba, ULONG *media_status)7 ^6 n+ N$ ]$ @% I5 j
  15. {
    4 u! |3 W; C: e3 w
  16.     UINT status = 0U;
    : p3 @) @  Y/ W5 m

  17. ' z4 R5 D( s( ?% H2 B7 E
  18.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);
    3 d, ?/ S" {7 G$ s- r
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);3 ^, l( f# K. ?0 _- g
  20.     status = check_sd_status(0);
    " L( K1 n+ |# y# n# T) N3 ~3 o
  21. % y' `! U% v0 E1 W5 W8 W
  22.     return (status);
    ' c3 H) Y( B3 Y. S( A
  23. }
复制代码

/ A/ M) E1 N$ ?  x用于实现SD模拟U盘的写入功能。: g9 V$ U0 Y# _! J$ I
) @4 @$ D& z6 l, W7 Q, i( A" N
3.3.4  接口函数注册* ^1 t8 }, \2 r" u0 r
接口函数的注册是在文件demo_sd_usbx.c里面:
8 ~& j$ k3 I& X/ i6 P, S* S+ R2 y& h( b1 a5 P
  1. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;
    4 G5 ]7 M  j4 x' B

  2. ' I; H4 d8 z  X9 A, ?; M% D- ^
  3. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write;
    6 S, @4 I1 w  T  [
  4. 0 u8 x4 x' Z3 {; b) Q( ?
  5. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;
复制代码
% Z: k7 S8 T. z( p0 C, h+ r
3.4   使用的MicroUSB接口并注意跳线帽设置* u( K, ^7 u2 i. I
本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:! v6 i6 R% I1 Z2 F) {
" U1 W3 @, g& u% T& i! [5 e
a9cb882c39474dd9bd63b8c7e14cb451.png

6 l2 J( [* w5 @  i3 ]5 W3 ~1 @1 v# A( G; V; g( U
注意使用的是MicroUSB接口:
  s. N6 s1 c8 Q0 p/ c( {" m# P$ G: l  O3 G& F
f871e17a6a2d4c03a9413daf725670c4.png

! d1 R  O3 ?7 J8 r3 X0 c
; `+ N8 T! c3 K" `- S
0 {0 B3 ]( A: i) u注意板子左下角跳线帽的设置:
! [# {( }3 y1 z4 H& x
4 q; {+ y5 b6 s$ \2 v9 U
41272c92c8c9483f9d5dc6a04cbf87b8.png
' o4 u$ _* w) V! B2 a

) [5 g6 \: r  R  k4 s% y
# Q5 E6 D3 S) _这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。8 y& ?0 k/ G5 s5 V4 L; {9 p
. l8 O: `: g: _1 ~6 |4 M
3.5   实验例程9 U; b  z: X9 }- ~; J
配套例子:
/ d1 [" N5 f1 t7 p6 F) N  T. a) H* S$ k  d3 E
V7-2401_ThreadX USBX Template
( a7 l( B/ W# j" f4 [9 g9 w, D
9 `' n" ~0 m4 f7 Y# A4 u+ U  n- }7 Y) q实验目的:
( v) A, |, ]/ e# K. P* m2 |) x# e* [- O; \1 y
学习USBX模板,通过SD来模拟U盘。
. ?% \$ V2 Q: K: F/ K4 C实验内容:: L! ?+ t: B' I9 j' K

; n8 N& h. _# Z  c/ `4 T, s2 s1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                 
& u5 `" L& Y( O! r0 \
) S  N  m* C. D% ]- h3 S) Y# z7 l* E  ========================================================" A. R# ~3 ~$ }# l1 n" N) ?! W
; Z  D; A5 H# R1 ]; o; I! m( {
         CPU利用率 =  0.89%8 [2 x5 H; {0 S( N/ _5 k5 ~

( U, a: ~' F, w: R         任务执行时间 = 0.586484645s# B: l7 Q, K; B1 x! `$ N1 m

. D' z! i* L- [4 e1 m/ L- |1 x         空闲执行时间 = 85.504470575s# {1 W9 k8 P' [4 _  X- E$ J
0 o) k8 `! B. v1 N
         中断执行时间 = 0.173225395s
6 E$ H: r& m4 S2 E+ |4 C5 }/ R
( r4 M$ E: d; c         系统总执行时间 = 86.264180615s              . u6 a" ]6 i1 Q8 ~5 p% N3 j. h- m: R
6 ^6 v2 o" ^; E7 f/ i6 {5 P/ z4 q/ K
=======================================================) [; G. p9 C  t. G" G$ `
1 S% r8 e" A" O6 A% X* C9 H
        任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名
$ t) G! B/ `2 n8 f% ^, W& `( @. Z0 T& M% Y- u2 M3 y$ a
          Prio     StackSize   CurStack    MaxStack   Taskname
. b& J$ @2 [3 E. I
1 A0 F  a" t) X7 ]          2         4092        303         459      App Task Start
  I0 y0 U' T1 B  j! d  z
9 ~8 o( p1 P% W$ `+ T: |( ?; Z  n0 E          5         4092        167         167      App Msp Pro2 l6 R. V& J8 L: E! y( m& N
# {" m1 N5 Z7 I7 J
          4         4092        167         167      App Task UserIF
9 P( W5 r. o( s2 h; C1 }
- j) q6 z2 S# j" W! Y$ I9 @5 ?           5         4092        167         167      App Task COM
* ~  e. _$ R/ i& l6 E! q5 J4 z/ `  i: I+ e8 Z: t
           0         1020        191         191      System Timer Thread           0 b% J# s( T; l& `) ~4 t

1 O/ q; R- L; \% H) g串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。8 u8 r: J3 n0 e) G5 Y7 |; o
2 b; j* ?' `2 P
App Task Start任务  :启动任务,这里用作BSP驱动包处理。( _, R1 s/ M! q4 l
* i5 o1 f% s) L8 u
App Task MspPro任务 :消息处理。
' F3 ~' K/ y# C% `2 U7 D+ u/ j  a! h0 Q4 K/ u9 O
App Task UserIF任务 :按键消息处理。# @$ K& Z3 ?8 S7 j: r& ~* S3 `. Q

$ U8 E% o! P! V! X; o( RApp Task COM任务   :这里用作LED闪烁。- d! U5 X- G$ g; \2 N' S4 f& o/ n& R
; ^3 C( A+ v3 H8 a  b8 f# T! i9 G% u
System Timer Thread任务:系统定时器任务
) C4 \) f: t. ~! M- V  `& _
4 |2 u, C+ R2 _7 X* L2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。! s7 r4 a; J# S5 {  n

7 F8 f" A6 |( x      (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。3 {2 E- M. g7 L! m8 r
: Z' a/ u* S0 j0 w5 L0 H- J4 ]
3、默认上电是通过串口打印信息,如果使用RTT打印信息
# f0 x1 A; p+ O
2 _1 z. i7 `0 L* Y  u: S5 K(1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可/ Y8 z& |6 k- E8 S! s3 d

( d" y7 a; Q+ l& t: o7 m#define Enable_RTTViewer  1
" s9 Y+ }4 s3 \/ _4 _& @6 w0 V+ ^8 r
(2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。% \/ e  i- _& G: R. ?# m( H0 v; V
, n; M# i7 x. ~- r4 j0 F- F
实验操作:1 F# n$ z4 ?' z' D# i2 `
% M3 _$ H- k4 w
测试前务必将SD卡插入到开发板左上角的卡座中。
- Q( F/ p7 n" G支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可4 {" g2 _' T) W0 b/ ~
printf("1 - 显示根目录下的文件列表\r\n");
2 V4 C6 l; p2 K" Pprintf("2 - 创建一个新文件armfly.txt\r\n");- Z" o! u: B7 p( F3 i
printf("3 - 读armfly.txt文件的内容\r\n");* o8 N8 G% {# E& D, c
printf("4 - 创建目录\r\n");) j6 D* P2 C8 @. b) m
printf("5 - 删除文件和目录\r\n");5 w- Z' d  ^* _$ a' D2 V# a
printf("6 - 读写文件速度测试\r\n");* }% O8 _- O& L/ g5 t
printf("a - 打开SD卡模拟U盘\r\n");1 M0 z! j# a% n/ X1 d+ `% ?
printf("b - 关闭SD卡模拟U盘\r\n");
( G6 H& y2 D" J9 Q' z/ Q- D串口打印的信息:8 e9 W# z2 ?8 b6 g, u5 w. a$ R

5 K2 h- ]' t) M波特率 115200,数据位 8,奇偶校验位无,停止位 1
7 _) f& N+ r; D9 j& Q
" q$ e/ f( F# N: j5 ]2 L
74d954c9e7b649289184a7a4bd58d6e6.png

% G: |* @' m& ?4 ]% J2 z
( B9 L# o8 N- d. f5 L
7 N7 I% V! z3 ^
/ f% o3 l' ~6 k& [- S* oRTT打印:7 a9 _) I" ~( g
1 i& ?3 f8 ]" x
cdcab0e093ed468a912923050806de22.png
( z3 {% a2 A1 j% W

: J$ j6 |! w, ~8 D4 X& f: z: J6 F! |6 k
' ~( Q) l( A6 m5 r3 |: {4 d
3.6   总结
, b4 u. `3 t5 t本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。
& b4 D, v( n5 D* j
4 |, L0 M  _9 A$ {/ L; _& b) D7 [; [2 M0 f
- v5 p! J8 f( w+ f8 C' E6 U
收藏 评论0 发布时间:2022-1-1 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

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