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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 19:00
3.1   初学者重要提示
( P: M- B6 H0 n6 \1、  本章使用的ST专门为STM32H7提供的软件包8 s- w5 R- t- R7 \+ G
8 [& V* O' _9 a. i% f# X6 o+ P
2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。4 G1 F, I) w# P/ Q" P
& O7 b4 T( s) J
3.2   USBX移植步骤2 U% s4 @) I  Y
ThreadX USBX的移植步骤如下:
, ~& v! b8 X7 t" l* d  G0 v0 Q4 V. l
3.2.1      第1步,了解整体设计框架1 V% ]) r4 y, p3 O! E5 m4 V
为了方便大家移植,需要大家先对移植好的工程有个整体认识:
9 G% g6 o* F* x1 ]) C: M3 B# H$ }! B0 J3 P, L9 i& r
556edb9b3bb947f5b69aac84272def1d.png

9 y6 N+ ?1 f. B& t  }( s( S  _% l  Z

' J$ e* ^/ s$ O: }2 q3.2.2      第2步,添加USBX和USB驱动到工程. W1 Z7 W# _6 g2 M1 Q  }' W
这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。
6 N& J8 N9 z/ h
  w9 |6 S% |" _5 e8 `  模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。& [( C3 F3 x7 Q* P
配套例子是放在\User\usb文件。7 ]5 e7 L; t/ R% ?! d; R4 h+ N
2 S  O& v. X9 d7 h
  USB驱动文件stm32h7xx_hal_hcd.c,stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c。
6 c9 }# Q# Y7 k+ k) t这个是STM32H7的HAL库自带的。3 [3 j# b3 K( b6 a3 _2 b, b7 a4 O: r

