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

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

[复制链接]
STMCU小助手 发布时间:2021-12-29 23:50
STM32驱动eMMC读写数据& j0 A/ V; \7 S' B) _- w
参照 JEDEC eMMC标准:JESD84-B51 (Revision of JESD84-B50.1, July 2014)
9 O2 F! [6 y6 H1 l! j/ M: \8 Z. d6 e驱动芯片采用stm32h7xx芯片。通过官方HAL库中stm32h7xx_hal_mmc.h文件驱动,采用8bit数据传输模式,与SD卡驱动类似。实测写入速度6-10MB/s左右。
$ g% q- o' j8 T' D/ R5 \7 i6 f5 @
9 O- W6 w/ r0 O# K+ a" N3 U初始化代码清单:
& k. L# c$ o; h/ {: Z
1 b6 R4 k1 E" G" p# H$ v" t9 h
  1. HAL_StatusTypeDef SDMMC1_MMC_Init(void)  B, T+ A  o; p. P% m
  2. {
    + z+ `# Y  @. r% p3 i8 }2 A
  3.   hmmc1.Instance = SDMMC1;
    , }3 t; I1 }3 X. o" C3 m
  4.   hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;4 n1 s' _6 V) V0 _; v
  5.   hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;, D7 O' Y/ X# _2 I; W6 h+ d
  6.   hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;( Q( ]) Y7 f$ ]/ u/ z9 u' a3 ^
  7.   hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;6 g1 l4 L. D4 F; `5 U, Q5 }3 {
  8.   hmmc1.Init.ClockDiv = 1;5 q, o$ l0 e0 x* a1 x7 z: [$ w
  9.   if (HAL_MMC_Init(&hmmc1) != HAL_OK)
    9 M. L! Y4 j3 w4 P
  10.   {( j- [  |$ l  {: H$ x
  11.       Error_Handler();. I) g; x1 M" A! A6 I, y& h+ k
  12.   }" T1 z$ b8 V7 S1 ~; H
  13.   return HAL_OK;
    * D9 Y- q8 H5 h
  14. }
复制代码
$ G! Y, Y" Z  `* b9 ~. b( ~
底层驱动代码清单:
* m) C" _2 o6 g5 W/ T/ ]
9 w9 m; t! w% a9 O1 Y" D
  1. void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc)" l% K# s0 ?2 P# h+ K: B4 }; s+ S
  2. {$ y7 a4 Q3 O1 S; h
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};
    5 z5 p7 n4 I4 w  h2 E
  4.   if(hmmc->Instance==SDMMC1)& Q: n1 P! ]7 I2 C& Z+ h+ ^7 U: S
  5.   {
    " f2 P) M5 ^7 _( j
  6.   /* USER CODE BEGIN SDMMC1_MspInit 0 */
    + v. Z2 Z: X( ]3 H. h  W
  7.     /* Peripheral clock enable */! H( P8 E3 c0 Z& I8 n
  8.     __HAL_RCC_SDMMC1_CLK_ENABLE();
    # W% n6 i8 H4 x  G7 g: O& A
  9.     __HAL_RCC_GPIOC_CLK_ENABLE();
    7 o8 f; c8 }; F5 h6 e, h
  10.     __HAL_RCC_GPIOD_CLK_ENABLE();8 w+ O3 Y4 K2 W% r0 ]1 D
  11.     /**SDMMC1 GPIO Configuration   
    ! F0 c; H" k8 r1 A# t1 T
  12.               PC8     ------> SDMMC1_D0/ a! L6 [$ k, N" |
  13.            PC9     ------> SDMMC1_D1 : P2 @# G4 q* V( Q4 {
  14.            PC10    ------> SDMMC1_D2
    * ~" _3 Z4 d- g0 A; U  x  _7 m" \& L
  15.            PC11    ------> SDMMC1_D3
    0 N/ A/ v! n) S! P3 N% P, {2 _# W
  16.            PB8     ------> SDMMC1_D4  A! t6 t, y9 k" D( O2 [: N
  17.            PB9     ------> SDMMC1_D5# [# ]( K' [5 o* D2 t
  18.            PC6     ------> SDMMC1_D69 D) x. j* n5 q' ]" m7 w9 k9 P, m
  19.            PC7     ------> SDMMC1_D7
    0 N2 y+ d' I" Y  Z5 c
  20.            PC12    ------> SDMMC1_CK
    3 z0 Z+ ?2 F7 n4 ~7 N+ |. C
  21.            PD2     ------> SDMMC1_CMD& h# ~$ S( o; c( s' p8 m: Q
  22.     */3 Y, G# Q9 A5 ?- `
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8
    4 Q. h. [' Y- z9 P6 I+ X8 o
  24.                           |GPIO_PIN_9|GPIO_PIN_6|GPIO_PIN_7;
      V3 y4 ^1 n9 F
  25.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;! y0 H: T2 x4 j" i6 D& a
  26.     GPIO_InitStruct.Pull = GPIO_NOPULL;% Y; Y& b5 _. \; v; i8 c/ B  r
  27.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;$ C* @8 p/ M: N$ U' N
  28.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
    1 T" t+ D8 B* d3 N/ E; g" Q
  29.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    8 P& Q- r) U) r- ~6 V5 A: q
  30. " F" V: V: V1 B* M6 b" Y  d
  31.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    % K, v7 ~  e0 l
  32.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    1 Z2 u7 ?  `6 C  ]
  33.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    * ^. U2 }; ]# s' k4 t# u1 n) |
  34.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    % f; w' n* T9 E$ \2 D1 g0 c
  35.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;0 O) ~6 `+ j( w  S* |' p
  36.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    ( u6 W7 x5 M* j0 j* V0 F& v

  37. . ?- F4 H. p" I- _6 O; z9 k) E
  38.     GPIO_InitStruct.Pin = GPIO_PIN_2;
    ; p: [' Q1 [( z
  39.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    7 @4 V+ q9 @! K8 D8 x
  40.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    ; M  `8 u9 A  y' ~8 @8 g$ z7 j
  41.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    # k7 z# C. h' \% `( \2 v4 L
  42.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;. P5 _# c9 g+ o
  43.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);" i; |/ j3 U% q+ d! [

  44. ) K) @6 H2 o3 ~4 W! u1 C8 |, ^8 A
  45.    HAL_NVIC_SetPriority(SDMMC1_IRQn,1,1);  //配置SDMMC1中断
    3 e5 e8 h, X7 R# {9 x" }
  46.    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);        //使能SDMMC1中断
    3 c& R" p4 g9 r: V, U
  47.    HAL_NVIC_SetPriority(SysTick_IRQn, 0x0E ,0);8 @0 l6 o6 `! e  |
  48.   }
    ' [4 R3 K. O8 X+ z# L
  49. }
复制代码

2 M* h& v0 _  C# f在DMA模式下,从MMC卡的指定地址读取数据:
2 f$ {# g" ]1 G/ K  w
6 z+ H" u8 |4 i& ^0 z( `
  1. /**
    : x2 u; ?# y+ z  w) y
  2.   * @brief  在DMA模式下,从MMC卡的指定地址读取数据( ~; j9 U( I9 k; [3 X
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针
    ( M+ K, c( y: S1 {' M% q  V
  4.   * @param  ReadAddr:要读取数据的地址$ ?9 w4 n8 C* P+ D# h& ?" B
  5.   * @param  NumOfBlocks:要读取的MMC块数量
    # _7 i$ `# Z8 b" t! f* c" W
  6.   * @retval eMMC状态
    ! _' u, ~) V2 B% W
  7.   */
    2 B) u) g# a1 ?) B/ O$ A# X, K
  8. uint8_t BSP_MMC_ReadBlocks_DMA(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    ; I$ t, b* Y  g9 Z7 _" o
  9. {
      w2 b7 s/ t  r* J  g
  10.    HAL_StatusTypeDef Status =  HAL_OK;
    % u  ]6 j# |% C) W3 Y

  11. 4 h- \- x1 Z! a* s$ V# M+ S% M
  12.    if(HAL_MMC_ReadBlocks_DMA(&hmmc1, pData, ReadAddr, NumOfBlocks) != HAL_OK); G8 B9 `1 H( K: I5 g, E: o
  13.    {  G4 {2 ^/ |7 f+ |5 ~+ y
  14.       Status = HAL_ERROR;* |& |: {0 H' M6 S$ `4 Y4 O
  15.    }
    6 ?% [% S9 m4 k4 f+ O1 G/ y9 u
  16.    return Status;
    # T0 ^& D9 Y$ `$ f0 ?
  17. }
