硬件环境:am335x + SD卡

SD卡类型:class4,class10

问题现象:板子使用sd卡启动,内核启动后,在检测sd卡的时候出错:”mmc0: error -110 whilst initialising SD card” ,换一张就的sd卡却可以正常识别。不能识别的卡是class10的,可以识别的卡是class4的,那么由此推断卡的速度太快导致无法正常识别卡?想想也说不通,因为并不是所有的class4的卡都能够识别,只有最旧的那一批卡才能识别。那么怎样才能定位问题所在呢?

方法一:对比开发板和自己的板子,发现硬件原理差不多,但开发板无论用哪一种卡都能正常启动,两者采用的内核镜像都一样的,但自己的板子用高速卡(class10)总是启动不了。

方法二:在内核源码中找到sd卡初始化的那部分(/driver/mmc/core/sd.c和/driver/mmc/core/core.c),用printk在关键的地方标注,那么就可以定位问题出在哪里。经过测试,发现每次卡起不来的地方都在设置总线宽度的地方,屏蔽总线宽度的设置后问题依然。

方法三:下载SD卡的协议文档仔细研究一下。SD4.0协议文档只有一百页左右,很快可以看完,我之所以找4.0的协议文档是因为有中文版,看起来方便。sd卡使用的是sdio总线,其中很重要的是要知道CMDx命令代表什么含义。通讯时主机端发送cmd请求,客户端就会应答,如果客户端超时不应答,主机端就会重发,默认重发三次,如果仍然不响应则会报出超时的错误“error -110”。

方法四:开启内核debug模式,打印sd卡初始化时发送的命令及响应码。开启debug模式可以直接在内核菜单里开启,在mmc配置里面有debug的开关,打开即可。