3 v% P$ m1 R% t& F8 Q; }  USBX相关源文件。& |* R7 t. F: u( d9 t1 G; c
大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在\USBX。* e8 w/ |" r; e6 a$ a3 r
0 j4 E; k1 R8 g/ ^9 |: H
3.2.3      第3步,添加工程路径
* u8 b, Y7 t. o6 Z大家根据自己添加的源文件位置,添加相关路径即可:% M& v6 t8 p- s( V/ a, Y
9 y5 D2 [5 N7 M3 y  K9 V
7d4292e15d424274b8e5aab1d6cd32a9.png
8 L. @8 Q& ^" W4 z1 n$ W  o' }
5 J9 d. ~2 [4 a' `  T
5 {3 p4 I/ [8 z! j) J
/ Q) U: Y- `& I+ H
3.2.4      第4步,禁止掉添加进来一些文件

7 Z$ H  {* T% H7 [( m6 Q1 E9 w$ D之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。
" Z# K0 ]. \3 u. q( _& }
7 F0 `3 g2 P0 `0 o$ E- Q
418a71e2dcbd48a199034bbf6765d9fc.png 4d161770a4734368b6881fe1ed982494.png
) a: s, x$ Z5 t! [# T

6 {' v" o4 ~" o4 U4 I9 l! @# n; ?0 \; S; Y
696837e6177b4f3caa286c6913cf4ea3.png f052ff2297b4462daa7186e7fc3b6ab8.png
9 q2 u. Y' p1 g
2 e& k$ R, j% X# l
0dadc8e05ea349beb4e04a737e86ed07.png
1 z* c3 C+ p$ [. V$ n  ]
/ y" d. L8 A" l) [- L' U) N
禁止的方法是右击此文件去掉如下对钩即可:
) ^# ^. r3 d% P0 w/ ^# X4 n3 M. v, E% k+ U4 _' E& R
4db1e499f0f7422f9e522bf1e7bcecfe.png
* @- t* j6 j  b- f% t6 k" i

4 m9 C% d7 Q/ S; N6 w& a, W9 c8 C+ J& b* Z, J

* ?2 ~6 f! q' x: {& J8 w3.2.5      第4步,配置GPIO和时钟
" z* M9 Q( \2 d# H( j; VUSB时钟配置在bsp.c文件的函数SystemClock_Config里面:
) H7 K, h' p; L( T4 g( C
, h0 ~1 B' U* l- G  E1 y
  1. {
    ( n9 e' {$ U+ x2 W  m
  2.                 /*3 V3 g, r. A" ]/ R- ?1 d) G0 L
  3.                 USB工作需要48MHz的时钟,可以由PLL1Q,PLL3Q和HSI48提供
    3 f9 V# [4 G4 ~( I7 @
  4.                         PLL1Q用于给SDMMC提供时钟
    " e) ~) {' L  w: S
  5.                     PLL3Q给LTDC提供时钟,也可以跟USB共用,不过得更USB设置相同的频率才可一起用。
    3 M& {" e( o. G7 j0 G
  6.                     HSI48可以供USB独享,就是精度不是很高。
    3 D7 k8 R+ L/ \9 v
  7.                 */
    ) D  _# c" d' ?1 |
  8.                 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
    , {9 m$ @: J' C
  9. #if 0$ l0 S" R% b. y, ~! P8 X& x
  10.                 /* PLL3-Q for USB Clock = 48M */
    . K2 J- f1 R9 W: Y( h# \
  11.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;3 J: f2 E7 W* D' p7 v
  12.                 PeriphClkInitStruct.PLL3.PLL3M = 5;' q3 z5 X) r! \' l( b6 T
  13.                 PeriphClkInitStruct.PLL3.PLL3N = 48;& |! C0 B. J% f, H5 Y! s+ u
  14.                 PeriphClkInitStruct.PLL3.PLL3P = 2;) f: h* y7 B' w+ i9 b. \
  15.                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
    5 o* J' G8 f5 M) }0 h2 S
  16.                 PeriphClkInitStruct.PLL3.PLL3R = 2;. n  P; O5 v4 y/ q1 i6 O5 S( {
  17.                 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;
    ( z+ Q& C# |$ d4 |
  18.                 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;/ ?) S) c3 `- O) J/ Y
  19.                 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;& A3 u; H7 D0 f6 D6 a5 P9 h& I
  20.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;- Y3 ?0 v: s+ i1 o  g
  21.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK)
    % w! F# T; V1 S; Z4 v
  22.                 {: g3 C/ w/ T& r2 X, ?% @
  23.                         Error_Handler(__FILE__, __LINE__);4 p$ K" w8 M3 Y3 u( w9 q
  24.                 }        # q# p1 B' }$ G# o+ J
  25. #else5 A* s# i% X7 d$ h
  26.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    . n8 W% @, v2 r! d1 A% ^
  27.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;, r, C& o! u& Y9 |( E) _
  28.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    % S6 q" E9 F* T$ G6 c! q6 k! P
  29.                 {
    / c3 v: x, {) c# }: \' c
  30.                         Error_Handler(__FILE__, __LINE__);. t4 {- {* q0 M, W$ i7 U9 |
  31.                 }5 C  n  j# A' y, |) n, b
  32.               HAL_PWREx_EnableUSBVoltageDetector();
    $ E5 e, Q* s' M2 M
  33. #endif
    0 i' h, z! o+ y  A, ?9 H* k5 ]
  34.         }        
复制代码

  T( h  D" j. P( ]USB的GPIO,NVIC初始化在demo_sd_usbx.c:
. W8 x0 ?5 w4 o7 x* \2 k0 H0 ?# c. k- [& w
  1. /* 配置USB GPIO, NVIC */) X" @* n! F3 C0 ]8 i  C
  2.     {8 k; T8 c* p$ c
  3.         GPIO_InitTypeDef  GPIO_InitStruct = {0};+ s) A! I% I  e! D

  4. , B3 J4 ~& r0 k- @  M& k5 s' {/ k
  5.         __HAL_RCC_GPIOA_CLK_ENABLE();
    % n7 y1 n$ v8 ?& i  \0 j

  6. 1 F$ ?0 S' n% S& d* n( G
  7.         GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
    : l# ^5 ^# y2 |1 K7 G
  8.         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;' h/ b! x9 `0 I0 a' f: S
  9.         GPIO_InitStruct.Pull = GPIO_NOPULL;
    / }$ ~& i. L: b* ]- b2 \. I
  10.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    ' f9 b% g7 M" b# Y; F0 _+ ?+ h# [
  11.         GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;, i/ F. X/ G8 x0 C$ ]" t0 r
  12.         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    / E( N; S- M0 u% V
  13. 5 y7 ?- }( g7 B8 h
  14.         /* 使能USB FS时钟 */
    : w) F/ D1 O5 t) x
  15.         __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();4 J: V0 S2 @( X" [0 ?. }

  16. 3 }& U9 F# D$ o$ ]5 m+ r5 i) c
  17.         /* 在睡眠模式下禁用USB时钟 */+ d: @8 a6 c, p/ s
  18.         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();
    7 j: [! n) k6 x4 E2 }) p

  19. / i  j( K8 `" u1 v3 B
  20.         /* 配置USB FS中断 *// p) ?3 m. Y. f( k: h# F; W
  21.         HAL_NVIC_SetPriority(OTG_FS_IRQn, 0x2, 0);
    # |6 a; a4 d* u: ~) g2 g8 z. ?7 ^
  22.         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
    ! B9 f" O& x; H* J* U) E
  23.     }/ M' w/ D* Y) F: d, I
  24. 4 K+ @" N0 [* I
  25.     /* 初始化USB */  h2 |( f  Y  B+ f5 S: M
  26.     {4 W2 v3 m% f4 A- k( f1 @
  27.         HAL_PWREx_EnableUSBVoltageDetector();
    . w, p- a: ]; d9 a5 E+ \% n- V5 \
  28. 8 h/ X' g9 \8 i# \3 p# a' X0 X
  29.         memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));
    ' r# z/ e7 ?6 K8 W* D
  30.         hpcd_USB_OTG_FS.Instance = USB2_OTG_FS;
    2 O( ?$ A( o  o* U) ?$ ^4 a! t
  31.         hpcd_USB_OTG_FS.Init.dev_endpoints = 8;
    * p$ G/ Y2 Q' C6 w( A
  32.         hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = 0;( @1 `0 y7 C2 n8 G, L) N
  33.         hpcd_USB_OTG_FS.Init.ep0_mps = 0x40;) k  Y: n5 G8 L5 S
  34.         hpcd_USB_OTG_FS.Init.low_power_enable = 0;
    7 p7 e/ l( F; A* `) F3 Q: D9 y) p1 G* @
  35.         hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;4 s- j: S3 n% Y" o) e3 K$ _. M, S
  36.         hpcd_USB_OTG_FS.Init.Sof_enable = 0;
    2 Q/ p+ K* E; |! X! ]1 v" E) A
  37.         hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;5 P* n! u: b" l) r* `; I: ?
  38.         hpcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;# g0 {$ Q8 d: s5 x" g0 A
  39.         hpcd_USB_OTG_FS.Init.lpm_enable = 0;0 a4 ?3 o# ~/ O" v1 Z) S

  40. " T  ?  i- A4 t5 r2 |% z4 S
  41.         /* 初始化USB  */
    $ |' B  ~2 i; o) t8 _; g1 y
  42.         HAL_PCD_Init(&hpcd_USB_OTG_FS);# X/ i& O1 [5 t5 C  |2 H

  43. $ `# f# X) x; q2 ?/ Q1 Y- |
  44.         /* 设置TX FIFO和RX FIFO */
    8 I% G& j' x# `
  45.         HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 1024);6 o6 U! @% d# j& s7 X6 h6 z7 t4 C; P
  46.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);2 V7 h, J7 U1 R7 N% E" f1 k, M
  47.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 1024);$ T7 t8 o1 Q  l% P" {& e

  48. ' \5 z9 u  d! t5 }3 _  o$ U$ \, v3 H
  49.         /* 注册STM32到USBX协议栈并初始化 */
    1 F8 a" }' O. ^. q2 k, T( h# d( A
  50.         status =  ux_dcd_stm32_initialize((ULONG)USB2_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);* z$ `  P1 ^0 G+ Z

  51.   g3 r+ W- P& R4 A$ {& \; G9 t( V6 Q
  52.         if (status != FX_SUCCESS)7 X+ f; G) O; }6 X" k. z
  53.         {+ q. X, Y, i5 Z$ `! g8 j
  54.             return;
      c& F$ {% W. ^8 C
  55.         }
    / U7 G4 ]  Q) ~+ u
  56. 8 m/ |  O; T* k8 k& u& C
  57.     }
