SD/eMMC初始化流程、读写流程(dwc mshc)

目录

1.芯片简介

1.1 模块与接口

1.2 SD/eMMC初始化流程

1.3 SD/eMMC数据传输流程

1.3.1 传输模式

 2.调试问题

2.1 uboot

2.1.1 连续读4个以上block超时

2.1.2 SD卡未识别

2.2 kernel

2.2.1驱动初始化依赖时钟配置

2.2.3 SD卡fdisk分区失败

3. 内核MMC

4.调试命令

4.1 uboot

4.2 kernel

4.2.1 mmc_test

4.2.2 文件系统读写

4.2.3 sysfs


1.芯片简介

1.1 模块与接口

SD/eMMC初始化流程、读写流程(dwc mshc)_第1张图片

AHB Slave接口用于寄存器访问。

AXI/AHB Master接口用于数据传输。

SD/eMMC接口对接SD卡(支持4bit)和eMMC芯片(支持4/8 bit)。

UHS-II接口对接PHY。

1.2 SD/eMMC初始化流程

SD卡初始化流程如下:

SD/eMMC初始化流程、读写流程(dwc mshc)_第2张图片

       从SD卡初始化流程可知,不管什么卡(卡分为4类:SD2.0高容量卡(SDHC,最大32G),SD2.0标准容量卡(SDSC,最大2G),SD1.x卡和MMC卡),首先执行卡上电,上电后发送CMD0,对卡进行软复位,之后发送CMD8命令,用于区分SD卡2.0,只有2.0及以后的卡才支持CMD8命令,MMC卡和V1.x的卡,是不支持该命令的。

      在发送CMD8的时候,通过其带的参数可以设置VHS位,以告诉SD卡,主机的供电情况,让SD卡知道主机的供电范围。

      这里使用参数0X1AA,即告诉SD卡,主机供电为2.7~3.6V之间,如果SD卡支持CMD8,且支持该电压范围,则会通过CMD8的响应R7将参数部分原本返回给主机,如果不支持CMD8,或者不支持这个电压范围,则不响应。

      在发送CMD8后,发送ACMD41(注意:发送ACMD41之前,要先发送CMD55),来进一步确认卡的操作电压范围,并通过HCS位来告诉SD卡,主机是不是支持高容量卡(SDHC)。

      对于支持CMD8的卡,主机设置ACMD41的参数HCS=1,告诉SD卡,主机支持SDHC卡。

      对2.0的卡,OCR的CCS位用于表示SDHC还是SDSC;对1.x的卡,则忽略该位;

      对MMC卡,则不支持ACMD41,MMC卡只需要发送:CMD0和CMD1即可完成初始化。

      SD卡在收到CMD2后,将返回R2长响应(136位),其中包含128位有效数据(CID寄存器内容),存放在SDIO_RESP1~4等4个寄存器里面。通过读取这四个寄存器,就可以获得SD卡的CID信息。

      CMD3用于设置卡相对地址(RCA,必须为非0),对于SD卡(非MMC卡),在收到CMD3后,将返回一个新的RCA给主机,方便主机寻址。RCA的存在允许一个SDIO接口挂多个SD卡,通过RCA来区分主机要操作的是哪个卡。对于MMC卡,则不是由SD卡自动返回RCA,而是主机主动设置MMC卡的RCA,即通过CMD3带参数(高16位用于RCA设置),实现RCA设置。同样MMC卡也支持一个SDIO接口挂多个MMC卡,不同于SD卡的是所有的RCA都是由主机主动设置的,而SD卡的RCA则是SD卡发给主机的。

      在获得卡RCA之后,便可以发送CMD9(带RCA参数),获得SD卡的CSD寄存器内容,从CSD寄存器可以得到SD卡的容量和扇区大小等十分重要的信息。

      至此,SD卡初始化基本就结束了,最后通过CMD7命令,选中要操作的SD卡,即可开始对SD卡的读写操作了。

1.3 SD/eMMC数据传输流程

1.3.1 传输模式

      分为LEGACY/SDMA/ADMA 3种传输模式,基本流程类似,LEGACY模式为轮询方式,需要CPU访问控制器的buffer寄存器直接存取数据。DMA方式则不需要,使用控制器自带的DMA控制器,CPU只需要准备好DMA使用的DDR基址或者DMA描述符,然后等待控制器自己完成数据搬移即可。

 1.3.2 读数据

单个block读取流程。

SD/eMMC初始化流程、读写流程(dwc mshc)_第3张图片

 多个block读取流程:

SD/eMMC初始化流程、读写流程(dwc mshc)_第4张图片

 1.3.3 写数据

