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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 19:00
3.1   初学者重要提示
' Q, n- L! r3 R9 s% R  l3 I9 m1、  本章使用的ST专门为STM32H7提供的软件包3 k( N: a8 {% Q6 q2 d( V, `% U
( }. k& t7 Z  D4 l! y
2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。
0 v, Q+ b8 ~0 Z# {6 g2 K7 Q- O  A) W8 X$ y" j" p: z
3.2   USBX移植步骤
5 d' H! C; x3 y5 q, r8 oThreadX USBX的移植步骤如下:
7 U/ h! M8 F9 \1 _2 J
0 L3 D. S* ]5 ]3.2.1      第1步,了解整体设计框架
$ I3 b( U  [( b* e# m/ O为了方便大家移植,需要大家先对移植好的工程有个整体认识:
& P# e; ?2 F0 @& t! I7 ~' u& E3 d* O3 O1 P1 n& Y2 O; h3 P0 e% V$ b
556edb9b3bb947f5b69aac84272def1d.png

0 y! ~; G  E- u: O2 T5 K5 @7 C' V/ \/ G1 ]& E& t+ R3 e! {& E- l

2 b2 {2 F$ s' ?3.2.2      第2步,添加USBX和USB驱动到工程
2 X! I  v3 e6 T! m" l3 X  u这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。
: Y! q9 M2 v' }2 t4 J. P
. W7 ^2 e2 P6 q  模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。
" i2 u5 M& I" s  K$ ^0 O4 f3 I配套例子是放在\User\usb文件。+ M5 d: j1 g2 k3 q; e$ ?
' h  ]$ p' E( X; V
  USB驱动文件stm32h7xx_hal_hcd.c,stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c。
* g; s6 J' j, D, X这个是STM32H7的HAL库自带的。" R4 Q9 v# D3 Y3 W/ O! f; g

6 C0 q5 S% i. d& o* e  USBX相关源文件。' P: h3 Q6 `3 M- o, A
大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在\USBX。- O% b: i( [/ i; J& m5 ]2 y9 Q

9 f# m% L" s; k3.2.3      第3步,添加工程路径
9 C  f1 x  `5 b2 ~* z大家根据自己添加的源文件位置,添加相关路径即可:4 [) J7 l1 c8 e8 y. |$ a+ @3 F' M# Y
& d& i0 e6 E  X3 ~1 o! ?
7d4292e15d424274b8e5aab1d6cd32a9.png

) j6 Y% Q: y. m$ x% M4 J3 ]8 P* s' r' f. _' z4 d) ?- v

& X/ U" _$ c7 I/ |( d6 v
7 u/ @9 c- J3 ~8 R/ ~4 c' v3.2.4      第4步,禁止掉添加进来一些文件

8 q2 X' ^: c! M  q, A" v0 w7 \3 r之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。
3 D- f: \! `( N& C
2 H2 n, O, P  D) w& r/ z  x
418a71e2dcbd48a199034bbf6765d9fc.png 4d161770a4734368b6881fe1ed982494.png

- P* |) F* C2 R4 C: S- h8 O0 b. t0 o+ X, c* Y' N2 Z& ]* {
696837e6177b4f3caa286c6913cf4ea3.png f052ff2297b4462daa7186e7fc3b6ab8.png

# F$ l) x8 [9 t2 W( l! ~, A4 Z( h* R6 I9 ^- n* P1 w3 H
0dadc8e05ea349beb4e04a737e86ed07.png

+ ]* n% k* A; y- B  c; i
: ]0 J6 y9 H3 B3 P禁止的方法是右击此文件去掉如下对钩即可:+ s. U' c9 w! i* ~* v1 i
! a& G5 m, L$ [  ^1 t  l+ W3 n
4db1e499f0f7422f9e522bf1e7bcecfe.png

! K) w* [3 U5 a5 D5 I7 ]. I4 ?6 F2 ]( v" h
0 |, q' G' `- G9 l

/ H4 l9 G' _7 m/ o, N* `. D7 }3.2.5      第4步,配置GPIO和时钟
/ h; ?; w  Y/ H  `! ~9 f# ?' n$ x( u& CUSB时钟配置在bsp.c文件的函数SystemClock_Config里面:
/ ?, @- E' I+ z  }- G
7 o7 v! x7 @0 V' M
  1. {
    0 u$ \3 z! \- G. I% [
  2.                 /*6 z! b9 S: b, t: L  ^# I
  3.                 USB工作需要48MHz的时钟,可以由PLL1Q,PLL3Q和HSI48提供* G; s% ?# W1 }: b0 g7 G4 V
  4.                         PLL1Q用于给SDMMC提供时钟
    - V+ a+ O0 N5 ~9 f3 e
  5.                     PLL3Q给LTDC提供时钟,也可以跟USB共用,不过得更USB设置相同的频率才可一起用。
    - @8 J# V1 s" Z7 \  [' X
  6.                     HSI48可以供USB独享,就是精度不是很高。2 N7 ^+ l8 B! o2 {
  7.                 */+ U% j- y+ G- ?. C! t+ _
  8.                 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
    # L; Z5 m# ~, N& y$ ~
  9. #if 0& e2 `6 Y& y  o' @
  10.                 /* PLL3-Q for USB Clock = 48M */
    4 j$ D2 I+ @# B3 _8 X2 Y; K6 h
  11.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    4 _* O2 \3 d. [
  12.                 PeriphClkInitStruct.PLL3.PLL3M = 5;
    ' n( S$ s2 |. b; [/ d
  13.                 PeriphClkInitStruct.PLL3.PLL3N = 48;
    # ]6 G- L4 ^3 f$ O" `
  14.                 PeriphClkInitStruct.PLL3.PLL3P = 2;
    ; K1 A# V" t; }8 `+ b
  15.                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
    0 s" D" C. r; V! [6 m" H
  16.                 PeriphClkInitStruct.PLL3.PLL3R = 2;
    ! M9 _. z- k7 E  U& v
  17.                 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;. I" J. M$ o$ J9 R" R
  18.                 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;& H( K5 K! \, B, U7 m7 F
  19.                 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    ) s* ?% d4 b8 r
  20.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;8 ~# U5 a7 f2 D# @$ O! t" \: ?
  21.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK)
    7 x$ [8 U) {( _1 `# V
  22.                 {3 y* s: j: l5 w5 V( N* ~( x
  23.                         Error_Handler(__FILE__, __LINE__);
    + M$ f2 r" ]+ U& y2 k! {* x
  24.                 }        " A7 U- B2 W! O2 l
  25. #else; u- ]- n# X. S8 R% ]) _) D' N
  26.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    $ ^; `7 c9 i. U3 {% @& B/ f
  27.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;2 K6 E2 l5 T" m! [$ a3 k- n
  28.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    ! @; L9 h4 M9 D& I% d  O
  29.                 {
    ! C; p2 K* F, c9 ~" Q' L0 A; z+ V0 s
  30.                         Error_Handler(__FILE__, __LINE__);0 r) S& g, M+ C3 {
  31.                 }
    2 y1 h5 i% g# Q0 Y/ b9 }
  32.               HAL_PWREx_EnableUSBVoltageDetector();
    ! G/ d! d. ~, e, J8 `. f
  33. #endif
    ) T; H% R& s$ @0 \- s; c
  34.         }        
复制代码
. q% y6 K8 x3 Y/ F8 I( v4 I2 Q
USB的GPIO,NVIC初始化在demo_sd_usbx.c:
; L: B! j! j2 [4 a8 M, r- X: i' n5 R' ^% T
  1. /* 配置USB GPIO, NVIC */
    6 d5 s  }+ z, e/ E' y
  2.     {
    2 V- I% z$ P: J  {5 l
  3.         GPIO_InitTypeDef  GPIO_InitStruct = {0};8 `2 X5 R( {: L8 v! y# h
  4. ; h/ h# q5 a  m& e
  5.         __HAL_RCC_GPIOA_CLK_ENABLE();
    % h8 w, D$ M( C/ T! J( |, `
  6. 6 K5 q0 R- R; W9 c! P
  7.         GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);4 Z" C; w" W/ F5 A1 ]1 E, R
  8.         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;8 u. j" ~8 N. W* v& d: n7 O  R/ {- K
  9.         GPIO_InitStruct.Pull = GPIO_NOPULL;& W" T- Q9 l6 o
  10.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    " c+ R# n# m+ J5 D* \" P, q" A
  11.         GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;
    & B( }5 r3 n0 o. Z
  12.         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);2 F& k3 J! V" b0 P1 @( K& t

  13. " O$ A: |) z, v, k& K5 {
  14.         /* 使能USB FS时钟 */: H; o9 `9 ]  M9 A2 [3 i8 A- Z
  15.         __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();
    ! Q3 y1 ?. i3 l( p& ?- g8 @/ ?

  16. . O" i4 S1 [% v' U- N+ R- H, \) E
  17.         /* 在睡眠模式下禁用USB时钟 */
    2 p- c9 {. o2 s3 j- D- l0 K
  18.         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();' [/ d4 V; D8 c* r5 S
  19. 3 k8 h( ]0 ^( a4 g& @" U% t
  20.         /* 配置USB FS中断 */6 |5 Q' G7 ?4 {# ^  @
  21.         HAL_NVIC_SetPriority(OTG_FS_IRQn, 0x2, 0);
    5 y: v3 g/ ^7 p. `) s* b& {
  22.         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);# M. S; w" F, v" d6 p; `% w
  23.     }
    2 f# p6 a3 p6 V8 L6 ]% K
  24. 4 a3 C# D. r; x" H  v
  25.     /* 初始化USB */
    : c  F0 m; E* R# i4 c% a
  26.     {
      f) Y  h/ V4 i& m1 ~2 P
  27.         HAL_PWREx_EnableUSBVoltageDetector();
    7 b' Q0 U6 R- d! ^2 X% }
  28. 1 V6 U3 z( U+ J/ {$ k, d
  29.         memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));5 J& B. }7 w  M  {9 V  d
  30.         hpcd_USB_OTG_FS.Instance = USB2_OTG_FS;# B4 S6 G% V' _9 N/ s
  31.         hpcd_USB_OTG_FS.Init.dev_endpoints = 8;
    1 q; j% `  g4 B( x3 F1 R
  32.         hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = 0;: d: G  {7 k% m! i  M  y9 A
  33.         hpcd_USB_OTG_FS.Init.ep0_mps = 0x40;
      R. Z+ l" w2 R# G3 |, d; q
  34.         hpcd_USB_OTG_FS.Init.low_power_enable = 0;
      i% u. q7 ^+ O% Y! l
  35.         hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;# W/ Z0 I3 @( L  K* l# \
  36.         hpcd_USB_OTG_FS.Init.Sof_enable = 0;
    / ^* X# V3 j9 l7 P/ i4 l1 Z! }0 T
  37.         hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;' P. z7 b- b1 ^- u4 P
  38.         hpcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;
    . w" d9 S, K" r# k( d
  39.         hpcd_USB_OTG_FS.Init.lpm_enable = 0;
    ' P' J3 u) z4 v+ T9 h( @

  40.   R1 x" d: p* p' g
  41.         /* 初始化USB  */
    ' P( O2 `- O  y6 I$ a3 o
  42.         HAL_PCD_Init(&hpcd_USB_OTG_FS);3 Z$ W, n6 Q  Z
  43. " s* k! ?: K6 {- L
  44.         /* 设置TX FIFO和RX FIFO */
    , @! C  D1 P; \& p, ~' {
  45.         HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 1024);
    6 I! F: y/ \: s9 ?1 u2 O! t
  46.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);( R* h  J7 C+ q
  47.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 1024);) W4 ?) A0 R7 k2 c0 Q! J

  48. 1 H6 C6 D% ?# {; i6 T
  49.         /* 注册STM32到USBX协议栈并初始化 */7 z: L- ~$ V. K' {7 o) I
  50.         status =  ux_dcd_stm32_initialize((ULONG)USB2_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);3 [8 D0 ]# H! b+ |6 y% j4 }

  51. # |$ y7 X5 r5 C$ O* P# R  d
  52.         if (status != FX_SUCCESS)) c4 I; u5 Y9 i5 _( }7 Y& Y
  53.         {
    # P* s) C8 [$ E2 f  U; y4 ]
  54.             return;% N4 _. _# S$ k4 w& J& U$ F
  55.         }! m; y4 o7 @6 P- G% i2 z
  56. ! H9 L$ h  A' `* X* r5 t* W
  57.     }
复制代码
# o$ Y1 ^8 p4 ]! d$ D8 |/ E
3.2.6      第5步,MPU配置

! v+ n( ~/ |: a/ i# \1 F为了方便大家移植测试,我们这里直接关闭AXI SRAM的读Cache和写Cache(这样就跟使用STM32F1或者STM32F4系列里面的SRAM一样)。此配置是在bsp.c文件的MPU_Config函数里面实现:0 b& Y. N7 Q% U7 h
  f4 F" G9 O6 q0 b/ O9 j" _/ y% N
  1. /*  @; G; a- y$ e% w/ J
  2. *********************************************************************************************************0 K; r& S0 ^/ m
  3. *        函 数 名: MPU_Config
    ; o- F) b- g: I
  4. *        功能说明: 配置MPU
    4 Q( d  K5 e. R8 t2 ?* M* }6 @
  5. *        形    参: 无/ ~; t7 @; Z: s6 l* c* a
  6. *        返 回 值: 无
    ! t( s# J; F3 |+ n
  7. *********************************************************************************************************5 {! {4 V9 t, O+ s
  8. */6 t) t1 S" ^3 p+ K+ C& o4 n( r8 j
  9. static void MPU_Config( void )- l4 b, L9 b# i- N6 D1 }
  10. {
    ) g' q* ^. S$ T( W8 H
  11.         MPU_Region_InitTypeDef MPU_InitStruct;8 A# P$ [% v, b5 O' s: \) j9 n

  12. 9 w; h) \1 S+ [. ?& H8 [
  13.         /* 禁止 MPU */5 l1 F7 b' O6 {( \# u% F+ g9 I6 d; C
  14.         HAL_MPU_Disable();
    # Y  _2 A" ]+ i& a. B7 k3 i  [5 ?

  15. : L5 B2 f# m' R, X+ a
  16. #if 00 D/ i6 |( |: O  V9 y
  17.            /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */2 }, z8 q( H0 y
  18.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;. t! L- X; x8 L
  19.         MPU_InitStruct.BaseAddress      = 0x24000000;5 g- E, [- K$ D/ c  y8 L' w: g. l& F
  20.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;7 O) f( h% p3 C7 w+ y0 q5 D
  21.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    ; b3 S* m7 v8 ~0 r7 v# K
  22.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;8 I4 s5 e! J4 P. e) C/ K# X
  23.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;; u) s( N/ n2 C5 _
  24.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;( s$ i! T) }. ?7 G
  25.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;. y$ @$ m: Z# b& W1 c5 H  B/ E  j
  26.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    7 O# x) g- B6 L/ ?+ v' `
  27.         MPU_InitStruct.SubRegionDisable = 0x00;
    2 z; j3 K! ]! P
  28.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;3 M7 U5 G; A- I# R. h" \
  29. # F: m* }0 a3 Y0 [. T+ j( b
  30.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    . }9 S3 b. t! A8 v

  31. - O. A* P5 @4 y# ?, U0 J, a
  32. #else" M* f5 g  L4 |& Y- Z
  33.      /* 当前是采用下面的配置 */
    2 M* Z' x- @- ]$ V# w0 I' P: D+ |
  34.         /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */5 G# R& A+ A$ v
  35.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    % q4 X% C4 y& l
  36.         MPU_InitStruct.BaseAddress      = 0x24000000;
    ' ~& x* o" ~# ^' N. Y. i! ~8 ?, q# c
  37.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;
    / [" Z# d) A- G
  38.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;$ l* d, J- z9 T" m, |3 X* Q
  39.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;! U6 I! @8 r3 |: s
  40.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;" W* T4 \3 o2 R4 L
  41.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    / z5 B+ ~& _( G
  42.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;% L& n$ f, W6 @! P0 V4 z' c
  43.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;
    3 K! ]5 |& ^! r0 v6 R
  44.         MPU_InitStruct.SubRegionDisable = 0x00;. |9 w/ b1 ^# s0 f
  45.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;# L. l' I0 @- {, V& l2 p1 ]) s7 o
  46. 0 }/ Z9 g. ]7 ]/ F3 j3 Z2 U' p
  47.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    ( [* @* Q! ~# E& k$ {
  48. #endif2 S9 d8 T( o, N( }& W+ b
  49.         /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */
    + ^; g  n8 m1 ?( m- Q" R
  50.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;+ u: _2 y; q3 F& N, _. c
  51.         MPU_InitStruct.BaseAddress      = 0x60000000;
    ; t) Z# Q# e4 V/ I
  52.         MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;        
    ) w' m; z6 N7 q/ W2 c* ~
  53.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;# F. n1 r& ^- k% T2 Q5 l8 V
  54.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    0 y/ @3 V3 g+ g" b
  55.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;  T/ J4 Z+ F/ P& b' G0 u' q
  56.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;  _; z: w' P# ?$ O, M- T  s7 u
  57.         MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
    % y! N# A* y8 D0 Z, A
  58.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;2 I2 R2 V& d# L% w2 \7 b
  59.         MPU_InitStruct.SubRegionDisable = 0x00;( X0 l: Q% k. [3 ~# h. a$ \7 M* p
  60.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;3 ]  n( `4 K9 `6 x
  61.         
    & d* V! X! M* z
  62.         HAL_MPU_ConfigRegion(&MPU_InitStruct);! I' O& L7 `8 ]2 W# [- m

  63. 1 g5 o4 J  A5 z$ H9 N' b
  64.         /*使能 MPU */
    : u: E1 c" p4 c4 l
  65.         HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);2 h& f  d5 P' Y
  66. }
复制代码

: o4 p2 Y3 i6 L+ U, M3.2.7      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)

, i  N2 W* G2 Z' L2 M- N  ]& ?USB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可
5 E) r4 b& Y# W3 ]2 b9 S: A6 L% r* o, d" i
特别注意USB中断服务程序别忘了添加。
  D: b' D  K  D& F
3 K  S" A2 S% y* `5 x7 c3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明- p/ x. v, x% r7 f4 u
这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。: P1 s3 o3 [( q% [
. q- N! L8 K; c+ k/ w/ S3 r
3.3.1  状态函数app_usb_device_thread_media_status  E& `" j9 Y  S/ g
代码如下:# w+ D- r% X+ D6 d6 E, b
0 |: m9 s! K: ~0 _9 }: S% F
  1. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
    ' G' n+ s  h  w# h
  2. {
    4 C& O# Y  t. Y8 I

  3. * b) S! N6 x/ K2 d* d
  4.   /* The ATA drive never fails. This is just for app_usb_device only !!!! */
    5 ]6 `4 K, Z9 t
  5.   return (UX_SUCCESS);
    4 l, F; ^% n) U, W6 m
  6. }
复制代码
0 g9 G. P' v) E
此函数主要用于获取SD卡模拟U盘的状态。+ z" Y+ M9 X% r; Z$ g7 F( R4 b

  k0 F( {# J" u% D+ B$ O$ q1 ?3.3.2  读取函数app_usb_device_thread_media_read
7 y6 L) t* T- H
代码如下:9 Q/ c# v  p. O8 w$ l% [: {9 F: Y

% N+ ]3 J* m! ~. D" Y1 T
  1. /**5 E( E! Q* u8 P! U5 O2 `
  2.   * @brief  Function implementing app_usb_device_thread_media_read.
    ; h3 x3 l: a4 j
  3.   * @param  storage : Not used' i5 X8 j' g( |, ^. \" ]
  4.   * @param  lun: Logical unit number
    2 E' X* `6 g' b4 S. m+ _# |5 f
  5.   * @param  lba: Logical block address" m  y% m; W+ t0 X* [7 w8 K3 N
  6.   * @param  number_blocks: Blocks number
    3 U) d0 n6 s$ @3 O" G) S
  7.   * @param  data_pointer: Data
    + l5 z) ?9 M+ }" T! ?) j
  8.   * @param  media_status: Not used( X$ N8 x1 R9 n  K; e3 d
  9.   * @retval Status (0 : OK / -1 : Error)+ z' x- }) S2 Z% v1 V$ z
  10.   */
    % D6 t/ [5 U: J8 d$ i
  11. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,
    2 R+ ]/ W, d  a+ `! M
  12.                                        UCHAR *data_pointer,' C/ g3 }8 h5 J3 X$ o
  13.                                        ULONG number_blocks,
    / S3 B! y* G, B& Z9 T( {* X' U5 L
  14.                                        ULONG lba, ULONG *media_status)3 |( J$ g# ^. K
  15. {& Y: Z. E* @9 M" i$ t
  16.     UINT status = 0U;  S/ R0 O* L6 H- U
  17. ( y! b5 s* ]) [& A/ e; k
  18.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                        
    9 V9 U) f0 v; E9 P& U7 z
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
    + _$ l3 D3 s4 J: c( S: k. t# ]- W
  20.     status = check_sd_status(0);   
    - q3 Z2 G) W) V8 P6 ~
  21.     return (status);
    ; J& A* K/ |, L& @# `5 J
  22. }
复制代码

- B6 W  a/ O. e用于实现SD模拟U盘的读取功能。+ s; V& B- b1 Q5 Q% I

6 E- N" C6 Y/ \6 A* [8 s/ v3.3.3  写入函数app_usb_device_thread_media_write, q% G' v9 |* h) R6 g! ~8 S
代码如下:
, z, G. Z5 |) p5 I8 W9 U
. K$ n, k" P! J' I
  1. /*** r9 O" {# T* D. a, n9 l1 m
  2.   * @brief  Function implementing app_usb_device_thread_media_write.3 |2 Z/ h% R' f/ G* O" `7 B
  3.   * @param  storage : Not used
    7 H: E: v8 h  {! {; B- G
  4.   * @param  lun: Logical unit number6 v  _, \& l) o0 V9 b
  5.   * @param  lba: Logical block address3 X  q6 w7 B9 L- Q
  6.   * @param  number_blocks: Blocks number
    ; U, d0 J, D  x
  7.   * @param  data_pointer: Data
    % }4 c; D% Z, Z  s2 Q( L" ?/ L0 F1 G) Q
  8.   * @param  media_status: Not used5 d) U* L( Z* O
  9.   * @retval Status (0 : OK / -1 : Error)! s7 d  O9 H3 t/ K  o& M; |6 b
  10.   */6 ~4 N% Z! w0 ~; f' S
  11. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,
    / Z9 J! |9 Y! ?" T
  12.                                         UCHAR *data_pointer,0 P1 X- m! a! ^; @- M1 w
  13.                                         ULONG number_blocks,
    . ^. o) l9 G3 F) k
  14.                                         ULONG lba, ULONG *media_status)
    9 z9 G: B% _, |% k: h, b
  15. {
    ' J; _( Q$ P4 d: f' z8 s: w
  16.     UINT status = 0U;( Z# t9 h, H- `# ^- G0 F5 Z
  17. ' [. V* N# b3 G8 A, u! c
  18.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);3 X$ J: v- }$ O/ P7 h
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
    $ [+ w* G+ [* k; E: b0 |
  20.     status = check_sd_status(0);6 x+ e, D3 G. @) y1 |' L

  21. 4 d6 D' [7 M8 \
  22.     return (status);
    & g7 M; s+ Z/ s% o# a
  23. }