复制代码
6 p) `9 ^# i! L, w( |" }; r
3.2.6      第5步,MPU配置

0 y* V# Q: Y0 w5 F2 {为了方便大家移植测试,我们这里直接关闭AXI SRAM的读Cache和写Cache(这样就跟使用STM32F1或者STM32F4系列里面的SRAM一样)。此配置是在bsp.c文件的MPU_Config函数里面实现:% R5 `0 u7 k8 d2 M$ ^: a
' Q. B) R3 d$ m
  1. /*1 J+ P. m& G0 K5 \
  2. *********************************************************************************************************
    0 P' \7 n8 ~7 Q- C
  3. *        函 数 名: MPU_Config
    . D* c6 ?2 Q1 x& j0 W" [
  4. *        功能说明: 配置MPU
    0 L6 n$ g7 q5 k; q
  5. *        形    参: 无
    - D8 P9 S: e( w9 a
  6. *        返 回 值: 无
    5 U% R% N. }* f, ^. c' ?
  7. *********************************************************************************************************
    ' g! U( z( ^: `2 z
  8. */5 g/ L. X- f2 g, h
  9. static void MPU_Config( void ); f0 J3 x, w( a  W" f1 z3 Y
  10. {
    + ?3 n" S5 R$ G; d4 Y+ F2 F0 a) x
  11.         MPU_Region_InitTypeDef MPU_InitStruct;; s4 E5 d$ P7 C3 e2 G+ L
  12. - v- v# v$ y- b  \
  13.         /* 禁止 MPU */
    6 k" m. B* H+ U+ H9 N
  14.         HAL_MPU_Disable();
    ( \. M) H7 S" \/ n: J% q6 l3 G8 I/ f

  15. ' a; x7 o) {7 h" S! `
  16. #if 0
    ' |! p) Q1 Q# B0 }0 V
  17.            /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */9 Q* ]2 k' ~" o4 u9 L( Z7 H" L
  18.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    : C2 j8 V1 P3 N$ r
  19.         MPU_InitStruct.BaseAddress      = 0x24000000;
    : K1 l3 _! r3 ^" I) N
  20.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    3 w/ w. f! O' s0 E% V( g
  21.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;  a& ~& V8 e) F  d( u
  22.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;+ a# v5 ^/ f5 N) \2 V; f+ h# q
  23.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;/ T/ {* m+ D; H9 t0 F) S
  24.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    6 x6 X/ j; O5 T3 \' @. ]# m, L
  25.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    - ]3 [6 z* u& f, B! p
  26.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    2 z2 X# r" E( z) ^, b1 X! E
  27.         MPU_InitStruct.SubRegionDisable = 0x00;5 T! ~: b7 N! S( C. `0 {
  28.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;; C- _1 C, N* t3 a9 e

  29. 3 C/ j, |& \7 y) _0 E
  30.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    , E2 G. t/ d6 I

  31. ! {: N" V+ r) _" R8 `
  32. #else( q4 w( r! {, ]5 {/ E. c
  33.      /* 当前是采用下面的配置 */) e& X: u# [5 J& ?; G
  34.         /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */
    ' n% M- T# _1 U2 W; Y
  35.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;* J( \& X+ v- F3 j& m6 B7 m5 t
  36.         MPU_InitStruct.BaseAddress      = 0x24000000;
    % ]8 o! z1 I8 S: o3 B
  37.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    5 S# Q+ K; O: ?
  38.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    8 L( D: B# R$ ~7 Y+ y% M+ u: e
  39.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;
    ! P# }+ `3 J# i  }+ F5 X
  40.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;
    , y! @3 l/ |# B' U  g, y
  41.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;! ]% F2 K& L& ?" u& x+ s
  42.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    ' H! p+ h3 X& h1 ^
  43.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    % {/ v, K3 O, B  b9 o
  44.         MPU_InitStruct.SubRegionDisable = 0x00;1 u% r9 F! ^2 B  K5 K
  45.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    2 `1 J% \& l" L6 e9 P- C

  46. " u; ^" D: ~- ]
  47.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    3 H9 @2 t- C6 l% @
  48. #endif  ]! W1 W* ?( b" W- X
  49.         /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */* P+ x& B5 M  c) A
  50.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    8 J  @% m0 p0 g% i5 y! C
  51.         MPU_InitStruct.BaseAddress      = 0x60000000;
    ' N! q. l7 n3 ]5 [; Q' @
  52.         MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;        - b' m9 W+ l# |* Z
  53.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    6 Z5 e! w! }8 w
  54.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;  E9 |/ j+ m. m0 M6 o
  55.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;# ], i* [$ h% E/ S$ V
  56.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;. M+ q) K  N/ e
  57.         MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
    : ]' _7 s% y$ z0 A! b
  58.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    0 k- }4 g3 U, G; T( J8 W
  59.         MPU_InitStruct.SubRegionDisable = 0x00;2 a! S# s3 _" s- C
  60.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    " K/ e+ g! @  J, x' D  X
  61.         
    0 y' Y0 K- ]4 s$ R% F5 V- o
  62.         HAL_MPU_ConfigRegion(&MPU_InitStruct);* P, E/ \8 \, X/ k

  63. 0 c( M" p& U+ [! Y3 h/ \
  64.         /*使能 MPU */
    # p! {' [+ K  o1 W6 u
  65.         HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);. ?: ~) g0 _' |# T
  66. }
复制代码

. ^1 A& X3 z2 v' ]3 }* `! H& N/ _3.2.7      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)

5 y) v) [. ^/ f% hUSB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可* Q! U% L; s' p0 T9 o9 L+ T
* d* E7 X: H0 ^$ O! W( k
特别注意USB中断服务程序别忘了添加。
& I8 l. d, x1 D" q$ H, o2 [2 [( x6 Q* o& }. S% e
3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明" a6 K" e, z* F$ m1 ]  K! _  a8 E
这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。
! I- o( I% R" C& Y7 G; m- Y* x2 R9 c( O0 r6 v. Y* H: u5 ?  `
3.3.1  状态函数app_usb_device_thread_media_status5 h0 p: e' {3 m' t" W+ b1 n
代码如下:& }2 b* y4 _: G; E) t8 k