单个block写入流程。

SD/eMMC初始化流程、读写流程(dwc mshc)_第5张图片

 多个block写入流程。

SD/eMMC初始化流程、读写流程(dwc mshc)_第6张图片

 2.调试问题

2.1 uboot

2.1.1 连续读4个以上block超时

【问题现象】

    Uboot命令行执行mmc read一次读4个以上block,提示超时失败。 

   (1) 连续读流程:CMD16 -> CMD18 -> CMD12;

   (2) Host发送CMD18开始读取多个block,前4个block能读到,第5个block读失败,中断状态寄存器未改变为期望的状态。从DDR中的内容看,前4个block的内容是正确的,说明问题出在读第5个block的时候;

   (3) 类似的流程,Host连续写4个以上block没有问题;

   (4) 使用Legacy或者DMA方式,现象一样。

【问题原因】

   设计人员仿真DMA方式传输5个block是可以的,怀疑是FPGA版本在buffer满的时候接口时钟没有关闭,这个跟实际芯片版本实现不一样,实际芯片版本当内部buffer满的时候,控制器会停掉供给card的时钟,这样就可以停止接收数据,当buffer内有一个block剩余空间的时候,重新打开时钟,这样就可以保证接收到正确的一个block。

   由于新出FPGA版本的问题,暂未确认上述怀疑及验证解决问题的版本。当前通过软件规避。当一次访问多个block时,按照4个block一组切片访问。当前ATF代码就是这样实现的。等正式版本出来,可以去掉该规避措施。

2.1.2 SD卡未识别

【问题现象】

   (1) SD卡与eMMC同时在位,分别连到控制器1和控制器0。Uboot执行命令行mmc info未扫描到SD卡;

   (2) 去掉mmc0的dts配置,仅保留mmc1的配置,还是没检测到。

=> mmc info                                                                                                                         

blk_find_device: if_type=6, devnum=0: [email protected], 6, 1                                                                        

MMC Device 0 not found                                                                                                              

no mmc device at slot 0                                                                                                             

Command failed, result=1                                                                                                            

=>           

【问题原因】

   Dts配置SD卡的别名,从mmc1改为sd0。

tsm_tx511_fpga.dtx

aliases {

mmc0 = &sdhci0;

sd0 = &sdhci1;       /*mmc1 = &sdhci1;*/

};

   Uboot命令行一次只能访问一个设备,通过mmc dev id#来切换设备。

=> mmc dev 0                                                                                                                        

blk_find_device: if_type=6, devnum=0: [email protected], 6, 0                                                                        

clock is disabled (0Hz)                                                                                                             

clock is enabled (400000Hz)                                                                                                         

clock is enabled (20000000Hz)                                                                                                       

clock is enabled (20000000Hz)                                                                                                       

blk_find_device: if_type=6, devnum=0: [email protected], 6, 0                                                                        

switch to partitions #0, OK                                                                                                         

mmc0(part 0) is current device    

=> mmc info                                                                                                                         

mmc num 2, curr_device 0                                                                                                            

blk_find_device: if_type=6, devnum=0: [email protected], 6, 0                                                                        

Device: mmc@f0d70000                                                                                                                

Manufacturer ID: 11                                                                                                                 

OEM: 100                                                                                                                            

Name: 032G7                                                                                                                         

Bus Speed: 20000000                                                                                                                 

Mode: MMC High Speed (52MHz)                                                                                                        

Rd Block Len: 512                                                                                                                   

MMC version 5.0                                                                                                                     

High Capacity: Yes                                                                                                                  

Capacity: 29.1 GiB                                                                                                                  

Bus Width: 4-bit                                                                                                                    

Erase Group Size: 512 KiB                                                                                                           

HC WP Group Size: 4 MiB                                                                                                             

User Capacity: 29.1 GiB WRREL                                                                                                       

Boot Capacity: 4 MiB ENH                                                                                                            

RPMB Capacity: 4 MiB ENH                                                                                                            

Boot area 0 is not write protected                                                                                                  

Boot area 1 is not write protected                                                                                                         

=>

=> mmc dev 1                                                                                                                        

blk_find_device: if_type=6, devnum=1: [email protected], 6, 0                                                                        

blk_find_device: if_type=6, devnum=1: [email protected], 6, 1                                                                        

clock is disabled (0Hz)                                                                                                             

clock is enabled (400000Hz)                                                                                                         

clock is enabled (20000000Hz)                                                                                                       

blk_find_device: if_type=6, devnum=1: [email protected], 6, 0                                                                        

blk_find_device: if_type=6, devnum=1: [email protected], 6, 1                                                                        

switch to partitions #0, OK                                                                                                         

