rk3128 如何读取 flash id
2019-06-14
关键字:mmc 唯一ID、flash 唯一识别码
Android 开发板中的唯一识别码
在 Android 的系统中,默认是会将 flash 的唯一识别码映射到文件系统中的。它的默认路径为
/sys/bus/mmc/devices
在这个路径下通常你的板子上有多少块存储芯片,就会有多少个文件。例如,笔者的开发板中它的文件结构就只有一个。
root@rk312x:/sys/bus/mmc/devices # ll lrwxrwxrwx root root 1970-01-01 00:00 mmc0:0001 -> ../../../devices/1021c000.rksdmmc/mmc_host/mmc0/mmc0:0001 root@rk312x:/sys/bus/mmc/devices #
我们直接进这个目录里去。
查看一下这个目录内的文件结构,可以发现有如下文件与目录
root@rk312x:/sys/bus/mmc/devices/mmc0:0001 # ll drwxr-xr-x root root 1970-01-01 00:00 block -r--r--r-- root root 4096 1970-01-01 00:00 cid -r--r--r-- root root 4096 1970-01-01 00:00 csd -r--r--r-- root root 4096 1970-01-01 00:00 date lrwxrwxrwx root root 1970-01-01 00:00 driver -> ../../../../../bus/mmc/drivers/mmcblk -r--r--r-- root root 4096 1970-01-01 00:00 enhanced_area_offset -r--r--r-- root root 4096 1970-01-01 00:00 enhanced_area_size -r--r--r-- root root 4096 1970-01-01 00:00 erase_size -r--r--r-- root root 4096 1970-01-01 00:00 fwrev -r--r--r-- root root 4096 1970-01-01 00:00 hwrev -r--r--r-- root root 4096 1970-01-01 00:00 manfid -r--r--r-- root root 4096 1970-01-01 00:00 name -r--r--r-- root root 4096 1970-01-01 00:00 oemid drwxr-xr-x root root 1970-01-01 00:00 power -r--r--r-- root root 4096 1970-01-01 00:00 preferred_erase_size -r--r--r-- root root 4096 1970-01-01 00:00 prv -r--r--r-- root root 4096 1970-01-01 00:00 raw_rpmb_size_mult -r--r--r-- root root 4096 1970-01-01 00:00 rel_sectors -r--r--r-- root root 4096 1970-01-01 00:00 serial lrwxrwxrwx root root 1970-01-01 00:00 subsystem -> ../../../../../bus/mmc -r--r--r-- root root 4096 1970-01-01 00:00 type -rw-r--r-- root root 4096 1970-01-01 00:00 uevent root@rk312x:/sys/bus/mmc/devices/mmc0:0001 #
其中,这个 cid 文件就是用于记载 flash 唯一识别码的文件。我们看看它记载的格式是怎样的
root@rk312x:/sys/bus/mmc/devices/mmc0:0001 # cat cid 11010030303447363002ca9c8c25a507 root@rk312x:/sys/bus/mmc/devices/mmc0:0001 #
真够简单干脆的。
这个 cid 码是一个 128 位,即 16 个字节的数值码。我们上面直接 cat 出来的是一个 32 字节的字符串,这说明这个唯一识别码在 cid 文件里的记载方式是每两个字符表示一个十六进制字符串形数值。
然后这个 cid 码也是有格式的,貌似是国际标准格式。
MID: [127:120] —— 8bit(1Byte)Manufacturer ID,由MMCA分配,比如Sandisk为0x02,Kingston为0x37,Samsung为0x15。 OID: [119:104] —— 16bit OEN/Application ID,OEM/应用ID号,也由MMCA分配。 PNM: [103:64] —— 40bit Product Name,产品名称。 PRV: [63:56] —— 8bit Product revision,产品版本,前4bit fw版本,后4bit hw版本。 PSN: [55:24] —— 32bit Product serial number,产品序列号。 MDT: [19:8] —— 12bit Manufacturing date,生产日期,前4bit是月份,后8bit为年份,0对应2000年。 CRC: [7:1] —— 7bit CRC7 checksum,循环冗余校验。
知道了它会以普通文件的形式出现在文件系统以后就可以拿来应用了。一种最简单的使用方式就是直接以 文件 的形式来对它进行读写。大不了我们在 init.rc 的 on post-fs-data 上手动修改一下读写权限就是了。
源码实现
上面这一系列文件在源码中又是如何来实现的呢?
./kernel/drivers/mmc
这个目录下的代码是关于 mmc ,即这个 flash 的一整套实现代码。
可以重点关注的代码主要是以下这个
./kernel/drivers/mmc/core/mmc.c
在这份源码中,入口函数是这个
int mmc_attach_mmc(struct mmc_host *host)
而关于 cid 相关的,在上面这个 mmc_attach_mmc 函数中有如下调用
/* * Detect and init the card. */ err = mmc_init_card(host, rocr, NULL); if (err) goto err;
在这个 mmc_init_card 函数中就可以看到诸如取 cid ,csd 等这些的函数调用了
/* * Handle the detection and initialisation of a card. * * In the case of a resume, "oldcard" will contain the card * we're trying to reinitialise. */ static int mmc_init_card(struct mmc_host *host, u32 ocr, struct mmc_card *oldcard) { ... /* * Fetch CID from card. */ if (mmc_host_is_spi(host)) err = mmc_send_cid(host, cid); else err = mmc_all_send_cid(host, cid); if (err) goto err; ... }
其实整套流程还不简单,有兴趣的自己去深入跟踪一下源码好了。
参考博客: https://blog.csdn.net/weixin_42049508/article/details/81032057