[    1.449158] sdhci: Secure Digital Host Controller Interface driver
[    1.455431] sdhci: Copyright(c) Pierre Ossman
[    1.461366] omap_hsmmc 48060000.mmc: Got CD GPIO
[    1.505216] mmc0: mmc_rescan_try_freq: trying to init card at 400000 Hz
[    1.511893] mmc0: starting CMD52 arg 00000c00 flags 00000195
[    1.518133] mmc0: req done (CMD52): -110: 00000000 00000000 00000000 00000000
[    1.525686] mmc0: starting CMD52 arg 80000c08 flags 00000195
[    1.531767] mmc0: req done (CMD52): -110: 00000000 00000000 00000000 00000000
[    1.540039] mmc0: starting CMD0 arg 00000000 flags 000000c0
[    1.546684] Synopsys Designware Multimedia Card Interface Driver
[    1.553058] mmc0: req done (CMD0): 0: 00000000 00000000 00000000 00000000
[    1.561968] mmc0: starting CMD8 arg 000001aa flags 000002f5
[    1.569251] sdhci-pltfm: SDHCI platform and OF driver helper
[    1.575356] mmc0: req done (CMD8): 0: 000001aa 00000000 00000000 00000000
[    1.582234] mmc0: starting CMD5 arg 00000000 flags 000002e1
[    1.595498] mmc0: req failed (CMD5): -110, retrying...
[    1.609506] mmc0: req failed (CMD5): -110, retrying...
[    1.615220] mmc0: req failed (CMD5): -110, retrying...
[    1.620786] mmc0: req done (CMD5): -110: 00000000 00000000 00000000 00000000
[    1.633543] mmc0: starting CMD55 arg 00000000 flags 000000f5
[    1.639573] mmc0: req done (CMD55): 0: 00400120 00000000 00000000 00000000
[    1.646606] mmc0: starting CMD41 arg 00000000 flags 000000e1
[    1.652621] mmc0: req done (CMD41): 0: 40ff8000 00000000 00000000 00000000
[    1.660622] mmc0: starting CMD0 arg 00000000 flags 000000c0
[    1.672314] can: controller area network core (rev 20120528 abi 9)
[    1.678806] mmc0: req done (CMD0): 0: 00000000 00000000 00000000 00000000
[    1.687765] mmc0: starting CMD8 arg 000001aa flags 000002f5
[    1.713784] mmc0: req done (CMD8): 0: 000001aa 00000000 00000000 00000000
[    1.720692] mmc0: starting CMD55 arg 00000000 flags 000000f5
[    1.739251] mmc0: req done (CMD55): 0: 00000120 00000000 00000000 00000000
[    1.746258] mmc0: starting CMD41 arg 40200000 flags 000000e1
[    1.751972] omap common late init begin 111
[    1.756200] mmc0: req done (CMD41): 0: 40ff8000 00000000 00000000 00000000
[    1.785306] mmc0: starting CMD55 arg 00000000 flags 000000f5
[    1.794037] mmc0: req done (CMD55): 0: 00000120 00000000 00000000 00000000
[    1.801024] mmc0: starting CMD41 arg 40200000 flags 000000e1
[    1.810307] mmc0: req done (CMD41): 0: 40ff8000 00000000 00000000 00000000
[    1.832705] mmc0: starting CMD55 arg 00000000 flags 000000f5
[    1.838722] mmc0: req done (CMD55): 0: 00000120 00000000 00000000 00000000
[    1.845734] mmc0: starting CMD41 arg 40200000 flags 000000e1
[    1.851805] mmc0: req done (CMD41): 0: c0ff8000 00000000 00000000 00000000
[    1.858836] mmc0: starting CMD2 arg 00000000 flags 00000067
[    1.864729] pdevinfo->name = cpufreq-dt,pdevinfo->id = 0xffffffff
[    1.870875] pdev = 0xddc0ec00
[    1.873962] pdevinfo->dma_mask= 0x0
[    1.877496] mmc0: req done (CMD2): 0: 03534453 43313647 80b91040 970127ab
[    1.884410] mmc0: starting CMD3 arg 00000000 flags 00000075
[    1.890044] pdev= 0xddc0ec00, pdevinfo->res=0x0,pdevinfo->num_res = 0x0, xxxxx444
[    1.897583] mmc0: req done (CMD3): 0: aaaa0520 00000000 00000000 00000000
[    1.904513] mmc0: starting CMD9 arg aaaa0000 flags 00000007
[    1.917946] mmc0: req done (CMD9): 0: 400e0032 5b590000 76b27f80 0a404013
[    1.924879] mmc0: starting CMD7 arg aaaa0000 flags 00000015
[    1.930817] mmc0: req done (CMD7): 0: 00000700 00000000 00000000 00000000
[    1.937740] mmc0: starting CMD55 arg aaaa0000 flags 00000095
[    1.959956] mmc0: req done (CMD55): 0: 00000920 00000000 00000000 00000000
[    1.966953] mmc0: starting CMD51 arg 00000000 flags 000000b5
[    1.972699] mmc0:     blksz 8 blocks 1 flags 00000200 tsac 100 ms nsac 0
[    1.979846] omap common late init begin 444
[    1.984153] mmc0: req done (CMD51): 0: 00000920 00000000 00000000 00000000
[    1.984162] mmc0:     8 bytes transferred: 0
[    1.995457] mmc0: starting CMD55 arg aaaa0000 flags 00000095
[    2.001188] am33xx_int process omap late init
[    2.005590] mmc0: req done (CMD55): 0: 00000920 00000000 00000000 00000000
[    2.012624] mmc0: starting CMD13 arg 00000000 flags 000001b5
[    2.018326] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 100 ms nsac 0
[    2.044602] mmc0: req done (CMD13): 0: 00000920 00000000 00000000 00000000
[    2.044611] mmc0:     64 bytes transferred: 0
[    2.055988] mmc0: starting CMD6 arg 00fffff0 flags 000000b5
[    2.061604] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 100 ms nsac 0
[    2.077084] mmc0: req done (CMD6): 0: 00000900 00000000 00000000 00000000
[    2.077093] mmc0:     64 bytes transferred: 0
[    2.088364] mmc0: host does not support reading read-only switch, assuming write-enable
[    2.103847] mmc0: starting CMD6 arg 80fffff1 flags 000000b5
[    2.109466] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 100 ms nsac 0
[    2.116389] ThumbEE CPU extension supported.
[    2.120739] Registering SWP/SWPB emulation handler
[    2.130224] mmc0: req done (CMD6): 0: 00000900 00000000 00000000 00000000
[    2.137086] mmc0:     64 bytes transferred: 0
[    2.141742] mmc0: starting CMD55 arg aaaa0000 flags 00000095
[    2.176752] mmc0: req done (CMD55): -110: 00000000 00000000 00000000 00000000
[    2.186582] mmc0: starting CMD55 arg aaaa0000 flags 00000095
[    2.192354] mmc0: req done (CMD55): -110: 00000000 00000000 00000000 00000000
[    2.199695] mmc0: starting CMD55 arg aaaa0000 flags 00000095
[    2.234747] mmc0: req done (CMD55): -110: 00000000 00000000 00000000 00000000
[    2.242419] mmc0: starting CMD55 arg aaaa0000 flags 00000095
[    2.277455] mmc0: req done (CMD55): -110: 00000000 00000000 00000000 00000000
[    2.284800] mmc0: error -110 whilst initialising SD card
[    2.290352] mmc0: starting CMD1 arg 00000000 flags 000000e1
[    2.325414] mmc0: req done (CMD1): -110: 00000000 00000000 00000000 00000000

