1.前言

前段时间测试同事在用androbench测试sdcard速率时,发现我们的机器总是比对比机器(三星S7)在读写速率方面慢很多,我们的机器读取速率基本在21MB/S左右,而对比机器一般在40MB/S左右。本文就介绍如上问题分析解决的整个过程。

2. 启动时的卡模式识别

通过启动时的打印可以看到我们的机器在识别卡的速率模式时,主要有两种情况:
卡识别情况一

通过三星S7对比样机的bugreport可以看到,同样一张卡(sandisk class10 32G UHI卡),三星 s7识别为ultra high speed DDR50

通过打印我们样机的dmesg, 发现我们的机器识别为high speed
通过如上的打印,很容易就定位到问题:由于卡识别的模式不同,自然速率也就不同,DDR50模式的工作速率为50MB/S,而high speed模式的工作速率为25MB/s。于是跟原厂最终的沟通结果是由于卡自身的原因导致报给MMC控制器的模式有问题,通过打印的结果也确实是上报给卡的最高速率为high speed(见下文),问题就此搁浅。
卡识别情况二
换另一张卡(TOSHIBA class10 32G UHI卡),我们的机器和对比机在启动时均能检测到卡的速率模式为DDR50,但是在实际速率测试时基本读速率为21MB/S, 偶尔也能测到39MB/S。
本文就以第二张卡的情况为例进行分析。
这里先对获取卡的速率模式,作一下简单说明,获取SD卡速率模式主要是依靠CMD6来完成,CMD6有两种功能一个是获取,另外一个是设置,同时还可以指定功能组,此处主要是利用CMD6的读取功能,功能组为1,也即是获取卡的速率模式。
对于上述卡识别情况一,通过在驱动中mmc_read_switch中加入打印,可以看到status[13] 返回的值为0x3,它就是CMD6 group1 查询模式时返回的SD卡支持的速率模式。
对应下表,0x3表示bit0和bit1置位,也就是支持Default和High-speed模式,不支持DDR50模式

注:对于UHI的卡,如果当前信号电压为3.3v, 则读取到的速率模式最高只能为HIGH SPEED/SDR25, 如果为1.8V, 才可以获取到所有支持的速率模式

3. 分析过程

对于第二张卡在初始识别时,与对比机器检测到为同一张卡,但是在测试时读取速率大多为21MB/S, 概率性的出现39MB/S, 而对比机器都是40MB/S左右,可以发现我们的问题就在于为何会概率性的读取速率为21MB/S,而让机器读取速率能稳定达到39MB/S以上是我们的目标。
读取速率问题跟整个IO栈都有关系,一开始不知道问题在哪里,就只能先通过工具,来缩小问题的范围。

3.1 fio测试

fio -direct=1 -iodepth=128 -rw=read -ioengine=libaio -bs=4k -numjobs=1 -runtime=30 -filename=/dev/block/mmcblk0p1 -name=test
首先通过fio测试来确认一下存储带宽的利用率,通过测试发现存储带宽利用率为98.5%,基本上接近满载,因此可以确认存储器件已经全负荷运转,不存在传输带宽利用不够的问题,同时通过fio进行裸分区测试可以进一步减少性能损耗,更接近器件的真实速率。

3.2 blktrace测试

通过blktrace加fio测试,来缩小问题的范围。
通过重现此问题,发现此卡有概率性读速率达到39MB/s的情况,抓取了此种情况的blktrace。同时抓取了读速率为21MB/S的blktrace进行比较(见下图),发现采用同样的fio测试命令,39M时的Q2C和D2C时间均小于21M时的Q2C和D2C,这说明21M时的耗时是发生在驱动及器件层,通过3.1 又知道传输带宽利用率较高,因此基本就确认不是由于文件系统层或block层导致的传输问题,而是由于驱动层及器件层导致的传输慢的问题。

读速率为21m时的D2C,横坐标为时间轴,纵坐标为D2C时间

读速率为21m时的Q2C,横坐标为时间轴,纵坐标为Q2C时间

读速率为39m时的D2C,横坐标为时间轴,纵坐标为D2C时间

读速率为39m时的Q2C,横坐标为时间轴,纵坐标为Q2C时间
注:如上对于blktrace的数据比较,也要考虑到request的大小,如果request大小不同,当然完成时间也不一样,这个可以通过下面的mmc trace event来进一步确认request的大小

3.3. mmc trace event

进一步通过抓取驱动层关于mmc的trace event,并对每个请求的执行时间进行统计,绘制散点图。通过mmc trace event抓取的信息分析,发现读取速率21MB/S时的每个request读数据完成时间均大于39M的。

读速率为 21MB/S时的request处理时间,横坐标为时间轴,纵坐标为request处理时间

