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

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

[复制链接]
STMCU小助手 发布时间:2022-1-1 19:00
3.1   初学者重要提示7 u+ c" L9 W. u% L( S0 S! ?
1、  本章使用的ST专门为STM32H7提供的软件包( v, ?6 V- m" i" P1 u* e4 g
: Q0 u1 F& E% v* h
2、  本章配套例子使用SD卡模拟一个U盘,使用的MicroUSB接口。
" U0 H2 F+ x; a
: G, ~; p0 Z' O% `1 Z3.2   USBX移植步骤- l! N) ]# X+ L9 r- f9 d
ThreadX USBX的移植步骤如下:
4 }9 L2 ?, h% H' R6 O( ^; \6 u* l; p$ t. Y1 W
3.2.1      第1步,了解整体设计框架* z0 o$ b3 k* q& b1 O
为了方便大家移植,需要大家先对移植好的工程有个整体认识:
* `' {! b- l: Z& J7 d, d! K
6 p: m. C  F, [
556edb9b3bb947f5b69aac84272def1d.png

0 h- @# }( ^/ H! s9 T( s- x* X. z. u5 {
6 [# U% u4 B( [+ r2 [' p5 G
3.2.2      第2步,添加USBX和USB驱动到工程
2 q+ f; {1 J$ U6 X/ S这里我们在FileX教程做的模板例子基础上添加USBX文件和USB驱动文件,大家可以直接从本章教程提供的例子里面复制。4 B- K5 k1 c- O& I- g6 N
! `  Z6 v  Y0 W2 J: A* u
  模拟U盘驱动文件ux_device_msc.c/.h和ux_device_descriptors.c/.h添加到自己的工程里面,路径不限。) S2 p& m: X2 c/ a& e
配套例子是放在\User\usb文件。/ y' ?+ f% y, l3 r* {: G
% h1 t$ x" T% y$ z3 b" _! c
  USB驱动文件stm32h7xx_hal_hcd.c,stm32h7xx_hal_pcd.c,stm32h7xx_hal_pcd_ex.c和stm32h7xx_ll_usb.c。# B4 p" [* I  K6 g$ _4 u# h# s$ R* |
