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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 19:00
3.1   初学者重要提示
- B+ T6 I8 o! ^, K9 y! g7 _* D1、  本章使用的ST专门为STM32H7提供的软件包
% |3 ]6 {/ F  Q" }; K/ q" ]  ^# e9 c4 p6 L2 I
2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。0 u* q& g) o9 H9 Y. m( {' Q* v

" y9 k: m1 U4 z4 Q3.2   USBX移植步骤9 ?. N: e2 `! ^. x9 l  u. K. t
ThreadX USBX的移植步骤如下:
+ |, o- a5 B( b% K# V0 |. K! b/ `; Y" [. T
3.2.1      第1步,了解整体设计框架
, L2 d( ?& R2 i( e为了方便大家移植,需要大家先对移植好的工程有个整体认识:3 ^: \3 U& a% ^: p
* V; W9 v9 P* C6 k6 @
556edb9b3bb947f5b69aac84272def1d.png

% Z, M6 g: Z" j+ u" k; n# M. b" {. ]1 A& d

5 w* W* q: a5 ?$ g1 y# N6 ]% v/ q" M3.2.2      第2步,添加USBX和USB驱动到工程
+ W' ^" V8 u3 d4 o/ \, ^9 F8 P4 a这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。
0 g1 P* \9 K8 I9 n1 q/ N: s
* s9 [$ ?8 m8 R3 M  模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。3 ^6 S. ~( h) z6 @
配套例子是放在\User\usb文件。
! W# e% b. V6 b9 T' @$ s4 l* b% W5 {1 [7 r- O+ i, ~" v5 k1 H
  USB驱动文件stm32h7xx_hal_hcd.c,stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c。9 q/ P4 f, ~4 W. L. f: i! z
这个是STM32H7的HAL库自带的。% Q& k9 }# X- l9 m1 U

7 i7 P. I: A  \; q. g& p5 x  USBX相关源文件。
$ z1 Q8 z) F) y+ ^4 V  _- P3 V) j大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在\USBX。
  Z4 y" v3 ?+ I; y2 N4 I3 X: B8 F" \! Z
3.2.3      第3步,添加工程路径
& a8 O, ?5 B; S/ g" y6 \) b大家根据自己添加的源文件位置,添加相关路径即可:4 e) w- f0 b7 @/ Y- W
' o, K2 n9 n& n
7d4292e15d424274b8e5aab1d6cd32a9.png

, b: m" }: M% x' r8 V& Q/ C3 A; g6 X
* r. W8 w( a6 N! ~" ]
* ?8 k1 W2 N; a+ r
3.2.4      第4步,禁止掉添加进来一些文件

2 Y* M. R& e' y: [1 p' o. Z( q" j之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。. ~( ]$ D9 g9 p

9 T: @  c( {6 _1 T( S- n
418a71e2dcbd48a199034bbf6765d9fc.png 4d161770a4734368b6881fe1ed982494.png
  w) o5 @1 f+ Q7 p  K$ y: E& ~2 W

; ~: A) k1 T% n* U3 a& e+ h3 Y
696837e6177b4f3caa286c6913cf4ea3.png f052ff2297b4462daa7186e7fc3b6ab8.png
* I# |) m) r" _5 \; |

2 a: g# m: k6 }' l3 ]/ x% i
0dadc8e05ea349beb4e04a737e86ed07.png

3 D1 I' J# O; f1 A: m# g& c; p  d" r  p7 d; h. [
禁止的方法是右击此文件去掉如下对钩即可:; U! ?2 r  {- j5 L" @) L) I# M9 }# H

" o  w) Q2 x1 ]# V9 d
4db1e499f0f7422f9e522bf1e7bcecfe.png

; `- S5 ?5 I: ~; _
" H' d, E; L; |& `# R
2 z9 @# G1 q/ l2 T/ x
/ g' M' L  h3 W8 `# _* k3.2.5      第4步,配置GPIO和时钟
/ O% _' J: u" F4 F4 hUSB时钟配置在bsp.c文件的函数SystemClock_Config里面:
; W9 d+ ~4 g6 A& J3 ^
$ G  `. k& m4 E: c3 Y1 R' C0 `
  1. {
    9 J# P- `; s2 A5 H% h' a
  2.                 /*
    8 T5 @( u. \4 j
  3.                 USB工作需要48MHz的时钟,可以由PLL1Q,PLL3Q和HSI48提供
    5 L: s; }8 A/ v3 [: a
  4.                         PLL1Q用于给SDMMC提供时钟" G# }; d+ v9 o% ^" E4 f
  5.                     PLL3Q给LTDC提供时钟,也可以跟USB共用,不过得更USB设置相同的频率才可一起用。
    ; f6 g( E1 n( w1 c. R( O) N+ q
  6.                     HSI48可以供USB独享,就是精度不是很高。
    * W: \! i: r8 k2 H" n
  7.                 */% L$ F1 ?, D6 e6 v+ D1 H8 ~+ }
  8.                 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};$ M3 o; p8 m4 K
  9. #if 0
    ' l( D7 J* [! V. }3 D
  10.                 /* PLL3-Q for USB Clock = 48M */4 Y. R5 _8 s. m5 W) U
  11.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;# w! g) w& L& ^& K- f; K
  12.                 PeriphClkInitStruct.PLL3.PLL3M = 5;! b9 z- ?: a2 t( A4 f
  13.                 PeriphClkInitStruct.PLL3.PLL3N = 48;6 Q/ O9 x5 g5 K3 D
  14.                 PeriphClkInitStruct.PLL3.PLL3P = 2;: F8 G3 `4 v/ e, D: g1 o
  15.                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
      J3 n8 R' y* {* z4 c* X/ }' v
  16.                 PeriphClkInitStruct.PLL3.PLL3R = 2;* r: w$ |0 X1 D2 d8 }$ x" N1 E
  17.                 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
    8 N$ X% Z/ L7 |
  18.                 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
    5 j8 H! D- t( y5 A
  19.                 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    6 x) A5 R% J$ g4 s! j: T! K
  20.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;8 m5 A* `" v  ~+ c
  21.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK)# M4 u1 w" _% N  D* {+ r
  22.                 {* \: I1 R) [( A$ {
  23.                         Error_Handler(__FILE__, __LINE__);+ c! P4 S1 D0 w0 N3 j9 P9 N
  24.                 }        - E% ~: J8 Q, ^$ ?5 B: z
  25. #else
    $ Y# i6 ?9 W3 T* u
  26.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;) p- T' b- T0 l) N' |0 Y* _
  27.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
    , b$ e% T9 Z( u1 g2 M
  28.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    6 p9 K9 ~: Z& m* ?6 Y
  29.                 {7 _( l* w. J  h/ b
  30.                         Error_Handler(__FILE__, __LINE__);6 m" A4 b& H( [2 s4 }4 v! o3 S+ l$ l
  31.                 }
    - Z* E4 K" b/ }3 o2 i3 l% v
  32.               HAL_PWREx_EnableUSBVoltageDetector();! Q, H- @( k' N4 V
  33. #endif
    # J, ?* f5 d, f; H
  34.         }        
复制代码
2 f# L2 e% F( R4 \- f5 @- e+ @$ ]
USB的GPIO,NVIC初始化在demo_sd_usbx.c:
+ u$ q" y5 A" F! ?4 L5 ~1 H- `  |
" g- E* b. o  h
  1. /* 配置USB GPIO, NVIC */3 N! W# V5 Y$ m( `, [
  2.     {+ X5 B  Y. r  J& ~
  3.         GPIO_InitTypeDef  GPIO_InitStruct = {0};
    6 @3 q6 m  l9 }5 x( p/ r/ u# d
  4. ' {$ f: e0 F9 }; |  K( n0 @
  5.         __HAL_RCC_GPIOA_CLK_ENABLE();' q4 U6 T3 {+ ]+ F( E- Q  v
  6. 8 O2 o6 I$ p7 s& a# n, E' C
  7.         GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
    . ]/ @- S+ J/ c2 F+ m. ]! V& O; D
  8.         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;5 ?3 U' a7 Q' ^* g2 a$ ~
  9.         GPIO_InitStruct.Pull = GPIO_NOPULL;
    2 E% S6 B* T1 A  O
  10.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;. U; o' n2 U7 {  h( s0 Z
  11.         GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;
    " t% w* f" P( [0 _' N7 \4 H
  12.         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    ! a% O) T4 `$ w1 m- n+ S
  13. 0 R9 D7 y) t/ B7 F( r/ [$ s, e
  14.         /* 使能USB FS时钟 */3 p& h- k4 l+ |- s
  15.         __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();
    1 K4 u; q' b( H' {8 V& d. G$ G, Z
  16. 3 |  E& u1 n9 n3 Q& G5 U" w! p
  17.         /* 在睡眠模式下禁用USB时钟 */
    8 g  M$ p; ^! e2 w! s
  18.         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();; N# {, l# F0 w

  19. ' F7 F4 V& O" l: u* j
  20.         /* 配置USB FS中断 */
    4 R0 W7 P4 N  D* L; a+ v- a
  21.         HAL_NVIC_SetPriority(OTG_FS_IRQn, 0x2, 0); ; \9 E7 }9 B" X3 |. Y6 F
  22.         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);0 ^) ~2 K6 Q2 n) X& Q7 d# |  q
  23.     }, ~, }, {% p  D7 T1 M

  24. 6 x3 f. L+ Q, [: O" f6 n% b" D
  25.     /* 初始化USB */
    ' Z& X' @3 q! u: E3 o* T, O* h6 `
  26.     {8 s) p3 j* f* G
  27.         HAL_PWREx_EnableUSBVoltageDetector();
    ! A) ]4 |: t' ^- D
  28. * N9 z: {1 y2 [0 q( g' `/ @/ P4 @
  29.         memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));
    & {6 T: k( X1 E3 G* m
  30.         hpcd_USB_OTG_FS.Instance = USB2_OTG_FS;
    : t; d$ B* Z0 X7 B7 e& T5 T/ k
  31.         hpcd_USB_OTG_FS.Init.dev_endpoints = 8;. u8 b; Z7 |! X8 `' c' F% |3 o
  32.         hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = 0;
    $ U( _4 u4 k: A) t% k/ e
  33.         hpcd_USB_OTG_FS.Init.ep0_mps = 0x40;
    # g1 R8 a/ M. d3 P0 Q
  34.         hpcd_USB_OTG_FS.Init.low_power_enable = 0;& U8 A3 i9 B) n5 t. A
  35.         hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;- ^8 Z& t) P& s
  36.         hpcd_USB_OTG_FS.Init.Sof_enable = 0;
    ; R: `, M4 q) ?" r* }) N4 F+ W
  37.         hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
    % g7 l; l8 d& z0 ^: r* ^
  38.         hpcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;+ k) i8 Y/ b5 M" z* t
  39.         hpcd_USB_OTG_FS.Init.lpm_enable = 0;
    0 ?8 N* l5 p+ ^: D/ S- T$ L
  40. ( ]. e$ r* l3 E! _8 _
  41.         /* 初始化USB  */
    . F% x. T6 v8 O' ]  {% E, z- c
  42.         HAL_PCD_Init(&hpcd_USB_OTG_FS);
    ; w9 D3 }0 A6 M, U: E( L: N
  43. ! o% e- b  D+ Z; T* t( h0 O$ h
  44.         /* 设置TX FIFO和RX FIFO */
    + }0 J, l( r# b" Y
  45.         HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 1024);
    7 d3 V: U1 m. `' ^8 Y* T
  46.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);- L+ H( g( Q4 k4 `
  47.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 1024);
    ! B8 {! y  N1 f- G
  48. : k+ C& I' A- Q6 M" F
  49.         /* 注册STM32到USBX协议栈并初始化 */$ z* `9 n; Q% n5 ^  q+ u
  50.         status =  ux_dcd_stm32_initialize((ULONG)USB2_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);" n  Z$ r! r8 j' r. D; `2 T$ R, R

  51. ; Y1 x. ^% M* }) U8 H4 q
  52.         if (status != FX_SUCCESS)
    % {. H$ b4 _. F% F4 ]; U$ o# ]' f
  53.         {7 f$ n* a& P9 Q  s( q/ [7 G
  54.             return;
    ; ^  w7 y; e  V
  55.         }
    / q6 x. ?  N* a6 u
  56. * m1 s. \+ O' V( z, w8 m  O, b: U! p5 C
  57.     }
复制代码

# f) G9 L  G* g2 K3.2.6      第5步,MPU配置
# D  K1 Q2 q* e
为了方便大家移植测试,我们这里直接关闭AXI SRAM的读Cache和写Cache(这样就跟使用STM32F1或者STM32F4系列里面的SRAM一样)。此配置是在bsp.c文件的MPU_Config函数里面实现:' z+ I0 s. [6 w2 x
/ F8 I4 h) V# l1 \( U: e
  1. /*/ C9 x- P! `$ a; T' z  r
  2. *********************************************************************************************************
    1 ?0 l6 ?$ k- V) ?3 P  ~3 y
  3. *        函 数 名: MPU_Config
    , n, s5 v8 q& Q7 X" c4 R4 h
  4. *        功能说明: 配置MPU
    : A5 ?. g( z1 F' ?: T; R  b
  5. *        形    参: 无- R0 s8 w" d+ H7 w  k7 {) R
  6. *        返 回 值: 无* A7 l: X( n, Q: P& `1 C+ B
  7. *********************************************************************************************************  ?8 z; a  x9 A% A7 k
  8. */
    6 n* j4 W3 y" e; W  F2 Q" Z9 o
  9. static void MPU_Config( void )
    ) p% @* z& n; E2 U+ u0 }) i
  10. {) ]" ~: ~6 A, G% |( `& N9 s
  11.         MPU_Region_InitTypeDef MPU_InitStruct;
    & z2 T( ~0 K. J5 m& }/ v- V
  12. ) J3 s- @( y6 s) `  E; `3 l2 o
  13.         /* 禁止 MPU */, l. |, ^1 E9 \3 E
  14.         HAL_MPU_Disable();7 j  G% }. A2 k9 S. Y5 }
  15. , {: g9 L( r: W6 W1 X
  16. #if 0
    ( N* D/ B+ [! u8 g; u7 \
  17.            /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */
    ( x% h1 p0 d5 q
  18.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;6 j: Z1 w+ `4 X: F
  19.         MPU_InitStruct.BaseAddress      = 0x24000000;8 Y3 n- A: \6 G6 b
  20.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    5 [( C9 A# A# `( o. w* t1 r
  21.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;7 m# T+ E) u/ o2 V, o  S/ a
  22.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;; T9 t9 a: T* ]$ J7 ~% w  @; E
  23.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;% x8 k7 m5 y" T
  24.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    + l- g6 |8 w; D0 n0 K% I- `% ~' G
  25.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    7 _. J% K- w% }. F1 j$ |( v, R
  26.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    ; G; z: p: U7 A8 L  b
  27.         MPU_InitStruct.SubRegionDisable = 0x00;
    + ~' y) r% r% T' C7 K' ]3 h1 P' j
  28.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;$ P  M: g- |; A* _; o

  29. 6 e) p9 `3 B/ M/ D" S* X( n
  30.         HAL_MPU_ConfigRegion(&MPU_InitStruct);( h% j  @6 U0 Q" c: ^% j

  31. * P- b) X( X, i. C& s
  32. #else
    / f6 q/ {9 [6 w! x, H# G3 W
  33.      /* 当前是采用下面的配置 */) U' \! T. N; ]: U" R7 X( A$ e
  34.         /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */: ?* C/ E7 M5 h( K
  35.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;% u& k6 j% F! H( k* p1 e. ]
  36.         MPU_InitStruct.BaseAddress      = 0x24000000;0 v7 \* |# x+ ~1 R( c
  37.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;6 R8 C# Y$ K0 d0 ?8 C' V4 |# o( Z+ A
  38.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    5 t. a+ w* r, Q$ U& r+ ^$ N
  39.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;+ s# m3 a/ u0 ^5 \! V0 b; b/ P
  40.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
    5 ?3 w$ {: b! c9 n  J
  41.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;' v7 ?7 J9 ]2 H& O0 J8 w, p
  42.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;' R, {5 F7 \) X% Z- x; f9 v* U+ I
  43.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;- R+ |2 ?2 g& k: h6 t% Q( ~
  44.         MPU_InitStruct.SubRegionDisable = 0x00;. l  p& \6 V* M4 j, T- G& E
  45.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;6 ], o! r8 ]1 q% s0 o2 J8 X

  46. ) ]( t% Q+ Y/ a7 C: E7 t2 f
  47.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    5 D3 Q3 P/ P0 c9 Q
  48. #endif6 }, Z& O+ ~# L, `3 g2 {
  49.         /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */4 `3 x% q& {3 \& Q! f
  50.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    . \; x( ?, Y; X9 ?8 x& c
  51.         MPU_InitStruct.BaseAddress      = 0x60000000;
    ! `; F: w; h. M: r5 k
  52.         MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;        8 C7 K/ |( s# P
  53.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    + U( B8 n) P  ]' u
  54.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;: s' }6 {5 O; N; Z" }
  55.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
    ; B0 q; C# {0 L2 n4 r1 F2 i
  56.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    2 _7 A; c8 a1 o. o
  57.         MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
    7 |" Q1 R7 t) g' t) ]
  58.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    & E* \$ a& Z$ \8 p3 s1 {4 D  V
  59.         MPU_InitStruct.SubRegionDisable = 0x00;" Q3 X/ D& l9 Z2 G4 @6 ?3 l
  60.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;& J  N- q& z: U, I, P
  61.         
    8 z5 j- E4 M9 q
  62.         HAL_MPU_ConfigRegion(&MPU_InitStruct);- b) H0 S* a5 A) M, \! [1 R( A! N

  63. / Q9 u9 S" a+ v; k" y1 H, i
  64.         /*使能 MPU */
    % o3 v3 E" V% E2 c
  65.         HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    * Y0 \) V) X8 h6 R# S8 A
  66. }
复制代码
% t# U- o6 f4 u# u4 d: K; ?# s0 J
3.2.7      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)
2 Z# p2 z' t6 n8 g3 V
USB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可3 m# b  |+ e& J  t) C' @
* N1 k! D/ A! G
特别注意USB中断服务程序别忘了添加。! J  l; |8 t# n% J% _! r

% T4 [# y+ u; W8 \3 w' K3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明4 H9 _3 I5 g- c& W/ A
这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。: i  n8 C1 a0 C

! B5 M  g* V# q7 T* d8 c3.3.1  状态函数app_usb_device_thread_media_status- P" \/ H% c8 F
代码如下:; v6 G8 L" l$ m+ }& S( G# _
9 j- b$ ~# a/ X# B' X. B5 S
  1. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
    6 L" e8 O* o+ s3 |- `! `! B
  2. {
    - _) A* w$ ]4 S
  3. 6 [5 ~! l$ r# |3 T
  4.   /* The ATA drive never fails. This is just for app_usb_device only !!!! */
    8 J7 ^: c. T5 h0 A
  5.   return (UX_SUCCESS);# k* w6 B6 `; n% D' s
  6. }
复制代码

% d/ v4 X4 d+ |3 t- s1 S此函数主要用于获取SD卡模拟U盘的状态。
8 z  ^0 h& u! t2 Y
! d$ k1 l4 A# a9 F" T1 ^, S2 Z3.3.2  读取函数app_usb_device_thread_media_read
+ O! E" Y, I4 u$ G' X% g3 A3 h
代码如下:
5 F1 {5 H# x+ ?/ h: H' t# E' Q7 _' G2 p8 Y3 B% I8 B! O$ B& ]
  1. /**" d5 P) b- \4 B( h( X. }. }6 M& P
  2.   * @brief  Function implementing app_usb_device_thread_media_read.
    3 S) O* J; S3 X% }7 @/ |& J) z7 a
  3.   * @param  storage : Not used7 S: b) o: @5 C) U8 T8 {
  4.   * @param  lun: Logical unit number1 o$ y6 R1 G& V3 E: s( \' _
  5.   * @param  lba: Logical block address
    : n3 c- E2 y4 x: s5 a+ V, l3 h
  6.   * @param  number_blocks: Blocks number
    . w  m2 M6 E$ ^) e4 k% b1 ~, [& h0 `  Y4 d
  7.   * @param  data_pointer: Data' j* p+ T, U8 r  {5 n: J
  8.   * @param  media_status: Not used
    2 D# Q9 D! Q2 G3 |* O( Z- C. I  L
  9.   * @retval Status (0 : OK / -1 : Error)
    % U3 \9 W$ Z$ J* u4 J
  10.   */
    ( a2 w$ r3 T$ k1 v( F' Z
  11. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,# w/ H3 ]2 c% V
  12.                                        UCHAR *data_pointer,
    $ X% E/ \' ?3 v8 G1 J/ e
  13.                                        ULONG number_blocks,
    1 Y0 r( J2 u9 i1 Z' y0 Q
  14.                                        ULONG lba, ULONG *media_status)# u7 J/ F* q1 e6 |8 S
  15. {
      |% M8 K2 E' H/ N' }+ V( N. n$ R" c+ M
  16.     UINT status = 0U;
    9 b3 e% ~; }; @2 B) y$ z, L
  17. 0 p/ c3 O( \& x
  18.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                        / s1 R9 D) Q- ^6 e8 W" M2 y
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);; D, L& k& M$ {0 X; G/ ~6 t
  20.     status = check_sd_status(0);    . x- V7 P& \( J* I( k+ B6 y# U! i
  21.     return (status);
    5 ~; g7 m. n+ H$ N0 e; |+ b9 r
  22. }
复制代码
/ V4 @4 `& y3 k' g4 y% p; {
用于实现SD模拟U盘的读取功能。3 v* X  f- g7 M& h. p. ]

  J/ `' T  }. x- J% C2 N8 Q3.3.3  写入函数app_usb_device_thread_media_write
8 [' I3 y! p7 P6 }/ r" L0 x2 R代码如下:
" P. c: _+ \+ Y$ L3 k8 C/ N( Z: Q+ f$ |, j9 Z
  1. /**
    ' Z- N( @; p$ Y$ o, k* b
  2.   * @brief  Function implementing app_usb_device_thread_media_write.
    ; h% I6 L1 x" c7 q2 O  ~; R
  3.   * @param  storage : Not used) i. u9 M) x7 q/ f* W
  4.   * @param  lun: Logical unit number2 a$ o$ c/ b. J/ y
  5.   * @param  lba: Logical block address* O% G# X* C& G0 |, \
  6.   * @param  number_blocks: Blocks number
    2 L8 x$ y  j; Y" r
  7.   * @param  data_pointer: Data
    * F$ C) Y2 A0 g8 [$ b
  8.   * @param  media_status: Not used
    ; H" X' C8 @, ~* D! [
  9.   * @retval Status (0 : OK / -1 : Error)
    " D6 a6 l; Q6 o3 m# P
  10.   */
    7 I& g7 H+ l% C) m) F4 u
  11. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,0 o* G; k+ S+ U
  12.                                         UCHAR *data_pointer,- t, O" e, w5 B: S  T* ]8 a
  13.                                         ULONG number_blocks,
    1 `$ U& J8 l# P5 ]2 y* v* R, h- e
  14.                                         ULONG lba, ULONG *media_status)" N+ Q4 h" G8 e: q' K
  15. {- V- |* b' C0 Q8 v# U4 |/ M( d0 q
  16.     UINT status = 0U;, q1 @$ H/ o8 t- ]: d/ y0 [

  17. " U& S- D, Z3 J0 V* t8 V) I* ?
  18.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);
    * U& P) `' D0 [4 H% {6 b; L
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);) U1 o0 Q/ ?1 D. s/ ]0 S0 h  s
  20.     status = check_sd_status(0);
    ! D$ L0 D3 }3 `7 v" Z4 ^9 Y1 K6 F6 F
  21. 5 Q+ K2 p) l4 R! ^2 ]
  22.     return (status);
    6 \/ P2 x* K9 ?- a0 @( P
  23. }
复制代码
* d# G, ?3 u; J; t( u
用于实现SD模拟U盘的写入功能。
1 b+ K0 N7 D' p" W: l
# v, H! @6 i$ L7 D$ l/ k  R3.3.4  接口函数注册* B. o, ^: f5 R; B3 G1 i
接口函数的注册是在文件demo_sd_usbx.c里面:: j+ f& b3 g7 |- m" F; G3 ]
. `7 ~/ }. O+ e0 H2 `
  1. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;/ R) s7 }9 U. D2 z2 g  P! I

  2. ; S5 e" }0 m3 _& [3 A+ g( s
  3. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write;
    " `( g1 P! P9 \* z8 T0 r

  4. ! o, O8 }. A0 \( ~. @) K# l
  5. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;
复制代码
* ~. L; f) G9 @/ Y
3.4   使用的MicroUSB接口并注意跳线帽设置) y- `2 F* L4 r+ M5 P
本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:2 U/ ^$ S" J- v1 }2 L/ ]( F
. k# i! \! @- K+ U
a9cb882c39474dd9bd63b8c7e14cb451.png
& C" ^$ S' \- m5 G% N/ [: Y* p1 R

- W8 N' `7 N/ Z, |# U, b注意使用的是MicroUSB接口:
( b1 }2 c9 T9 k6 g' t5 y) ?) q( S* @" x* K" U
f871e17a6a2d4c03a9413daf725670c4.png