复制代码

& @6 B; U5 `% i: ^在DMA模式下,向MMC卡的指定地址写入数据:
9 G, @# X5 C; V
; e! s/ V6 S/ s% q& J# _5 H
  1. /**
    3 \+ w. l1 \9 [! N: ]
  2.   * @brief  在DMA模式下,向MMC卡的指定地址写入数据2 W  O  o9 y& D
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针
    ) l7 Z2 t+ n3 X+ D) q7 \( t
  4.   * @param  WriteAddr:要写入数据的地址3 H# R8 I8 K# j; y% a: A
  5.   * @param  NumOfBlocks:要写的MMC块的数量
    6 C  z* L. }$ I- r4 M8 P( G
  6.   * @retval MMC状态2 i- i. a, U3 A
  7.   */
    7 }0 ]5 D4 y0 F5 K# Z9 o) S
  8. uint8_t BSP_MMC_WriteBlocks_DMA(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    4 [4 o( w6 ?# x7 p+ E' S
  9. {
    # \" k  p7 ]+ e7 m6 C+ O
  10.   HAL_StatusTypeDef Status =  HAL_OK;- \! ^  Y# O; E3 _" s
  11. . t- S' Q, R" R7 C! x/ Y% S
  12.   /* Write block(s) in DMA transfer mode */% M6 s, ]1 M% x- B
  13.   if (HAL_MMC_WriteBlocks_DMA(&hmmc1, pData, WriteAddr, NumOfBlocks) != HAL_OK)* e4 D* T+ e1 g
  14.   {
    0 K9 ~4 X5 a. F& y4 H$ F. ^
  15.     Status = HAL_ERROR;
    : J' ]. T5 V9 U- H, r% E! m6 B
  16.   }" U1 F- {; V) T% d1 ~
  17.   return Status;
    ( K# J! k; y) }  O
  18. }
复制代码
% D* l$ m' o4 a8 z0 L7 C+ ^
擦除eMMC卡数据:
" P% w' t6 F9 |/ b8 D
8 t8 Y% U& ?9 o4 h9 c* X' }
  1. /**
    / L4 j+ x& K- ^/ H8 F; `
  2.   * @brief  擦除eMMC卡数据
    / C' w7 S) e; b* g: S# q3 J5 j
  3.   * @param  无! d1 w0 q1 D* O
  4.   * @retval 无
    3 X; _& }! T- L8 J1 L  c+ M
  5.   */
    ( N/ a5 ]( Z9 H& o* k3 {  M
  6. void MMC_EraseTest(void)
    / e$ U/ f- i$ e3 H" p, B$ B* h2 r
  7. {
    ' x0 V; l/ F" @# y& u$ I
  8.    HAL_StatusTypeDef Status = HAL_OK;' E+ J- O2 B9 c7 |, M% F2 t7 n
  9.    HAL_StatusTypeDef EraseStatus = HAL_OK;
    4 K& H: V% v) ]8 U8 Z. R0 J
  10.    if (Status == HAL_OK)
    + J; C! ]& O% j" G- C& f8 d( l
  11.    {& n0 r, Q0 J( H1 [
  12.       Status = HAL_MMC_Erase(&hmmc1, 0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));- C' H, V  v% K# g7 A( j+ z
  13.       //等待擦除完成5 Z0 ^1 z  d/ |4 K* c
  14.       if(Wait_SDCARD_Ready() != HAL_OK)
      w" }( a5 ?, X! @7 E; ]  E: Z
  15.       {# k* i/ K9 Q* `- ]1 K: w- Y9 `& {: k
  16.          EraseStatus = HAL_ERROR;
    1 J) X1 Q$ j9 \3 {$ A
  17.       }6 m: T+ m4 {$ u! g
  18.    }
    * J  l5 ~# a3 F' R' |' U& @
  19.    if(EraseStatus != HAL_OK)
    * U8 }) j, S% o" d+ a6 D" V% g9 i
  20.    {    * V! u( g; ^0 t' X3 o
  21.       Error_Handler();
    " n- B7 C3 b6 y0 r; i% x. V0 W
  22.    }- |9 f$ t6 B1 s2 p1 I1 T4 o* s
  23. }