这个是STM32H7的HAL库自带的。
3 C6 y$ Q$ w: ?- h& s/ ?* s. _7 u4 [. U- {' D* @( t. A$ M2 ~0 C
  USBX相关源文件。# Q4 ?( s) H, ^. ^# v& W/ w. A; d
大家可以将所有相关文件都复制到自己的工程里面,配套例子是放在\USBX。
$ a1 g+ c1 @9 b% v- |
$ D2 g! V) ]8 Q4 L8 V) U3.2.3      第3步,添加工程路径! {, ~* L' \: q7 C) D
大家根据自己添加的源文件位置,添加相关路径即可:% k/ }0 |9 s# c4 {
2 z, y3 d; X5 Y+ ]9 c# p8 ?1 R# O
7d4292e15d424274b8e5aab1d6cd32a9.png
; [- |2 v/ Y( c& U
, u3 T8 _+ ^6 l9 g+ \, R

& }$ ~0 @$ n' Z" ^& X" S6 m/ p/ W: q7 y: [0 m/ B$ `$ e# y, _. U
3.2.4      第4步,禁止掉添加进来一些文件

/ @7 M. e$ @; d2 o, G之所以要禁止掉是因为这些文件要用到NetXDUO网络协议栈,或者大家不添加进来都是可以的。添加进来后再禁止的优势是添加时候可以全选添加。
/ i# s* l" B: X- p# k# ~# d  ]$ ?
418a71e2dcbd48a199034bbf6765d9fc.png 4d161770a4734368b6881fe1ed982494.png
' E" [% ]4 j" h7 y: }7 b

, T9 Y# m4 a. O5 _# N7 b
696837e6177b4f3caa286c6913cf4ea3.png f052ff2297b4462daa7186e7fc3b6ab8.png
4 `( O  o9 F1 g0 D9 g) B" ?. W
! b  N( E% r: j3 r
0dadc8e05ea349beb4e04a737e86ed07.png

' S" n8 O/ W2 i9 p  w. f1 c
0 ?, k2 y9 S: X8 W6 r禁止的方法是右击此文件去掉如下对钩即可:: k. e" R! _( R

2 M( }/ S. G" u8 I" S5 _' A
4db1e499f0f7422f9e522bf1e7bcecfe.png
2 z, l/ K6 h. \  n& R8 d' Q2 `# W& x

" f+ r8 d4 ^& P, O: A  I5 a, f( m5 H/ s! H/ G5 U

: K+ j2 e" p0 {# @/ Q, B0 G3.2.5      第4步,配置GPIO和时钟- z, S! X8 s3 B( h  J
USB时钟配置在bsp.c文件的函数SystemClock_Config里面:7 W/ C" e% q5 ]4 C7 ]" X5 e
4 e" V; J5 U+ j
  1. {1 c. V& e1 p5 Q4 A# E8 m% K
  2.                 /*1 E& j; H! O; J% F+ G/ V6 N
  3.                 USB工作需要48MHz的时钟,可以由PLL1Q,PLL3Q和HSI48提供
    5 ?$ y4 h  H4 U) ]7 R
  4.                         PLL1Q用于给SDMMC提供时钟
    " \) d# e# f# u% S5 ?
  5.                     PLL3Q给LTDC提供时钟,也可以跟USB共用,不过得更USB设置相同的频率才可一起用。
    7 q6 }) U5 h# l
  6.                     HSI48可以供USB独享,就是精度不是很高。8 p5 a/ x; S+ y, z
  7.                 */) O2 l) O; B  w4 B, Q, J' W
  8.                 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
    ( s  w  Q+ `0 G2 [' S
  9. #if 0* X( }" R8 T! g, s5 B5 \
  10.                 /* PLL3-Q for USB Clock = 48M */
    # B+ f# a4 Q; x
  11.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    7 j- }. Z: o& Y+ G$ V( f1 I
  12.                 PeriphClkInitStruct.PLL3.PLL3M = 5;
    + t+ y& K: @5 l" S1 q' F! ~6 s; J# q3 i
  13.                 PeriphClkInitStruct.PLL3.PLL3N = 48;4 I- N" Y& A' C2 @; l% G- y1 E) e
  14.                 PeriphClkInitStruct.PLL3.PLL3P = 2;$ x6 A9 x# R$ Y8 Y' N% _
  15.                 PeriphClkInitStruct.PLL3.PLL3Q = 5;
    % \( ]9 F4 E. @
  16.                 PeriphClkInitStruct.PLL3.PLL3R = 2;4 k% y# {* l3 F# a
  17.                 PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;1 v0 D' T+ E  y  o# M  i' t6 r
  18.                 PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
    6 L: ]% M. Z! p' M, f9 R1 Z
  19.                 PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
    6 n1 z) G, c* T1 W
  20.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_PLL3;6 z2 ~+ B7 ^; }, R$ p: ?
  21.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct)!= HAL_OK)
    ( G9 @) @" u( K  `9 o) k
  22.                 {* E! c, M( N6 ~+ u: m( ?
  23.                         Error_Handler(__FILE__, __LINE__);
    9 A! u, s! J1 x* H# |( @" y
  24.                 }        
    * Z7 s. D6 x/ b( }7 c
  25. #else
    , q% }6 d2 P# E* i, o
  26.                 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;& N# {8 P& Z5 i/ E& y
  27.                 PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
    6 W  _& D* b. O* A6 y9 D
  28.                 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    0 b) }3 _. a" E& E, |$ Z
  29.                 {: `2 p' R/ h) l* O: W' l- c
  30.                         Error_Handler(__FILE__, __LINE__);# i/ I& E" O+ K" b& N' P  k
  31.                 }, g! `9 A/ ]# |  m
  32.               HAL_PWREx_EnableUSBVoltageDetector();
    ! }% W. L" T/ p
  33. #endif9 b. O# z+ V( W
  34.         }        