( |) O* A- {( {
  1. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status), c, f: G0 q5 l/ J+ P2 l
  2. {  v/ L" U. _3 v
  3. / {! ^% E9 M' M: R  E& g9 H
  4.   /* The ATA drive never fails. This is just for app_usb_device only !!!! */8 D7 \2 f( q% r0 m
  5.   return (UX_SUCCESS);
    0 ]. |) j1 i5 ^2 v
  6. }
复制代码
, U% i) w5 B* {* _8 w* z& c+ ~# [( ^
此函数主要用于获取SD卡模拟U盘的状态。7 Y3 p0 f. V: [# y! }9 v: X

& b$ M# y, S  `/ I5 k3.3.2  读取函数app_usb_device_thread_media_read

% W+ ]) E% W5 s( A7 o8 R代码如下:
$ N' E  _# Q, D
/ @( p; p* L& O" G7 e# [$ ~9 o
  1. /**
    ' u) [0 F4 @3 }/ }/ |& p$ |7 g+ I1 B* c
  2.   * @brief  Function implementing app_usb_device_thread_media_read.
    " F9 \) \; T0 b% ]& x* E4 V
  3.   * @param  storage : Not used
    * W0 U' j' R( o/ F! O4 a8 w! [: _
  4.   * @param  lun: Logical unit number
    3 N! m' _/ [" j; @
  5.   * @param  lba: Logical block address
    ; f4 c& ?" O  l1 w) i) l" i
  6.   * @param  number_blocks: Blocks number
    ! y) q) f5 M) |4 ~# `; }) k& s- D
  7.   * @param  data_pointer: Data/ a9 v- k$ [- L8 c: \$ b4 f5 ?
  8.   * @param  media_status: Not used
    ( F5 R# d' [) I& i6 j2 j$ q- E
  9.   * @retval Status (0 : OK / -1 : Error)
    0 c7 x3 }( |- S* j
  10.   */5 H) W: j% ~6 Y$ C4 x  I
  11. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,! \) I/ \; l& |( j0 m
  12.                                        UCHAR *data_pointer,+ M7 }: n" f$ X  }3 {6 t- ?
  13.                                        ULONG number_blocks,+ |  y/ y0 l3 f) `
  14.                                        ULONG lba, ULONG *media_status)- w. M; g2 k3 H+ s6 [) D
  15. {, n9 U0 ^) \! }0 h" v* {3 y
  16.     UINT status = 0U;& q7 K' K4 V, K, {" Y

  17. " n7 e7 {6 P6 O% X
  18.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                        
    , P) f7 s- z, b+ j. S
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);) N; B1 h% b2 D2 x
  20.     status = check_sd_status(0);    / S5 A% w9 I+ O: p' i2 r5 b
  21.     return (status);
    - W5 C, C6 e9 G, W% L2 f8 V8 z
  22. }
复制代码

- c2 F  D' ?# L用于实现SD模拟U盘的读取功能。; p( K* a; c9 x( H+ S4 d
1 G# ?4 R5 o% `4 D3 W0 M
3.3.3  写入函数app_usb_device_thread_media_write
$ s6 e) L* U6 L% |7 z8 o; J3 j代码如下:
: z7 @& z9 S2 F- N; ]; R% l4 g4 E- |3 U; X) e3 ^3 y2 K
  1. /**9 ]$ c- e( N) Z7 L" Z
  2.   * @brief  Function implementing app_usb_device_thread_media_write.
    & p& V$ W8 x* I1 r
  3.   * @param  storage : Not used
    - t# l/ |8 U4 W' S' D
  4.   * @param  lun: Logical unit number; J, L" |5 [$ W6 k' r
  5.   * @param  lba: Logical block address/ r9 M  u% J, @6 \) {) z
  6.   * @param  number_blocks: Blocks number3 w5 ~$ l& |7 \* _3 Z5 p
  7.   * @param  data_pointer: Data3 B2 l3 d# H. `9 t: _0 L8 o
  8.   * @param  media_status: Not used7 s3 `" t* h: `
  9.   * @retval Status (0 : OK / -1 : Error)1 l% P' {) Y3 a% s
  10.   */! ^) W; e3 u# {, Y2 e
  11. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,
    ) D6 z) {& g+ K9 h0 @  _& L  @5 i
  12.                                         UCHAR *data_pointer,
    ! U7 V: r+ ~# q! n2 h; |
  13.                                         ULONG number_blocks,
    5 U1 f7 L, G. S( ~$ p1 f/ B
  14.                                         ULONG lba, ULONG *media_status)( c) t+ u+ x$ o% {6 n
  15. {( P- |0 |2 S+ d+ f; A. {
  16.     UINT status = 0U;5 Y5 m5 A1 Y) D4 N, l* S/ x" k2 b
  17.   E" n7 O. Y- T" [; _. m
  18.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);- U. p/ v1 l- m
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);8 }3 W2 ~7 R$ U; ]. H/ {
  20.     status = check_sd_status(0);4 v! |2 s; h% T1 K
  21. ( ]! C1 p  e+ x
  22.     return (status);
    . x: ?" S" A2 m8 K8 J# X2 `
  23. }
复制代码
- q, [' M% ]- B, i
用于实现SD模拟U盘的写入功能。
/ H+ c" y0 \! _% {- {
* j: G5 V5 k$ _, M3.3.4  接口函数注册7 s$ W: d$ }; R) l! g
接口函数的注册是在文件demo_sd_usbx.c里面:) `4 w, `$ @( v4 L- ]8 k

