本文共 4293 字,大约阅读时间需要 14 分钟。
近日开始研究mmc模块。老是看代码不免困意来袭,为了克服困意,可以通过一些小的试验来加深对该模块的理解。
第一步:
首先,自己创建了一个小的测试模块,通过获取mmc模块初始化时sdhci_host结构体的指针(初始化时就将这些sdhci_host结构的指针保存在一个数组,并提供接口导出该数组首地址供其它模块使用)为神秘的mmc子系统打开一扇窗口。
注册sdhci_host的文件中需要做如下改动:测试文件获取到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);
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/