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

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

[复制链接]
STMCU小助手 发布时间:2021-12-29 23:50
STM32驱动eMMC读写数据% q/ i. r# W2 c4 r+ ~
参照 JEDEC eMMC标准:JESD84-B51 (Revision of JESD84-B50.1, July 2014)
# v: z, B- q) Y; n& {. o% R) j7 [" X驱动芯片采用stm32h7xx芯片。通过官方HAL库中stm32h7xx_hal_mmc.h文件驱动,采用8bit数据传输模式,与SD卡驱动类似。实测写入速度6-10MB/s左右。
, T3 S# I/ Q7 ?* E8 l5 G: y4 V- P+ ]$ ]( P
初始化代码清单:. g, z1 B, c, s6 m3 g
5 x! I8 ]% Z" y$ w1 z$ b( J
  1. HAL_StatusTypeDef SDMMC1_MMC_Init(void)
    ' O: E6 T- L6 ^) b. n, U4 `! V
  2. {
    ) d( ~2 n3 Z* i% b! X; z
  3.   hmmc1.Instance = SDMMC1;1 O& {" U" c; S9 [) d
  4.   hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
    9 h! g3 B4 a2 P' G- Y1 y
  5.   hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
    # u) |! J0 V+ G; d" R
  6.   hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;
    ; j: h* U6 q* E+ Z" C7 C
  7.   hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    ! |2 Q) W# s* c) t$ l, R- c/ R$ Z
  8.   hmmc1.Init.ClockDiv = 1;1 D+ b, R9 Z( Z3 `! s7 r
  9.   if (HAL_MMC_Init(&hmmc1) != HAL_OK)
    ( z& `. `8 g6 M; _$ S* `2 ~
  10.   {9 j* P: P. S$ |* ^2 N/ W: {
  11.       Error_Handler();1 _9 x4 a0 U: b; a' T% P
  12.   }. ]% l8 ^! H; B/ i/ U8 D8 _) h' R
  13.   return HAL_OK;
    / s4 `7 w% r  a4 t( u9 `, t6 [; s! g
  14. }
复制代码
+ ]7 c  [: G  E. p% J
底层驱动代码清单:& H( I* l1 L5 K5 o

9 j$ @% K3 y3 B5 O. J4 _: X2 z9 G0 @
  1. void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc)0 A/ R, E( }( H2 {- U3 k
  2. {% M) ~, _& G& v, i# W
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};/ i5 x: o% _# D1 b8 V% M
  4.   if(hmmc->Instance==SDMMC1)6 i2 F( R8 j8 j, \
  5.   {; h- {6 m& E& n3 _0 S4 C6 y5 j
  6.   /* USER CODE BEGIN SDMMC1_MspInit 0 */
    5 u  P3 N$ U7 |1 a0 d& ^  }
  7.     /* Peripheral clock enable */
    % m) K7 O9 o4 W
  8.     __HAL_RCC_SDMMC1_CLK_ENABLE();
    , n5 d5 ]- s( w3 O9 J
  9.     __HAL_RCC_GPIOC_CLK_ENABLE();
    4 c6 X3 r8 c/ W' q  i
  10.     __HAL_RCC_GPIOD_CLK_ENABLE();
    4 r$ k2 l) ]( m6 z. Y5 y
  11.     /**SDMMC1 GPIO Configuration   
    2 M- L/ j- Z7 G* z+ d
  12.               PC8     ------> SDMMC1_D0
    ' N7 n/ p+ V; `
  13.            PC9     ------> SDMMC1_D1 2 N% [0 w' |: T( g
  14.            PC10    ------> SDMMC1_D21 z) |  [  Q3 G6 i# a. Q
  15.            PC11    ------> SDMMC1_D3
    4 C9 ^9 ~/ C5 D% n
  16.            PB8     ------> SDMMC1_D4; r4 X. s5 I# l1 T0 o0 G
  17.            PB9     ------> SDMMC1_D5
    1 f8 r, l5 P. B  P6 B, Y9 I
  18.            PC6     ------> SDMMC1_D6
    & n& d+ [4 ^+ Q+ R  Q
  19.            PC7     ------> SDMMC1_D7
    7 o/ \9 [4 \% o5 j& c0 g- n% K+ x
  20.            PC12    ------> SDMMC1_CK8 ~& h" R- ?2 ^& u0 z/ w% ?
  21.            PD2     ------> SDMMC1_CMD
    6 K0 J  R2 r. H9 \& C# l* O8 K
  22.     */' Q( S8 G( s8 W% H' k. \
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8
    / ?: Z3 g8 v' l
  24.                           |GPIO_PIN_9|GPIO_PIN_6|GPIO_PIN_7;
    ! y4 ^6 l) O9 V$ O9 D. U
  25.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    . v1 F  L/ y4 q& O5 l
  26.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    ; K1 {- v! g# \2 |/ ?
  27.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;7 Q) W4 P% e, ]& u+ [* \* {9 Q
  28.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
    6 I/ p, }, W# o! Q9 D) F
  29.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);% F3 y; Z5 K- j) w

  30. & C+ a5 ~. T# c/ H4 Q1 F5 {
  31.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;; n. G( b  K' _
  32.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;! H# Q" T. t6 s- d5 ?, J9 a0 X% z
  33.     GPIO_InitStruct.Pull = GPIO_NOPULL;& Q( Z' j% l) e$ u2 W
  34.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    / s. T" i2 @( b# j' J; t; m* `, B
  35.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;$ j/ \# s4 z$ f* L
  36.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    : }& ]# O1 R" g. r% @2 }6 C9 H
  37. / s0 \+ _7 ]  ?1 s( T; F
  38.     GPIO_InitStruct.Pin = GPIO_PIN_2;  X# x) P+ G; K* G7 j7 ]% l( j9 W
  39.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    0 \; R4 Z8 Y% g" Z  Q% l
  40.     GPIO_InitStruct.Pull = GPIO_NOPULL;1 p2 ?; z6 B' J* D  P4 \7 s
  41.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;+ r# k) l! b1 Y: `$ V$ a9 ]3 b
  42.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
    8 @) p8 o4 h" R% [8 W- j( @: N! G* I, l
  43.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);5 i1 k' e7 z9 J) A( Y1 \; A6 |  y

  44. 6 u+ p8 S( T: X& h7 B, L4 ~
  45.    HAL_NVIC_SetPriority(SDMMC1_IRQn,1,1);  //配置SDMMC1中断
    % @  P. X9 {& R/ Z/ c; K
  46.    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);        //使能SDMMC1中断  @3 p! e: [6 [5 M
  47.    HAL_NVIC_SetPriority(SysTick_IRQn, 0x0E ,0);7 L4 {3 ]# l% {- d
  48.   }/ b- a/ y/ z/ B9 E
  49. }
