本文介绍如何三招搞定Linux SD卡驱动调试。
一、SD卡介绍
SD Card(Secure Digital Memory Card):即安全数码卡,是一种基于半导体快闪存储器的新一代高速存储设备。
SD卡架构如下:
网络图片
下面简单整理下SD卡的外部引脚、内部寄存器、速度等级和容量等级。
1、外部引脚
SD卡支持三种传输模式:SPI模式、1bit SD模式和4bit SD模式。
在实际项目中,自己主要调试后面两种模式,SD卡共有9个引脚,汇总如下:
引脚名称 |
引脚描述 |
备注 |
CLK |
时钟信号 |
|
CMD |
命令/回复引脚 |
|
DATA0 ~ 3 |
数据线 |
1bit SD模式:只使用DATA0,CD:卡检测。4bit SD模式:CD/DATA3:卡检测/数据3 |
VDD |
电源 |
|
VSS1/2 |
地 |
2、内部寄存器
SD卡相关寄存器整理如下:
寄存器名称 |
寄存器描述 |
OCR(Operating Conditions Register) |
运行条件寄存器 |
CID(Card IDentification Register) |
卡识号寄存器,每张卡都有唯一的识别号 |
CSD(Card Specific Data Register) |
描述数据寄存器 |
SCR(SD Card Configuration Register) |
SD卡配置寄存器 |
RCA(Relative Card Address) |
卡地址寄存器 |
DSR(Driver Stage Register) |
驱动级寄存器 |
3、速度等级
根据数据传输速度,SD卡有不同的速度等级表示方法。
协议规范 |
简介 |
SD1.0 |
使用X表示不同的速度等级,较少使用。 |
SD2.0 |
普通卡(Class2、Class4、Class6)和高速卡(Class10)。 |
SD3.0 |
使用UHS速度等级1和3。 |
SD4.0 |
使用UHS-II |
4、容量等级
SD卡容量目前支持:SD、SDHC和SDXC。
SD卡类型 |
协议规范 |
容量大小 |
支持文件格式 |
SD |
SD1.0 |
~2GB |
FAT 12,16 |
SDHC(SD High Capacity) |
SD2.0 |
2GB ~ 32GB |
FAT 32 |
SDXC(SD eXtended Capacity) |
SD3.0 |
32GB ~ 2TB |
exFAT |
二、SD卡调试
1、原理图
预调驱动,先看原理图。
下图是RK3568和microSD卡槽之间的连接方式。
microSD卡连接图
2、SDCard配置
RK3568 SD卡配置文件:
1)arch/arm64/boot/dts/rockchip/rk3568.dtsi
sdmmc0: dwmmc@fe2b0000 { compatible = "rockchip,rk3568-dw-mshc", "rockchip,rk3288-dw-mshc"; reg = <0x0 0xfe2b0000 0x0 0x4000>; interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>; max-frequency = <150000000>; clocks = <&cru HCLK_SDMMC0>, <&cru CLK_SDMMC0>, <&cru SCLK_SDMMC0_DRV>, <&cru SCLK_SDMMC0_SAMPLE>; clock-names = "biu", "ciu", "ciu-drive", "ciu-sample"; fifo-depth = <0x100>; resets = <&cru SRST_SDMMC0>; reset-names = "reset"; status = "disabled"; };
2)arch/arm64/boot/dts/rockchip/rk3568-firefly-core.dtsi
&sdmmc0 { max-frequency = <150000000>; supports-sd; bus-width = <4>; cap-mmc-highspeed; cap-sd-highspeed; disable-wp; sd-uhs-sdr104; vmmc-supply = <&vcc3v3_sd>; vqmmc-supply = <&vccio_sd>; pinctrl-names = "default"; pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>; status = "okay";};
其中:
clocks:表示SD卡控制器时钟、driver和sample时钟。
max-frequency:SD卡的最大运行频率,根据不同的模式进行调整。
supports-sd:表示为SD卡功能,必须添加。否则无法初始化SD卡。
bus-width:SD卡使用4线模式。如果不配置,默认1线模式。
cap-mmc-highspeed/cap-sd-highspeed:支持highspeed的SD卡。
vmmc-supply、vqmmc-supply:SD卡电源域。
SD3.0速度模式:
sd-uhs-sdr12:时钟频率不超过24M,信号电压1.8Vsd-uhs-sdr25:时钟频率不超过50M,信号电压1.8Vsd-uhs-sdr50:时钟频率不超过100M,信号电压1.8Vsd-uhs-ddr50:时钟频率不超过50M,采用双沿采样,信号电压1.8Vsd-uhs-sdr104:时钟频率不超过208M,信号电压1.8V
pinctrl-0:SD卡pinmux配置。
3、SDCard驱动
RK3568驱动文件:drivers/mmc/host/dw_mmc-rockchip.c,主要关注:
static const struct dw_mci_drv_data rk3288_drv_data = { .caps = dw_mci_rk3288_dwmmc_caps, .num_caps = ARRAY_SIZE(dw_mci_rk3288_dwmmc_caps), .set_ios = dw_mci_rk3288_set_ios, ## 配置时钟、总线、电源、片选、时序等 .execute_tuning = dw_mci_rk3288_execute_tuning, ## 调节driver clk和sample clk phase .parse_dt = dw_mci_rk3288_parse_dt, .init = dw_mci_rockchip_init,};
RK3568 SD控制器使用Synopsys IP,主要关注:dw_mci_rk3288_set_ios()和dw_mci_rk3288_execute_tuning()。
系统启动后,可通过如下命令查看SD卡属性(驱动实现:drivers/mmc/core/debugfs.c):
[root@xiaotianbsp:/]# cat /sys/kernel/debug/mmc1/iosclock: 150000000 Hzactual clock: 148500000 Hzvdd: 21 (3.3 ~ 3.4 V)bus mode: 2 (push-pull)chip select: 0 (don't care)power mode: 2 (on)bus width: 2 (4 bits)timing spec: 6 (sd uhs SDR104)signal voltage: 1 (1.80 V)driver type: 0 (driver type B)
三、SDCard测试
下面测试基于SanDisk Ultra 1 32G SD卡完成。
1、SD卡检测
系统启动后,SD卡启动日志如下:
[ 1.225398] dwmmc_rockchip fe2b0000.dwmmc: Successfully tuned phase to 266[ 1.225420] mmc1: new ultra high speed SDR104 SDHC card at address aaaa[ 1.226456] mmcblk1: mmc1:aaaa SD32G 29.7 GiB[ 1.227643] mmcblk1: p1
如果SD卡没有正常初始化,出现如下日志:
[ 182.501273] mmc_host mmc1: Bus speed (slot 0) = 375000Hz (slot req 400000Hz, actual 375000HZ div = 0)[ 182.672282] mmc1: error -123 whilst initialising SD card[ 182.686489] mmc_host mmc1: Bus speed (slot 0) = 375000Hz (slot req 300000Hz, actual 187500HZ div = 1)[ 182.699318] mmc_host mmc1: Bus speed (slot 0) = 375000Hz (slot req 375000Hz, actual 375000HZ div = 0)[ 182.717513] mmc_host mmc1: Bus speed (slot 0) = 375000Hz (slot req 200000Hz, actual 187500HZ div = 1)
原因:mmc_sd_init_card()失败。出错信息定义(include/uapi/asm-generic/errno.h):
#define ETIMEDOUT 110 /* Connection timed out */...#define ENOMEDIUM 123 /* No medium found */
2、SD卡寄存器
通过如下命令,可以查看SD卡相关寄存器的值。
[root@xiaotianbsp:/]# cd /sys/class/mmc_host/mmc1/mmc1:aaaa[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# lsblock driver hwrev oemid scr typecid dsr manfid power serial ueventcsd erase_size name preferred_erase_size ssrdate fwrev ocr rca subsystem[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# cat cid03534453443332478554c496d501636f## 其它寄存器查看方式类似
SD卡其它参数的查看方法如下:
[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# cat erase_size512[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# cat fwrev0x5[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# cat hwrev0x8[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# cat manfid0x000003[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# cat nameSD32G[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# cat oemid0x5344[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# cat serial0x54c496d5[root@xiaotianbsp:/sys/devices/platform/fe2b0000.dwmmc/mmc_host/mmc1/mmc1:aaaa]# cat typeSD
3、挂载/卸载
SD卡分区挂载命令:
[root@xiaotianbsp:/]# mount -t vfat /dev/mmcblk1p1 /tmp/[ 244.746983] FAT-fs (mmcblk1p1): utf8 is not a recommended IO charset for FAT filesystems, filesystem will be case sensitive![ 244.749331] FAT-fs (mmcblk1p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck.[root@xiaotianbsp:/]# mount.../dev/mmcblk1p1 on /tmp type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=936,iocharset=utf8,shortname=mixed,errors=remount-ro)
SD卡分区卸载命令:
umount /dev/mmcblk1p1
4、创建分区
使用fdisk命令,可在SD卡上重新创建分区。
[root@xiaotianbsp:/]# fdisk /dev/mmcblk1...Command (m for help): p ## 1、查看现有分区Disk /dev/mmcblk1: 30 GB, 31914983424 bytes, 62333952 sectors3880 cylinders, 255 heads, 63 sectors/trackUnits: cylinders of 16065 * 512 = 8225280 bytesDevice Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type/dev/mmcblk1p1 0,0,17 1023,254,63 16 62333951 62333936 29.7G c Win95 FAT32 (LBA)Command (m for help): d ## 2、删除分区Selected partition 1Command (m for help): pDisk /dev/mmcblk1: 30 GB, 31914983424 bytes, 62333952 sectors3880 cylinders, 255 heads, 63 sectors/trackUnits: cylinders of 16065 * 512 = 8225280 bytesDevice Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id TypeCommand (m for help): n ## 3、创建新分区,共创建了2个分区Command action e extended p primary partition (1-4)pPartition number (1-4): 1First cylinder (1-3880, default 1): Using default value 1Last cylinder or +size or +sizeM or +sizeK (1-3880, default 3880): 1940Command (m for help): pDisk /dev/mmcblk1: 30 GB, 31914983424 bytes, 62333952 sectors3880 cylinders, 255 heads, 63 sectors/trackUnits: cylinders of 16065 * 512 = 8225280 bytesDevice Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type/dev/mmcblk1p1 0,1,1 1023,254,63 63 31166099 31166037 14.8G 83 LinuxCommand (m for help): nCommand action e extended p primary partition (1-4)pPartition number (1-4): 2First cylinder (1941-3880, default 1941): Using default value 1941Last cylinder or +size or +sizeM or +sizeK (1941-3880, default 3880): Using default value 3880Command (m for help): pDisk /dev/mmcblk1: 30 GB, 31914983424 bytes, 62333952 sectors3880 cylinders, 255 heads, 63 sectors/trackUnits: cylinders of 16065 * 512 = 8225280 bytesDevice Boot StartCHS EndCHS StartLBA EndLBA Sectors Size Id Type/dev/mmcblk1p1 0,1,1 1023,254,63 63 31166099 31166037 14.8G 83 Linux/dev/mmcblk1p2 1023,254,63 1023,254,63 31166100 62332199 31166100 14.8G 83 LinuxCommand (m for help): w ## 4、保存新分区
5、读写测试
测试SD卡写命令:
[root@RK356X:/]# time dd oflag=direct,nonblock if=/dev/zero of=/dev/mmcblk1p1 bs=1M count=100100+0 records in100+0 records out104857600 bytes (105 MB, 100 MiB) copied, 3.4844 s, 30.1 MB/sreal 0m 3.49suser 0m 0.00ssys 0m 0.16s
测试SD卡读命令:
[root@RK356X:/]# time dd iflag=direct,nonblock if=/dev/mmcblk1p1 of=/dev/null bs=1M count=100100+0 records in100+0 records out104857600 bytes (105 MB, 100 MiB) copied, 1.65236 s, 63.5 MB/sreal 0m 1.65suser 0m 0.00ssys 0m 0.03s
上面命令中配置的iflag和oflag属性,可以规避文件系统cache,直接读写,不使用buffer cache。
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:dandanxi6@qq.com