复制代码
9 X- i, D1 J7 ]4 k) @  H4 L# e
USB的GPIO,NVIC初始化在demo_sd_usbx.c:
/ H. k  j$ @) h% u+ R' V* l5 R% \$ C3 t7 ]- P
  1. /* 配置USB GPIO, NVIC */
    ; m" q+ g- a: i/ Q5 A: x5 e+ x
  2.     {
    - g# l( Y8 n3 K  N# G
  3.         GPIO_InitTypeDef  GPIO_InitStruct = {0};
    7 F+ O8 Q1 k# @1 e* f- D
  4. 6 k& b& l7 ^  z) K
  5.         __HAL_RCC_GPIOA_CLK_ENABLE();
    5 s! \5 e  _+ n! b1 R7 s3 W
  6. 9 m. ?- S8 [! k* l+ o
  7.         GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
    ' \& P6 i3 n2 Z% d9 [. [8 g
  8.         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    7 R" O, ]4 ?. c5 U8 Q
  9.         GPIO_InitStruct.Pull = GPIO_NOPULL;
    2 N; K; s8 ]2 H/ k( h* F5 N
  10.         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    - {" n5 v& o, M0 Y: w& h+ [
  11.         GPIO_InitStruct.Alternate = GPIO_AF10_OTG1_FS;" s  }+ Q! I1 O2 ^
  12.         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    9 v0 M  e. m: L
  13. & P# g2 P5 K" ~) W
  14.         /* 使能USB FS时钟 */
    % l- G& r: d* b- Q
  15.         __HAL_RCC_USB2_OTG_FS_CLK_ENABLE();- S! K3 S3 Z: P/ I$ y' c
  16. ! J3 Z2 A6 V" K1 V" |
  17.         /* 在睡眠模式下禁用USB时钟 */
    * ^0 m" p# Y; _
  18.         __HAL_RCC_USB2_OTG_FS_ULPI_CLK_SLEEP_DISABLE();
    ; i% J( r0 H  T! F2 N

  19. - B/ b; A5 z# z5 s" X0 \% r1 e
  20.         /* 配置USB FS中断 */
    3 ^( t# ^3 b3 w
  21.         HAL_NVIC_SetPriority(OTG_FS_IRQn, 0x2, 0);   c' P2 i2 ]/ {3 w. G
  22.         HAL_NVIC_EnableIRQ(OTG_FS_IRQn);+ r+ z& F5 L* I; J  Z
  23.     }, h* M+ v( G; p. |5 f( u. \

  24. % Z. h& [! u8 s. v+ y& D5 Y  w& `7 [
  25.     /* 初始化USB */, k# F7 q; e2 g7 D8 r% D- `9 g2 E
  26.     {' y1 ^9 W  b. B  ^* X( c
  27.         HAL_PWREx_EnableUSBVoltageDetector();. d% X4 B' P, H* O: E
  28. 8 }" q- R5 J2 I2 b, v( A
  29.         memset(&hpcd_USB_OTG_FS, 0x0, sizeof(PCD_HandleTypeDef));" X1 s- y; }! M7 N4 }$ A2 P  j
  30.         hpcd_USB_OTG_FS.Instance = USB2_OTG_FS;
    7 p& S) _; c1 J" I
  31.         hpcd_USB_OTG_FS.Init.dev_endpoints = 8;
    ' p2 v* n: H8 d% y- d9 A2 W
  32.         hpcd_USB_OTG_FS.Init.use_dedicated_ep1 = 0;+ C' J- s1 k- i; G6 J
  33.         hpcd_USB_OTG_FS.Init.ep0_mps = 0x40;5 @' x0 I) f1 {- P; |/ Y- ^7 \
  34.         hpcd_USB_OTG_FS.Init.low_power_enable = 0;
    $ q4 \$ i/ y& f4 m. i2 e
  35.         hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;6 C# T, g) I* f# N( I2 Y3 l' l1 q- _
  36.         hpcd_USB_OTG_FS.Init.Sof_enable = 0;2 a& R. t0 n' S; g) ~7 {% Z
  37.         hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
    / q4 ~1 C1 g: N
  38.         hpcd_USB_OTG_FS.Init.vbus_sensing_enable = 0;; L: d# @# L1 h5 R
  39.         hpcd_USB_OTG_FS.Init.lpm_enable = 0;
    ; @4 t/ m- j# V" V4 k  @

  40. 2 N5 M2 w$ b' ^' _7 W; t# K, ^
  41.         /* 初始化USB  */
    ; ^. i2 M8 R6 i
  42.         HAL_PCD_Init(&hpcd_USB_OTG_FS);
    . j! d! ]* L3 z& k) {

  43. / W8 g9 }) w  {( ?4 D4 W; D
  44.         /* 设置TX FIFO和RX FIFO */$ U( \2 {( N# ]2 Y5 N' E
  45.         HAL_PCDEx_SetRxFiFo(&hpcd_USB_OTG_FS, 1024);1 `; [5 k5 I. q, x) M, L7 q) U
  46.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 0, 64);* h* B& N# x3 t8 R4 l
  47.         HAL_PCDEx_SetTxFiFo(&hpcd_USB_OTG_FS, 1, 1024);& V/ j0 c; P$ b. ?. M' y
  48. 3 N/ F, J( K, o4 y' j
  49.         /* 注册STM32到USBX协议栈并初始化 */
    4 Z# K; a- X9 t; [7 u: z, W
  50.         status =  ux_dcd_stm32_initialize((ULONG)USB2_OTG_FS, (ULONG)&hpcd_USB_OTG_FS);
    # K# j; J9 y. E# l6 d( l/ X

  51. & q' }8 y6 s# c1 E# [0 d
  52.         if (status != FX_SUCCESS)
    - E5 ~, l/ J9 X( P3 c3 E: n8 W
  53.         {1 Z5 v, y9 y4 x) O/ I
  54.             return;+ n( |3 M# ]& O; j; f* I2 t! u1 X
  55.         }9 `& X( D) k" m! c- J1 q  z1 ?
  56. ( i; ]  U) r% z# o9 a3 k
  57.     }
复制代码

+ h: u" E, |, b  Y2 n# H3.2.6      第5步,MPU配置

9 F8 O& H# _2 l为了方便大家移植测试,我们这里直接关闭AXI SRAM的读Cache和写Cache(这样就跟使用STM32F1或者STM32F4系列里面的SRAM一样)。此配置是在bsp.c文件的MPU_Config函数里面实现:
( v$ m. P) u6 n- i* Y" y9 g+ k2 i# U$ t3 e) x
  1. /*
    & s  F/ z) E/ G7 J2 y: B
  2. *********************************************************************************************************$ g/ I; B+ m3 |
  3. *        函 数 名: MPU_Config
    4 E( N/ I  s' I( E
  4. *        功能说明: 配置MPU' k0 B, ~* [2 u: ]( b5 f
  5. *        形    参: 无
    # w& \; W! @9 l% p# ^
  6. *        返 回 值: 无
    , V4 k# E0 A( v$ j  t( W
  7. *********************************************************************************************************
    ( ?2 }$ p/ ]& i: C' S5 ]: P
  8. */0 ^  v  a0 z# o6 V1 C
  9. static void MPU_Config( void )1 z# N. L3 Z$ }) w+ k! g
  10. {$ a+ ^( Z/ z! Z/ z6 c6 C7 {
  11.         MPU_Region_InitTypeDef MPU_InitStruct;
    - P7 q+ V1 Q. P. I, Y- I* v1 }# I
  12.   N# k' @- }1 Y; j3 ^
  13.         /* 禁止 MPU */
    1 U2 ]2 y) j4 A+ B9 J* w$ V. z! H
  14.         HAL_MPU_Disable();
    4 y' g8 w( E4 `- R1 r( K* N

  15. / \' _6 _% ]/ }/ l  ?) \( {
  16. #if 0
    1 S- `2 U, [% N$ I4 _
  17.            /* 配置AXI SRAM的MPU属性为Write back, Read allocate,Write allocate */, ~; @3 M" [# T' o; b3 k8 o
  18.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    4 H! e$ ^6 V! B, B1 h
  19.         MPU_InitStruct.BaseAddress      = 0x24000000;
    3 \* V  d; i3 Z+ g2 }' v
  20.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;1 D8 a  x' T( }" K# [
  21.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;+ i% [* p, e$ q1 `' i
  22.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;
    5 l* m. _5 s8 S) {8 g& L
  23.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_CACHEABLE;
    ' I% V5 C; i3 D1 T, k. x/ ]
  24.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    + N4 V( B! O# L7 E; j
  25.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;! i2 M* A: U1 T. ?
  26.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;4 x. x$ C) l- W8 S
  27.         MPU_InitStruct.SubRegionDisable = 0x00;
    0 r3 W& m- B* ]4 i: W0 m8 W
  28.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;; q/ [: g7 A( l) Z6 K
  29. ( P3 Y& U* L/ L4 I
  30.         HAL_MPU_ConfigRegion(&MPU_InitStruct);( w+ r2 I& Q1 r( w: q2 j; u' U

  31. 8 j, y" r, g( m( h7 m0 D
  32. #else) c0 m! i. Z2 Q7 m  o' V
  33.      /* 当前是采用下面的配置 */5 x, c+ o; J+ i" ^
  34.         /* 配置AXI SRAM的MPU属性为NORMAL, NO Read allocate,NO Write allocate */
    $ E$ F& D  ]: _. m) w! C7 @
  35.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;
    9 u. Y* E; X+ @8 Q7 Q7 `* Z% l2 }
  36.         MPU_InitStruct.BaseAddress      = 0x24000000;% ~0 W4 `( w4 T& f: M, C
  37.         MPU_InitStruct.Size             = MPU_REGION_SIZE_512KB;6 z- o- S$ q+ c
  38.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    3 Y* g! {' l1 G1 G1 w
  39.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_NOT_BUFFERABLE;
    ! _' {( M+ n2 I( T
  40.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;. k+ ?3 d3 r: P# B) h# D& h. k9 `
  41.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    & ^+ F" C; u! }6 Y$ L; u; l
  42.         MPU_InitStruct.Number           = MPU_REGION_NUMBER0;
    6 B3 E& n. t7 T2 \
  43.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL1;. Y; x/ F$ f( P/ y" C
  44.         MPU_InitStruct.SubRegionDisable = 0x00;3 ~1 ?7 E! R; e; N  V1 }: Y
  45.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;4 a5 [9 q4 n5 G* U) _  Z; o0 Z
  46. $ A! @0 L3 [; o, M
  47.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    - z9 L  U4 i' ?) v) m+ `/ L9 I
  48. #endif
    ) b- X* ?: z: {4 J$ C1 i
  49.         /* 配置FMC扩展IO的MPU属性为Device或者Strongly Ordered */4 \% X0 `" U3 u' D" I: s
  50.         MPU_InitStruct.Enable           = MPU_REGION_ENABLE;, a4 T2 K9 R1 H+ ?' }/ T
  51.         MPU_InitStruct.BaseAddress      = 0x60000000;+ }: _2 a8 O+ P+ ?/ b2 W2 i
  52.         MPU_InitStruct.Size             = ARM_MPU_REGION_SIZE_64KB;        
    0 `7 T1 F  E$ N! i6 S  g
  53.         MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;- n. q  u; _' b
  54.         MPU_InitStruct.IsBufferable     = MPU_ACCESS_BUFFERABLE;7 q2 Q  ]. s& p1 k) {! n
  55.         MPU_InitStruct.IsCacheable      = MPU_ACCESS_NOT_CACHEABLE;- D0 W: u/ a" @7 Y- D
  56.         MPU_InitStruct.IsShareable      = MPU_ACCESS_NOT_SHAREABLE;
    ( Y# P  G3 I6 `: Q9 u
  57.         MPU_InitStruct.Number           = MPU_REGION_NUMBER1;
    $ J; U' x) ]+ l+ Q
  58.         MPU_InitStruct.TypeExtField     = MPU_TEX_LEVEL0;
    ; J8 L) a  c: [3 A$ e) M$ x$ h5 B' x) _
  59.         MPU_InitStruct.SubRegionDisable = 0x00;
    2 [8 u6 `- U: g
  60.         MPU_InitStruct.DisableExec      = MPU_INSTRUCTION_ACCESS_ENABLE;
    / z# U* Z2 s- D3 ^7 @
  61.         
    ! U$ {- h- C# x* D# r# i  g
  62.         HAL_MPU_ConfigRegion(&MPU_InitStruct);
    1 N2 O$ @) h5 b4 e) y4 b. w
  63. * E' \- {, D& q: F
  64.         /*使能 MPU */* p6 H: Q3 L. w/ N& d* X3 C
  65.         HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);. R' @1 Y2 \* e0 B  I4 A- V
  66. }
复制代码

. K- C/ ]& o7 W4 H# q* `( S3.2.7      第7步,添加应用代码(USB中断,打开U盘和关闭U盘)
7 i) G$ r# M+ R
USB操作专门整理到了文件demo_sd_usbx.c。主要三部分,打开U盘,关闭U盘和USB中断服务程序。这三个函数基本是通用的,大家直接复制粘贴使用即可
, V* v' Z$ l- w- {1 K' E/ H
* s- L. l* I0 X7 C0 b特别注意USB中断服务程序别忘了添加。
0 Y% U& G5 y; f4 L- ]  Y* h/ J  p5 D% d) p& z+ _
3.3   USBX的模拟U盘移植接口文件ux_device_msc.c说明  f) `9 X, r  F. J+ g1 r5 G) U% u
这里将USBX的底层接口文件ux_device_msc.c的实现为大家简单做个说明。, [4 B% ]+ H* `! R

! T/ A" i  o: m) Q% G' K3 W. [3.3.1  状态函数app_usb_device_thread_media_status
+ E7 q  I& T. n代码如下:3 k+ u1 z* J1 S5 R' S3 n6 H
4 r& E! I% q! U: x* Z+ z5 H
  1. UINT  app_usb_device_thread_media_status(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status)
    ; f2 ?5 R6 L5 @9 f+ |
  2. {
    $ o1 X3 a/ c( f' o- P* g% i8 N
  3. ' R# T1 ~4 a/ R& s% @0 G: S- |1 x
  4.   /* The ATA drive never fails. This is just for app_usb_device only !!!! *// x9 z. w3 n3 \5 Q$ U, a
  5.   return (UX_SUCCESS);
    + D0 \7 U9 A3 m+ A. [8 o9 n
  6. }
复制代码

' P. O. M: [) N7 @此函数主要用于获取SD卡模拟U盘的状态。2 d0 L+ ^! J9 h0 T, P- Y! X" z

4 E6 I& [9 k9 y- Q! [0 r3.3.2  读取函数app_usb_device_thread_media_read
, B5 E, H6 [. W1 G0 a7 ]+ _
代码如下:
" ]- r5 R3 s* M+ l2 X3 `) J) p
2 `% _6 L$ d$ I/ s
  1. /**
    . s3 H! x, C/ g) [. n
  2.   * @brief  Function implementing app_usb_device_thread_media_read.
    9 x9 r6 M5 V* x) L
  3.   * @param  storage : Not used3 O" N/ \1 r  V" U9 [* r
  4.   * @param  lun: Logical unit number
    ) n' I9 [0 D. j
  5.   * @param  lba: Logical block address, C5 F6 v- Z3 G) A  L
  6.   * @param  number_blocks: Blocks number
    * o1 @* s+ K, j" i
  7.   * @param  data_pointer: Data- d( A: d* }9 Q6 h$ p
  8.   * @param  media_status: Not used, d8 _) Y7 M/ `: u
  9.   * @retval Status (0 : OK / -1 : Error)0 Y5 D1 o9 `' n. B# O7 M( R% [# }
  10.   */1 [; O, w6 f/ O% |/ @
  11. UINT  app_usb_device_thread_media_read(VOID *storage, ULONG lun,: l+ {3 O1 ^. `/ q$ R
  12.                                        UCHAR *data_pointer,) ?' C, G) o) }* b4 H
  13.                                        ULONG number_blocks,' |4 f1 {. f3 d
  14.                                        ULONG lba, ULONG *media_status)
    : ~- v! O* g# e$ p$ d
  15. {
    9 ], h( O! h/ G
  16.     UINT status = 0U;
    " I  N, u+ q( I' G8 d

  17. # ~7 ?: j0 {* h$ p& @9 M9 ?3 p
  18.     BSP_SD_ReadBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);                                                                        7 ]2 G" V# w' |* Y, n
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);$ P6 F* Q  f, y% W! g% m( ]
  20.     status = check_sd_status(0);    9 \# p1 P, p$ h9 _5 h
  21.     return (status);
    ) b2 c. n) U3 m2 Z
  22. }
复制代码

# X) j. X, j  f5 s; H用于实现SD模拟U盘的读取功能。
$ j  q6 b+ ?8 T/ Z
& E+ W- v) [; H; A% p; f' f2 e" w3.3.3  写入函数app_usb_device_thread_media_write
# Q3 Q4 R( ^  n- {/ ?8 C代码如下:
% H8 Z- H# v4 X. Y/ D6 |: W/ D. {5 ~  Q1 g5 O  {: Q: }
  1. /**
    6 ~$ x8 `% _- r, m+ [; h( D
  2.   * @brief  Function implementing app_usb_device_thread_media_write.
    & v- c5 U( O! A% w% {: T6 e5 c
  3.   * @param  storage : Not used+ }2 k; J7 S* n# K! P* L# r$ y
  4.   * @param  lun: Logical unit number" {* \8 w! h: x
  5.   * @param  lba: Logical block address$ [+ A# n2 h0 M- ~2 u& L1 y) N
  6.   * @param  number_blocks: Blocks number
    % ~/ X( M7 Z5 x& d9 g+ y
  7.   * @param  data_pointer: Data
    3 b. Y0 o& W- J" l% U
  8.   * @param  media_status: Not used
    - V% x# E+ p7 E
  9.   * @retval Status (0 : OK / -1 : Error)! g& A- D: H& W, y
  10.   */
    1 M* T7 K; B5 k3 X; j2 q
  11. UINT  app_usb_device_thread_media_write(VOID *storage, ULONG lun,& ^3 O  p3 \" u2 N
  12.                                         UCHAR *data_pointer,7 Z2 f+ u; `: V( s# M5 O: F9 u
  13.                                         ULONG number_blocks,* ]8 b. ^# F+ e  |" E' ~5 T! ~# N. e$ L
  14.                                         ULONG lba, ULONG *media_status)
      a- y1 }; R" f( r3 I5 Q# }
  15. {
    2 t1 ?* o: I: i, y) y, I( f
  16.     UINT status = 0U;4 T2 k' l7 k# M

  17. , C( C4 `) L3 \/ U. a+ V
  18.     BSP_SD_WriteBlocks((uint32_t *) data_pointer, lba, number_blocks, 500);& w6 W0 ?! c1 g5 Y0 s9 M
  19.     //while(BSP_SD_GetCardState() != SD_TRANSFER_OK);
      ?! u3 N, l& b9 [# X* P
  20.     status = check_sd_status(0);6 T. n2 u0 n) J

  21. . o& z# x7 b# I' a
  22.     return (status);
    2 L& {1 i/ P2 q
  23. }
复制代码

, R9 J. ~5 I2 E: t0 q; t用于实现SD模拟U盘的写入功能。1 g& ~$ M4 f' m3 A  l. ~* H6 {% n

; M' h5 p  B. z  V: V" u+ W8 x3.3.4  接口函数注册: H. X/ i! h& w6 a" _
接口函数的注册是在文件demo_sd_usbx.c里面:
8 z. `. ]# p1 U: P
" B( U% [/ ^- t7 S  c$ {& ]" x, C' y
  1. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_read  =  app_usb_device_thread_media_read;0 S# p* E6 c% {% l$ E& u1 v

  2. - p- ]5 G0 {, N: }  J
  3. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_write  =  app_usb_device_thread_media_write;
    & R8 x4 u0 T1 E4 D5 U9 z8 r

  4. 9 t) F- K. W0 j! i$ r
  5. storage_parameter.ux_slave_class_storage_parameter_lun[0].ux_slave_class_storage_media_status =  app_usb_device_thread_media_status;
复制代码
  \6 C, b. O& t/ a$ w6 U4 d
3.4   使用的MicroUSB接口并注意跳线帽设置/ E0 M, n/ ~8 g. U. r
本周教程移植的例子使用内部RAM模拟了一个U盘,效果如下:) ?5 b5 i( [0 s7 n' }* m9 W
  b" Q" s4 c3 G) o
a9cb882c39474dd9bd63b8c7e14cb451.png

5 g8 S& d7 v( U: R, }
( K) N* v; ^# }/ ]& L: a注意使用的是MicroUSB接口:! l+ ~7 C8 a, W2 A) q

9 v/ ?4 x% C4 R- v9 ~/ z( q0 b
f871e17a6a2d4c03a9413daf725670c4.png

# g5 P, q: S, X2 O$ \; P- ]+ m
" Z9 l# ~- `" R+ U
5 X: x! v; G; G% i& f* C注意板子左下角跳线帽的设置:
6 H# a2 Z7 F5 W4 E  {
& x& H4 G- M( T
41272c92c8c9483f9d5dc6a04cbf87b8.png

( q3 l. a- O7 M7 |
7 L5 V* g. u, f, ^9 d
# x' v' G! ?% k* }8 j( A这里是用于选择CAN1 TX使用PB9或者PA12引脚,CAN1 RX使用PB8或者PA11引脚。大家这里可以什么都不接,或者CAN1 TX通过跳线帽短接PA12,CAN1 RX通过跳线帽短接PA11。切记不可以短接到PA12和PA11引脚上,USB要使用这两个引脚。
7 h) g. ^5 A2 V  t+ M+ I  N
; D1 V! f' P9 ~: C  `. q3.5   实验例程
6 s9 u- V7 y1 Y# v# w) O5 z: g  }配套例子:
/ w7 B/ Y' Y3 e( E& d% |: N8 Y0 c
! t$ ^( J. a, q9 RV7-2401_ThreadX USBX Template0 ?1 P  h* S5 N5 T' |- m  b" t

& b" O. ?! n5 `/ v2 R实验目的:
" A& t6 E3 d; p; z: |% {2 v7 @: s$ `) Y
学习USBX模板,通过SD来模拟U盘。2 v. N# [0 C& s+ z) w
实验内容:$ r  K7 m% e$ ~7 `+ P* |' \& J3 B

+ I7 ~& T5 ^! D3 e0 \  d6 E' D1、共创建了如下几个任务,通过按下按键K1可以通过串口或者RTT打印任务堆栈使用情况                                 ; c5 i! i% p$ f% o# k7 T7 l8 n/ i% M

! h& y% H  q3 W+ [% ~  ========================================================2 ]7 ?8 [- u4 s) q

$ r* ^3 j6 s7 _" _& u8 J: v  F, ?         CPU利用率 =  0.89%: \8 O  a4 M" K! T6 C. h

) l$ E* K; O( P/ [5 }         任务执行时间 = 0.586484645s. z, G/ v, g/ o# `+ m/ r5 C( ~

, I4 R* M7 F( u- y' S         空闲执行时间 = 85.504470575s
$ u4 O1 Z' @6 K
7 X) V( t4 b, P         中断执行时间 = 0.173225395s$ \0 ]( g" H, m. h+ |

. ~4 C/ {$ V8 B% H1 y4 ]         系统总执行时间 = 86.264180615s              
: l2 k/ F/ E. C: |6 O* l1 q* p8 A/ M, D5 j1 E2 h! `
=======================================================
9 }" @" ]% F: U6 D, P5 w2 N! g4 O
        任务优先级 任务栈大小 当前使用栈  最大栈使用   任务名0 x) d% A) M+ I

$ h2 w/ z; s  t6 L$ w0 O- ^          Prio     StackSize   CurStack    MaxStack   Taskname" o8 C: O  g+ R' U9 i

# m# f$ |! q3 l8 e% T          2         4092        303         459      App Task Start
$ G" _' W4 d$ h4 L# T2 c; F/ x  g& J$ i# {" {$ J' X
          5         4092        167         167      App Msp Pro! [8 w* ~2 j. \1 N

0 A- ]0 n" m) H2 {# G8 z          4         4092        167         167      App Task UserIF7 R$ ]9 u4 Z& F: a5 ?+ {

% \. E/ E! x, [9 r) q! Z           5         4092        167         167      App Task COM
+ L1 U9 J7 w; {' j, q7 F0 U) w) K) \8 F  u& b" M2 U
           0         1020        191         191      System Timer Thread           - A6 z1 b; N9 ~* ?. e, @
* w/ M/ M6 x; P: r
串口软件可以使用SecureCRT或者H7-TOOL RTT查看打印信息。2 \8 V  U. {/ F
/ x% R) v% b. w: M0 _1 Z1 {
App Task Start任务  :启动任务,这里用作BSP驱动包处理。& |. Z. b  s, |5 G

! i* c% q/ p3 s4 a) L# @# |# J% H1 sApp Task MspPro任务 :消息处理。' B  Z  D( P( z1 e* K
, |2 d' i7 Z  @' [
App Task UserIF任务 :按键消息处理。
: X* T4 ]2 F8 k/ i
9 h; X2 R  e- T1 R$ W7 tApp Task COM任务   :这里用作LED闪烁。& A7 z9 H/ X, q
6 @# |4 T/ O  B3 _; D
System Timer Thread任务:系统定时器任务: _* Q8 F' c; W$ K+ `

) _3 m/ M  ^- N1 F3 x- z2、(1) 凡是用到printf函数的全部通过函数App_Printf实现。
- T" p+ b& P7 M5 I+ X
( x$ n$ D5 s6 u8 G      (2) App_Printf函数做了信号量的互斥操作,解决资源共享问题。
) V+ Z4 S& i0 S' X3 W& y4 m( I) N1 k* v1 f  J* m9 W/ J
3、默认上电是通过串口打印信息,如果使用RTT打印信息
) R, B/ Y- G4 k9 J' x4 l- ?; a* n! Q- P' |, K
(1)   MDK AC5,MDK AC6或IAR通过使能bsp.h文件中的宏定义为1即可
7 A6 T: Q/ g' i$ I8 R6 P- w; G( G$ b. r$ I
#define Enable_RTTViewer  1+ g2 `9 _0 j/ W7 u9 _

" Q+ U$ O* k$ ?+ \) ^3 S  A(2)   Embedded Studio继续使用此宏定义为0, 因为Embedded Studio仅制作了调试状态RTT方式查看。
% v4 P$ |8 O& d) s# k3 ^$ I' W6 _
实验操作:
# u& H8 d, H& m/ n9 a
/ H' k  u! S6 J4 P0 \. l3 w6 q4 a测试前务必将SD卡插入到开发板左上角的卡座中。0 H$ _& _8 f4 R& d" q1 s$ {4 i
支持以下6个功能,用户通过电脑端串口软件发送数字1-6给开发板即可
" L' ~  [; `' l5 v- j' o) rprintf("1 - 显示根目录下的文件列表\r\n");# n' L$ `, b; R- \0 \# u! v
printf("2 - 创建一个新文件armfly.txt\r\n");
7 p* u' j% ?" O5 K/ h0 H3 W! zprintf("3 - 读armfly.txt文件的内容\r\n");
. [  \. x$ H7 v; O3 [printf("4 - 创建目录\r\n");
6 L  Q& V7 M2 e) Uprintf("5 - 删除文件和目录\r\n");
4 e$ V) Z# n) ?' _8 ^: X0 k; A8 Aprintf("6 - 读写文件速度测试\r\n");
, R( |: Y& I% W0 q0 Dprintf("a - 打开SD卡模拟U盘\r\n");1 M" ?; O2 R+ a( T4 O! |  Y: d
printf("b - 关闭SD卡模拟U盘\r\n");9 j. K+ k+ I: T/ b2 c+ ?" v' T
串口打印的信息:
& Q6 G! l9 i: T& m$ n( j  @) o7 b  B
波特率 115200,数据位 8,奇偶校验位无,停止位 1+ n3 V5 T0 i5 c% H: _' F: k9 l

7 |9 t1 m) ~! B' y4 u
74d954c9e7b649289184a7a4bd58d6e6.png

# u% W. d( o! N% J4 w8 r6 P; g) E) ]' ]/ y  ]! h9 u

* C0 ]4 a% l. z; P  l, ^$ |* z" m6 o* o, P
RTT打印:/ q' W7 T  I6 O2 C6 t; q% Q

" V7 F3 x: x% D0 z& X
cdcab0e093ed468a912923050806de22.png
8 f/ o- h# u! _0 a; d4 O
0 D6 L/ |$ K3 {# w. a0 J

  U/ P$ C1 T5 G/ Y. ^/ f. Q6 m! i( \
3.6   总结
2 ]0 f- O. ~9 ]+ Y: y8 I本章节就为大家讲解这么多,后面章节再为大家详细讲解USBX的玩法。
: Y" v& O* I* Y2 q' Q" x! `! @1 x, V: t2 T* c+ v7 f+ @# Z4 a' f+ `

1 i% K  ?4 U( o, i  Q
7 s) \- K1 C- P3 {
收藏 评论0 发布时间:2022-1-1 19:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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