读速率为 39MB/S时的request处理时间,横坐标为时间轴,纵坐标为request处理时间
我们知道MMC在读取操作时首先发送读取命令,然后执行数据读取,当数据读取命令完成和数据读取完成都会触发中断,并分别记录一条trace event,通过计算这两条trace event的时间差,可以作为一个request的器件读取时间,提取每个request的读取时间来作散点图,可进一步确认两种读取速率的差异。
因此通过上面的分析进一步确认了数据传输速率慢的原因就是器件的传输速率慢,这其中有可能的原因是:clock频率低,dev frequence调频,gating/ungating,通过对这些可能原因做调整基本没有改善。

3.4. 查看/sys/kernel/debug/mmc0/ios节点

在fio测试时,通过ios节点来查看卡的工作模式,发现卡在39MB/S读取速率时是工作在1.8V的工作模式,而卡在21MB/S读取速率时是工作在3.3v的工作模式。根据SD卡的规范,高速必须工作在1.8V,低速工作在3.3v,因此要想跑DDR50模式,必须首先将卡切换到1.8V,因此这里就要分析为何有时卡能切换到1.8v, 有时却不能。

读速率为 39MB/S时的ios信息

读速率为 21MB/S时的ios信息

3.5. 电压切换

通过进一步定位可以发现在如下代码中切换电压时,由于检测sdcard处于busy状态(实际是检测data0是否为低电平,低电平为busy状态),导致切换电压失败

我们根据spec中关于电压切换的描述如下:

实际测量电压切换波形如下,其中C1(黄色)为CLK,C2(红色)为CMD, C4(绿色)为DATA0

可以看出与spec中有如下差异:
切换命令后电压任然为3.3V,也即是在clk从stop重新变为start时,高电平仍然为3.3v,这显然是与spec不符合的,spec中约定clk从stop重新变为start时,高电平将为1.8V。
正常情况下,在切换电压成功后,信号电压之后的工作都将切换到1.8V, 然而通过示波器看却没有,为何?我们要找到电压切换的代码去看下。

3.6 电压切换流程

通过调用栈可以看到如下的电压切换流程:

[    7.538086] [<6>][78, kworker/6:1] sdhci_start_signal_voltage_switch+0x68/0x2d8
[    7.538087] [<6>][78, kworker/6:1] mmc_host_set_uhs_voltage+0x134/0x270
[    7.538088] [<6>][78, kworker/6:1] mmc_set_uhs_voltage+0xf8/0x1e8
[    7.538091] [<6>][78, kworker/6:1] mmc_sd_get_cid+0x128/0x230
[    7.554775] [<6>][78, kworker/6:1] mmc_sd_init_card+0x58/0x4c0
[    7.554777] [<6>][78, kworker/6:1] mmc_attach_sd+0x108/0x1c0
[    7.554779] [<6>][78, kworker/6:1] mmc_rescan+0x244/0x328
[    7.574050] [<6>][78, kworker/6:1] process_one_work+0x204/0x458
[    7.574051] [<6>][78, kworker/6:1] worker_thread+0x304/0x480
[    7.574052] [<6>][78, kworker/6:1] kthread+0x118/0x128
[    7.574053] [<6>][78, kworker/6:1] ret_from_fork+0x10/0x18

sdhci_start_signal_voltage_switch函数中在设置1.8v时会通过sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2)来触发power irq,由sdhci_msm_pwr_irq>sdhci_msm_set_vdd_io_vol函数完成电压切换, 这里我们惊奇的发现无论设置为多少的电压,示波器量到的都是3.3V左右,而打印的电压值都是1.8V,这个让我们怀疑是电压配置有问题,去查下dts

3.7 dts电源检查

通过反编译最后的fdt文件,发现vdd io的电压范围值1.8~1.8, 也就是只能设置为1.8v,这路电压应该是1.8V~3.3V才对。对照原理图发现是将卡插拔检测的电压源配置为VDD IO的电压源导致的问题。通过修改DTS中关于此部分的设置,读写速率正常

4. 总结

本文主要总结了sdcard速率问题的分析思路,主要的思路就是通过逐步缩小问题范围,最终定位到问题点。分析过程中运用了一些工具,这些工具对定位问题起到很重要的作用,但是除了工具,分析代码的流程以及对SD规范的了解也是必不可少的。当然有些检查点是一开始就要去检查的,比如一开始就要检查dts配置是否正确,但是由于卡本来是可以工作的,所以阴差阳错的没有考虑到这个问题。另本问题在测试速率为21m和39M的情况下,是否可以想象为2倍的关系,进而直接证实猜测。
本次调试得到李大和各位的耐心指导,在此表示感谢!

