Rockchip RK3399 - MMC&SD&SDIO基础
----------------------------------------------------------------------------------------------------------------------------
开发板 :NanoPC-T4开发板
eMMC :16GB
LPDDR3 :4GB
显示屏 :15.6英寸HDMI接口显示屏
u-boot :2023.04
linux :6.3
----------------------------------------------------------------------------------------------------------------------------
MMC是MultiMedia Card的简称,从本质上看,它是一种用于固态非易失性存储的内存卡规范,定义了诸如卡的形态、尺寸、容量、电气信号、和主机之间的通信协议等方方面面的内容。
从1997年MMC规范发布至今,基于不同的考量(物理尺寸、电压范围、管脚数量、最大容量、数据位宽、clock频率、安全特性、是否支持SPI mode、是否支持DDR mode等等),进化出了MMC、SD、micro SD、SDIO、eMMC等不同的规范;
需要注意的是:这张图只供参考,2012年之后的规范并没有绘制。
SD卡基于MMC发展而来,二者最初的外观尺寸也很类似,SD卡比MMC卡厚0.7mm。
早期SD卡对MMC卡的兼容性较强,多数支持SD卡插槽的设备都可以同时支持MMC卡,反之只有MMC卡插槽的设备不能够支持SD卡。
随着MMC卡和 SD卡的发展竞争,二者之间的差异越来越大,走向了截然不同的发展方向。
发展到今天, MMC卡基本退出了历史舞台,转而走向了嵌入式领域,推出了eMMC(embedded MMC) 标准,在嵌入式存储方面应用广泛。
SD卡在移动存储卡领域的地位越发稳固,不断向大容量和高速度方向发展,推出了一系列接口标准,目前最新的理论传输速率已达 985MB/s。
从二者目前的发展趋势看,eMMC正在被更先进的UFS技术标准取代,SD的发展前景似乎更为广阔。
一、MMC发展历史
MMC卡的全称是MultiMedia Card,中文翻译为“多媒体卡”。
MMC卡的设计目标是提供一种“广泛应用于电子玩具、pda、照相机、智能手机、数字录音机、MP3播放器、寻呼机等等领域”的通用低成本数据存储和通信媒体。
1.1 MMC 1.x/2.x版本阶段
从目前可检索到的MMC技术文档来看,MMC初始1.0版本的Spec在1996年就已经制定完成,1997年推出相关产品。
从1.0到2.0版本的发展阶段在1996-2000年,该阶段MMC卡的形态及技术规格没有大的变化,主要是一些内部功能性的演进。
这个阶段MMC卡的主要特性:
Size:24mm x 32mm x 1.4mm;Pins:7pins;Bus Width:1bit;Bus Mode:MMC mode&SPI mode;Voltage:2.7 - 3.6V;Clock:0 – 20MHz;
1.2 MMC v3.x版本阶段
v3.0版本是MMC发展历史上一个重要的版本,该版本相对于1.0/2.0版本有重大变化。
但是由于v3.0版本在内部寄存器定义中有严重错误,v3.0版本很快被更新为v3.1,并且v3.0版本被废弃。
v3.1版本新增了两个重要特性:
- 引入
Low Voltage规格,支持1.65 - 1.95V工作电压; - 增加
multiple block read/write特性,提升Performance;
v3.3版本也是一个重要的版本,该版本新增RS-MMC(Reduced Size MMC)规格,制定24mm x 18mm x 1.4mm尺寸规格,将MMC 卡的大小减少近一半。
RS-MMC只是物理尺寸的定义,硬件接口没有变化。
1.3 MMC v4.x版本阶段
v4.x系列版本从2004年开始发布,v4.x是MMC最为流行的版本,也是目前为止持续时间最长的版本,从2004年v4.1发布到2013 v5.0 发布共持续了9年。
其间,JEDEC (Joint Electron Device Engineering Council电子元件工业联合会)采用MMC4.1标准作为JEDEC的闪存卡标准;
随后MMCA(Multi Media Card Association快闪记忆卡标准组织)正式并入 JEDEC,MMC标准由JEDEC主导推进。
目前,从JEDEC官方站点可以下载到的MMC最早版本为v4.1,其直接继承自MMCA的MMC v4.1版本。
1.3.1 MMC v4.1版本
鉴于之前版本的MMC卡性能较差,v4.1版本增加了以下重要的特性以提升性能并做到向后兼容:
- 工作频率支持三种模式:
0-20MHz、0-26MHz、0-52MHz; Bus Width支持三种模式:1/4/8bits;- 定义了最低
Performance标准:2.4MB/s; - 向后兼容
v3.x版本MMC(1 bit data bus,multicard systems); MMC mode只支持one card per MMC bus;SPI mode支持MMC Chip Select Signal,可实现multiple cards per MMC bus;- 提升
MMC卡的存储容量;
符合v4.1版本规格的MMC卡称为HS MMC(High Speed MMC),由于bus width变化,所以HS MMC卡的接口增加了6pins,变成 13pins。
v4.1版本对市场上的MMC产品进行了明确的划分,定义了两种MMC卡类型:MMC plus和MMC mobile,只有符合相应规格的卡片才能使用 MMC plus或MMC mobile logo。
MMC plus 和 MMC mobile应用于不同的使用场景,均向后兼容v3.x 20MHz clock的工作模式.
(1 )MMC plus规格:
size:24mm x 32mm x 1.4mm,全尺寸;Voltage:2.7 - 3.6V;Pins:13pins;bus width:1/4/8bits;Bus Mode:MMC mode&SPI mode;Clock:26MHz(52MHz可选);Performance:不低于2.4MB/s;
(2) MMC mobile规格:
size:24mm x 18mm x 1.4mm,符合RS-MMC标准;Voltage:2.7 - 3.6V/1.65 - 1.95V,支持Low Voltage模式;Pins:13pins;bus width:1/4/8bits;Bus Mode:MMC mode & SPI mode;Clock:26MHz(52MHz可选);Performance:不低于2.4MB/s;
(3) MMC mirco规格:
Samsung于2004年底发布了一款MMC mirco卡,该卡不同于MMC Spec中定义的MMC plus和MMC mobile规格,其尺寸降低至:12mm x 14mm x 1.1mm,大概为RS-MMC的1/3。
MMC micro 是Samsung发布的第三方规格,初期并没有收录到MMC标准中,依靠Samsung自身的影响力及其轻巧的尺寸占有一定的市场地位。
随后,MMCA协会也正式发布了MMCmicro的技术规范。在2005年6月底于瑞士苏黎世举行的MMCA夏季大会上,MMCA全体参会成员一致同意将MMC micro卡确立为MMCA新一代标准。
继2004年底MMCA发布MMC plus卡和MMC mobile卡之后,全新的微小尺寸的MMC micro卡可谓是MMC技术的新一代标准。
1.3.2 MMC v4.2版本
v4.1版本定义的寻址方式为Byte寻址,理论上可以支持最大容量为4GB。
v4.2版本增加了sector寻址模式,每个sector为512Byte,小于2GB容量的卡采用Byte寻址模式,大于2GB容量的卡采用sector 寻址模式。
同时v4.2版本将Low Voltage工作电压范围修改为1.7 - 1.95V。
1.3.3 MMC v4.3版本
v4.3版本也是MMC发展史上一个具有里程碑式意义的版本,该版本引入了eMMC规格定义,支持eMMC boot启动功能,进入嵌入式领域。
重新定义了CID寄存器的格式,以区分Device是eMMC还是MMC卡。
虽然MMC Spec并没有正式收录MMC micro卡的规格,但是在v4.3 Spec还是增加定义了MMC micro的 signal input capacitance(信号输入电容标准)。
1.3.4 MMC v4.4x版本
v4.4版本一个重要的改动是加入了DDR(Dual Data Rate)模式,即信号的双边采样,在clock的上升沿和下降沿都会采样一次数据。
DDR mode将理论传输速率提升了一倍,达到104MB/s。
v4.4版本还新增了RPMB(Replay Protected Memory Block)功能,用于实现数据的加密读写。RPMB主要用于系统一些关键私密的数据的存储。
接下来的v4.41版本主要增加了Background Operations 和 High Priority Interrupt两个可选的功能,不强制要求实现。
Background Operations赋予MMC/eMMC执行后台操作的能力;High Priority Interrupt允许MMC/eMMC的某些命令执行允许被更高优先级的任务中断;
1.3.5 eMMC v4.5x版本
v4.5版本是MMC发展史上另一个里程碑式的版本,该版本封面正式移除了MMCA的logo,只保留了JEDEC的logo,MMCA退出历史舞台。
同时v4.5版本移除了MMC卡的支持,只保留eMMC的规格定义,MMC 卡也退出了历史舞台,进入了eMMC标准时代。
v4.5版本其他重要的改进包括:
-
增加
HS200 mode,将工作频率提高到200MHz,理论传输速率可达200MB/s; -
增加
Cache功能,进一步提升eMMC的性能;
1.4 eMMC v5.x 版本阶段
该阶段eMMC的发展的主要方向在于提升性能。
2013年发布的v5.0版本增加了HS400 mode,在HS200的基础上增加DDR mode(信号双边采样),将理论传输速率提升至400MB/s。
2015年发布的v5.1版本增加了Command Queue功能,优化eMMC内部的操作效率,提升eMMC整体的Performance。
v5.1版本同时发布了一个Command Queue Host Controller Interface(CQHCI)标准,用于Host端实现Command Queue硬件支持的设计标准。
另外v5.1版本新增了HS400ES mode,在HS400 mode的基础上提高了CMD Responce接收到可靠性。
1.5 总结
MMC发展到今天,只剩下嵌入式应用的eMMC标准,但是在2015年v5.1版本发布后,已经有4年没有更新标准了。
eMMC如果想进一步提升性能,就需要采用更高频率的clock,对于eMMC使用的并行接口而言,可能会遇到信号完整性等方面的瓶颈。
2016年JEDEC发布的UFS存储标准采用差分串行总线取代了eMMC的并行接口,可以达到远超eMMC的性能,有替代eMMC的趋势。
目前在高端手持移动设备领域,UFS正在逐步替代eMMC;在车机、低成本/低端的手持设备以及其他一些嵌入式设备中,eMMC还占有较高的应用比例。
eMMC和UFS目前都是JEDEC在维护开发,不存在竞争关系,从现状看,eMMC再推出革命性的版本升级的可能性不大。
因此,可以猜测未来的发展趋势:eMMC可能会逐步被UFS取代,成为过时的技术;eMMC也会长期存在于一些低成本或对存储性能要求不高的设备上。
二、SD发展历史
SD(Secure Digital Memory Card) 卡是在MMC卡基础 上发展起来的,中文名称为:安全数字存储卡。
SD卡发布之初,与MMC卡的最大区别就在安全(Secure)上,其支持SDMI标准,可提供保护SD卡上存储的音乐版权等功能。
SD卡于1999年开发研制,Panasonic、Sandisk和Toshiba于2000年成立了 SDA(SD Association) 协会主导SD卡的标准制定。
到目前为止,SD卡的标准已经发展到v7.0,在移动存储卡领域已经占据主导性地位。
2.1 v1.xx版本阶段
v1.xx版本阶段从2000年开始,持续到2006年v2.xx版本发布。
也许是受益于后发优势,SD卡在初始v1.00版本就支持了双电压操作模式和1/4bits bus width,上市之初其被市场接纳程度就超过同期的MMC卡。
SD卡初始发布的v1.00版本规格的主要特性有:
Size:24mm x 32mm x 2.1mm(Normal)/24mm x 32mm x 1.4mm(Thin);Pins:9pins;Bus Width:1/4bits;Bus Mode:SD mode&SPI mode;Voltage:2.0 - 3.6V/1.6 - 3.6V;Clock:0 – 25MHz;Performance:10MB/s;
为了应对RS-MMC的市场竞争,2003年由SanDisk率先推出了miniSD,尺寸为:21.5mm x 20mm x 1.4mm,号称当时最小尺寸的 Nand存储卡。
SD卡和MMC卡在竞争中向前发展,2004年发布的SD v1.10版本的主要竞争对手是MMC v4.x标准。
SD v1.10引入了High Speed mode,将Clock频率提升到0 - 50MHz,最大理论Performance为 25MB/s,兼容MMC v2.11标准。
同时推出TransFlash Card,又称 T-Flash 或者TF卡,后来统一为microSD卡。
microSD的尺寸只有:11mm x15mm x 1mm。
至此,SD的物理尺寸一共有三种:SD、miniSD、microSD,在后来的市场筛选中只保留了SD和mircoSD两种标准,也就是现在可以买到的两种SD卡(如下图所示);
2.2 v2.xx版本阶段
SD卡和MMC卡类似,在三个方向发展进化:速度,容量,尺寸。
v1.xx版本阶段,SD卡的尺寸规格已基本定型,2006年推出的v2.00标准将SD卡的容量扩展到32GB,将SD卡容量分为SD/SDHC两种规格:
SD:Standard Capacity SD Memory Card,指2GB及以下容量的SD卡;SDHC:High Capacity SD Memory Card,指2GB – 32GB容量的SD卡;
2.3 v3.xx版本阶段
2009年开始发布的v3.xx版本是SD卡发展历史上很重要的一个阶段,虽然现在SD卡标准已发展到v7.xx,但是v3.xx依然非常流行。
v3.xx在v2.xx版本的基础上有如下重大更新:
- 新增
SDXC容量标准,SDXC规格的SD卡容量为32GB – 2TB; - 引入
UHS-I(Ultra High Speed)总线标准,将Clock提升到208MHz,最高理论传输速率为104MB/s;
到v3.xx版本,SD卡基本分类:
- 容量:
SD(0-2GB),SDHC(2 - 32GB),SDXC(32GB – 2TB); - 速度:
Default(0 - 25MHz),High Speed mode(0 - 50MHz),UHS - I(0 -208MHz);
2.4 v4.xx版本阶段
从v3.xx版本到v4.xx版本,可以算作SD卡发展到一个分水岭。
在v3.xx版本,SD卡支持的Bus规格都是4bits宽度的并行总线,最高工作频率达到208MHz,理论传输速率可达104MB/s。
和eMMC遇到的问题一样,v3.xx版本的SD标准想进一步提高传输速率的话,4bits的并行总线会成为其阻力。
因此v4.xx版本引入了UHS-II mode,该mode使用了低电压串行差分总线技术,将理论传输速率提升至312MB/s,支持全双工模式,单路理论速率为1.56Gbps。
2.5 快速发展阶段
v4.20版本之后,SD标准进入了一个快速发展阶段,下面这张SD技术演进图可以很好地展示其发展脉络;