. _8 C8 Z+ G& U- ^4 t+ ^, \, F. }6 c' Q: {
8 ^0 b; U$ ]& Y% V7 B
注意板子左下角跳线帽的设置:
: ~. {% m  T, C1 ^) h( ?  {% W' H. v& z0 D( _$ e
41272c92c8c9483f9d5dc6a04cbf87b8.png
/ Z. c4 `0 q1 [9 [
- g9 g1 k5 U) g) W- E; J
, h5 k' [# Q% r* H/ \$ ^* {% G0 i
这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。
, i4 ?9 S2 B1 u. n# n6 V
' M' [' c4 u& A( C( t! I+ {8 M( i3.5   实验例程5 S# R6 q3 [4 l( H& `, \! z% i
配套例子:; s- m/ H3 Y0 u. M5 c* c2 ]1 }

5 t6 y. O( I2 l' `1 jV7-2401_ThreadX USBX Template
: ^8 }% W; Y4 e
3 l6 Q, ]' f! N& f实验目的:
2 u7 j2 u& i9 C8 S! r: L; N4 j  H0 K  N& x4 X  N. X
学习USBX模板,通过SD来模拟U盘。
5 z; {' t7 G1 g8 E" m实验内容:
8 z7 q& ^3 a/ |) j% S1 |& H7 `6 k2 S! x
1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                 : }3 w4 u7 Y0 u& F- p1 a
+ F& V! ~, ?6 h
  ========================================================
# M; s9 n5 \' ?5 D: H! \. k  J4 F
         CPU利用率 =  0.89%
2 c( F' g) _$ @' f. U* Y5 r/ ~" }' |7 c' {$ c# E
         任务执行时间 = 0.586484645s( R7 ^; m* C: ]9 X5 x2 f
/ F7 P/ j/ Q) A+ a# q0 q
         空闲执行时间 = 85.504470575s
5 w) z: z/ P) ^( Z1 U2 @# ]" j% \2 S+ S/ c, r" ?1 [& H+ |" Q. w
         中断执行时间 = 0.173225395s6 e8 g( V' q' ]) I* X" s

5 I! U6 P5 b' ^         系统总执行时间 = 86.264180615s              7 y* O9 Y/ b2 Q. X9 \& w7 w) h$ P

, t7 R. V2 D, \5 N=======================================================
& D- s8 H' g4 G% j: {
2 {2 u  b; O# J/ ^) t% c7 r        任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名) s- g8 g( k# L8 y5 M+ E5 R
% z; \0 ~0 C" Z7 J# i
          Prio     StackSize   CurStack    MaxStack   Taskname
% }. ^% @; V0 p
8 B/ I: i1 Z9 E          2         4092        303         459      App Task Start; Y( W( |2 L/ ?6 `0 X
3 J  s1 q; }# m6 ^4 i- i; ~/ R2 D
          5         4092        167         167      App Msp Pro# P4 W2 w1 n+ N4 ]( P