关于sdcard读写速率慢的问题排查相关推荐

  1. linux怎么测试磁盘读写,怎样测试Linux磁盘的读写速率

    为了测试Linux磁盘的读写速率,否运用dd号令,dd号令是一个十分运用的号令,否用于文件的拷贝,上面小编便给各人引见了若何运用dd号令测试Linux磁盘的读写速率吧. 一.先相熟二个特殊的设施: ( ...

  2. android 申请sdcard权限_Android sdcard读写权限问题之中的一个

    博主在刚刚在学习过程中发现了一个关于android往sdcard读写的问题, 配置了该配置的提示无读写权限. 在AndroidManifest.xml文件里配置清单例如以下 package=" ...

  3. Android sdcard读写权限问题之中的一个

    博主在刚刚在学习过程中发现了一个关于android往sdcard读写的问题, 配置了该配置的提示无读写权限. 在AndroidManifest.xml文件里配置清单例如以下 <manifest ...

  4. Android sdcard读写文件(二)

    继续说sdcard读写文件的情况,这篇博客说的是在sdcard根目录中读写文件,着重的而是多种方式的读写文件.直接给出代码: FileService.java package com.llp.clas ...

  5. Android5.0后外置SDCard读写

    首先得明确一个概念:Android有获取外置SDCard路径的API,但是这个外置 SDCard的概念是指系统内部分出来的外置和我们插上的那张外置SDCard, 系统对于这两种SDCard是区分不出来 ...

  6. java面试(二十五)--(1)redis为什么读写速率快性能好(2)说说web.xml文件中可以配置哪些内容(3)和的区别(4)扑克牌顺子

    1. redis为什么读写速率快性能好? 1.Redis将数据存储在内存上,避免了频繁的IO操作 2.Redis其本身采用字典的数据结构,时间复杂度为O(1),且其采用渐进式的扩容手段 3.Redis ...

  7. Proxmox VE PVE 机械盘、固态盘、固态缓存盘ceph存储性能对比(iops 读写速率)

    今日因工作需要搭建了Proxmox VE PVE私有云,顺便把纯机械盘ceph.纯固态盘ceph.以及机械盘+固态缓存盘ceph的性能(含iops和读写速率)进行了对比测试.测试物理服务器为HP DL ...

  8. 8TB高速存储卡,6GB/s的读写速率,适合高速流盘、信号采集存储的各种应用场景

    高速信号采集和回放系统,需要有足够高的速率把连续采集的数据存储到磁盘,或者把信号生成的数据从磁盘中读取出来.一般应用中,数据主要通过SATA.USB.RJ45(百兆.千兆)等多种方式传输,但这些速率对 ...

  9. 使用PDH性能计数器(Windows)获取CPU使用率、可用物理内存、上传/下载速率、磁盘读写速率

    最近要写一个windows下的监控客户端,需要收集计算机的一些信息. 其中CPU使用率.可用物理内存(用于计算内存使用率).上传/下载速率.磁盘读写速率,都需要实时的.各种资料查询之后,决定使用pdh ...

最新文章

  1. 取消水晶报表的数据库登录框 分享
  2. APPIUM Android 定位方式
  3. 信息系统项目管理师-配置管理知识点
  4. 海思Hi3519A 进行4k60 h264编码帧率不足的问题
  5. 使用XFire+Spring构建Web Service(二)
  6. linux线程(互斥锁、条件)
  7. iOS 5 编程(1)-图像视图、滑块和步进控件的使用(源码下载)
  8. Java分布式锁的概念以及使用优点
  9. bt python_bt宝塔 安装个python失败? 阿里云轻量香港
  10. python中如何判断词性_python进行词性分析
  11. 虚拟机usb服务器,VM虚拟机支持USB启动的方法
  12. Linux隧道sit
  13. 【每日早报】2019/10/08
  14. Laravel数据库 Eloquent 操作返回值
  15. Memcached应用总结
  16. WUSTOJ 1923 一笔画 【回溯】
  17. 【机试题】2014大疆嵌入式笔试题(附超详细解答,下篇)
  18. 该升级了,阿里云Code升级Codeup | 云效
  19. [英语阅读]投机者-Lame duck
  20. 西城微方案设计——电子秤PCBA蓝牙语音秤方案

热门文章

  1. 2021年高处安装、维护、拆除考试试卷及高处安装、维护、拆除证考试
  2. 鲲鹏devkit(迁移 测试 性能分析) boostkit
  3. PIO操作与DMA操作
  4. 数据外泄保护与国土安全部
  5. 【数据分析自学】一、系统认识数据分析
  6. 几组超神奇的网页应用代码要你在IE浏览器任意打开一个网站,然后在浏览器上输入如下代码神奇的代码,可随意修改复制页面内容!
  7. CSR867x — Speaker Equalizer曲线调试笔记
  8. 吊炸天MyCat入门
  9. js+css如何制作(音频)图标【切换播放动画】效果?
  10. 计算机病毒与防护学生反思,计算机病毒与防治教学反思