v5.xx版本统一了SD卡容量和速度的分类规范;
v6.xx版本引入了新的速度模式,UHS-III,将理论传输速率提升至524MB/s;
v7.xx版本在速度和容量都有升级,推出了SDUC容量规格,总线传输支持PCIe,理论传输速率提升到940MB/s;
2.6 总结
从SD标准的技术发展现状和市场现有的SD卡产品来看,标准的制定已经远远领先于产品技术的发展。
当下SD卡的发展方向无非就是更大的容量和更快的速度,这两个发展方向都依赖于固态存储的技术进步。
SD标准已经将传输管道做得足够粗,接下来就看各SD卡厂商如何填满这个粗管道,有效利用其传输性能。
三、SDIO
SDIO是在SD卡接口的基础上发展起来的外设接口,SDIO接口兼容以前的SD卡,并且可以连接SDIO接口的设备,目前根据SDIO协议的SPEC,SDIO接口支持的设备总类有WIFI、Bluetooth、GPS等等。
3.1 SDIO总线引脚定义
SDIO是Host (主机)和SDIO接口设备 (比如SD卡) 之间的通信总线,包括6根信号 ,这些信号的电平标准为3.3V ;
| 名称 | 方向 | 描述 |
|---|---|---|
| SDCMD | 当发起命令时Host输出;当响应时SDIO接口设备输出 | 传输命令和响应 |
| SDCLK | 由主机产生 | 时钟信号 |
| SDDAT0 | 当写数据时Host输出;当读数据时SDIO接口设备输出 | Data line 0 |
| SDDAT1 | 当写数据时Host输出;当读数据时SDIO接口设备输出 | Data line 1 |
| SDDAT2 | 当写数据时Host输出;当读数据时SDIO接口设备输出 | Data line 2 |
| SDDAT3 | 当写数据时Host输出;当读数据时SDIO接口设备输出 | Data line 3 |
下图展示了SD卡 和microSD卡的SDIO信号定义。SD卡(9个引脚)和microSD卡(8个引脚)除了外形尺寸外,功能上没有差别。