从debug的信息里面可以知道SD卡识别出错是报了超时的错误,CMD55响应超时,那么CMD55代表什么意思?查看SD协议可知CMD55是“特定应用命令 ”,就是说发送特定应用的命令之前必须先发送CMD55, 那么究竟是哪个命令导致CMD55超时呢?往前一个命令是CMD6,这个CMD6是切换功能命令,包含四种功能组:
(1) 访问模式:SD 总线接口速度模式的选择
(2) 命令系统:通过一套共有的命令来扩展和控制特定的功能
(3) 驱动强度:在 UHS-I 模式下选择合适的输出驱动强度,取决于主机环

(4) 电流/功率限制:UHS-I 卡在 UHS-I 模式下最大电流的选择,取决于
主机电源能力和散热能力(heat release)。这个字段在 UHS-II
卡中被重新定义为功率限制,因为 UHS-II 卡具有两种电源电压。

通过命令参数“mmc0: starting CMD6 arg 80fffff1 flags 000000b5”,可知该命令是用于切换SD卡的速度,猜测这里是由于切换SD卡速度导致通讯发生异常,CMD55也就会响应超时。带着这个假设,我把SD卡切换高速模式的那部分代码屏蔽掉,重新编译内核,发现问题依旧。

方法5::着对比旧的SD卡,看看有什么不同。把带有debug信息的内核拷贝到旧SD卡里面,插到板子上电测试,系统启动后打印下面的信息:

[    1.870768] mmc0: starting CMD7 arg 00010000 flags 00000015
[    1.886008] mmc0: req done (CMD7): 0: 00000700 00000000 00000000 00000000
[    1.892918] mmc0: starting CMD55 arg 00010000 flags 00000095
[    1.902160] mmc0: req done (CMD55): 0: 00000920 00000000 00000000 00000000
[    1.909148] mmc0: starting CMD51 arg 00000000 flags 000000b5
[    1.914896] mmc0:     blksz 8 blocks 1 flags 00000200 tsac 100 ms nsac 0
[    1.929329] mmc0: req done (CMD51): 0: 00000920 00000000 00000000 00000000
[    1.929340] mmc0:     8 bytes transferred: 0
[    1.940623] mmc0: starting CMD55 arg 00010000 flags 00000095
[    1.954517] mmc0: req done (CMD55): 0: 00000920 00000000 00000000 00000000
[    1.961477] mmc0: starting CMD13 arg 00000000 flags 000001b5
[    1.974016] mmc0:     blksz 64 blocks 1 flags 00000200 tsac 100 ms nsac 0
[    1.980902] omap2_common_pm_late_init: omap2 common 11xxx
[    1.986420] mmc0: req done (CMD13): 0: 00000920 00000000 00000000 00000000
[    1.986429] mmc0:     64 bytes transferred: 0
[    1.997795] mmc0: host does not support reading read-only switch, assuming write-enable
[    2.014792] mmc0: starting CMD55 arg 00010000 flags 00000095
[    2.020523] mmc0: req done (CMD55): 0: 00000920 00000000 00000000 00000000
[    2.027510] mmc0: starting CMD6 arg 00000002 flags 00000015
[    2.033162] am33xx_int process omap late init
[    2.037552] pdevinfo->name = pm33xx,pdevinfo->id = 0x0
[    2.042795] mmc0: req done (CMD6): 0: 00000920 00000000 00000000 00000000
[    2.049720] mmc0: new SDHC card at address 0001
[    2.070290] mmcblk0: mmc0:0001 SD8GB 7.28 GiB
[    2.076244] mmc0: starting CMD18 arg 00000000 flags 000000b5
[    2.081961] mmc0:     blksz 512 blocks 8 flags 00000200 tsac 100 ms nsac 0
[    2.097570] mmc0:     CMD12 arg 00000000 flags 00000095
[    2.103326] xxxxxx888 ret = 0x0
[    2.106499] am33xx_int process pm init
[    2.110326] ThumbEE CPU extension supported.
[    2.119725] mmc0: req done (CMD18): 0: 00000900 00000000 00000000 00000000
[    2.119734] mmc0:     4096 bytes transferred: 0
[    2.119749] mmc0:     (CMD12): 0: 00000b00 00000000 00000000 00000000
[    2.137958]  mmcblk0: p1 p2

只需对比sd卡启动的部分,发现旧的SD卡并没有切换SD卡速度的命令(切换速度的命令是CMD6,ACMD6是用于切换总线宽度,区别是前面带有CMD55),由此得出的结论是旧卡没有切换SD的到高速模式,所以能正常工作,新卡切换了高速模式,导致通讯异常,卡无法识别。那为什么屏蔽设置高速模式的那部分代码并不能解决问题呢?其实在测试过程中就得到了答案,当我打开调试模式时,屏蔽高速模式的那部分代码后SD卡是能正常工作,而去掉调试模式后SD卡却无法正常工作,那么两者有啥区别?答案是有调试模式时,代码执行速度变慢了,导致时序也变慢,SD卡识别的时候就没那么容易超时了。那么解决问题的切入点就在延时方面下手,如果加delay应该在哪加呢?看了一会代码,发现加delay会影响SD卡的读写速度,可以选择另外一种方式:调整CMD命令的重发次数,默认重发次数是3,修改为10后再测试,发现问题解决了。以此印证之前的猜想,重发次数改为10,再配合去掉SD卡高速切换就能解决问题。说明板子用新卡的时候重发次数有可能超过三次,从而导致无法识别卡。