复制代码

+ _" Q! R2 o, x0 Z在DMA模式下,从MMC卡的指定地址读取数据:
, H* Q  g# e  P% Z$ L
- Q8 L- l# z8 g. u8 A+ B- B
  1. /**$ N% a' K+ y% X+ V
  2.   * @brief  在DMA模式下,从MMC卡的指定地址读取数据0 n+ ?5 g) I( p. `
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针6 s! ?6 @/ Z; i7 ]; B& Q: P/ m& B
  4.   * @param  ReadAddr:要读取数据的地址! V8 d" N6 k; {6 t
  5.   * @param  NumOfBlocks:要读取的MMC块数量! S. Z$ P5 f' Z
  6.   * @retval eMMC状态
    5 S" O2 Y7 w; ?+ F; {1 w
  7.   */
    $ Y) `! m! b+ [9 Y, W/ L* J
  8. uint8_t BSP_MMC_ReadBlocks_DMA(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    + x" T+ t  A* V6 T$ \, ]
  9. {6 c: y! d$ Y  p9 E) ]3 b% E( W
  10.    HAL_StatusTypeDef Status =  HAL_OK;- }9 q1 R6 A$ Y" s
  11.   B2 Y$ r: {+ `
  12.    if(HAL_MMC_ReadBlocks_DMA(&hmmc1, pData, ReadAddr, NumOfBlocks) != HAL_OK)
    % N6 a9 i$ W6 ]4 ~8 D8 R
  13.    {
    9 i: a4 G  a9 Q  I( u+ v+ p; r
  14.       Status = HAL_ERROR;
    6 M, P  o% Z- P- o9 U* }$ H8 B
  15.    }
    + x- o! @( l! _$ C3 }8 |! H" q
  16.    return Status; # S+ \' I5 a8 c0 S% n( a, r9 E% F
  17. }
复制代码
% H, [3 `4 e2 J: e& {
在DMA模式下,向MMC卡的指定地址写入数据:2 V# z$ w" |0 v+ U  c) D% _% G
3 q$ p, e# k1 p" m0 ?+ O* z. d
  1. /**8 P7 D, u% W1 u! l6 H( Z  H6 C& t
  2.   * @brief  在DMA模式下,向MMC卡的指定地址写入数据
    0 r* s2 H  }; {+ }% ^
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针; r6 Y7 a3 @$ I# W7 x1 i1 e$ ]
  4.   * @param  WriteAddr:要写入数据的地址
    ( s4 b  ~- a# t  ~6 c
  5.   * @param  NumOfBlocks:要写的MMC块的数量
    9 e2 i, ^0 {; e3 d, _
  6.   * @retval MMC状态
    5 \/ ^: M# a* s3 k" r- P& ?% E9 }' K
  7.   */4 R* T; Q3 ~& C6 F, u
  8. uint8_t BSP_MMC_WriteBlocks_DMA(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    3 C* W: a3 [  P, _; \3 y2 U
  9. {
    ' n& p- y9 ?1 `7 c5 b. Q7 z3 [
  10.   HAL_StatusTypeDef Status =  HAL_OK;$ R$ Q! y7 i! Z3 s% C( T( ~

  11. + p0 @% o) i0 ?% Z
  12.   /* Write block(s) in DMA transfer mode */3 C% B, b. _$ `8 C6 q9 j' S" [
  13.   if (HAL_MMC_WriteBlocks_DMA(&hmmc1, pData, WriteAddr, NumOfBlocks) != HAL_OK)( I& }) G0 z) P/ }; m. i. R: B8 y
  14.   {9 d9 s6 J/ j& `6 L$ U8 T
  15.     Status = HAL_ERROR;/ @; y2 r+ H& T4 Q4 B1 e
  16.   }! r$ R$ M) B; I0 T- V
  17.   return Status;
    & Y+ r# v9 E' I; T! G4 e
  18. }
