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

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

[复制链接]
STMCU小助手 发布时间:2021-12-29 23:50
STM32驱动eMMC读写数据& }, Y3 W" n. k1 h& j
参照 JEDEC eMMC标准:JESD84-B51 (Revision of JESD84-B50.1, July 2014)
# B! N4 \0 `# Q& `0 ^驱动芯片采用stm32h7xx芯片。通过官方HAL库中stm32h7xx_hal_mmc.h文件驱动,采用8bit数据传输模式,与SD卡驱动类似。实测写入速度6-10MB/s左右。2 k5 W8 r1 O; E8 v/ |" a0 ^
+ b7 }$ H+ u2 I7 u" F
初始化代码清单:* B& o* L/ K! b

  }! F% V8 b7 N9 i: t. K# n. b5 T1 W
  1. HAL_StatusTypeDef SDMMC1_MMC_Init(void)
    7 S9 v5 l& E5 P
  2. {
    : @2 _" Z" t3 C+ g" c0 o' v% Y4 _
  3.   hmmc1.Instance = SDMMC1;
    9 u' o: r& h' Q6 S7 k) k: w
  4.   hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;- c' P: G7 r/ D* g. I! I' D5 Q
  5.   hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;$ P& w: p, @( f7 z2 W
  6.   hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;+ \/ f! y0 l% X, h
  7.   hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    ) a) k- g) p+ W& v+ e$ ?. G2 r* {2 M
  8.   hmmc1.Init.ClockDiv = 1;8 K2 V( t9 p) t$ X' W+ V5 Q
  9.   if (HAL_MMC_Init(&hmmc1) != HAL_OK)0 C2 C& [% r% u2 R  X4 p
  10.   {
    ; T- G8 W) q0 D. t% }3 O
  11.       Error_Handler();* ^# \3 I( a2 |
  12.   }
    3 w9 n% d2 l) I
  13.   return HAL_OK;
    9 G( c0 l. g/ @! o( o
  14. }
复制代码
: W- R2 H5 r& W9 ^
底层驱动代码清单:
9 d# k* z. m2 ^6 \8 Y( ~
3 v9 F4 y, I; W% c) d2 l
  1. void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc)
    , e9 `: A1 K- T; J7 E
  2. {* q, d. p7 `$ j5 ^
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};" V  a9 K- i; l9 B  w
  4.   if(hmmc->Instance==SDMMC1)
    ! ]$ ?) ^9 e" i' A4 `+ {; O, S/ g
  5.   {
    2 d/ h4 I; X3 G& F& V
  6.   /* USER CODE BEGIN SDMMC1_MspInit 0 */
    1 K, r1 j: W* p. O/ @1 \; |. y
  7.     /* Peripheral clock enable */
    ! P; G; e1 b- z1 z
  8.     __HAL_RCC_SDMMC1_CLK_ENABLE();
    8 i5 @/ h' E9 \' h
  9.     __HAL_RCC_GPIOC_CLK_ENABLE();
    / }6 B! @$ @) u6 F
  10.     __HAL_RCC_GPIOD_CLK_ENABLE();
    - S6 a* \$ r8 I
  11.     /**SDMMC1 GPIO Configuration    7 {( [& Z3 b' T; Q/ }# I0 u( V5 F
  12.               PC8     ------> SDMMC1_D0* X' ^9 f" P1 f& Q
  13.            PC9     ------> SDMMC1_D1 2 G+ S$ @+ Y9 @6 {/ l
  14.            PC10    ------> SDMMC1_D2
    5 z' i9 r* r& m; v
  15.            PC11    ------> SDMMC1_D3$ l; d; S* D' }8 u6 s2 l8 \+ v7 T0 I
  16.            PB8     ------> SDMMC1_D4
    9 X& L2 B% {  n" K8 ?
  17.            PB9     ------> SDMMC1_D5
    " p( Y- J" ~# }( ]6 }1 `
  18.            PC6     ------> SDMMC1_D6
    ' W: U1 z1 B* m
  19.            PC7     ------> SDMMC1_D76 k1 {' S7 W8 \/ Y9 q
  20.            PC12    ------> SDMMC1_CK; f& c! I% W% W/ t0 b, [
  21.            PD2     ------> SDMMC1_CMD3 B( P8 m& p3 X. Y' o. y
  22.     */
    * z+ r$ ?1 {: l) N5 i# x8 u* G2 X3 r
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8
    7 o$ Z, D; e, x( P+ l
  24.                           |GPIO_PIN_9|GPIO_PIN_6|GPIO_PIN_7;& T  t; P% I3 L2 W0 x/ @; k* N
  25.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    , F1 k7 E; e: l: C# S
  26.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    ) |  B$ A% V& V2 f7 f
  27.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    $ y2 U  q* ^7 n
  28.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
      |3 Z  p5 |7 w
  29.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);$ g3 E. g. p# k7 [  ~+ l9 y  l  o( X% M
  30. ! X& Z& u; \" N# H
  31.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
      A9 _, M' S% H6 d3 l, p. i' m
  32.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    8 y2 A' N  r  X, _
  33.     GPIO_InitStruct.Pull = GPIO_NOPULL;$ Y. T  Q5 i$ N' n
  34.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;+ v3 t4 J( D( |  c& u& }" f' C. _- L
  35.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
    / K, c* g& w" A3 W7 }
  36.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);' i. s' m% n3 c- W' k

  37. ; i7 a& n; i. W( x( N* H" E6 ]
  38.     GPIO_InitStruct.Pin = GPIO_PIN_2;- C# {$ w2 u4 @
  39.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;9 Z; w' ]! i. Q
  40.     GPIO_InitStruct.Pull = GPIO_NOPULL;2 I) w/ Q# q) H% U3 L! T
  41.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;* ~" X2 Q9 J" N! Y
  42.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;' U% M, n" S3 f9 _6 H+ g. e; f0 P) O
  43.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);. h. F$ y! ~  |) Q2 d
  44. " Q  U0 ]1 ~; b' I7 c4 G* A
  45.    HAL_NVIC_SetPriority(SDMMC1_IRQn,1,1);  //配置SDMMC1中断+ b& B8 Y7 |9 |, a' R# {
  46.    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);        //使能SDMMC1中断2 v6 I8 ~6 _, P2 [8 z' l5 h
  47.    HAL_NVIC_SetPriority(SysTick_IRQn, 0x0E ,0);
    ' O/ f! {7 l8 h
  48.   }
    2 \+ p( ]9 `3 ?  C" ~& ^
  49. }
复制代码
% a, z0 G; N1 B9 j* N7 O
在DMA模式下,从MMC卡的指定地址读取数据:
+ ]5 x8 F' G& x8 L
/ U, T, w: \$ c4 e8 j  V9 C: E9 o2 |' m
  1. /*** G3 n, H$ f0 }' L! p0 l) B4 l
  2.   * @brief  在DMA模式下,从MMC卡的指定地址读取数据
    ' c+ ?# k2 c/ A$ I" P. f9 K3 y- _
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针
      f7 \1 [* Z* x+ {
  4.   * @param  ReadAddr:要读取数据的地址
    9 D" d3 I4 q( P" b# v
  5.   * @param  NumOfBlocks:要读取的MMC块数量
    1 F/ [0 X7 h2 L( z* Y6 {' t' ]1 c% d
  6.   * @retval eMMC状态
    1 W4 T+ S$ S  \) y! a
  7.   */9 |- G  J/ G4 {4 g  S# q
  8. uint8_t BSP_MMC_ReadBlocks_DMA(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    + Y; b8 V) S& f( A1 y2 I6 Y6 Z
  9. {
    3 k! s$ d+ W2 Z/ A/ X* `8 G( \6 b
  10.    HAL_StatusTypeDef Status =  HAL_OK;5 |) ^1 J2 E0 @8 \( S
  11. % i# z) i" @; {  [7 I; K$ h
  12.    if(HAL_MMC_ReadBlocks_DMA(&hmmc1, pData, ReadAddr, NumOfBlocks) != HAL_OK)' V- ^6 ^" n/ o( Q' m# r
  13.    {, |7 Q0 a+ `- L
  14.       Status = HAL_ERROR;
    . K6 U* @; w0 H& {; S. G
  15.    }
    & M3 X: M$ x; C- {
  16.    return Status; ; e5 s* M4 t- e# G! f. E3 d
  17. }
复制代码

2 X8 {' G" V5 U在DMA模式下,向MMC卡的指定地址写入数据:
* m" J8 {2 ^) z9 P3 k2 S0 r
; a2 g, P5 J" Z; w) N
  1. /**6 p/ v8 q' b8 D( N% \/ i0 n* a4 K
  2.   * @brief  在DMA模式下,向MMC卡的指定地址写入数据2 D& o0 U3 u# b( m+ U' L
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针
    ; R4 G* e5 \! v. |$ l$ W
  4.   * @param  WriteAddr:要写入数据的地址
    9 D8 z$ E/ s6 l3 {
  5.   * @param  NumOfBlocks:要写的MMC块的数量: L* l0 d7 t+ s3 H, K, X( x
  6.   * @retval MMC状态* x& }0 d6 f. t0 Y; A
  7.   */8 U2 D2 _. k" U; Y! u& i  e
  8. uint8_t BSP_MMC_WriteBlocks_DMA(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    5 q5 O& w# Q! j7 u5 O4 K, B* E/ Q
  9. {
    ; H: F+ R& h. _0 H, l3 M7 m
  10.   HAL_StatusTypeDef Status =  HAL_OK;$ c5 V7 z0 F: `

  11. ( p3 ^4 h$ e# Y6 \5 q
  12.   /* Write block(s) in DMA transfer mode */5 W, U5 q/ Q8 O; M9 o) N
  13.   if (HAL_MMC_WriteBlocks_DMA(&hmmc1, pData, WriteAddr, NumOfBlocks) != HAL_OK)+ K  ]2 ~2 S( E
  14.   {
    - D+ ~  R' h" t5 m/ Z; R3 |
  15.     Status = HAL_ERROR;* E+ @. |% N  v& C3 V
  16.   }
    7 V/ g& r7 Y/ Q! `4 Y$ n1 M2 G
  17.   return Status;   |4 L" o& J4 J/ p0 k& Q
  18. }
复制代码
: `/ @; B; G) l/ y
擦除eMMC卡数据:+ E+ ?( b9 k6 V9 x) ^

. V1 Z! F: G  Z, U' u9 F2 ]
  1. /**
    . m. z+ `4 I7 {. P1 P3 \
  2.   * @brief  擦除eMMC卡数据
    ( B; \, A2 \# x* ~8 y) M
  3.   * @param  无
    9 {+ W+ e( j6 f
  4.   * @retval 无' o2 j& h5 s. w
  5.   */
    0 r' y" N+ [: V2 p
  6. void MMC_EraseTest(void)+ }% M# k& V3 e+ ^
  7. {
    / M. Q$ w( t3 E% v& r% V
  8.    HAL_StatusTypeDef Status = HAL_OK;
    * k9 {" m2 ?* c2 g' U, o: Y% O* a
  9.    HAL_StatusTypeDef EraseStatus = HAL_OK;
    $ U% R0 R; T# X$ \
  10.    if (Status == HAL_OK)
    5 w$ @! \* T+ d! U4 C
  11.    {
    , x8 V0 M/ U/ g. ~0 u: Q  A
  12.       Status = HAL_MMC_Erase(&hmmc1, 0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));
    . d8 H2 K* F$ d
  13.       //等待擦除完成$ ~; v7 T0 F! G
  14.       if(Wait_SDCARD_Ready() != HAL_OK)
    / p% x6 p6 \, P! ^  g1 n# z" z  C
  15.       {2 _2 _. y2 J& T
  16.          EraseStatus = HAL_ERROR;8 C3 O& f$ }1 w) c
  17.       }
    ( }- T% T/ l* N3 z( Y
  18.    }
    8 x- I% v- f4 l* ~! G7 D
  19.    if(EraseStatus != HAL_OK): B# U8 m) g( m) @* `2 ^3 m! D
  20.    {    1 F( V( y3 o) W# ~& d" ]. o
  21.       Error_Handler();. Y: d7 ?' l% p8 Q
  22.    }$ Q$ E; ^. H6 i1 R' E7 A
  23. }
复制代码

4 Y) @$ e/ V7 P/ aeMMC卡等待擦除完成函数:
' E$ t" m" ?' i4 M& v( x" c* K( w$ g7 P6 w6 |( ]; y. Y
  1. /**7 u$ r7 \$ z2 P9 e" u& n) w
  2.   * @brief  eMMC卡等待擦除完成函数
    9 D: ~5 T/ ?! l$ A' s
  3.   * @param  无, _6 h8 @: C8 A6 l& }
  4.   * @retval HAL_OK:擦除成功;HAL_ERROR:擦除失败. N( c+ A0 o: B" A9 u, o- K
  5.   */
    . D( p- z  X' H. W+ r* K
  6. static HAL_StatusTypeDef Wait_SDCARD_Ready(void)/ ~& E2 w1 L9 x+ w8 b$ @
  7. {
      P7 ?) k. v% M  s# x; I) R, k
  8.    uint32_t loop = MMC_TIMEOUT;( [5 r$ L* M5 \8 e9 m
  9. & Q6 m) f( \+ d  V. J
  10.    /* Wait for the Erasing process is completed */2 `4 L, @/ b4 E& K! b, j% l; q
  11.    /* Verify that SD card is ready to use after the Erase */
    6 o2 x  K3 x, E, }  D! |
  12.    while(loop > 0)
    # z0 `7 i: [, q1 @
  13.    {
    1 l/ O) m& N3 f8 ~" d: E& |% ?
  14.       loop--;
    . [7 Z% _: b3 G$ K
  15.       if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)2 K3 M0 C5 t: B/ }( t- F2 P. H$ A% g
  16.       {7 w5 p# P& ~8 d* W; D5 |1 B4 ?
  17.          return HAL_OK;
    - X: }% Y" W; {! A" Z
  18.       }
    , j, e2 |; e$ E8 R$ S
  19.    }5 j7 Z8 ?* G* w& N
  20.    return HAL_ERROR;! @8 M: D9 y; U+ C: J! f2 S
  21. }
复制代码

# z4 G- J( C: p2 C2 ~最近移植的eMMC卡的驱动程序,分享出来希望对各位开发者有所帮助。还移植了FATFS文件系统到eMMC驱动程序中,之后整理好再分享。
8 S. e2 A9 M# k' s$ `# J% h/ o1 E: M, ^# \3 Y
6 N- m3 ]6 N$ @' X5 L, W
收藏 评论0 发布时间:2021-12-29 23:50

举报

0个回答

所属标签

相似分享

官网相关资源

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