从Linux用户空间发送命令到SD卡的任何方法?

7

我有一个Debian 7.0 Linux 3.2嵌入式ARM TI AM335x系统。这是我们开发的自定义板,但至少SD卡部分与开发板相同。我想向卡发送一些供应商特定的SD卡命令,即使用CMD56读取一些SMART数据。

是否有任何方法可以发送命令到SD卡控制器并从用户空间读取响应?


1
弗雷德,驱动程序负责与SD卡控制器的工作(检查dmesg输出)是什么? - osgx
我现在无法访问该系统(它在办公室),但我认为它是标准的SD卡驱动程序。 - fred basset
没有“标准驱动程序”。在Linux内核中有标准的核心MMC/SD子系统和数十个控制器驱动程序。您能否在问题中添加一些信息:确切的ARM芯片/SoC/板名称(SD控制器通常内置于SoC中),您想要发送到SD卡的命令是什么?它是SDIO还是SD卡?卡使用的SD标准版本是哪个? - osgx
1
好的,周一我拿到开发板后会进一步完善我的问题。 - fred basset
谢谢,额外的信息(确切的命令CMD56,也称为供应商特定的GEN_CMD和TI文档)帮助我进行正确的网络搜索,并找到了在Linux中发送短自定义命令的通用MMC / SD ioctl mmc-toolsMMC_IOC_CMD。在Windows中,有类似的DeviceIoControl(drv_hdl,IOCTL_SFFDISK_DEVICE_COMMAND,SDCMD_DESCRIPTOR sdCmdDescriptor结构体。 - osgx
3个回答

10

根据http://processors.wiki.ti.com/index.php/AM335x_MMC/SD_Driver%27s_Guide,你的驱动程序是omap_hsmmc,还有一些信息可以在https://www.kernel.org/doc/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt中找到。

在搜索支持sd卡的SMART监控时,我发现了一个查询命令mmc smartctl(因为smartctl是Linux中*ATA的SMART监控实用工具,而mmc是内核子系统,用于实现MMC、SD、SDHC卡和控制器)。我在https://code.google.com/p/chromium/issues/detail?id=315380看到了Gwendal Grignou提交的反馈,其中指出了某些移动PC操作系统上的问题。

如果根设备是SATA设备:

  • 添加命令输出 hdparm -I /dev/sda
  • 添加命令输出 smartctl -a /dev/sda

如果根设备是eMMC设备:

  • 当mmc-utils将成为映像的一部分时,请添加类似的命令输出。

听起来mmc-utils是实现SD卡的SMART的首选工具。在http://git.kernel.org/cgit/linux/kernel/git/cjb/mmc-utils.git/tree/上有mmc-utils的主页git。

我在这里没有看到“SMART”,但mmc-utils/mmc_cmds.c具有发送自定义命令到卡的代码,可以使用ioctl(fd, MMC_IOC_CMD, (struct mmc_ioc_cmd*)&ioctl_data) (希望这对大多数SD控制器都有效) ,其中fd指向正确的mmcblkX设备。Johan RUDHOLM编写了此代码(来自st-ericsson,2012年,GPLv2):

   int read_extcsd(int fd, __u8 *ext_csd)
   {
       struct mmc_ioc_cmd idata;
       memset(&idata, 0, sizeof(idata));
       memset(ext_csd, 0, sizeof(__u8) * 512);
       idata.write_flag = 0;
       idata.opcode = MMC_SEND_EXT_CSD;
       idata.arg = 0;
       idata.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
       idata.blksz = 512;
       idata.blocks = 1;
       mmc_ioc_cmd_set_data(idata, ext_csd);

       return  ioctl(fd, MMC_IOC_CMD, &idata);
   }

   int write_extcsd_value(int fd, __u8 index, __u8 value)
   {
       struct mmc_ioc_cmd idata;

       memset(&idata, 0, sizeof(idata));
       idata.write_flag = 1;
       idata.opcode = MMC_SWITCH;
       idata.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
            (index << 16) |
            (value << 8) |
            EXT_CSD_CMD_SET_NORMAL;
       idata.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;

       return ioctl(fd, MMC_IOC_CMD, &idata);
   }

2011年12月20日,Shashidhar Hiremath在LKML上发布了关于MMC_IOC_CMD的一些文档和示例"[PATCH 1/1] mmc: User Application for testing SD/MMC Commands and extra IOCTL Command for MMC card reset"

struct mmc_ioc_cmd的官方用户API(uapi)可以在Linux源代码树中找到include/uapi/linux/mmc/ioctl.h:

  6 struct mmc_ioc_cmd {
...
 10         /* Application-specific command.  true = precede with CMD55 */
 11         int is_acmd;
...
 51  * Since this ioctl is only meant to enhance (and not replace) normal access
 52  * to the mmc bus device...

非常感谢您详细和专业的回复。我希望本周能够尝试一下。测试完成后,我会将其标记为已解决。 - fred basset
1
我终于有时间来处理这个问题了,通过mmc-utils方法,CMD56起作用了。 - fred basset
Fred,你能否把你的mmc-utils分支放在GitHub上吗? - Brad
@fredbasset,我看到你尝试了osgx提供的更改并且它对你有效。你能否帮助我执行extcsd命令并获取SD卡的ext-csd信息?这可能吗?谢谢。 - Dixit

-1

是的,有一些特定于供应商的SD卡命令,您可以使用CMD56从SD卡读取SMART数据到您的设备。

主机必须能够支持供应商命令“CMD61”和“CMD56”。并且在发出CMD61和CMD56之间需要有5ms的FW繁忙时间延迟。

保罗。




-1

最简单的方法是mmap SD控制器的内存空间,然后将SD控制器数据手册中的命令写入控制器。


Ezio,你确定在Linux中将MMC / SD端口控制器或SD卡本身内置的IO存储器映射到用户空间是可能的吗?是否有此类mmap的示例?我们应该编写哪个命令将CMD56发送给SD卡? - osgx
@osgx 我确定。虽然没有现成的例子,但自己做起来很容易。 - Ezio
Ezio,你已经做过这个了吗?我应该映射哪个文件?什么偏移量?写入什么以及在哪里写入? - osgx
@osgx,你可能误解了我的想法。在我看来,你需要将sd控制器的地址空间映射到内存地址(参考man mmap),而不是一个文件。写入的偏移量和位置基于sd控制器的数据表(你可以参考sd卡的驱动程序)。 - Ezio
Ezio,我该如何从用户程序中找到控制器地址空间?我知道man mmap。但我应该映射哪个文件和什么偏移量?我认为你的帖子不是真正的答案,这篇帖子可能会被投票降低。 - osgx
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接