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
等不同的规范;
![](https://gitee.com/zyly2033/blog-pic/raw/master/202309222158884.gif)
需要注意的是:这张图只供参考,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
卡(如下图所示);
![](https://gitee.com/zyly2033/blog-pic/raw/master/202309231254877.jpeg)
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
,比较宽裕,同时保证保持时间不被违反;
![](https://gitee.com/zyly2033/blog-pic/raw/master/202309231402948.png)
为了满足SDIO
总线的时序,Host
输出时应该在sdclk
的下降沿将信号 (sdcmd, sddat
) 置位。Host
输入时应该在sdclk
的下降沿采样 (SD
卡置位的下降沿的下一个下降沿);或者在上升沿到下降沿的中点采样 (SD
卡置位的下降沿的下一个上升沿到下一个下降沿)。。
四、NanoPC-T4 SDMMC
配置
4.1硬件原理图
NanoPC-T4
开发板带有一个microSD
卡槽,microSD
卡槽接线图如下所示:
![](https://gitee.com/zyly2033/blog-pic/raw/master/202309222248109.png)
注意:这里sdcmd
和sddat0~3
通过电阻下拉到GND
,为啥不是上拉我也有点不是特别明白。
RK3399 SDMMC
引脚接线如下图所示:
![](https://gitee.com/zyly2033/blog-pic/raw/master/202309222311728.png)
补充:实际上并没有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
)来控制使能;
![](https://gitee.com/zyly2033/blog-pic/raw/master/202309231450375.png)
在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
发展历史