• mmc命令(do_mmcops函数的源码分析)


    以下内容源于网络资源的学习与整理,如有侵权请告知删除。

    在文章如何将镜像烧写至iNand(fastboot命令的源码分析)中写到,system、kernel、bootloader的烧写都是write_to_ptn函数直接或间接调用do_mmcops函数来完成的。这里简单分析该函数。

    一、mmc命令基本用法

    1. x210 # help mmc
    2. mmc read addr blk# cnt
    3. mmc write addr blk# cnt
    4. mmc rescan
    5. mmc list - list available devices
    6. x210 # mmc list
    7. S3C_HSMMC0_dev0
    8. S3C_HSMMC2_dev1
    9. x210 # mmc read 0 3A000000 17 32
    10. MMC read: dev # 0, block # 17, count 32 ...32 blocks read: OK
    11. x210 #

    (1)列出mmc设备:mmc list

    列出系统中的mmc设备。

    (2)读/写mmc设备:mmc read/write  addr blk# cnt

    device num:表示mmc设备的编号。开发板上可能有多个mmc设备,比如X210开发板的inand编号为0,外接的SD卡编号是1。

    addr:表示将mmc设备上的数据读取到哪个内存地址(将哪个内存地址的内容写入mmc设备)。

    blk:表示从mmc设备的哪个扇区开始读取(写入)。

    cnt:表示读取(写入)多少个扇区的数据。

    比如“mmc read 0 3A000000 17 32”,表示从mmc设备0上,以第17扇区为开始,读取32个扇区的数据,存储到以内存地址3A000000为开始的内存空间中。

    因为环境变量就存储在inand的第17扇区开始的32个扇区内,因此这条命令其实就是把环境变量读取到内存3A000000开始的内存空间中,后续我们可以用md命令来验证一下。

    一开始我以为这条命令中的17、32是16进制的,因为uboot默认采用16进制,但其实是十进制的,这取决于mmc这个命令对应的源码中如何对参数进行解析的。

    注意读取到某个地址为开始的内存空间,这段内存空间不能与uboot在内存中的空间有重叠,否则uboot会被覆盖。因为uboot的链接地址对应的物理地址是33E00000,而内存空间的物理地址范围是0x30000000~0x4FFFFFFF(见博客uboot中的虚拟地址映射),所以这里选取一个比较安全的地址3A000000作为测试。

    拓展:可以用md命令打印查看某段内存中的值。

    经过测试证明,第二个参数是十六进制的数字,而且以字节为单位的。

    1. x210 # mmc read 0 3A000000 17 32
    2. MMC read: dev # 0, block # 17, count 32 ...32 blocks read: OK
    3. x210 # help md
    4. md [.b, .w, .l] address [# of objects]
    5. - memory display
    6. x210 # md.b 3A000000 9
    7. 3a000000: ca 25 4f 80 6d 74 64 70 61 .%O.mtdpa
    8. x210 # md.b 3A000000 22
    9. 3a000000: ca 25 4f 80 6d 74 64 70 61 72 74 3d 38 30 30 30 .%O.mtdpart=8000
    10. 3a000010: 30 20 34 30 30 30 30 30 20 33 30 30 30 30 30 30 0 400000 3000000
    11. 3a000020: 00 62 .b
    12. x210 #
    13. x210 # md.b 3A000000 200
    14. 3a000000: ca 25 4f 80 6d 74 64 70 61 72 74 3d 38 30 30 30 .%O.mtdpart=8000
    15. 3a000010: 30 20 34 30 30 30 30 30 20 33 30 30 30 30 30 30 0 400000 3000000
    16. 3a000020: 00 62 6f 6f 74 64 65 6c 61 79 3d 33 00 62 61 75 .bootdelay=3.bau
    17. 3a000030: 64 72 61 74 65 3d 31 31 35 32 30 30 00 65 74 68 drate=115200.eth
    18. 3a000040: 61 64 64 72 3d 30 30 3a 34 30 3a 35 63 3a 32 36 addr=00:40:5c:26
    19. 3a000050: 3a 30 61 3a 35 62 00 73 65 72 76 65 72 69 70 3d :0a:5b.serverip=
    20. 3a000060: 31 39 32 2e 31 36 38 2e 31 2e 31 34 31 00 67 61 192.168.1.141.ga
    21. 3a000070: 74 65 77 61 79 69 70 3d 31 39 32 2e 31 36 38 2e tewayip=192.168.
    22. 3a000080: 31 2e 31 00 69 70 61 64 64 72 3d 31 39 32 2e 31 1.1.ipaddr=192.1
    23. 3a000090: 36 38 2e 31 2e 38 38 00 6e 65 74 6d 61 73 6b 3d 68.1.88.netmask=
    24. 3a0000a0: 32 35 35 2e 32 35 35 2e 32 35 35 2e 30 00 62 6f 255.255.255.0.bo
    25. 3a0000b0: 6f 74 61 72 67 73 3d 63 6f 6e 73 6f 6c 65 3d 74 otargs=console=t
    26. 3a0000c0: 74 79 53 41 43 32 2c 31 31 35 32 30 30 20 72 6f tySAC2,115200 ro
    27. 3a0000d0: 6f 74 3d 2f 64 65 76 2f 6d 6d 63 62 6c 6b 30 70 ot=/dev/mmcblk0p
    28. 3a0000e0: 32 20 72 77 20 69 6e 69 74 3d 2f 6c 69 6e 75 78 2 rw init=/linux
    29. 3a0000f0: 72 63 20 72 6f 6f 74 66 73 74 79 70 65 3d 65 78 rc rootfstype=ex
    30. 3a000100: 74 33 00 62 6f 6f 74 63 6d 64 3d 6d 6f 76 69 20 t3.bootcmd=movi
    31. 3a000110: 72 65 61 64 20 6b 65 72 6e 65 6c 20 33 30 30 30 read kernel 3000
    32. 3a000120: 38 30 30 30 3b 20 62 6f 6f 74 6d 20 33 30 30 30 8000; bootm 3000
    33. 3a000130: 38 30 30 30 00 00 73 6f 6c 65 3d 74 74 79 53 41 8000..sole=ttySA
    34. 3a000140: 43 32 2c 31 31 35 32 30 30 00 69 70 61 64 64 72 C2,115200.ipaddr
    35. 3a000150: 3d 31 39 32 2e 31 36 38 2e 31 2e 38 38 00 62 6f =192.168.1.88.bo
    36. 3a000160: 6f 74 63 6d 64 3d 6d 6f 76 69 20 72 65 61 64 20 otcmd=movi read
    37. 3a000170: 6b 65 72 6e 65 6c 20 33 30 30 30 38 30 30 30 3b kernel 30008000;
    38. 3a000180: 20 62 6f 6f 74 6d 20 33 30 30 30 38 30 30 30 00 bootm 30008000.
    39. 3a000190: 00 6e 6f 6e 65 00 00 38 2e 31 2e 32 30 00 00 30 .none..8.1.20..0
    40. 3a0001a0: 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0...............
    41. 3a0001b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    42. 3a0001c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    43. 3a0001d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    44. 3a0001e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    45. 3a0001f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
    46. x210 #

    二、do_mmcops函数的源码分析

    当执行mmc相关命令时,实际执行的是do_mmcops函数。

    该函数位于/common/cmd_mmc.c文件中,内容与分析如下:

    1. /*以“mmc read 0 3A000000 17 32”为例进行说明
    2. argc=6
    3. argv[0]="mmc"
    4. argv[1]="read"
    5. argv[2]="0" 选取哪个mmc设备
    6. argv[3]="3A000000" 读取到哪个内容地址
    7. argv[4]="17" 从哪个扇区开始读写
    8. argv[5]="32" 读取多少个扇区
    9. */
    10. int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
    11. {
    12. int rc = 0;
    13. switch (argc) {
    14. default: /* at least 5 args */
    15. if (strcmp(argv[1], "read") == 0)
    16. {
    17. int dev = simple_strtoul(argv[2], NULL, 10);//dev=0
    18. void *addr = (void *)simple_strtoul(argv[3], NULL, 16);//读取数据到哪个内存地址
    19. u32 cnt = simple_strtoul(argv[5], NULL, 10);//读取多少个扇区
    20. u32 blk = simple_strtoul(argv[4], NULL, 10);//从哪个扇区开始读写
    21. u32 n;
    22. u32 read_cnt;
    23. u32 cnt_to_read;
    24. void *addr_to_read;
    25. struct mmc *mmc = find_mmc_device(dev);//寻找dev=0的这个设备
    26. if (!mmc)
    27. return 1;
    28. printf("\nMMC read: dev # %d, block # %d, count %d ...",
    29. dev, blk, cnt);
    30. rc = mmc_init(mmc);
    31. if(rc)
    32. return rc;
    33. n = 0;
    34. addr_to_read = addr;
    35. do {
    36. if (cnt - n > MAXIMUM_BLOCK_COUNT)
    37. cnt_to_read = MAXIMUM_BLOCK_COUNT;
    38. else
    39. cnt_to_read = cnt - n; //设备0
    40. read_cnt = mmc->block_dev.block_read(dev, blk, cnt_to_read, addr_to_read);
    41. n += read_cnt;
    42. blk += read_cnt;
    43. addr_to_read += read_cnt * 512;
    44. if(cnt_to_read != read_cnt) {
    45. printf("%d blocks read: %s\n",
    46. n, "ERROR");
    47. return -1;
    48. }
    49. } while(cnt > n);
    50. /* flush cache after read */
    51. flush_cache((ulong)addr, cnt * 512); /* FIXME */
    52. printf("%d blocks read: %s\n",
    53. n, "OK");
    54. return 0;
    55. }
    56. else if (strcmp(argv[1], "write") == 0)
    57. {
    58. int dev = simple_strtoul(argv[2], NULL, 10);
    59. void *addr = (void *)simple_strtoul(argv[3], NULL, 16);
    60. u32 cnt = simple_strtoul(argv[5], NULL, 10);
    61. int blk = simple_strtoul(argv[4], NULL, 10);
    62. u32 n;
    63. u32 written_cnt;
    64. u32 cnt_to_write;
    65. void *addr_to_write = addr;
    66. struct mmc *mmc = find_mmc_device(dev);
    67. if (!mmc)
    68. return 1;
    69. printf("\nMMC write: dev # %d, block # %d, count %d ... ",
    70. dev, blk, cnt);
    71. rc = mmc_init(mmc);
    72. if(rc)
    73. return rc;
    74. n = 0;
    75. addr_to_write = addr;
    76. do {
    77. if (cnt - n > MAXIMUM_BLOCK_COUNT)
    78. cnt_to_write = MAXIMUM_BLOCK_COUNT;
    79. else
    80. cnt_to_write = cnt - n;
    81. written_cnt = mmc->block_dev.block_write(dev, blk, cnt_to_write, addr_to_write);
    82. n += written_cnt;
    83. blk += written_cnt;
    84. addr_to_write += written_cnt * 512;
    85. if(cnt_to_write != written_cnt) {
    86. printf("%d blocks written: %s\n",
    87. n, "ERROR");
    88. return -1;
    89. }
    90. } while(cnt > n);
    91. printf("%d blocks written: %s\n",
    92. n, "OK");
    93. return 0;
    94. } else {
    95. printf("Usage:\n%s\n", cmdtp->usage);
    96. rc = 1;
    97. }
    98. return rc;
    99. }
    100. }

  • 相关阅读:
    UWA上新|真人真机测试新增海外机型专区
    JS系列1-布尔陷阱以及如何避免
    key值的应用场景
    Blender中的高级边缘控制和纹理映射
    python教程:exec和eval
    paddle 复现ResNet模型(只关注模型)
    爆肝整理,最全单元测试-测试用例总结(全覆盖)及拿即用...
    springboot+旅游管理系统 毕业设计-附源码261117
    无人零售:创新优势与广阔前景
    贯穿设计模式第二话--开闭原则
  • 原文地址:https://blog.csdn.net/oqqHuTu12345678/article/details/127758984