博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用mmc_test.c研究mmc模块
阅读量:4225 次
发布时间:2019-05-26

本文共 4293 字,大约阅读时间需要 14 分钟。

        近日开始研究mmc模块。老是看代码不免困意来袭,为了克服困意,可以通过一些小的试验来加深对该模块的理解。

        第一步:

        首先,自己创建了一个小的测试模块,通过获取mmc模块初始化时sdhci_host结构体的指针(初始化时就将这些sdhci_host结构的指针保存在一个数组,并提供接口导出该数组首地址供其它模块使用)为神秘的mmc子系统打开一扇窗口。

注册sdhci_host的文件中需要做如下改动:

static unsigned int host_addr[5] = {0}; static unsigned int host_count = 0; static int xxx_sdhci_host_probe(struct platform_device *pdev){... host = sdhci_alloc_host(&pdev->dev, sizeof(struct xxx_sdhci_host)); host_addr[host_count ++] = host;...}unsigned int *export_host_addr(){ return host_addr;}EXPORT_SYMBOL(export_host_addr);

测试文件获取到sdhci_host结构体的方法:

 

extern unsigned int *export_host_addr();int test_init(){... unsigned int *host_addr = export_host_addr(); struct sdhci_host *host = NULL; struct mmc_host *mmc = NULL; struct mmc_card *card = NULL;... host = (struct sdhci_host *)host_addr[0];//至此,我们已经成功获取到sdhci_host mmc = host->mmc; card = mmc->card;...}

 

 

        通过上述代码可以看出,我们获取到sdhci_host结构体之后,可以进一步获取到对应的mmc_host 结构体,进而获取到和该控制器对应的mmc_card结构体。我当前的mmc子系统用到3个mmc_host(mmc/sdio/sd),对应两个mmc_card:mmc——emmc,sd——外接sd卡。

 

        第二步:

        获取到这些重要的结构体后,我们就可以参考mmc_init的流程,向mmc发送一些指令,如go_idle/send_op_cond/send_cid/send_csd/send_ext_csd(遵循mmc_init流程,其他指令都能顺利执行,唯独send_ext_csd指令会超时,至今原因不明,哪位朋友知道请告知,不胜感激)等,掌握mmc控制器和card交互的最基本指令。

 

        第三步: 

        接下来,想研究一下I/O接口的调用方法,毕竟emmc/sd卡最重要的作用是用来存储数据。恰好,在mmc/card/目录下发现了文件mmc_test.c,打开一看,好像有用来测试读写接口的方法,真是天助我也!果断将该文件编译为动态模块,但加载后发现并未执行任何实际操作,仅仅添加了一个测试驱动。继续看代码,发现只有触发probe函数才会做一些具体的事情:在debugfs中创建两个文件节点test和testlist,供用户通过"echo/cat"指令进行操作——事实上所有实际工作都是用户通过操纵在debug文件系统中创建的两个节点来进行。我们知道,想要触发probe函数,还需要注册一个和驱动名一致的设备。难道我们为了创建这两个文件节点,一定要注册一个名为"mmc_test"的设备才行吗?

 

        答案是不需要如此麻烦!我们完全可以将这两个创建文件节点的接口移到init函数中嘛,或者直接在init函数中就去调用probe函数,问题不久迎刃而解了吗?

 

        再来看probe函数,只需要给它传入一个合法的mmc_card指针就足够了,而我们在第一步已经介绍过如何获取到合法的mmc_card指针,这里直接拿来用就可以了(mmc = sdhci_host->mmc, card = mmc->card)。

 

        万事俱备,开始试验!

# ls

ls
state
status
test
testlist

        加载该测试模块后可以看到,在该目录下创建了2个测试节点:test和testlist。执行第25项测试的指令如下:
# echo 25 > test

      测试结果如下:
<6>[ 2479.634882] c1 mmc_test: mmc1: Starting tests of card mmc1:1234...
<6>[ 2479.634912] c1 mmc_test: mmc1: Test case 25. Best-case read performance into scattered pages...
<6>[ 2479.748526] c2 mmc_test: mmc1: Transfer of 1 x 8 sectors (1 x 4 KiB) took 0.000564193 seconds (7259 kB/s, 7089 KiB/s, 1772.44 IOPS, sg_len 1)
<6>[ 2479.748570] c2 mmc_test: mmc1: Result: OK
<6>[ 2479.748633] c2 mmc_test: mmc1: Tests completed.

 

       下述指令,可以看出test模块支持的测试项:

# cat testlist
cat testlist
1:      Basic write (no data verification)
2:      Basic read (no data verification)
3:      Basic write (with data verification)
4:      Basic read (with data verification)
5:      Multi-block write
6:      Multi-block read
7:      Power of two block writes
8:      Power of two block reads
9:      Weird sized block writes
10:     Weird sized block reads
11:     Badly aligned write
12:     Badly aligned read
13:     Badly aligned multi-block write
14:     Badly aligned multi-block read
15:     Correct xfer_size at write (start failure)
16:     Correct xfer_size at read (start failure)
17:     Correct xfer_size at write (midway failure)
18:     Correct xfer_size at read (midway failure)
19:     Highmem write
20:     Highmem read
21:     Multi-block highmem write
22:     Multi-block highmem read
23:     Best-case read performance
24:     Best-case write performance
25:     Best-case read performance into scattered pages
26:     Best-case write performance from scattered pages
27:     Single read performance by transfer size
28:     Single write performance by transfer size
29:     Single trim performance by transfer size
30:     Consecutive read performance by transfer size
31:     Consecutive write performance by transfer size
32:     Consecutive trim performance by transfer size
33:     Random read performance by transfer size
34:     Random write performance by transfer size
35:     Large sequential read into scattered pages
36:     Large sequential write from scattered pages
37:     Write performance with blocking req 4k to 4MB
38:     Write performance with non-blocking req 4k to 4MB
39:     Read performance with blocking req 4k to 4MB
40:     Read performance with non-blocking req 4k to 4MB
41:     Write performance blocking req 1 to 512 sg elems
42:     Write performance non-blocking req 1 to 512 sg elems
43:     Read performance blocking req 1 to 512 sg elems
44:     Read performance non-blocking req 1 to 512 sg elems
45:     eMMC hardware reset

        由此,可以打开一个操作mmc/sd卡的入口,再结合代码,很轻松就可以弄清楚各个指令是如何调用。

转载地址:http://xqbqi.baihongyu.com/

你可能感兴趣的文章
MySQL的基本管理
查看>>
MySQL 表结构与键值
查看>>
MySQL存储引擎,表记录管理
查看>>
Mysql多表查询语句,授权用户与密码更改
查看>>
MySQL 备份与恢复
查看>>
函数可重入性及编写规范
查看>>
想成为嵌入式程序员应知道的0x10个基本问题
查看>>
可重入函数与不可重入函数
查看>>
关于预处理器的学习
查看>>
Windows CE下操作GPIO的方法(以ARM9 S3C2410为例)
查看>>
s3c2410物理地址和虚拟地址空间
查看>>
VC中常用数据类型转换
查看>>
VC中常用类型转换2
查看>>
windows变量前缀总结(转载)
查看>>
UNICODE编程
查看>>
LPTSTR、LPCSTR、LPCTSTR、LPSTR的意义
查看>>
Visual C++中的ODBC编程
查看>>
AD590的引脚使用
查看>>
VC++工程文件下的各个文件说明
查看>>
VC中常用调试技巧
查看>>