复制代码
" r5 \* y  p. F; c' D* g
用于实现SD模拟U盘的写入功能。
/ J0 U7 W2 ^# n8 x) f6 e
, \! Y# o9 @; b5 s5 f1 _3.3.4  接口函数注册+ s' B7 `6 l5 z+ H- d
接口函数的注册是在文件demo_sd_usbx.c里面:: S- n! N& W" K" x1 w

4 i$ G+ J$ ?& ^, v5 N! L9 Z
  1. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;
    / `% ^% J. z7 d  _8 k' f* X

  2. ; A# I" L, ?# s4 ]& c: `  l
  3. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write;
    , T2 ]  F5 d0 k. W6 b% u% |4 f- e

  4. * m; o5 ]$ j. T$ H' m
  5. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;
复制代码
! J& l! m5 X. O! I' M5 M; G
3.4   使用的MicroUSB接口并注意跳线帽设置& [5 v* }" ]) Z- x
本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:' B: Q0 U0 ^4 ]) u: v8 W- `5 Q( s

+ |0 ], i/ F% u5 ]
a9cb882c39474dd9bd63b8c7e14cb451.png

, e8 Y  F2 ?& f- k) H4 _$ [) ^( C# T6 U
注意使用的是MicroUSB接口:
7 K, U1 Z' l. w8 [/ f: r
- t8 i+ }/ C+ w
f871e17a6a2d4c03a9413daf725670c4.png
- _2 J: u2 R& Z+ E( K9 n6 o

3 @1 K* a) \2 o& M1 h6 i1 @) V$ w
3 h, H6 ^8 }: B  t注意板子左下角跳线帽的设置:
( ^! c0 _" d5 w( H2 w
, t6 \0 Y0 R; X2 k9 I, n
41272c92c8c9483f9d5dc6a04cbf87b8.png

1 J$ y, Z, F, K9 O1 k% @
% ^" T5 A1 x6 N# R6 s' t% e( _( v+ z0 F6 f" d4 {3 {
这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。
/ q9 r& z+ [3 j  n0 l" O7 [9 |* ~2 b5 O  y
3.5   实验例程
* l, w  _* X5 L0 H配套例子:
  [/ H9 F  S* O& F# S8 r0 R
" g/ @) e$ m+ pV7-2401_ThreadX USBX Template7 G- v7 `. I1 z

% B# S  e' S: h实验目的:9 _' G  ^$ a7 K

( m8 O6 _/ v$ q, P2 a" P学习USBX模板,通过SD来模拟U盘。
! @: |! [! r. O! E% c, y* D/ d( w3 D实验内容:1 \5 Y. x1 Q2 k9 U# \: m6 N) j+ E

3 Y: Y6 I4 O! N: R; c9 B9 Q3 V1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                 5 V/ l5 k. X1 w. p
7 a1 p! k, n5 D5 m7 d+ B7 _
  ========================================================
+ `  i8 n6 T. k9 e" h$ p$ D
* F/ _; s* V9 W3 `. C: C         CPU利用率 =  0.89%
8 P, x: h' g7 M; c7 C, ?4 |4 S0 _/ Y, H- I
         任务执行时间 = 0.586484645s$ o0 i4 T2 C, M$ e3 w

  C# d+ s6 ]# f0 D         空闲执行时间 = 85.504470575s
# N3 D3 g$ T. M/ E5 M5 {. _( ?4 K5 P
         中断执行时间 = 0.173225395s! t  b$ s/ U2 j8 e- c
) _/ \' w  g+ e% k9 z, U7 @$ j/ Z
         系统总执行时间 = 86.264180615s              5 y: A1 {) l8 p- p

" z- Q6 s7 k! J% R' E=======================================================
& u: T% h& m% O/ a% S' `% y* }% K  X8 D! D" F# @, [
        任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名& m) j/ w( K, p( l
3 l, @) J7 p2 ?) Y4 K6 o
          Prio     StackSize   CurStack    MaxStack   Taskname
- z: C; b# i4 s# V0 F- k! Q. U
$ G6 l7 x1 Z- F0 j  e$ Y  r          2         4092        303         459      App Task Start
' |& c: Y- _8 n/ `
1 O1 C! {& G; V4 m          5         4092        167         167      App Msp Pro
0 o' S  @! e* g* q4 c. }9 K0 Q0 x% r+ z) _1 Z3 K7 F
          4         4092        167         167      App Task UserIF
. ^0 Q: i& ?1 N' p( c3 {) |1 D1 L! L" j; N% b% ~
           5         4092        167         167      App Task COM  B0 ?1 }! }6 O: g3 D8 D3 U
; q% ^1 u% p! m' n' c+ A( y. [
           0         1020        191         191      System Timer Thread           ) d+ I7 k6 ^2 Y* p

# L; B: @3 f* M! c" L3 ~& q8 E串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。
+ _" I! z  K  r2 Y' V8 a+ l- i: r& Q
. M" Q( L. ]6 L/ L  m3 YApp Task Start任务  :启动任务,这里用作BSP驱动包处理。4 T  e6 n& `- i  @0 R- y3 W8 m/ T

! W- r$ k) }6 w  C: V4 N) M1 XApp Task MspPro任务 :消息处理。2 n/ A7 r  `2 `6 \- u; E. O
; H# ?2 `- N. I, }. s
App Task UserIF任务 :按键消息处理。* J' b0 d; m; t0 v2 \0 e5 X

  H% e8 \. D/ k' \& L1 X9 W9 ?App Task COM任务   :这里用作LED闪烁。
  a; }; T' X6 @2 J5 I& E3 ~4 ?$ v" c( O0 |
System Timer Thread任务:系统定时器任务8 ]) ]$ N$ X  w" p% j
( |1 B  \9 o8 r: o8 k! Y, S+ Q5 Q2 T
2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。
' {  `6 A* i; y3 i; A. i9 {' ~9 V* Y" U( q9 ~5 @6 j; [1 T
      (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。4 Y/ g6 \/ K) R* l6 I% y

9 |' [: o. |) u0 ~" E3、默认上电是通过串口打印信息,如果使用RTT打印信息1 D/ J# r' d9 U

+ l) `' e8 \$ _5 a* U& f- H+ [8 K(1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可: X5 V7 ?: y9 n0 R/ q" M- R

" r4 j1 t8 u) d% w: l" y#define Enable_RTTViewer  1' V6 H% V0 z/ h- {7 t
4 q8 k5 I8 m3 V0 x& \8 m
(2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。) b. ?! @! I9 I

+ @, H7 F/ U% v实验操作:
! }' w* A  i4 I$ y/ f- W' R! P3 N2 Y
  q( i, I" N9 a9 w* I测试前务必将SD卡插入到开发板左上角的卡座中。% ~- ]2 g8 E  k' X& \* C
支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可' t1 A/ q1 Z$ D6 f0 f. ^
printf("1 - 显示根目录下的文件列表\r\n");: {2 H3 a1 b! p6 y4 @6 C3 P
printf("2 - 创建一个新文件armfly.txt\r\n");4 v7 p8 B  j7 {( z5 Q$ M* A
printf("3 - 读armfly.txt文件的内容\r\n");5 p+ B. l; z+ r" I* l( ~0 K, v/ g
printf("4 - 创建目录\r\n");
# r& ~0 j. \0 g6 [) y6 l( vprintf("5 - 删除文件和目录\r\n");: |* Y# G5 P3 ~! D! g8 j
printf("6 - 读写文件速度测试\r\n");
2 t  d6 r7 P  }7 j0 f/ ?' Nprintf("a - 打开SD卡模拟U盘\r\n");
  w; a* }9 @9 Iprintf("b - 关闭SD卡模拟U盘\r\n");9 W% `9 l7 M$ Y9 n# _0 j. W8 @
串口打印的信息:7 }! p) X  r' p! l- |) Z# _

- n6 _( |  Y& }' Y% P波特率 115200,数据位 8,奇偶校验位无,停止位 1# _8 x' p( Q4 T  F3 ]. n

5 y0 K7 w4 g$ g/ Q' N  d
74d954c9e7b649289184a7a4bd58d6e6.png
8 V' }7 O2 l, I

" A& O8 A* y" y0 A" B7 F' N1 g! w
% n5 e" g, v. f/ i  y& y, t' M5 Z0 C* d9 }
RTT打印:9 M' ^* K4 S# R

* _4 k2 Q' w1 Y8 J* F- G$ y; U
cdcab0e093ed468a912923050806de22.png
: A. @# R& y- S

* ?7 {0 k) ]7 \. |6 S0 k' N5 d' X. x# y
" a9 j8 {' S8 g$ Q' p# }$ O
3.6   总结* D1 _. I" l0 W! ^  c
本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。% [9 G0 e" Z, N$ e& l8 G
5 }: }/ [3 t- F4 W9 E. J

5 k$ X  o1 P8 F: R% p$ s2 n4 a* C2 r+ d) G" c
赞 收藏 评论0 发布时间:2022-1-1 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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