mmc1 is current device                                                                                                              

=> mmc info                                                                                                                         

mmc num 2, curr_device 1                                                                                                            

blk_find_device: if_type=6, devnum=1: [email protected], 6, 0                                                                        

blk_find_device: if_type=6, devnum=1: [email protected], 6, 1                                                                        

Device: mmc@f0d71000                                                                                                                

Manufacturer ID: 3                                                                                                                  

OEM: 5344                                                                                                                           

Name: SB16G                                                                                                                         

Bus Speed: 20000000                                                                                                                 

Mode: SD High Speed (50MHz)                                                                                                         

Rd Block Len: 512                                                                                                                   

SD version 3.0                                                                                                                      

High Capacity: Yes                                                                                                                  

Capacity: 14.8 GiB                                                                                                                  

Bus Width: 4-bit                                                                                                                    

Erase Group Size: 512 Bytes                                                                                                            

=>

2.2 kernel

2.2.1驱动初始化依赖时钟配置

【问题现象】

   probe失败,打印时钟解析错误。

root@(none):/lib# insmod sdhci-of-dwcmshc.ko  

sdhci_of_dwcmshc: loading out-of-tree module taints kernel.   

[dwcmshc_probe] enter                                                                                                               

host ffffffc020652580                                                                                                               

pltfm_host->clk fffffffffffffffe                                                                                                    

sdhci-dwcmshc f0d70000.sdhci: failed to get core clk: -2     

sdhci-dwcmshc: probe of f0d70000.sdhci failed with error -2                                                                         

root@(none):/lib#

【问题原因】

   驱动模块初始化依赖时钟配置,需要在dts中显式配置,FPGA版本中配上桩。

sdhci0: sdhci@f0d70000 {

compatible = "snps,dwcmshc-sdhci";

status = "disabled";

interrupt-parent = <&gic>;

interrupts = <0 60 4>;

reg = <0x0 0xf0d70000 0x0 0x1000>;

clocks = <&misc_clk>, <&misc_clk>;

clock-names = "core", "bus";

};

2.2.2 mmc_test破坏eMMC中内容

【问题现象】

   执行mmc_test测试项之后重启,BL2被破坏。

root@(none):/# mount -t debugfs none /sys/kernel/debug                                                              

root@(none)::/# echo -n mmc0:0001 > /sys/bus/mmc/drivers/mmcblk/unbind

root@(none)::/# echo -n mmc0:0001 > /sys/bus/mmc/drivers/mmc_test/bind

root@(none)::/# cd /sys/kernel/debug/mmc0/mmc0:0001

root@(none):/sys/kernel/debug/mmc0/mmc0:0001# echo 2 > test 

mmc0: Starting tests of card mmc0:0001... 

mmc0: Test case 2. Basic read (no data verification)... 

mmc0: Result: OK                                                                                                                    

mmc0: Tests completed.                                                                                                              

root@(none):/sys/kernel/debug/mmc0/mmc0:0001#

   重启后启动失败:

NOTICE:  Booting Trusted Firmware                        

NOTICE:  BL1: v2.4(debug):e8b6f69-dirty     

NOTICE:  BL1: Built : 09:25:34, Dec 28 2021  

INFO:    BL1: CODE 0xf0d40000 RAM 0xf122e000 - 0xf123a000 

INFO:    emmc_8 boot.                                                                                                               

INFO:    BL1: Loading BL2                                                                                                           

WARNING: Firmware Image Package header check failed.     

WARNING: Failed to obtain reference to image id=1 (-2)     

ERROR:   Failed to load BL2 firmware.  

【问题原因】

   测试项会破坏内容,prepare函数会将缓存设置为00 01 02 03这样的内容,测试时写入,cleanup中会将缓存清零后写入。后将mmc_test测试地址偏移了2MB,以免破坏卡中内容。

SD/eMMC初始化流程、读写流程(dwc mshc)_第7张图片

2.2.3 SD卡fdisk分区失败

【问题现象】

   (1) Probe提示SD设备为ro,执行fdisk分区时无法写入分区表。

   (2) 对比操作eMMC,没有该问题,内核起来后重新mount eMMC,分区内容还在。

root@(none):/lib# insmod sdhci-of-dwcmshc.ko   

mmc1: sdhci: Version:   0x00000005 | Present:  0x03f70000    

mmc1: sdhci: Caps:      0x2768ffa0 | Caps_1:   0x08008077   

mmc1: Unknown controller version (5). You may experience problems. 

mmc1: sdhci: Auto-CMD23 available                                                                                                 

mmc1: SDHCI controller on f0d71000.sdhci [f0d71000.sdhci] using ADMA 