/ [9 B7 V+ p2 I. S
          4         4092        167         167      App Task UserIF3 u* h# Y' L6 W% [; p- M+ c

1 m/ ^9 n, i% v& L# F* P% Q           5         4092        167         167      App Task COM
9 E2 J. S5 ?( P3 O; _8 C
5 [1 ?$ u# x4 ]9 I  T8 U           0         1020        191         191      System Timer Thread             h2 x4 O5 ^4 b3 y' G/ q

1 a, f( X, M  T" q, y串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。. O, l% v  c1 z* F1 i5 \  w; b

. D1 a" i5 R+ Y! y2 EApp Task Start任务  :启动任务,这里用作BSP驱动包处理。% Q0 d) q6 ^) ^5 K' T5 ]9 p
7 m* j5 ]4 ?! d
App Task MspPro任务 :消息处理。& k2 t9 W9 E, }& Q9 f; E

! C+ S: W& X# ?8 O) R; Y! d2 u' d. _App Task UserIF任务 :按键消息处理。% M3 E  S9 `6 [' M6 ~. w

3 Q, U  F: ~3 U6 ^3 WApp Task COM任务   :这里用作LED闪烁。
4 v! f; [# o. |2 S# X5 V# N; j' e# b; Y# g# Z: p* N# G
System Timer Thread任务:系统定时器任务
% Y4 B% J/ ^- E% W3 I" O  ?+ a3 i2 N* D  n0 o# ]/ S
2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。
7 L8 `+ V& Z0 }7 {0 W* Z4 r9 Y$ \0 L/ C- |
      (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。7 W+ G$ O3 F- E* q% @& p7 `8 }

+ Z0 m! i3 U6 T  @& \! Z$ Q3、默认上电是通过串口打印信息,如果使用RTT打印信息
5 M1 g/ i6 O6 C$ p( N0 k$ X! k) D5 l, Q! I# e; H* ]+ M* T
(1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可
4 w* c$ Q8 c4 F% |- q2 \% S- g; ^& n6 q
#define Enable_RTTViewer  1
3 z" H5 d, f7 ]. i' T/ |  {+ H* P( X8 D  R7 v3 F
(2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。8 S) k( |# d6 ?. T
* Z! H7 Y7 f+ I  K( l5 l
实验操作:7 y; W* {3 u) X* r

+ S$ V/ d8 Y$ u" T" m测试前务必将SD卡插入到开发板左上角的卡座中。
  c- l) j+ V. R支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可0 M2 R/ T$ M" R$ L2 E5 O$ e; O* M
printf("1 - 显示根目录下的文件列表\r\n");
# l1 E9 f2 V0 c7 o: vprintf("2 - 创建一个新文件armfly.txt\r\n");
( P1 @* _2 m6 ^! b8 Sprintf("3 - 读armfly.txt文件的内容\r\n");
6 R3 M1 h7 d* }) v1 Z, Aprintf("4 - 创建目录\r\n");" p) l1 T* B4 y3 g
printf("5 - 删除文件和目录\r\n");) W, ?% P+ k3 {
printf("6 - 读写文件速度测试\r\n");9 g5 ^, w" {; V' r& F
printf("a - 打开SD卡模拟U盘\r\n");' Z: `$ H6 c0 E& d, z
printf("b - 关闭SD卡模拟U盘\r\n");" R- e& X3 {2 T; L
串口打印的信息:
: x# R2 ?, v7 ?2 s5 h
. v0 u# i( n  @* \( J' ~8 N波特率 115200,数据位 8,奇偶校验位无,停止位 1& f% u+ Z- ?' n# F

+ n4 X5 D( S: x
74d954c9e7b649289184a7a4bd58d6e6.png

% f5 ^9 E  H% j/ O, x- f
' n  T! `7 X$ t6 ^: q) J
- ^4 d9 e0 B" C" ~
1 W/ o" i; ]" }) S/ b- X5 y" ]$ TRTT打印:% y7 O+ f! o' l" j% a  N
$ o. i* d" f0 s2 L
cdcab0e093ed468a912923050806de22.png
# G8 q. F0 a& {5 \/ h9 x% }
6 L/ A5 \# h, A% {

* t. W! H% y, l) K7 Q, E3 p5 L
2 p# t, q0 K: {) j3.6   总结8 x7 W3 L: ~2 z7 [
本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。
7 d$ P8 l9 k% r& J" m9 a2 ?" q" a2 f; w( v; p9 ~
& F8 y/ r$ ?# b) W4 ~
1 y7 n4 S) x! R8 u% C5 |
收藏 评论0 发布时间:2022-1-1 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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