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

【经验分享】STM32驱动eMMC读写数据

[复制链接]
STMCU小助手 发布时间:2021-12-29 23:50
STM32驱动eMMC读写数据* Z& P0 h! e4 |- Y7 w" H% G# Y
参照 JEDEC eMMC标准:JESD84-B51 (Revision of JESD84-B50.1, July 2014)
: }# W( q% G( T) i3 V5 V. M0 U驱动芯片采用stm32h7xx芯片。通过官方HAL库中stm32h7xx_hal_mmc.h文件驱动,采用8bit数据传输模式,与SD卡驱动类似。实测写入速度6-10MB/s左右。
3 e- z% `% Z8 q4 y
4 n$ w& g: }6 x% ~6 q1 R7 z, i初始化代码清单:
; k9 ^% j! L9 l! F
; M: {. r1 H0 o% w5 c. I+ ^$ v
  1. HAL_StatusTypeDef SDMMC1_MMC_Init(void)
    3 x/ z# g* s. m! z% K1 {/ S
  2. {
    & V% }. j- ]$ q' Q: ^+ r
  3.   hmmc1.Instance = SDMMC1;
    5 A: U, o9 C  Q" }# ^8 H
  4.   hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
    ! n' {+ P. w, T5 T3 C
  5.   hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;9 r6 @/ j  M0 D' e; ^6 C
  6.   hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;
    9 \5 Y" Z% Z( j/ ]8 E
  7.   hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    ' \4 x' X7 _+ W; b9 b
  8.   hmmc1.Init.ClockDiv = 1;  ?* c* G% i( |
  9.   if (HAL_MMC_Init(&hmmc1) != HAL_OK)2 [* o! K) O$ [  d! K- e
  10.   {
    ; c* k. A/ d/ W' `, P
  11.       Error_Handler();  v3 `, H1 a# c( j! D
  12.   }; B" A- R9 K4 e7 _4 n* k
  13.   return HAL_OK;, b+ v  m/ K  @  X. Y4 c' r
  14. }
复制代码

; A, s6 S& ^' V/ ~: B3 Z底层驱动代码清单:
* s* s5 B7 b. ?: T
+ m: m2 {6 c$ B) I# k. }
  1. void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc)) x7 L/ [, [7 r/ P
  2. {1 f& a6 W, |! }/ p6 ?% z
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    4 L# E, A) J5 [. X/ x
  4.   if(hmmc->Instance==SDMMC1)! i0 x# U! c( v) {
  5.   {$ S3 h# r; w! k5 I1 S
  6.   /* USER CODE BEGIN SDMMC1_MspInit 0 */
    / G- `4 b! u4 g
  7.     /* Peripheral clock enable */+ T' G7 a) m  P! p
  8.     __HAL_RCC_SDMMC1_CLK_ENABLE();
    ; ]+ q8 ?4 W8 z  b# J% o+ k
  9.     __HAL_RCC_GPIOC_CLK_ENABLE();
    " T9 f8 ]% I! x! V
  10.     __HAL_RCC_GPIOD_CLK_ENABLE();
    & D. ]/ ^& j! v' t! n/ F( d
  11.     /**SDMMC1 GPIO Configuration   
    . m9 I) e( n" p- `  ^3 D3 A
  12.               PC8     ------> SDMMC1_D0
    # V7 K2 x# ~5 X# B
  13.            PC9     ------> SDMMC1_D1 * j5 d7 G6 Y' U
  14.            PC10    ------> SDMMC1_D2
    ) d% ]/ R. o; y) i! T  i% B! m
  15.            PC11    ------> SDMMC1_D3
    7 |7 \! B; O4 h& G
  16.            PB8     ------> SDMMC1_D4
    $ I3 {$ y) {* B2 v
  17.            PB9     ------> SDMMC1_D5
    ( C$ N0 K; @' {& A# n9 d
  18.            PC6     ------> SDMMC1_D6
    ! H# z6 m' S& M  n
  19.            PC7     ------> SDMMC1_D7- X8 I" W& x0 R
  20.            PC12    ------> SDMMC1_CK
    ) t- n4 h# g8 ?1 Y0 W& ~
  21.            PD2     ------> SDMMC1_CMD
    ( j. z! t% }) ~  b2 o( E4 V
  22.     */' }7 X6 O$ q) v1 n' I
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8 " ?, p* q. ^9 G
  24.                           |GPIO_PIN_9|GPIO_PIN_6|GPIO_PIN_7;' p- }  N2 I- m9 y: O+ \+ K
  25.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    + d% T- L5 o3 _
  26.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    4 i. C, C1 G: Z+ ]
  27.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    # v0 p% Q0 z2 g' N
  28.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
    9 J3 j: |8 O5 @) {/ w
  29.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    ! `$ ?7 x3 ~( |* `/ G
  30. 9 p4 s3 V9 N* t3 l( J2 P+ p
  31.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;% k; d/ C. \( a- I8 X8 S
  32.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;, @& |7 |/ y# a5 g6 N% L) e' w5 [9 ^
  33.     GPIO_InitStruct.Pull = GPIO_NOPULL;7 U# f5 r8 X3 K; `- |" i" o
  34.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    " Y8 P4 J6 r- H" r9 F* O! }
  35.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;4 K. y5 j1 ~" o: p: k; z. o
  36.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);& s5 z" s! s, _6 F" R
  37. + Q4 L. s; Y' P3 i
  38.     GPIO_InitStruct.Pin = GPIO_PIN_2;- @) M$ j. b1 R4 y. S2 w, k% z, N7 P
  39.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    0 e- Z/ F) p) p+ J
  40.     GPIO_InitStruct.Pull = GPIO_NOPULL;5 K1 ]; d- Q. U. c, ~; \# ?
  41.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;2 L: @0 t; M0 b- c
  42.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;& s* D  Z- z9 c( f1 u
  43.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    3 ^) H6 L1 B$ y" P( H% n9 L* u/ |

  44. 9 a3 r* Q2 K! }  B, f# b4 u
  45.    HAL_NVIC_SetPriority(SDMMC1_IRQn,1,1);  //配置SDMMC1中断
      K; t& @/ I+ C( |
  46.    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);        //使能SDMMC1中断
    " |# q& L! c2 p1 \) [
  47.    HAL_NVIC_SetPriority(SysTick_IRQn, 0x0E ,0);
    , @  A5 q" k& {: J( j% v" t9 G( ~( s
  48.   }; z- R" V  B- \
  49. }
复制代码

% j: I& f3 ]; q- A0 n/ f! F( _4 u6 ?在DMA模式下,从MMC卡的指定地址读取数据:
1 o) ~5 ^0 O( x' S( M' y& }( Q1 D& e  T# ?: l
  1. /**4 ~/ M/ C! |; f- t
  2.   * @brief  在DMA模式下,从MMC卡的指定地址读取数据5 [4 ]! H& ?/ z8 E" s4 i% j
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针# l& _6 [6 ^, y' p7 M
  4.   * @param  ReadAddr:要读取数据的地址0 D6 s; }$ _7 W
  5.   * @param  NumOfBlocks:要读取的MMC块数量
    ; P3 F  ]  q2 {" i
  6.   * @retval eMMC状态; ?% @# ~1 q% s' a4 H3 t( r# c
  7.   */4 |6 K; j4 a7 [  |$ s  I- g% m" l: k  c
  8. uint8_t BSP_MMC_ReadBlocks_DMA(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    ; S0 ]4 A0 Q$ ~% }( k
  9. {7 V+ {2 h; t* \' [
  10.    HAL_StatusTypeDef Status =  HAL_OK;( f: K" A, o; W% b4 m% M
  11. 1 _; o0 W7 x5 ]+ ]
  12.    if(HAL_MMC_ReadBlocks_DMA(&hmmc1, pData, ReadAddr, NumOfBlocks) != HAL_OK)
    7 c8 U8 O: {0 r* n$ Y
  13.    {9 s0 R$ p( ?# \- y
  14.       Status = HAL_ERROR;2 X# C7 a" Z6 @4 x( _7 y' }
  15.    } * e" Z; y& k% b% @2 w
  16.    return Status;
    " f4 w9 n0 m: K! Y) R
  17. }
复制代码
" j; }  v+ P& D9 }8 |9 P' p: o
在DMA模式下,向MMC卡的指定地址写入数据:* O" S- I6 A# `5 o
/ U- L, `: [' R" e( ~* Q0 T7 C
  1. /**4 v7 X( Q5 n+ V2 H/ H
  2.   * @brief  在DMA模式下,向MMC卡的指定地址写入数据
    ! o8 U- Z; c" x( a4 q
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针
    ; [' C+ k7 m& _1 W% l- a1 }  h( _
  4.   * @param  WriteAddr:要写入数据的地址8 N- C6 U' x, u# }, n% |: E4 `7 F
  5.   * @param  NumOfBlocks:要写的MMC块的数量3 o9 H) X; z: E& ~
  6.   * @retval MMC状态
    * ]' T) S, X# ?. x5 m
  7.   */3 ^% W5 l' N2 d4 M2 y4 |
  8. uint8_t BSP_MMC_WriteBlocks_DMA(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    ; x( z0 i1 ]1 t' b2 @# u! U
  9. {
    - k# l, g/ Y! i* u" r1 `+ a
  10.   HAL_StatusTypeDef Status =  HAL_OK;# D( [, c. f# F: E5 l
  11. 8 ]! ]) Y! Z+ S3 v2 b. h) w5 q1 U
  12.   /* Write block(s) in DMA transfer mode */* D  P; `: N, l* `. \3 c) d0 o' O6 d
  13.   if (HAL_MMC_WriteBlocks_DMA(&hmmc1, pData, WriteAddr, NumOfBlocks) != HAL_OK)
    * V* s  [/ \1 g2 E; Y. x) g
  14.   {
    , n. l, U+ }( J( V
  15.     Status = HAL_ERROR;
    1 X7 v2 q0 n( u3 Y% K$ v
  16.   }
    ' I+ d) W* {. J/ o4 U4 c: M) \
  17.   return Status; ; z) B5 u( \/ k3 D6 D3 }9 M# y
  18. }
复制代码

1 I% [4 R  D: p& i擦除eMMC卡数据:
. W5 S- @: S. B3 _- z9 I6 N7 ^+ D# ^
  1. /**
    1 K" k, l! s/ ]
  2.   * @brief  擦除eMMC卡数据' ?; P' M: Y5 }4 H0 @2 ]% A0 ]1 }1 T
  3.   * @param  无
    & I: f8 J. U  V1 v' }8 L
  4.   * @retval 无: k$ C# a, D) ]
  5.   */
    & v$ a! _! v8 d% o5 t/ `/ l
  6. void MMC_EraseTest(void)
    2 z8 _2 O0 J1 K
  7. {& ^/ |; p( S) x8 `3 Q7 r5 [5 m
  8.    HAL_StatusTypeDef Status = HAL_OK;* E! [( E. r/ ^) M
  9.    HAL_StatusTypeDef EraseStatus = HAL_OK;
    4 x( _: F% E! O2 [+ \. _4 Z( j
  10.    if (Status == HAL_OK)
    $ k+ s# g4 d' V1 s2 Q
  11.    {) P. i8 s- [; i+ k& g1 m. o! j! X
  12.       Status = HAL_MMC_Erase(&hmmc1, 0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));
    + Z  S! O/ {2 f& n# U5 ]
  13.       //等待擦除完成4 ]5 R  m$ F! B  d6 I$ o
  14.       if(Wait_SDCARD_Ready() != HAL_OK)/ d  E9 U% b5 w# {+ ~
  15.       {; E, h. _! v  ]% I
  16.          EraseStatus = HAL_ERROR;
    # q/ X- t! K5 w, w: N  k( {
  17.       }
    0 c0 y% ?- f8 U# S. ~
  18.    }  e; h2 G3 }' H6 ^
  19.    if(EraseStatus != HAL_OK)
      X  K9 B- X7 h. C: H
  20.    {    9 \9 ?0 D+ b% }/ s4 ?3 m
  21.       Error_Handler();
    9 A: h* X. A4 r# b
  22.    }
    2 a7 h2 B* {. d0 K
  23. }
复制代码
! H5 N2 C9 {% L: s
eMMC卡等待擦除完成函数:
- M9 @0 O3 W' c( K* I' }
$ k" t5 {, f1 y" a, n' ]3 D4 u  |
  1. /**$ x: \, }7 [& s6 h1 w
  2.   * @brief  eMMC卡等待擦除完成函数
    9 J: K% z( t8 Z7 G2 J5 E! ?
  3.   * @param  无3 i7 y! G% S& H' `" T
  4.   * @retval HAL_OK:擦除成功;HAL_ERROR:擦除失败! Q$ N6 i5 M( ~" p; R0 a7 E$ n3 Y
  5.   */
    8 b' g# Z5 b1 _
  6. static HAL_StatusTypeDef Wait_SDCARD_Ready(void)% P4 N8 }' `" ?
  7. {
    " \; i* n: T, u/ D
  8.    uint32_t loop = MMC_TIMEOUT;
    - Q0 }# z6 \; D, c' z; S4 ^

  9. $ S8 r# [( X5 V! X* V4 E# Q
  10.    /* Wait for the Erasing process is completed */2 r0 G! V) C3 u/ `/ @
  11.    /* Verify that SD card is ready to use after the Erase */; d0 D, Z9 c* J- M) |% n# Z
  12.    while(loop > 0)* S* z9 f7 ?: G6 V$ B0 H6 b
  13.    {+ W3 T! @5 e+ r! Q& c' p
  14.       loop--;
    & s4 M, k( w6 d. x- _9 U2 g3 g
  15.       if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)/ {8 N7 @0 X" H/ x; T+ i' k
  16.       {
    ! G! L& x& Z3 C9 T2 e
  17.          return HAL_OK;" u( V+ d" Q1 T3 f; Q2 s3 \, e8 d
  18.       }3 A- c# ~" E& s8 @: _+ @
  19.    }; @6 J* d" H8 w% ^
  20.    return HAL_ERROR;: }  A# w, |# m3 J- ~
  21. }
复制代码

$ w6 I" E; s, H5 a4 z2 u% H( T! U# l% u最近移植的eMMC卡的驱动程序,分享出来希望对各位开发者有所帮助。还移植了FATFS文件系统到eMMC驱动程序中,之后整理好再分享。
0 ~, B3 h! I6 l# ]8 [
- e, o7 _% e8 l& r( ?
8 Z6 B0 \8 u+ m& v0 R
收藏 评论0 发布时间:2021-12-29 23:50

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版