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

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

[复制链接]
STMCU小助手 发布时间:2021-12-29 23:50
STM32驱动eMMC读写数据5 v9 J" A2 @9 U. t$ {7 i4 r; V3 ^
参照 JEDEC eMMC标准:JESD84-B51 (Revision of JESD84-B50.1, July 2014)
! t; [, c- n" k& w5 J, k驱动芯片采用stm32h7xx芯片。通过官方HAL库中stm32h7xx_hal_mmc.h文件驱动,采用8bit数据传输模式,与SD卡驱动类似。实测写入速度6-10MB/s左右。
% z: \) Y, k% g/ X& `3 E
( c9 Y5 A  _, A% s1 c  q初始化代码清单:/ J9 A7 ^. {  {8 {! A# h

; D0 M5 u2 N, X0 B/ A  \
  1. HAL_StatusTypeDef SDMMC1_MMC_Init(void)
    ) c8 y/ q& C& z) t* d8 g
  2. {
      P, g$ P9 ]3 U! X* j: ?) y
  3.   hmmc1.Instance = SDMMC1;8 K# S6 h- F! t4 o! b% [
  4.   hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
    2 n9 l8 Z* j& {, J' l2 r
  5.   hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;; w; J5 ?. i3 X- f" c% ^* K
  6.   hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;2 Y, I3 T! o6 _( J1 B: s, `
  7.   hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
    6 M8 y, P  ]! x$ F1 f7 L0 P6 W* Q
  8.   hmmc1.Init.ClockDiv = 1;* ~1 ~: ]2 x  s. [* U3 X
  9.   if (HAL_MMC_Init(&hmmc1) != HAL_OK)
      N6 m3 u. s6 M$ O. x
  10.   {
    . q7 @0 p( F& @& G6 d1 h
  11.       Error_Handler();
    3 P1 B+ T0 |$ G5 [8 k4 A
  12.   }
    4 j* `5 b) u8 N' `" x! m2 D8 L
  13.   return HAL_OK;
    1 o: x! {. B& g) h9 s9 y
  14. }
复制代码
1 J9 g4 f: H1 b. ^, `/ ?! Z
底层驱动代码清单:+ {% h3 }" _) T9 D4 [

& h5 ^! P+ v1 ^! y& |
  1. void HAL_MMC_MspInit(MMC_HandleTypeDef* hmmc)! S* o2 m4 p, `, |2 E$ F
  2. {
    " V# b' k; C  m5 z% k$ B! t
  3.   GPIO_InitTypeDef GPIO_InitStruct = {0};% y) b6 `- y0 A6 B0 t1 H4 {( J
  4.   if(hmmc->Instance==SDMMC1)
    . d; `' K% M2 \, C$ [4 a+ E
  5.   {7 P/ H/ ~6 Y# ^" V2 \1 D
  6.   /* USER CODE BEGIN SDMMC1_MspInit 0 */- |' q1 w4 S! P$ Q
  7.     /* Peripheral clock enable */( b% X/ X& y. Z5 k- G3 W
  8.     __HAL_RCC_SDMMC1_CLK_ENABLE();
    " H4 B6 Y' T) n- w9 m, m$ W
  9.     __HAL_RCC_GPIOC_CLK_ENABLE();
    : q; K+ G( D, E/ X
  10.     __HAL_RCC_GPIOD_CLK_ENABLE();
    5 N- q$ k# @5 c; \2 `
  11.     /**SDMMC1 GPIO Configuration    8 Y. u4 h7 Q( E( K. W; a% C
  12.               PC8     ------> SDMMC1_D0/ T6 E& _2 f  p0 [" K5 j! f4 [
  13.            PC9     ------> SDMMC1_D1
    1 n8 Y) d: t7 _& C
  14.            PC10    ------> SDMMC1_D2
    2 a- a0 R' w, t5 S* ?& b
  15.            PC11    ------> SDMMC1_D38 z* G" W  H% R  ^* c
  16.            PB8     ------> SDMMC1_D4
    , S, H8 @7 L! q. ?( d5 k/ M
  17.            PB9     ------> SDMMC1_D5
    4 j! V6 A/ v! o; p9 {
  18.            PC6     ------> SDMMC1_D61 P$ ?' P/ i4 x5 k  w- G( Q7 y- S
  19.            PC7     ------> SDMMC1_D7
    : U) w' t& W5 u# s
  20.            PC12    ------> SDMMC1_CK
    3 J' W" _$ P* b. Z/ }( w
  21.            PD2     ------> SDMMC1_CMD2 `8 L4 J* ?1 ]" [
  22.     */
    ; u4 V1 S+ R& b* [2 |& R: d* u4 q
  23.     GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_8
    ! Z4 K/ F1 J7 v9 b
  24.                           |GPIO_PIN_9|GPIO_PIN_6|GPIO_PIN_7;
    ) W: ^& D! R- V  j5 u' i# \/ v7 \
  25.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;  d  s6 p+ M) M. d6 K- x  {" n( h
  26.     GPIO_InitStruct.Pull = GPIO_NOPULL;8 ]. I, z' q; w
  27.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;# K1 l; h% S1 f
  28.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;
    * n' G+ p2 L: \- i5 N; X
  29.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);: \* E! X, y1 T% f1 C) H

  30. ; m) p. I! {8 r
  31.     GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    , l7 Y0 y' ?' x* |3 G4 `
  32.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;! Y. }; a- ^0 F- r' R9 w
  33.     GPIO_InitStruct.Pull = GPIO_NOPULL;
    , m# x5 l1 G8 i& F, p
  34.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    8 B; w: q; G2 w* H2 l; M- @8 \+ V) E
  35.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;$ o% n6 ?# w( G' r- R
  36.     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    5 _& b8 r" t, ^6 i2 A* N" _

  37. 4 K1 Y2 O9 v5 d# p$ v" J0 O
  38.     GPIO_InitStruct.Pin = GPIO_PIN_2;9 O+ C% c2 r8 Q- b
  39.     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;6 X# k0 V" i; n
  40.     GPIO_InitStruct.Pull = GPIO_NOPULL;) k% X- G5 v; O' ~0 g! v+ R/ n
  41.     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    ' t2 \& L, ?9 e, `
  42.     GPIO_InitStruct.Alternate = GPIO_AF12_SDIO1;' r; O! v6 A8 E8 V6 y& n$ _3 x! e
  43.     HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    0 ~1 g# H* D* H  ?$ ?
  44. 9 @& `9 u0 Y  b9 \- H* L
  45.    HAL_NVIC_SetPriority(SDMMC1_IRQn,1,1);  //配置SDMMC1中断; X! @1 q& A" @' x* S* U. u$ G7 F+ M" w
  46.    HAL_NVIC_EnableIRQ(SDMMC1_IRQn);        //使能SDMMC1中断, Y; e7 D! \2 ]3 o* x" y5 P
  47.    HAL_NVIC_SetPriority(SysTick_IRQn, 0x0E ,0);8 u7 s% p8 i$ j& I
  48.   }4 M; l+ A! E. p- A
  49. }
复制代码

/ b& {- d0 P9 r' Z/ D7 R在DMA模式下,从MMC卡的指定地址读取数据:) c  a7 h6 `# j  r' C4 I. Y+ o! `8 s
1 c; e1 d2 R/ G& n! B+ G8 b( V5 O( I
  1. /**# L5 A# c& V5 [- q0 s# N: N
  2.   * @brief  在DMA模式下,从MMC卡的指定地址读取数据
    6 F+ c& R7 P, X
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针
    2 H( D6 {8 G1 K5 d
  4.   * @param  ReadAddr:要读取数据的地址
    ' l& G3 [2 k' M
  5.   * @param  NumOfBlocks:要读取的MMC块数量
    4 b2 E; Z. P7 n
  6.   * @retval eMMC状态1 ?& E" W0 c; N" ]6 h2 @' i
  7.   */
    # z6 D7 b6 k. k
  8. uint8_t BSP_MMC_ReadBlocks_DMA(uint8_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks)
    4 x3 H9 C0 b+ t7 }$ w/ s
  9. {
    % [( V' ?$ f; c+ r
  10.    HAL_StatusTypeDef Status =  HAL_OK;3 W  j2 w; j# T

  11. / U+ Q5 P3 H1 z/ b# v
  12.    if(HAL_MMC_ReadBlocks_DMA(&hmmc1, pData, ReadAddr, NumOfBlocks) != HAL_OK)
    8 z+ X" s  B, l0 k$ C  v( o
  13.    {
    - \* w, d4 Q7 N' D2 j4 U4 x
  14.       Status = HAL_ERROR;
    0 `1 t% f% z- t- W/ `
  15.    } 2 ?7 q; X/ P5 m" Z
  16.    return Status;
    5 F0 a% G+ a5 m1 S6 P1 j
  17. }
复制代码
5 a  ~) n, U6 {, R1 m  J; |
在DMA模式下,向MMC卡的指定地址写入数据:3 r. e5 b" g- Z4 ]( k1 x$ H
; J( K3 \3 l! x( H# z$ [
  1. /**/ A, \- O7 I1 d; z% L
  2.   * @brief  在DMA模式下,向MMC卡的指定地址写入数据) {) i* H5 S# e0 X. s, Y! N' `2 t
  3.   * @param  pData:指向将包含要传输的数据的缓冲区的指针
    ( {' |( X8 T" E% K0 H
  4.   * @param  WriteAddr:要写入数据的地址: B$ U! r) V- q( @  k
  5.   * @param  NumOfBlocks:要写的MMC块的数量7 \% G" W  y/ a' K
  6.   * @retval MMC状态: }$ C6 c6 Q- m
  7.   */# C9 I9 w1 l) |, T& t7 S0 y
  8. uint8_t BSP_MMC_WriteBlocks_DMA(uint8_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)( [8 ?- p2 A# v7 F4 W* \* ^. l" `% u5 T
  9. {1 d$ p. `! q$ b5 h
  10.   HAL_StatusTypeDef Status =  HAL_OK;1 X7 m' L9 W1 a) ~4 F) e. D

  11. " j" z& x9 b; W! z6 \% B" D6 {
  12.   /* Write block(s) in DMA transfer mode */; j3 x3 s" v# x  C) i3 @
  13.   if (HAL_MMC_WriteBlocks_DMA(&hmmc1, pData, WriteAddr, NumOfBlocks) != HAL_OK)
    + {/ N* t% B1 n! @9 i
  14.   {5 n4 N5 Z+ N* b
  15.     Status = HAL_ERROR;/ E( \- f% o. Z1 p; g' Z7 S
  16.   }; x6 z/ a3 ~# }3 u  Z! F
  17.   return Status; ) n3 _4 l6 l4 i+ K( S
  18. }
复制代码

) O6 l. y. _5 _擦除eMMC卡数据:8 ^7 l5 B* L) L" p; r! w0 \9 }
" R) P& j/ K9 |( [7 g" H. n
  1. /**8 F; T" M( p* a+ h6 M# |& b
  2.   * @brief  擦除eMMC卡数据
    ( `4 y- B+ n  Y$ z8 @. E: b
  3.   * @param  无0 j0 t1 L# N' g
  4.   * @retval 无- `; M' `; D) B. }7 l' V
  5.   */
    8 p/ O1 x7 p0 k, m6 O0 o
  6. void MMC_EraseTest(void)
    5 p8 H/ B' o4 y# M) h: a7 C/ X3 a3 R
  7. {. D0 q3 c6 y7 u- ]  ^' f
  8.    HAL_StatusTypeDef Status = HAL_OK;
    1 b2 Y  h1 Q) t
  9.    HAL_StatusTypeDef EraseStatus = HAL_OK;, Y1 a# x; i. L) R9 [2 p$ {0 X
  10.    if (Status == HAL_OK)  {" s& i9 r2 G( I. Z
  11.    {
    # D* T4 Q/ q: \3 o
  12.       Status = HAL_MMC_Erase(&hmmc1, 0x00, (BLOCK_SIZE * NUMBER_OF_BLOCKS));
    7 j; y# |- c+ Q4 {6 t
  13.       //等待擦除完成
    % W, C! ?& K& }4 |8 o' Z
  14.       if(Wait_SDCARD_Ready() != HAL_OK)8 s1 ?; }& Q$ x2 F/ B& d0 X" C# v( V+ s
  15.       {
    : D. b6 U# u: E
  16.          EraseStatus = HAL_ERROR;
    8 G9 T# b  E/ U' Y
  17.       }
    1 m" q- Q, B, l5 p5 Y# R$ Z+ T
  18.    }
    & U+ H1 R, v3 V/ e4 }
  19.    if(EraseStatus != HAL_OK)
    # p3 p; C0 q% X
  20.    {   
    $ c9 B5 {  f9 o: V, Q
  21.       Error_Handler();
    + d# m( f0 g  G! p3 p" e, d/ L
  22.    }+ s1 R& Y5 I7 r
  23. }
复制代码

1 H0 ]& n' K0 F5 H( Z; NeMMC卡等待擦除完成函数:/ M, \, _# c3 V. G% I

  L$ n+ e+ ~0 }# Q
  1. /**
    / n  M+ @3 N* Y2 K
  2.   * @brief  eMMC卡等待擦除完成函数5 ^, T( f: b) |4 R
  3.   * @param  无
    5 z" P, s1 p$ H' v) s
  4.   * @retval HAL_OK:擦除成功;HAL_ERROR:擦除失败
      G8 r2 M0 N1 v/ N3 U
  5.   */
    , w6 F: e! L- `! r
  6. static HAL_StatusTypeDef Wait_SDCARD_Ready(void)
      O/ |- ~/ A: o4 |
  7. {
    7 U5 @. G% E6 E; @. i7 J
  8.    uint32_t loop = MMC_TIMEOUT;5 h! M8 m9 r3 e
  9. 1 z8 G' P/ Q% m: L9 k
  10.    /* Wait for the Erasing process is completed */$ x9 V0 L$ h; d
  11.    /* Verify that SD card is ready to use after the Erase */
    ! ^: u6 X$ _, Z! x
  12.    while(loop > 0)+ Z, o$ |: b- i9 y. M9 g, r
  13.    {
    ) v3 H- W2 [: H) G
  14.       loop--;$ \0 ~  k+ I: I, N' P, S
  15.       if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)8 M& t2 ?( z/ H
  16.       {
    " z# Y7 \; r: Z( j8 w2 u0 n
  17.          return HAL_OK;$ W* ]8 k# ~5 W2 M
  18.       }% I7 _2 e* |" f  P5 e
  19.    }1 r- w) U* \. a' M3 O
  20.    return HAL_ERROR;3 a* Z6 W5 A# U0 Z
  21. }
复制代码
0 I6 w: ^5 {# f0 ?+ p7 W
最近移植的eMMC卡的驱动程序,分享出来希望对各位开发者有所帮助。还移植了FATFS文件系统到eMMC驱动程序中,之后整理好再分享。
  h- I( }2 T: x+ ?+ r# N5 p7 G5 ^% M& x% t# `! l

/ A* `- F- K8 G1 [
赞 收藏 评论0 发布时间:2021-12-29 23:50

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版