下图是SD卡接口电路设计示意图。其中sdcmd和sddat0~3是双向信号,需要通过电阻上拉到3.3V 。当Host和SD卡都不驱动时,这些信号为弱上拉的高电平。除了SDIO的6根信号外,SD卡还需要3.3V的电源供电。

3.2 信号时序
SDIO是同步总线,信号 (sdcmd, sddat) 的置位和采样都要和时钟 (sdclk) 同步,每个时钟周期中的每个信号可以传输1bit,需要满足一定的时序来保证信号的接收端能够正确的采样数据。SD2.0版本(SD和SDHC,它们都遵循SD 2.0协议)规范规定SD卡需要满足如下时序;

3.2.1 时钟要求
对于时钟 (sdclk)):
- 在
SD卡初始化过程中,时钟频率最低是100kHz(周期10000ns) ,最高不能超过400kHz(周期2500ns);。 - 初始化完成后,时钟频率最低不限,最高不能超过
25MHz(周期40ns))。 - 时钟的上升和下降时间不能超过
10ns;
初始化操作是通过向 card 发送一个命令序列来实现的,后文会讲到。
3.2.2 Host→SD卡时序要求
sdcmd和sddat都是双向信号,在两个方向上都要满足上面图中的时序要求。
当SD卡输入时Host→SD卡,例如Host通过sdcmd发送命令给SD卡,这些信号会在sdclk的上升沿被输入端采样。
建立时间\(t_{ISU}\)和保持时间\(t_{IH}\)的最小要求5ns ,换句话说,上升沿之前5ns到之后5ns这段时间之间要让信号稳定下来,避免SD采到不稳定的数据。
考虑到时钟周期最小为40ns ,从下降沿到上升沿之间有20ns的时间,我们可以让Host在下降沿置位(更新)数据,很容易满足这个要求。
3.2.3 SD卡→Host时序要求
当SD卡输出时 (SD卡→Host,例如 SD卡通过sdcmd发送响应给Host) ,这些信号会在sdclk的下降沿被更新。此时需要分别考虑初始化前后两种情况:
在初始化过程中,SD卡端的输出延迟 \(t_{ODLY,OD}\) (从时钟下降沿到信号稳定))最大为50ns 。考虑到在初始化过程中的时钟周期最小为2500ns ,从下降沿到上升沿之间有1250ns的时间,因此可以让Host在时钟上升沿采样数据,可以采样到稳定的数据。
在初始化后,SD卡端的输出延迟\(t_{ODLY,PP}\)最大为14ns 。考虑到此时的时钟周期最小为40ns ,从下降沿到上升沿只有20ns的时间,我们讨论Host的采样时机的3种方案:
Host在下降沿后的上升沿采样数据,则建立时间只有20-14=6ns。考虑到从Host到SD卡一个来回的走线延迟 (Host发出时钟下降沿→SD卡收到时钟下降沿并更新信号→更新的信号传回Host),6ns的时间可能不够宽裕;Host在下降沿后的下一个下降沿采样数据,则建立时间有40-14=26ns,非常宽裕。但有可能违反Host采样所需的保持时间 (取决于Host IO的保持时间要求) ,虽然一般来讲违反的概率不大;- 如果
Host内部有一个比sdclk更快的时钟 (一般是整个Host控制器的驱动时钟) ,可以在上升沿到下降沿的中点采样数据 ,则建立时间有30-14=16ns,比较宽裕,同时保证保持时间不被违反;
为了满足SDIO总线的时序,Host输出时应该在sdclk的下降沿将信号 (sdcmd, sddat) 置位。Host输入时应该在sdclk的下降沿采样 (SD卡置位的下降沿的下一个下降沿);或者在上升沿到下降沿的中点采样 (SD卡置位的下降沿的下一个上升沿到下一个下降沿)。。
四、NanoPC-T4 SDMMC配置
4.1硬件原理图
NanoPC-T4开发板带有一个microSD卡槽,microSD卡槽接线图如下所示:
注意:这里sdcmd和sddat0~3通过电阻下拉到GND,为啥不是上拉我也有点不是特别明白。
RK3399 SDMMC引脚接线如下图所示:
补充:实际上并没有SDMMC卡或者是SDMMC接口;这里SDMMC就是SD卡。
需要注意的是:RK3399的电源域包含了sdmmc,如果要使用SDMM0必须要配置电源域,SDMMC0_VDD引脚连接的电源VCC_SDIO是由rk808下的12号引脚VLDO4输出的。
| RK3399引脚 | 方向 | 描述 |
|---|---|---|
| GPIO4_B4/SDMMC0_CLKOUT | O | SDMMC card clock |
| GPIO4_B5/SDMMC0_CMD | I/O | SDMMC card command output and response input |
| GPIO4_B0/SDMMC0_D0 | I/O | SDMMC card data input and output line 0 |
| GPIO4_B1/SDMMC0_D1 | I/O | SDMMC card data input and output line 1 |
| GPIO4_B2/SDMMC0_D2 | I/O | SDMMC card data input and output line 2 |
| GPIO4_B3/SDMMC0_D3 | I/O | SDMMC card data input and output line 3 |
| GPIO0_B0/SDMMC0_WRPRT | I | SDMMC card protect |
| GPIO0_A7/SDMMC0_DET | I | SDMMC card detect signal, a 0 represents presence of card |
| SDMMC0_VDDPST | O | Pin out to external capacitor |
4.2 设备树配置
设备节点配置可以参考官方文档:Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml;
在arch/arm64/boot/dts/rockchip/rk3399-evb.dts中sdmmc设备节点追加属性;
&sdmmc {
bus-width = <4>;
cap-sd-highspeed;
cap-mmc-highspeed;
cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
disable-wp;
pinctrl-names = "default";
pinctrl-0 = <&sdmmc_bus4 &sdmmc_clk &sdmmc_cmd &sdmmc0_det_l>;
sd-uhs-sdr104;
vmmc-supply = <&vcc3v0_sd>;
vqmmc-supply = <&vcc_sdio>;
status = "okay";
};
其中:
bus-width:配置SD卡的线宽,SD卡最大支持4线模式,如果不配置就默认使用1线模式。另外,这个位只支持的数值为1,4,配置其他数值会认为是非法数值,强制按照1线模式进行使用;cap-sd-highspeed、cap-mmc-highspeed:此配置为标识此卡槽支持SDHC)。 如果不配置,表示不支持SDHC卡;cd-gpios:配置SD卡热插拔检测引脚,这里配置为GPIO0_A7;SD卡插入为低电平,拔出为高电平,因此有效点评配置为GPIO_ACTIVE_LOW;pinctrl-names、pinctrl-0:引脚配置节点,后面单独介绍;sd-uhs-sdr104:配置SD3.0的速度模式,需要根据使用的芯片是否支持SD3.0协议来决定是否要配置 ;sd-uhs-sdr12: 时钟频率不超过24M;sd-uhs-sdr25: 时钟频率不超过50M;sd-uhs-sdr50: 时钟频率不超过100M;sd-uhs-ddr50: 时钟频率不超过50M,并且采用双沿采样;sd-uhs-sdr104: 时钟频率不超过208M;
vmmc-supply:这里我们使用VCC3V0_SD作为SD卡设备的3V3电源控制引脚;vqmmc-supply:SD3.0协议,需要配置vqmmc这一路的SDMMC控制器的IO电源:配置SDMMC0_VDD引脚电源供应;这里我们使用rk808电源管理芯片12号引脚VLDO4输出作为SDMMC0_VDD的电源控制引脚;
sdmmc设备节点定义在arch/arm64/boot/dts/rockchip/rk3399.dtsi;
sdmmc: mmc@fe320000 {
compatible = "rockchip,rk3399-dw-mshc",
"rockchip,rk3288-dw-mshc";
reg = <0x0 0xfe320000 0x0 0x4000>;
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>;
max-frequency = <150000000>; /* SD卡的运行频率,虽然设置为 150M,但是还要根据SD卡的不同模式进行调整 */
assigned-clocks = <&cru HCLK_SD>;
assigned-clock-rates = <200000000>;
clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
<&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
power-domains = <&power RK3399_PD_SD>;
resets = <&cru SRST_SDMMC>;
reset-names = "reset";
status = "disabled";
};
其对应驱动程序位于drivers/mmc/host/dw_mmc-rockchip.c文件。
4.2.1 电源配置
(1)VCC3V0_SD是由RT9193稳压管输出;由引脚SDMMC0_PWR_H(连接到RK3399的GPIO0_A1)来控制使能;
在arch/arm64/boot/dts/rockchip/rk3399-evb.dts中配置;
vcc3v0_sd: vcc3v0-sd {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA1 GPIO_ACTIVE_HIGH>; /* GPIO0_A1使能,高电平有效 */
pinctrl-names = "default";
pinctrl-0 = <&sdmmc0_pwr_h>;
regulator-always-on;
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
regulator-name = "vcc3v0_sd";
vin-supply = <&vcc3v3_sys>;
};
并添加引脚配置节点sdmmc0_pwr_h;
&pinctrl {
......
sdmmc {
sdmmc0_det_l: sdmmc0-det-l {
rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;
};
sdmmc0_pwr_h: sdmmc0-pwr-h {
rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; /* 配置为GPIO口 */
};
};
};
(2) SDMMC0_VDD连接rk808电源管理芯片12号引脚VLDO4,在arch/arm64/boot/dts/rockchip/rk3399-evb.dts中配置;
&i2c0 {
......
rk808: pmic@1b {
......
regulators {
......
vcc_sdio: LDO_REG4 {
regulator-always-on;
regulator-boot-on;
regulator-init-microvolt = <3000000>;
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-name = "vcc_sdio";
regulator-state-mem {
regulator-on-in-suspend;
regulator-suspend-microvolt = <3000000>;
};
};
};
};
};
4.2.2 引脚配置节点
引脚配置节点共有4个sdmmc_bus4、sdmmc_clk、sdmmc_cmd、sdmmc0_det_l,其中前三个已经在arch/arm64/boot/dts/rockchip/rk3399.dtsi中配置了;
pinctrl: pinctrl {
......
sdmmc {
sdmmc_bus1: sdmmc-bus1 {
rockchip,pins =
<4 RK_PB0 1 &pcfg_pull_up>;
};
sdmmc_bus4: sdmmc-bus4 { /* 数据引脚功能复用为sdmmc */
rockchip,pins =
<4 RK_PB0 1 &pcfg_pull_up>,
<4 RK_PB1 1 &pcfg_pull_up>,
<4 RK_PB2 1 &pcfg_pull_up>,
<4 RK_PB3 1 &pcfg_pull_up>;
};
sdmmc_clk: sdmmc-clk { /* 时钟引脚功能复用为sdmmc */
rockchip,pins =
<4 RK_PB4 1 &pcfg_pull_none>;
};
sdmmc_cmd: sdmmc-cmd { /* 命令引脚功能复用为sdmmc */
rockchip,pins =
<4 RK_PB5 1 &pcfg_pull_up>;
};
sdmmc_cd: sdmmc-cd {
rockchip,pins =
<0 RK_PA7 1 &pcfg_pull_up>;
};
sdmmc_wp: sdmmc-wp {
rockchip,pins =
<0 RK_PB0 1 &pcfg_pull_up>;
};
};
};
我们需要在arch/arm64/boot/dts/rockchip/rk3399-evb.dts中配置sdmmc0_det_l;
&pinctrl {
......
sdmmc {
sdmmc0_det_l: sdmmc0-det-l {
rockchip,pins = <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>; /* GPIO0_A7配置为GPIO口 */
};
sdmmc0_pwr_h: sdmmc0-pwr-h {
rockchip,pins = <0 RK_PA1 RK_FUNC_GPIO &pcfg_pull_none>; /* GPIO0_A1配置为GPIO口 */
};
};
};
4.3 配置内核
执行make menuconfig配置内核:
Device Drivers --->
<*> MMC/SD/SDIO card support --->
<*> Synopsys DesignWare Memory Card Interface
<*> Rockchip specific extensions for Synopsys DW Memory Card Interface
配置完内核之后记得保存配置:

