You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:11:15