SD卡无法识别的问题解决 ”mmc0: error -110 whilst initialising SD card”相关推荐

  1. mmc0: error -84 whilst initialising SD card

    玩zynqMP的板子上的SOC,TF作为root启动petalinux系统, 碰到如下报错: error -84 whilst initialising SD card 查询Kernel代码中的sd. ...

  2. SD卡无法识别怎么办?

    SD卡是一种可移动存储设备,广泛应用于各种电子设备,如Android智能手机.平板电脑或相机等,您可以将SD卡连接到计算机以传输一些文件.但有些时候,当您打开文件资源管理器后,可能会发现您的SD卡不显 ...

  3. 多媒体卡和SD卡的卡识别过程

    多媒体卡和SD卡的卡识别过程是有区别的: 对于多媒体卡,卡识别过程以时钟频率Fod开始,所 有SDIO_CMD输出为开路驱动,允许在这个过程中的卡的并行连接,识别过程如下: 1.  总线被激活 2. ...

  4. Linux格式化sd卡博客,linux设备驱动那点事儿之SD卡驱动理论篇

    一.SD/MMC卡介绍 1.1.什么是MMC卡 MMC:MMC就是MultiMediaCard的缩写,即多媒体卡.它是一种非易失性存储器件,体积小巧(24mm*32mm*1.4mm),容量大,耗电量低 ...

  5. 海思IPC平台快速拔插SD卡会出现SD卡不识别解决方法

    内核需要定时检测SD卡是否插入或拔出,默认给的定时检测时间为200ms. 此定时检测时间也可通过配置内核menuconfig更改.配置路径及配置选项如下: Device Drivers ---> ...

  6. linux内核镜像sd卡,【原创】Linux QT镜像的制作--制作SD卡启动盘

    最近买了个新的开发板,原生的是Android操作系统,需要自己少个启动盘,制作Linux+QT操作系统. 新的开发板带这个制作的源文件,要先把这个文件拷贝到虚拟机Ubunbtu的共享目录下. 打开sh ...

  7. sd卡测速工具_拍完照回家发现SD卡损坏,拯救你的照片就用这个办法!

    SD卡可以说是目前相机存储的主要工具,一旦拍照结束后出了问题,那可是最头疼的事情. 我昨天就碰到了这样奇怪的事情,拍照回来正要导出数据,发现电脑系统提示要格式化存储卡,经过几次插拔发现依然不能识别.如 ...

  8. sd卡的照片误删了怎么办 不小心删了sd卡的照片

    sd卡的照片误删了怎么办?不小心删了sd卡的照片?SD卡现在使用相对较少,但很多人以前的重要文件都已经存储在里面了,那么如何恢复SD卡中的重要照片和其他文件呢?小编在这里有一个很好的方法,让我们一起来 ...

  9. android 模拟器 sd卡文件 fileexport,linux下android模拟器的启动和SD卡的使用介绍.pdf...

    主机配置主机配置 32 位 XP vbox 虚拟机 32 位 ubuntu10 04 android2 2 源码 JDK1 5 1 编译编译 android2 2 源码源码 编译环境准备好之后 在终端 ...

  10. linux sd卡 u盘区别,linux下实现U盘和sd卡的自动挂载

    目的:使U盘和sd卡在linux系统中进行插入和拔除时能自动挂载和卸载,不需要手动mount和umount.步奏:1.在/etc/init.d/rcS中加入以下语句 echo /sbin/mdev & ...

最新文章

  1. vue上传录音_vue用到H5+的录音功能 真机模拟的时候不能实现
  2. 全志代码中的bug之2
  3. fatal error C1083: Cannot open include file: 'ceconfig.h': No such file or directory
  4. php-v 查看不到版本,解決php -v查看到版本於phpinfo()打印的版本不一致問題
  5. oracle字符串使用函数,oracle函数大全-字符串处理函数
  6. World Currency Symbols世界货币符号
  7. BZOJ2006:[NOI2010]超级钢琴——题解
  8. 关于python函数参数的描述中、错误的是_在Python中,以下关于函数的描述错误的是哪一项?...
  9. 常见神经系统疾病的临床诊断及处理原则题库【1】
  10. android无障碍功能开发,威尼斯游戏-官网首页
  11. 密码学系列 - 棱镜门
  12. 我将进化成一条狗(7)——脑机接口
  13. Android R.java类的手动生成
  14. 基于Java开发的分布式在线教育系统,支持考试、直播、问答
  15. 人脸检测,身份证扫描调三方接口获取图片base64路径转file,存入数据库(Vue)
  16. 人员抽烟行为识别检测算法
  17. 关键点检测-HRNet
  18. python女朋友_原来Python可以找到女朋友,真的是出乎我的意料之外啊
  19. 阿里云服务器配置免费https服务
  20. Java与C/C++的连动

热门文章

  1. 中国传统的节日(端午节)
  2. 80C51汇编语言编程实验报告,80C51单片机-实验报告.doc
  3. 爬虫入门经典(十六) | 一文带你爬取斗鱼主播相关信息
  4. 主播名字和热度的字符串该怎么写啊,他们两个量前面的字符一样
  5. YouTube:如何删除油管频道Channel
  6. DSPE-PEG-Alkyne/CHO 磷脂聚乙二醇炔基/醛基
  7. wordpress 如何添加Canonical 标签(不通过插件)
  8. 用非门74HC04与无源晶振产生时钟信号的两种电路
  9. JavaScript工具函数
  10. 论文笔记:多标签学习——ACkEL算法