存档:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# mv rk3399_defconfig ./arch/arm64/configs/
重新配置内核(如果不想重新编译内核,可以存档一份到.config):
root@zhengyang:/work/sambashare/rk3399/linux-6.3# make rk3399_defconfig
4.3.1 编译内核
在linux内核根目录下执行如下命令进行编译内核:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# make -j8
u-boot-2023.04路径下的mkimage工具拷贝过来,然后在命令行使用mkimage工具编译即可:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# cp ../u-boot-2023.04/tools/mkimage ./
root@zhengyang:/work/sambashare/rk3399/linux-6.3# ./mkimage -f kernel.its kernel.itb
4.3.2 通过tftp烧录内核
给开发板上电,同时连接上网线,进入uboot命令行。我们将内核拷贝到tftp文件目录:
root@zhengyang:/work/sambashare/rk3399/linux-6.3# cp kernel.itb /work/tftpboot/
接着给开发板上电。通过uboot命令行将kernel.itb下到内存地址0x10000000处:
=> tftp 0x10000000 kernel.itb
通过mmc write命令将内核镜像烧录到eMMC第0x8000个扇区处:
=> mmc erase 0x8000 0xA000
=> mmc write 0x10000000 0x8000 0xA000
4.4 测试
内核启动完成后,将microSD卡插入开发板后,内核输出日志信息如下:
[ 88.515351] mmc_host mmc2: Bus speed (slot 0) = 148500000Hz (slot req 150000000Hz, actual 148500000HZ div = 0)
[ 88.759085] dwmmc_rockchip fe320000.mmc: Successfully tuned phase to 202
[ 88.759152] mmc2: new ultra high speed SDR104 SDHC card at address 0001
[ 88.760468] mmcblk2: mmc2:0001 00000 14.9 GiB
[ 88.763893] mmcblk2: p1 p2
[ 89.955393] EXT4-fs (mmcblk2p1): mounted filesystem ff313567-e9f1-5a5d-9895-3ba130b4a864 with ordered data mode. Quota mode: none.
[ 89.966431] EXT4-fs (mmcblk2p2): recovery complete
[ 89.966472] EXT4-fs (mmcblk2p2): mounted filesystem 269e9152-5cb6-035b-9c34-e1ed87cca310 with ordered data mode. Quota mode: none.
在输出信息中,我们了解到总线速度为148.5Mhz,并且识别到一个ultra high speed SDR104 SDHC card,地址为0001;
设备名称为mmcblk2,因此我们可以在/dev下看到整个设备节点,/dev/mmcblk2表示的是microSD这个设备,其主设备号为179,次设备号为96;并且该设备被划分了2个分区,p1和p2, 文件系统类型为ext4;
root@rk3399:/# ll /dev/mmcblk2*
brw-rw---- 1 root disk 179, 96 Sep 23 15:25 /dev/mmcblk2
brw-rw---- 1 root disk 179, 97 Sep 23 15:25 /dev/mmcblk2p1
brw-rw---- 1 root disk 179, 98 Sep 23 15:25 /dev/mmcblk2p2
4.4.1 查看设备容量
这里我们可以通过df -hT查看磁盘空间信息;
root@rk3399:/# df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/root ext4 15G 5.4G 8.2G 40% /
devtmpfs devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs tmpfs 386M 1.9M 384M 1% /run
tmpfs tmpfs 5.0M 4.0K 5.0M 1% /run/lock
tmpfs tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
tmpfs tmpfs 386M 12K 386M 1% /run/user/0
tmpfs tmpfs 386M 4.0K 386M 1% /run/user/1000
/dev/mmcblk2p1 ext4 4.5G 4.4G 35M 100% /media/root/rootfs
/dev/mmcblk2p2 ext4 11G 263M 9.8G 3% /media/root/userdata
可以看到:
- 设备节点
/dev/mmcblk2p1被挂载到了/media/root/rootfs路径下,大小为4.5G; - 设备节点
/dev/mmcblk2p2被挂载到了/media/root/userdata路径下,大小为4.5G;
4.4.2 读写测试
我们进入/media/root/rootfs目录,查看目录内容:
root@rk3399:/# cd /media/root/rootfs
root@rk3399:/media/root/rootfs# ll
total 92
drwxr-xr-x 23 root root 4096 Jan 1 1970 ./
drwxr-x---+ 4 root root 4096 Sep 23 15:25 ../
drwxr-xr-x 2 root root 4096 May 8 2019 bin/
drwxr-xr-x 2 root root 4096 Oct 19 2015 boot/
drwxr-xr-x 4 root root 4096 Jun 25 2018 dev/
drwxr-xr-x 103 root root 4096 Aug 19 2022 etc/
drwxr-xr-x 4 root root 4096 Jul 17 2019 home/
drwxr-xr-x 18 root root 4096 Jul 17 2019 lib/
drwx--S--- 2 root root 4096 Jan 1 1970 lost+found/
drwxr-xr-x 3 root root 4096 Dec 9 2020 man/
drwxr-xr-x 2 root root 4096 Oct 21 2015 media/
drwxr-xr-x 4 root root 4096 Jul 29 2016 mnt/
drwxr-xr-x 10 root root 4096 Oct 15 2020 opt/
drwxr-xr-x 2 root root 4096 Oct 19 2015 proc/
drwxr-xr-x 9 root root 4096 Aug 19 2022 root/
drwxr-xr-x 9 root root 4096 Mar 15 2017 run/
drwxr-xr-x 2 root root 4096 Mar 24 2020 sbin/
drwxr-xr-x 2 root root 4096 Oct 21 2015 srv/
drwxr-xr-x 2 root root 4096 Oct 16 2015 sys/
drwxr-xr-x 4 root root 4096 Jul 17 2019 system/
drwxrwxrwt 2 root root 4096 Aug 19 2022 tmp/
drwxr-xr-x 13 root root 4096 Dec 9 2020 usr/
drwxr-xr-x 12 root root 4096 Jul 17 2019 var/
这个目录下我存放的开发板SD启动时烧录的系统固件,这里我们不去修改它,我们使用/media/root/userdata做测试;
在/media/root/userdata目录下创建一个test.txt文件;
root@rk3399:/media/root# cd /media/root/userdata
root@rk3399:/media/root/userdata# touch test.txt
写入内容:
root@rk3399:/media/root/userdata# echo 'hello rk3399' > test.txt
读取内容:
root@rk3399:/media/root/userdata# cat test.txt
hello rk3399
删除该文件:
root@rk3399:/media/root/userdata# rm -rf test.txt
参考文章
[4] MMC/SD/SDIO介绍
[7] MMC & SD 发展历史

浙公网安备 33010602011771号