复制代码

! [1 ?4 v) ]* m! r3 C3 [擦除eMMC卡数据:
: J: _9 f' |! v! m$ A- R4 W: d/ d* t. W+ O+ W# l
  1. /*** Z, c: G* I/ f  N; S
  2.   * @brief  擦除eMMC卡数据
    ) \2 [$ I0 [( t6 S( D* p
  3.   * @param  无6 O. q# `! }4 e
  4.   * @retval 无
    $ O" u9 g9 E: s3 ~: g" z% M
  5.   */3 r8 w5 y" K; m2 `- D; `
  6. void MMC_EraseTest(void)
    3 d8 @1 n* v* H+ O: I2 n+ d, w+ {
  7. {3 g2 w8 I/ Q3 w4 M- q" c
  8.    HAL_StatusTypeDef Status = HAL_OK;
    ' J: x2 a9 c1 a; N. v
  9.    HAL_StatusTypeDef EraseStatus = HAL_OK;
      k3 w6 |( {9 x& s$ r
  10.    if (Status == HAL_OK). p& c9 f5 i& D
  11.    {1 l2 a) v& g5 `' _: A
  12.       Status = HAL_MMC_Erase(&hmmc1, 0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));* X" F9 _2 j9 B: t9 F& [* }
  13.       //等待擦除完成0 g4 Z6 q, q' x9 [% R4 E
  14.       if(Wait_SDCARD_Ready() != HAL_OK)& X$ R& i2 f/ j& _( \
  15.       {/ O" {# s" G/ e
  16.          EraseStatus = HAL_ERROR;
    8 n, L' E' t* E( y4 E) x
  17.       }
    ) E( I0 j1 A& ~
  18.    }+ d9 T5 ]# q, i+ a) F, }
  19.    if(EraseStatus != HAL_OK)* Y- R+ V, k* b- b' L9 c* G0 a8 p3 X
  20.    {   
    ; i% }2 D# L5 U) x" a) z# Q
  21.       Error_Handler();
    - o8 D9 S  Y/ o
  22.    }3 L$ D8 Y; |* x7 M3 k/ w9 @
  23. }
复制代码

% Q$ v& S. a0 F0 |: \& oeMMC卡等待擦除完成函数:
4 [) D0 |# }, _9 Q
  T/ S* ^' s0 x1 w
  1. /**8 N3 C3 C$ v5 r" v
  2.   * @brief  eMMC卡等待擦除完成函数
    % U' t7 e- b7 h; O4 [! e/ }
  3.   * @param  无: t1 Z7 c3 A# K$ z, L! G' p$ Z+ }
  4.   * @retval HAL_OK:擦除成功;HAL_ERROR:擦除失败4 [( q  w  }; B" C" l% [+ g
  5.   */2 X* g& J5 X4 G
  6. static HAL_StatusTypeDef Wait_SDCARD_Ready(void)
    5 c3 F  S0 J7 r
  7. {
    + c6 x# Z; I0 S# b1 K- S
  8.    uint32_t loop = MMC_TIMEOUT;5 N( O2 X' j" r* d* w

  9. 0 J: Q2 F( Y2 H9 v# [% z" a5 F
  10.    /* Wait for the Erasing process is completed */( R3 s( U" r' a. X$ h
  11.    /* Verify that SD card is ready to use after the Erase */
    ) y; d' E, E1 I4 u
  12.    while(loop > 0); j) j8 P$ v  l, C* x
  13.    {
      W- G2 ~: C8 [1 t- T6 O$ Z
  14.       loop--;; m6 `7 k4 P/ V) V
  15.       if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)" g+ I" s0 x* q; X4 b, y  f
  16.       {( S. N7 U: K+ w# a  d$ u
  17.          return HAL_OK;
    3 w7 z! U2 l6 Q6 Y5 [$ ^3 B2 C
  18.       }) |% {' O* M! q6 y& F; Y8 K
  19.    }- ^6 e) X1 M% J6 X1 a& v
  20.    return HAL_ERROR;
    * I( d7 T) k% A# J3 l" {- Q
  21. }
复制代码
+ c4 ]3 \" i4 s
最近移植的eMMC卡的驱动程序,分享出来希望对各位开发者有所帮助。还移植了FATFS文件系统到eMMC驱动程序中,之后整理好再分享。
+ ]0 K; W1 r2 e& ^5 T4 C+ g
" B* X* ]8 U# p8 l  P( |- \" B4 z
收藏 评论0 发布时间:2021-12-29 23:50

举报

0个回答

所属标签

相似技术帖

官网相关资源

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