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

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

[复制链接]
STMCU小助手 发布时间:2021-12-29 23:50
STM32驱动eMMC读写数据5 r) Q( T4 j3 m/ |9 p
参照 JEDEC eMMC标准:JESD84-B51 (Revision of JESD84-B50.1, July 2014)
1 A8 K- Y* F7 U% G, V驱动芯片采用stm32h7xx芯片。通过官方HAL库中stm32h7xx_hal_mmc.h文件驱动,采用8bit数据传输模式,与SD卡驱动类似。实测写入速度6-10MB/s左右。- Z2 j* u& H7 t8 E( t* ~4 Z
$ z5 ~+ {( W! E) Y4 H1 l; M
初始化代码清单:
% |* o( M' q& ~8 R2 j3 a) c( E8 m$ U$ Q5 a
  1. HAL_StatusTypeDef SDMMC1_MMC_Init(void)* x+ `. G- ^: ?- F* j  O0 |
  2. {& a, Y* T5 v- U3 W0 K
  3.   hmmc1.Instance = SDMMC1;  p8 _3 y, Y# v( y% H/ y6 |
  4.   hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;& ^) g6 [- p. r& m0 k  I7 K( G
  5.   hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;6 [' V, a; H) M9 g: z
  6.   hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;" }. W8 y8 o( \0 f
  7.   hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    ' V5 U# E% W3 y" ^8 ]& X7 S) P2 {
  8.   hmmc1.Init.ClockDiv = 1;
    ) ^( w# z7 A- ~( {- A/ [' j4 u
  9.   if (HAL_MMC_Init(&hmmc1) != HAL_OK)* t# F1 a1 u% Z' u
  10.   {
    9 w8 d' R; q( V/ C
  11.       Error_Handler();
    9 ]$ p1 Y; V. I. h4 f' ~0 i9 u
  12.   }7 o) e( [* w% G$ w. d7 U
  13.   return HAL_OK;
    5 Z; n; s  h1 x* x" G9 ]& g
  14. }
复制代码

9 g3 v$ _1 {$ |, ^3 z. c底层驱动代码清单:
8 s* H' s  B( j& L6 `3 V1 p6 s% W/ C) o3 n: q( P# w
  1. void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc)6 ^* u' ]. Y! n0 h) }, L  ^7 H
  2. {  T7 D. R+ ^$ G4 H
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    1 F* E9 ^. f% H7 M: g
  4.   if(hmmc->Instance==SDMMC1)3 m4 s( D$ V8 i+ R1 Y4 u6 \- P; w
  5.   {- U0 K7 U. U  ?& P5 D- B
  6.   /* USER CODE BEGIN SDMMC1_MspInit 0 */
    " P* B* x, v) i$ S0 h8 ?
  7.     /* Peripheral clock enable */
    6 o% X$ R+ d0 U' p- G+ I1 }
  8.     __HAL_RCC_SDMMC1_CLK_ENABLE();4 ^0 V, \, z/ D& N" D
  9.     __HAL_RCC_GPIOC_CLK_ENABLE();( _9 o/ j0 K, m% E4 g
  10.     __HAL_RCC_GPIOD_CLK_ENABLE();
    2 H+ I8 H+ X9 k
  11.     /**SDMMC1 GPIO Configuration   
    ( Q! J, n2 L# k- @
  12.               PC8     ------> SDMMC1_D0  y0 j0 G$ d; S2 y, }$ d
  13.            PC9     ------> SDMMC1_D1
    / K7 K8 w% ^2 R( a+ F
  14.            PC10    ------> SDMMC1_D2
    " K- B" _' P" I+ f& I7 E
  15.            PC11    ------> SDMMC1_D3
    ' Z! `; x# R9 Y, k! K. n" N. R
  16.            PB8     ------> SDMMC1_D4
    ( w* {6 P9 y4 Z) I" L& z! j9 a
  17.            PB9     ------> SDMMC1_D5
    % M0 ^) N& p: q/ o+ n( O
  18.            PC6     ------> SDMMC1_D6" W" `$ c4 q2 v: {/ d! U& Z$ E
  19.            PC7     ------> SDMMC1_D7
    * c0 ?, u( {! s) i+ ^0 `# N' l7 M
  20.            PC12    ------> SDMMC1_CK: _+ h* s7 x0 l9 S  J# _" m5 z
  21.            PD2     ------> SDMMC1_CMD
    4 D7 r% ], b$ T  M# K* z( u
  22.     */6 T# l- b# L' E6 i( Z. t) U
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8
      x! Y+ L5 K5 M. a7 _; z9 {
  24.                           |GPIO_PIN_9|GPIO_PIN_6|GPIO_PIN_7;
    6 \1 {1 Y# e6 s
  25.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;, \# b* b( o) ?7 i$ y. q
  26.     GPIO_InitStruct.Pull = GPIO_NOPULL;  u# B# x5 K1 B+ v
  27.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    . |. S( g/ c% i' S% d9 n
  28.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;0 r: @: |  j9 F5 w8 m; N8 x  o
  29.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    * |* ^$ y4 d/ Z* [: Z7 A

  30. ' s& V, V1 `$ r4 w/ R
  31.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    1 T; [' h* W$ \5 R6 U3 Q
  32.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;" g3 k2 a3 W- I& a3 ]+ |3 O+ z
  33.     GPIO_InitStruct.Pull = GPIO_NOPULL;" {7 W' V8 C4 q& i3 ^; \. E+ w6 \7 b
  34.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    4 ]6 K3 e' S4 _  k' [2 q( ]
  35.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
    " n6 t, G* w8 O- [. u
  36.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    % {7 ~5 r; e  \  f! M$ A

  37. 7 W; D5 D( t3 s' F# t6 y! @6 d
  38.     GPIO_InitStruct.Pin = GPIO_PIN_2;
    0 Y' Z3 b7 }1 v9 J% Y% L
  39.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;! d/ }6 t, K0 S5 n
  40.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    ' ]% Q3 m" I  m
  41.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
      F# B* D, d* K2 E
  42.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
    3 O0 e' [# P6 ^6 f2 v
  43.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    , G2 g3 H4 s3 n0 P! c
  44. 5 o. r# U9 ?( j: _& a" G
  45.    HAL_NVIC_SetPriority(SDMMC1_IRQn,1,1);  //配置SDMMC1中断
    - m/ W. s7 h; A9 g2 ?
  46.    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);        //使能SDMMC1中断" l3 F, R/ Z8 T# V9 b
  47.    HAL_NVIC_SetPriority(SysTick_IRQn, 0x0E ,0);* ^6 N# P! h; X& N' P
  48.   }, U6 G" P- U& g2 B
  49. }
复制代码

' Z. ?* T; @4 d! @1 x$ @7 A% b! d在DMA模式下,从MMC卡的指定地址读取数据:
3 z# ?( E4 ]4 }2 Q0 A: O7 v8 V& i/ S- o+ x9 O
  1. /**. C3 C( }8 o& A0 [  c! b$ e) P
  2.   * @brief  在DMA模式下,从MMC卡的指定地址读取数据
    2 m& B" e5 M) Z/ u
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针; L5 ^0 I0 S3 R
  4.   * @param  ReadAddr:要读取数据的地址
      `3 D9 h, \2 \% K
  5.   * @param  NumOfBlocks:要读取的MMC块数量- L$ w: d  k3 {4 C0 K, g' u# c
  6.   * @retval eMMC状态+ ~2 x3 n/ l* P- g
  7.   */
    * T. a# k0 z& p4 B
  8. uint8_t BSP_MMC_ReadBlocks_DMA(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    6 L8 v- {# A. b1 n, e
  9. {' `4 {4 j( n# x; S+ W
  10.    HAL_StatusTypeDef Status =  HAL_OK;! D% {* F- ~  `, g

  11. + w# u2 s9 H5 Z- o& U& E
  12.    if(HAL_MMC_ReadBlocks_DMA(&hmmc1, pData, ReadAddr, NumOfBlocks) != HAL_OK)6 S5 Z9 b# D1 g  }6 t3 W
  13.    {
    5 N2 |9 g' m+ C/ g) L: R$ y
  14.       Status = HAL_ERROR;, w" Z& [7 T! e! Z. D' F: k5 t
  15.    } " `' i, ^5 ]) ~, B
  16.    return Status;
    " c- m7 ^! O" g: p) p2 K& b
  17. }
复制代码

0 \! m+ p* \& t在DMA模式下,向MMC卡的指定地址写入数据:
/ x; R8 p! \8 E5 c8 d; N  V; |3 n& H; s+ M+ s( D  S# q
  1. /**
    9 l# R' N0 b2 r+ G+ w. S# ~
  2.   * @brief  在DMA模式下,向MMC卡的指定地址写入数据
    1 F5 F. M" \$ V1 v2 m- h- y, x- \& q- U
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针
    - w- X% E# e) x7 V# U
  4.   * @param  WriteAddr:要写入数据的地址( i# L% k0 s+ @8 ^, H) P0 s3 v! F
  5.   * @param  NumOfBlocks:要写的MMC块的数量4 Q7 S9 q% P% F! w9 |% A
  6.   * @retval MMC状态
    5 O( `/ b1 i# ^8 G6 k$ A, X
  7.   */( {  G8 L: F9 s9 m( }# S9 g1 L
  8. uint8_t BSP_MMC_WriteBlocks_DMA(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
      ^- J0 Q7 y8 D9 E6 M$ t3 {0 V
  9. {
    , o3 D6 \  w! ~1 Q" i' K
  10.   HAL_StatusTypeDef Status =  HAL_OK;3 C* h. i) [, p% @4 I
  11. ; C+ r# g9 v2 I' P, C
  12.   /* Write block(s) in DMA transfer mode */
    , Z6 I' Z% ?  R& B7 l
  13.   if (HAL_MMC_WriteBlocks_DMA(&hmmc1, pData, WriteAddr, NumOfBlocks) != HAL_OK)# |+ b9 R. |6 V: u2 ?* J8 L
  14.   {: L8 J2 D0 c* Y& c) p1 F5 w
  15.     Status = HAL_ERROR;
    5 _- z' f9 o# m& Y; a
  16.   }( h, C  X$ a  p$ ^4 n6 I
  17.   return Status; 1 ~& {8 q! ~2 n+ U
  18. }
复制代码
0 ]. d& Y0 R3 R
擦除eMMC卡数据:
. F( s# [. _: C5 @% i. R; O% ?3 ^" y. x% B7 p
  1. /**! r1 U9 T: y- u8 t4 ]! |9 G7 D
  2.   * @brief  擦除eMMC卡数据+ ]6 l( R& c, R: S, z
  3.   * @param  无
    " A( F1 }6 S( O5 {, `8 }; p
  4.   * @retval 无
    7 S+ w* g! @$ M0 f
  5.   */
    7 D" b% G# s* N# \
  6. void MMC_EraseTest(void)/ E: h; f# x5 J, m3 L0 ~
  7. {) o& Q7 G. _! L/ X# T' C
  8.    HAL_StatusTypeDef Status = HAL_OK;! \9 ^; U4 Z* r" D
  9.    HAL_StatusTypeDef EraseStatus = HAL_OK;4 u( M) z- G! C  H$ Y% [5 Q6 V
  10.    if (Status == HAL_OK)
    + h! E  F1 N) `
  11.    {6 @5 p! j$ w3 W* A0 H% `
  12.       Status = HAL_MMC_Erase(&hmmc1, 0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));2 K7 t9 O6 t& i/ N2 }8 g
  13.       //等待擦除完成
    9 z3 j9 d) M* v6 c4 s' q
  14.       if(Wait_SDCARD_Ready() != HAL_OK)6 W8 Y% e! R/ e0 W# ^
  15.       {
    3 n5 h  N' j9 S
  16.          EraseStatus = HAL_ERROR;  w- D# c2 n  P
  17.       }" A2 f; F; d( ]% G* g' z
  18.    }
    : _$ @+ J$ ^3 p- F% c
  19.    if(EraseStatus != HAL_OK)
    ! c  e, e$ b5 k
  20.    {   
    ! i, J$ B% o  o
  21.       Error_Handler();! f. S- f' q6 {$ U* e# M5 \# e+ i
  22.    }9 g3 W4 x2 X  z2 [
  23. }
复制代码
* J' S" g7 Y0 i. i7 n# _
eMMC卡等待擦除完成函数:
0 D: A/ p3 C! ^9 E) e9 f' y
: Z$ Y. n* r6 Y* `" Y% {
  1. /**& p( h6 l; f: i/ {9 t
  2.   * @brief  eMMC卡等待擦除完成函数# R8 A2 i) L3 d0 O# n: _
  3.   * @param  无
    : @2 Z% P8 {( F, h' s
  4.   * @retval HAL_OK:擦除成功;HAL_ERROR:擦除失败! s6 q! x1 N( }8 n7 I% n; K
  5.   */$ |1 U5 K/ j' Q  x0 R) C. D
  6. static HAL_StatusTypeDef Wait_SDCARD_Ready(void)6 x0 h3 s: Q# D1 _( M
  7. {. Z8 k% X' F9 w5 Z) E5 t
  8.    uint32_t loop = MMC_TIMEOUT;$ z; ?( @6 {  f+ x1 I. [

  9. : H) U) r; u  W; s* @& m+ r5 x. ~& t
  10.    /* Wait for the Erasing process is completed */
    $ D0 T9 b2 u: l% W9 c- W
  11.    /* Verify that SD card is ready to use after the Erase */
    . i6 M' @" ]+ Q5 s
  12.    while(loop > 0)& `* q+ A* c4 ?8 v0 o. h7 a
  13.    {: M& N3 z+ X2 S- e9 d
  14.       loop--;$ q5 |: D5 |2 b; }8 d3 D/ ?
  15.       if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)
    ; A( _; U& R( T- }1 y& f
  16.       {; y# U2 L2 q% y! g. \7 z  F
  17.          return HAL_OK;
    & |) W+ J. j" Z
  18.       }
    + d& B' \" S" w1 s: S- Q- o
  19.    }
    ! Y0 }# k+ X1 d) A
  20.    return HAL_ERROR;
    2 Q, m' e1 w- k2 U
  21. }
复制代码

2 P2 L" m0 C' |: m9 z/ i5 a8 q" h最近移植的eMMC卡的驱动程序,分享出来希望对各位开发者有所帮助。还移植了FATFS文件系统到eMMC驱动程序中,之后整理好再分享。: s% d" f0 s8 r  `+ u. H

; k$ I& {8 {$ |8 x, M' Y
/ Z9 M: S. x  S3 ~" g$ h  Z
收藏 评论0 发布时间:2021-12-29 23:50

举报

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