mmc1: new high speed SDHC card at address aaaa    

mmcblk1: mmc1:aaaa SB16G 14.8 GiB (ro)                                                                                              

root@(none):/lib#  

# fdisk /dev/mmcblk1                                                                                                                

'/dev/mmcblk1' is opened for read only                                                                                              

Device contains neither a valid DOS partition table, nor Sun, SGI, OSF or GPT disklabel    

Building a new DOS disklabel. Changes will remain in memory only, 

until you decide to write them. After that the previous content   

won't be recoverable. 

Command (m for help): w                                                                                                             

fdisk: write error: Bad file descriptor  

#

【问题原因】

   SD卡初始化过程会判断PSTATE寄存器的写保护状态,该寄存器WR_PROTECT_SW_LVL默认为0,软件认为卡写保护,因此Probe和写操作失败。

   mmc_test之所以可以正常读写,是因为将SD卡驱动从mmcblk切换到了mmc_test,测试过程中忽略了写保护状态。

   eMMC可以正常分区和读写,是因为eMMC跟SD卡走了不一样的软件流程,不判断写保护状态。

   与设计人员确认,硬件上不支持写保护,因此需要在配置中去使能写保护检测。

sdhci1: sdhci@f0d71000 {

compatible = "snps,dwcmshc-sdhci";

status = "disabled";

interrupt-parent = <&gic>;

interrupts = <0 62 4>;

reg = <0x0 0xf0d71000 0x0 0x1000>;

clocks = <&misc_clk>, <&misc_clk>;

clock-names = "core", "bus";

bus-width = <4>;

disable-wp;

};

3. 内核MMC

   Linux MMC 子系统主要分成三个部分:

   (1)MMC 核心层:完成不同协议和规范的实现,为 host 层和设备驱动层提供接口函数。MMC 核心层由三个部分组成:MMC,SD 和 SDIO,分别为三类设备驱动提供接口函数;

   (2)Host 驱动层:针对不同主机端的 SDHC、MMC 控制器的驱动;

   (3)Client 驱动层:针对不同客户端的设备驱动程序。如 SD 卡、T-flash 卡、SDIO 接口的 GPS 和 wi-fi 等设备驱动。

 系统框架:

SD/eMMC初始化流程、读写流程(dwc mshc)_第8张图片

  Linux MMC framework的工作流程如下:

SD/eMMC初始化流程、读写流程(dwc mshc)_第9张图片

4.调试命令

4.1 uboot

(1) mmc读操作

mmc read addr blk# cnt

(2) mmc写操作

mmc write addr blk# cnt

(3) mmc擦除操作

mmc erase blk# cnt

(4) 重新搜索mmc设备

mmc rescan

(5) 列出mmc的分区

mmc part - lists available partition on current mmc device

(6) 查看当前的设备号,或者设置设备号及分区

存在多个mmc设备时,可使用该命令切换设备

mmc dev [dev] [part] - show or set current mmc device [partition]

(7) 显示boot分区号

mmc bootpart [dev] [part] - show or set boot partition

(8) 列出当前的mmc设备

mmc list - lists available devices

(9) 打印当前mmc设备的信息

mmc info

(10) dump当前mmc控制器的寄存器信息

mmcdump       

4.2 kernel

4.2.1 mmc_test

(1) 挂载debugfs;

(2) 切换设备驱动到mmc_test;

(3) 在debugfs下执行测试项。

# mount -t debugfs none /sys/kernel/debug   

for eMMC                                                           

# echo -n mmc0:0001 > /sys/bus/mmc/drivers/mmcblk/unbind

# echo -n mmc0:0001 > /sys/bus/mmc/drivers/mmc_test/bind

# cd /sys/kernel/debug/mmc0/mmc0:0001

for SD

# echo -n mmc1:aaaa > /sys/bus/mmc/drivers/mmcblk/unbind

# echo -n mmc1:aaaa > /sys/bus/mmc/drivers/mmc_test/bind                                       

# cd /sys/kernel/debug/mmc1/mmc1\:aaaa/

debugfs下

cat testlist打印所有测试项

echo test_item > test执行测试项

4.2.2 文件系统读写

(1) 执行fdisk对设备分区;

(2) 执行mkfs创建文件系统;

(3) 执行mount挂载文件系统;

(4) 读写挂载的分区。

root@(none):~# fdisk /dev/mmcblk1                                                                                                   

Device contains neither a valid DOS partition table, nor Sun, SGI, OSF or GPT disklabel 

Building a new DOS disklabel. Changes will remain in memory only, 

until you decide to write them. After that the previous content   