4 o* R) X  d4 _; C( a) |: X
  1. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;' i, Q% B$ ~0 a4 A
  2. 3 @) o) i; b8 W- c7 t
  3. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write; ; K, v9 f7 J# Q* ~$ r& e% M( l

  4. 2 d4 @. N: }6 y* L5 B. U8 |4 R
  5. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;
复制代码

4 E6 o/ t" g0 d; l  }3.4   使用的MicroUSB接口并注意跳线帽设置
1 c8 x* N- \  C5 ^& F: v本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:1 h8 f3 m; Y9 K# i6 {9 F
& y, z( n2 q/ `* S2 P
a9cb882c39474dd9bd63b8c7e14cb451.png

9 D* N( H' l9 G
6 Y4 x% X3 I. S% i- q% V注意使用的是MicroUSB接口:! @; f  i/ ?; @3 [  d

/ d: k  o* b+ ?$ T/ {
f871e17a6a2d4c03a9413daf725670c4.png
, }3 L2 o' E9 l
. K4 q9 g2 x  a& u+ e) t2 H- \

, j0 r" K8 l; K: t/ e0 \' f. X, j注意板子左下角跳线帽的设置:
- ^* u3 W5 l: Q, d/ X+ B8 t% C+ Q" B' H7 d
41272c92c8c9483f9d5dc6a04cbf87b8.png

/ w9 B6 ]9 _) b% H; S+ V7 v6 I
" u" l- ^( O" g& r( ?+ b& {0 b0 f$ s, c0 F
这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。
& h% ?& m$ w( e; }% o5 d
0 N  U* f. |. S3.5   实验例程0 t9 T  O; B& H7 O1 B' y( l1 c
配套例子:
7 p+ ]. c1 X) q% v8 W& t
7 g  A- b) B8 c  uV7-2401_ThreadX USBX Template
2 ]2 A# b% ]3 c- O, i  e; F7 i& v% |5 C8 T8 |! Q
实验目的:
$ g/ u# Q9 J% f5 ^) g; p& Z3 ~9 i3 \, a; A2 r  K
学习USBX模板,通过SD来模拟U盘。- Q" X* f5 M, z5 P, X
实验内容:) a. W  U! L6 v9 s; {' g
2 l  T% t3 R5 [- D/ n. S. j
1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                 8 s6 H* Y1 p+ M) R; l5 s
% v2 C* {/ u$ d& y8 M
  ========================================================: G0 U% d# x# ], m5 z, a
6 C2 R& e2 Q) o  r
         CPU利用率 =  0.89%
# i1 v% v+ J$ [
, X6 P4 ?6 R/ `. x7 C         任务执行时间 = 0.586484645s
4 `1 q; v. `% D
" I8 Y; j; W9 z2 l2 J# p/ H; e         空闲执行时间 = 85.504470575s
7 c9 u( e9 L. i0 i. l) ?& |7 [3 W2 D6 k1 V$ I5 |
         中断执行时间 = 0.173225395s' b: r; ~& b* @0 v: X1 s  n2 H
, z+ e" R0 N6 _9 q
         系统总执行时间 = 86.264180615s              / D7 e( O/ N# _8 k1 e+ _
; R$ r4 X& m4 ]$ c& H. n
=======================================================
) ~9 x2 T$ L1 m1 q4 B" l9 g/ o+ u( ?
" f; a+ U9 i) X! I, G8 \        任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名" {* M# E5 Z$ S% \, J/ S+ L7 |
& Q) v9 G& F& c
          Prio     StackSize   CurStack    MaxStack   Taskname
. W8 Y' U( I, I* J( G1 r  i
- s  Z9 A( R. U0 m- y          2         4092        303         459      App Task Start. [& b, G2 P8 y, d, \* _

7 T2 O& b( X8 W1 q% {* Z          5         4092        167         167      App Msp Pro1 f, K  ?4 {2 y) ]+ v- J

( ~  O% [" z4 C' K; P          4         4092        167         167      App Task UserIF$ s* k$ G& O6 I! R6 j$ p
/ y% E. W, ^# }- h1 H
           5         4092        167         167      App Task COM. g' J# f0 h" {) O

; C# E8 Y% T$ ]$ x% D           0         1020        191         191      System Timer Thread           9 D5 w% L$ K9 B) Y. U2 E
& N. C* F0 f! A$ [, @7 F
串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。4 }- r; B' f- I5 Z! ^3 T
; e% s3 z: d/ E
App Task Start任务  :启动任务,这里用作BSP驱动包处理。
; I# y3 A1 {! E! }& l; j" \: D' m" I
App Task MspPro任务 :消息处理。# E% x8 |  U; V6 |2 g2 k- x$ C
( l+ ~( Z$ ?# s  U- q/ n5 h9 J
App Task UserIF任务 :按键消息处理。
& C4 a- J6 c2 |( D  T" k$ }  g2 C7 h& h( L  @' T
App Task COM任务   :这里用作LED闪烁。
; p% W+ X( @3 Q2 t# h. b8 E
) v: R% @% u: b  I! m9 M8 X9 HSystem Timer Thread任务:系统定时器任务
4 k& {! T5 r2 e: o
: m6 B7 b- y; c) g9 ~# Q2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。
' l7 E. j7 s5 T; E+ i! O4 U( u) h; Z+ f% V+ G! A( ?6 e2 m
      (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
' N) p% B0 U- w. \7 A0 h* i3 O  c; g& ~3 M5 ^
3、默认上电是通过串口打印信息,如果使用RTT打印信息4 X$ b$ E" x3 h. y3 d3 f' A4 I

' V9 T' [, O% q) I5 \4 Z( J(1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可0 `& [* M, R' Q+ G  N- l3 _
. P' D3 h( J% J$ S! Y
#define Enable_RTTViewer  1) ~& ]) a+ S$ b. d- W8 P: X6 a1 \

+ e/ w% @( R, n6 B# R(2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。
; g% z( t- D( s7 k6 G0 W6 y! T& j  ?; p9 F* w
实验操作:; q5 R# f8 q1 K) k5 {3 @
* `3 H( _5 x& w6 y
测试前务必将SD卡插入到开发板左上角的卡座中。. w: I/ f5 m& _( Q! x& ?
支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可
  k) R0 R6 e8 k6 qprintf("1 - 显示根目录下的文件列表\r\n");
$ n7 o0 u& {; Q( z- B& M3 c/ u# @printf("2 - 创建一个新文件armfly.txt\r\n");
8 H6 z6 w+ V. h0 w9 {printf("3 - 读armfly.txt文件的内容\r\n");+ R8 J/ r$ Y  q$ z. }5 A+ s+ J
printf("4 - 创建目录\r\n");6 M) h& l7 |4 h$ b- r/ T
printf("5 - 删除文件和目录\r\n");
+ w# M* [) ~2 }- d9 jprintf("6 - 读写文件速度测试\r\n");
2 Q1 o9 J6 U  F. x1 D; H, _  Xprintf("a - 打开SD卡模拟U盘\r\n");
  X3 ^  M& R8 U% Wprintf("b - 关闭SD卡模拟U盘\r\n");
: W: l8 l5 H% Z) ]串口打印的信息:
4 S$ [8 x% C  c' O' w" S! ], K( c. {# _" y3 f1 a& z1 g
波特率 115200,数据位 8,奇偶校验位无,停止位 1( e1 }8 t! E1 m4 z' s

/ z9 V0 C3 d. Y/ L# c# E
74d954c9e7b649289184a7a4bd58d6e6.png
# G- ^  V: ]5 K/ s! d, ?

# r* ^! A! \3 @! J8 H8 Q0 v' S* [, z* `0 H. M; I! I$ w

% b) g$ J+ T. L8 h  u2 tRTT打印:
; s* R! `, d6 f9 A
6 F' W% V  m: E
cdcab0e093ed468a912923050806de22.png
- ]7 l2 p) H  O+ |, P! k) s" o9 z

: y8 g% g, [1 @' g4 x% x5 X
( h4 l6 k/ w; V" T% F; \2 N  \2 l# q& u2 _
3.6   总结
0 h: @! V# r# V% s( c' U5 Y! M6 P本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。& p- f4 e2 l  Y8 G2 ?: `

+ m6 F- |7 l% U# }/ ?! ?8 v* U$ m0 W) Q7 a
5 N, y3 w6 ?4 b3 B
收藏 评论0 发布时间:2022-1-1 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

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