Linux下读取三星4.5 eMMC的CID超时,求助MMC IOCTL问题
解决三星4.5 eMMC读取CID时的“Connection timed out”问题
嘿,刚接触MMC IOCTL踩这个坑太正常了!我帮你梳理下可能的原因和解决办法,一步步来排查~
一、先把基础权限和设备节点搞对
- 一定要用root权限运行:访问
/dev/mmcblk0这类eMMC设备节点需要管理员权限,别用普通用户直接跑,要么加sudo,要么先切换到root用户。要是嫌麻烦,临时给设备节点加权限也行(sudo chmod 666 /dev/mmcblk0,测试用,用完记得改回去,不安全)。 - 确认设备节点没选错:有时候eMMC的节点可能是
/dev/mmcblk0或者/dev/mmcblk0boot0,用lsblk命令看看,找到对应的eMMC设备,别瞎选节点。
二、检查CMD10的IOCTL结构体是否填对
你用的mmc.h和mmc-utils类似,那核心就是mmc_ioc_cmd结构体的字段不能填错,这是最容易踩的坑:
struct mmc_ioc_cmd cmd = {0}; unsigned char cid_buf[16] = {0}; // CID固定是16字节,缓冲区要够 cmd.opcode = MMC_SEND_CID; // CMD10对应的宏就是MMC_SEND_CID,别写错 cmd.arg = 0; // 读取已选中卡的CID时,arg必须是0 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; // CMD10的响应类型是R1,还要加自动命令标记 cmd.blksz = 16; // 块大小必须匹配CID的长度,填错直接超时 cmd.blocks = 1; // 只需要读1块 cmd.data_ptr = (unsigned long long)cid_buf; // 指向存CID的缓冲区
要是flags或者blksz填错了,设备根本没法正确响应你的命令,自然就超时了。
三、三星4.5 eMMC的特殊小细节
这个版本的eMMC可能有初始化要求:
- 先确认卡被系统识别了:跑
dmesg | grep mmc看看日志,有没有类似mmc0: new high speed SDHC card at address xxxx的输出。要是没有,说明卡根本没被系统识别,那肯定读不了CID,得先排查硬件连接或者驱动问题。 - 确认卡处于选中状态:CMD10是给已经选中的卡发的命令,要是你还没通过CMD3选中卡,发CMD10肯定失败。不过mmc-utils的IOCTL封装一般会帮你处理,但保险起见,你可以先看看系统有没有完成卡的初始化流程。
四、实用调试技巧
- 打印错误详情:调用
ioctl之后,用perror("IOCTL failed")打印具体错误,比如是参数错误(EINVAL)还是真的超时(ETIMEDOUT),能帮你快速定位问题。 - 对比mmc-utils的代码:既然你用的头文件和它类似,直接看mmc-utils里
mmc_cid函数的实现,对比自己的代码哪里不一样,比如它是怎么处理结构体的,有没有额外的初始化步骤。
最后给你个简化的可参考代码片段:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <fcntl.h> #include <errno.h> #include "mmc.h" #include <unistd.h> int main() { int fd = open("/dev/mmcblk0", O_RDWR); if (fd < 0) { perror("Failed to open eMMC device"); return 1; } struct mmc_ioc_cmd cmd = {0}; unsigned char cid[16] = {0}; // 填充CMD10的参数 cmd.opcode = MMC_SEND_CID; cmd.arg = 0; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.blksz = 16; cmd.blocks = 1; cmd.data_ptr = (unsigned long long)cid; int ret = ioctl(fd, MMC_IOC_CMD, &cmd); if (ret < 0) { perror("IOCTL command failed"); close(fd); return 1; } // 打印CID printf("eMMC CID: "); for (int i = 0; i < 16; i++) { printf("%02x ", cid[i]); } printf("\n"); close(fd); return 0; }
编译的时候直接用gcc -o read_cid read_cid.c,然后sudo ./read_cid运行就行。
内容的提问来源于stack exchange,提问作者Thale
相关产品推荐
相关产品推荐