won't be recoverable.                                                                                                                         

The number of cylinders for this disk is set to 486192.     

There is nothing wrong with that, but this is larger than 1024, 

and could in certain setups cause problems with: 

1) software that runs at boot time (e.g., old versions of LILO) 

2) booting and partitioning software from other OSs          

   (e.g., DOS FDISK, OS/2 FDISK)                                                                                                    

Command (m for help): n                                                                                                             

Partition type                                                                                                                      

   p   primary partition (1-4)                                                                                                      

   e   extended                                                                                                                     

p                                                                                                                                   

Partition number (1-4): 1                                                                                                           

First sector (16-31116287, default 16):                                                                                             

Using default value 16                                                                                                              

Last sector or +size{,K,M,G,T} (16-31116287, default 31116287): +131072                                     

Command (m for help): w                                                                                                             

The partition table has been altered.                                                                                               

Calling ioctl() to re-read partition table                                                                                          

 mmcblk1: p1                                                                                                                        

root@(none):~# fdisk /dev/mmcblk1

The number of cylinders for this disk is set to 486192.   

There is nothing wrong with that, but this is larger than 1024, 

and could in certain setups cause problems with:       

1) software that runs at boot time (e.g., old versions of LILO)     

2) booting and partitioning software from other OSs  

   (e.g., DOS FDISK, OS/2 FDISK)                                                                                                    

Command (m for help): p                                                                                                             

Disk /dev/mmcblk1: 15 GB, 15931539456 bytes, 31116288 sectors 

486192 cylinders, 4 heads, 16 sectors/track  

Units: sectors of 1 * 512 = 512 bytes                                                                                               

Device       Boot StartCHS    EndCHS        StartLBA     EndLBA    Sectors  Size Id Type   

/dev/mmcblk1p1    0,1,1       1023,3,16           16     131088     131073 64.0M 83 Linux                                           

Command (m for help): q                                                                                                             

root@(none):~# mdev -s                                                                                                              

root@(none):~# ls -lt /dev/mmc*                                                                                                     

brw-rw----    1 root     0         179,  25 Apr 15 08:05 /dev/mmcblk1p1 

brw-rw----    1 root     0         179,  24 Apr 15 08:04 /dev/mmcblk1 

brw-rw----    1 root     0         179,   0 Apr 15 08:02 /dev/mmcblk0    

brw-rw----    1 root     0         179,   8 Apr 15 08:02 /dev/mmcblk0boot0        

brw-rw----    1 root     0         179,  16 Apr 15 08:02 /dev/mmcblk0boot1           

crw-rw----    1 root     0         247,   0 Apr 15 08:02 /dev/mmcblk0rpmb            

root@(none):~# mkfs.ext2 /dev/mmcblk1p1                                                                                             

Filesystem label=                                                                                                                   

OS type: Linux                                                                                                                      

Block size=1024 (log=0)                                                                                                             

Fragment size=1024 (log=0)                                                                                                          

16384 inrandom: mkfs.ext2: uninitialized urandom read (16 bytes read)      

odes, 65536 blocks                                                                                                                  

3276 blocks random: mkfs.ext2: uninitialized urandom read (16 bytes read)     

(5%) reserved for the super user                                                                                                    

First data block=1                                                                                                                  

Maximum filesystem blocks=262144                         

8 block groups                                                                                                                      

8192 blocks per group, 8192 fragments per group   

2048 inodes per group                                                                                                               

Superblock backups stored on blocks: 

        8193, 24577, 40961, 57345                                                                                                   

root@(none):~# mkdir -p /mnt/sd1                                                                                                    

root@(none):~# mount /dev/mmcblk1p1 /mnt/sd1/                                                                                       

EXT4-fs (mmcblk1p1): mounting ext2 file system using the ext4 subsystem     

EXT4-fs (mmcblk1p1): mounted filesystem without journal. Opts: (null)   

root@(none):~# cd /mnt/sd1                                                                                                          

root@(none):/mnt/sd1# ls                                                                                                            

lost+found                                                                                                                          

root@(none):/mnt/sd1# cp /lib/sdhci-of-dwcmshc.ko ./22.ko       

root@(none):/mnt/sd1# ls -lt                                                                                                        

total 28                                                                                                                            

-rwxr-xr-x    1 root     0            15080 Apr 15 08:06 22.ko   

drwxr-xr-x    2 root     0            12288 Apr 15 08:05 lost+found  

root@(none):/mnt/sd1#   

4.2.3 sysfs

cat /sys/dwc_mshc/dwcmshcdbg

交替dump两个控制器的寄存器内容。

你可能感兴趣的:(emmc模块,emmc)