复制代码
; I9 [! D- v' p/ L$ U
eMMC卡等待擦除完成函数:
& Y) ]! H3 ~% r6 k( L' ?' B( T1 x1 _6 ]8 Z, I
  1. /**: f1 ~5 t% `% ^2 e( x1 ]7 h% m
  2.   * @brief  eMMC卡等待擦除完成函数8 Q/ m, z$ G, R/ l7 j
  3.   * @param  无1 Q5 F/ d$ ?, |
  4.   * @retval HAL_OK:擦除成功;HAL_ERROR:擦除失败# k& {& M6 h- m3 y, k' Q* W
  5.   */) l7 |8 ^/ I: B& x' T4 a
  6. static HAL_StatusTypeDef Wait_SDCARD_Ready(void)
    * F' N. p4 L/ r- y, h# I
  7. {
    % J/ e% `# D5 U  I. L' a
  8.    uint32_t loop = MMC_TIMEOUT;) d$ D7 b' c. }, _$ {

  9. : P" N" i& z+ k: W7 k. h5 E
  10.    /* Wait for the Erasing process is completed */5 s% W! A* |* I1 h
  11.    /* Verify that SD card is ready to use after the Erase */
    * }' q% m7 t8 t8 n/ C/ s( V
  12.    while(loop > 0)" S+ u! l8 j  Y( g0 m1 v
  13.    {4 K/ r3 S+ t4 b+ m" }! R/ X; R
  14.       loop--;2 [% n& \4 z# _; B: i# @
  15.       if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)/ i' h/ _4 q5 ^$ M1 y0 N) _
  16.       {
    # h4 M: t2 h$ U$ ^: f
  17.          return HAL_OK;
    . Y0 [9 @0 C4 n2 r
  18.       }8 F, U! \0 a! c: o# l1 G9 N
  19.    }
    / A4 {7 ^$ ]9 u! u/ @
  20.    return HAL_ERROR;
    , z% k; W" p, _9 {; F: v+ t# Z' a
  21. }
复制代码

1 J* T6 n6 A- n% b' y7 x最近移植的eMMC卡的驱动程序,分享出来希望对各位开发者有所帮助。还移植了FATFS文件系统到eMMC驱动程序中,之后整理好再分享。; {# q7 l& h4 D
' K( t( z; F/ y9 V2 i3 ?
, |, Z" X" O: ?4 I
收藏 评论0 发布时间:2021-12-29 23:50

举报

0个回答

所属标签

相似分享

官网相关资源

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