linux下是sdcard驱动学习
调一款加密ic ET300时,发现通信不上,报错-110,就是超时出错,检查了gpio和sdcard配置,也检查了sd供电,发现sdio的供电域是1.8v,而根据协议初始化时默认是3.3v,然后切换到1.8v,通过飞线,使用一个ldo来供电。修改后,还是通信异常。
加打印调试,在mmc_send_cid函数报错了,就是读不到卡的cid信息。默认读不到cid,代码就退出了。 检查了再检查,实在找不出问题,于是修改代码,强制往下跑,看log,居然读到了卡的信息。
也就是只有CMD2命令跑不过,其他命令都跑过了。
发送CMD2命令前会先切换到1.8v的电压,对应平台的sdio驱动
也就是sdio host的名字是sdio_sd才会复位下平台的sdio host,而dts配置名字不是sdio_sd,导致没有复位平台的host,修改名字后,代码能正常跑过。
调是调完了,顺便把相关的代码逻辑整理下。
从mmc_rescan这个函数讲起,相关内容已在https://blog.csdn.net/mike8825/article/details/103604359描述过。
//以不同频率去扫描卡,但实际上某些平台定义的最小频率是400k(只会以400k去扫)
void mmc_rescan(struct work_struct *work)
{
...
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min)))
break;
if (freqs[i] <= host->f_min)
break;
}
...
}
static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
{
mmc_power_up(host, host->ocr_avail);
if (!(host->caps2 & MMC_CAP2_NO_SDIO))
sdio_reset(host);
mmc_go_idle(host);
mmc_attach_sd(host);
mmc_power_off(host);
return -EIO;
}
int mmc_attach_sd(struct mmc_host *host)
{
...
err = mmc_send_app_op_cond(host, 0, &ocr);
mmc_attach_bus(host, &mmc_sd_ops);
if (host->ocr_avail_sd)
host->ocr_avail = host->ocr_avail_sd;
rocr = mmc_select_voltage(host, ocr);
err = mmc_sd_init_card(host, rocr, NULL);
mmc_release_host(host);
err = mmc_add_card(host->card);
mmc_claim_host(host);
...
}
比较关键了几个函数mmc_send_app_op_cond,mmc_sd_init_card仔细看的话,实际上是sd协议的代码实现。如果扫描到了sd卡,会在/sys/bus/mmc/devices
生成相应的设备节点。
说到sd协议,比较权威的资料就是官网文档了,下载地址https://www.sdcard.org/downloads/pls/index.html,下这一篇(Physical Layer Simplified Specification)速度慢点,还是能下载的(自己也上传了一份https://download.csdn.net/download/mike8825/13135676)。
比较关键的一张图,然后按照代码慢慢看吧。
推荐阅读
-
linux下是sdcard驱动学习
-
Linux 驱动学习笔记 - 小型模板设备树(四)
-
什么是777权限?Linux及Windows下如何设置文件夹的权限为777?
-
Linux学习(一)--VMware下Linux安装和配置
-
数据库学习之--Linux下Mysql源码包安装
-
Linux下如何安装Run文件格式NVIDIA显卡驱动
-
零基础学习教程之Linux下搭建android开发环境
-
linux 中的MYSQL命令汇总 适合学习linux下配置mysql的朋友
-
零基础学习教程之Linux下搭建android开发环境
-
在linux下写的代码,用的是utf-8,结果拿到XP下运行的时候,所有的中文都成乱码