查看: 33|回复: 0

[经验] 飞凌嵌入式ElfBoard ELF1板卡-mfgtools烧写原理

[复制链接]

该用户从未签到

发表于 昨天 09:10 | 显示全部楼层 |阅读模式
分享到:
MfgTools工具目录
MfgTool工具是一个NXP提供的OTG烧录工具,工具主目录主要由以下文件组成:
7-1.png
Profiles/目录:
(一)Profiles\Linux\OS Firmware\files中,存储着将要烧写到存储介质(启动介质)的目标镜像(uboot、内核、文件系统、设备树等)
(二)Profiles\Linux\OS Firmware\firmware中,存储着引导烧写的镜像(uboot、内核、ramfs文件系统、设备树)
(三)Profiles\Linux\OS Firmware中,存储着ucl2.xml脚本和mksdcard.sh.tar分区脚本。
mx6ull-4gemmc-512mddr-qt5.6.vbs主要用于启动MfgTool2.exe程序,并向其传递配置参数,MfgTool2.exe程序会根据这些参数执行Profiles\Linux\OS Firmware\ucl2.xml中的命令。
MfgTool工具工作过程
MfgTool工具工作过程主要分以下几个步骤:
(一)拨码无误,开发板上电之后,首先boot ROM(SOC内部code,boot ROM具体作用在以后章节会进一步讲解)开始运行,对USB外设进行初始化,并将开发板枚举成HID设备。
(二)Mfgtool工具检测到此HID设备,并与之建立连接。然后Mfgtool工具会解析Firmware\目录下uboot,并使用uboot中的内存配置信息对开发板DDR进行初始化配置。
(三)DDR内存初始化完成之后,Mfgtool工具就会按照mfgtools\Profiles\Linux\OS Firmware\ucl2.xml脚本中的命令将mfgtools\Profiles\Linux\OS Firmware\firmware\目录下uboot镜像、内核镜像、设备树以及ramfs加载到DDR内存中指定地址,然后发送指令给boot ROM,跳转到DDR内存的uboot入口地址,执行uboot,uboot进而启动内核,内核挂载ramfs文件系统。
(四)系统启动之后,会枚举USB作为一个MSC设备,此时SoC可以和主机进行高速数据传输。
(五)然后,Mfgtool会逐一执行mfgtools\Profiles\Linux\OS Firmware\ucl2.xml脚本中的命令,将mfgtools\Profiles\Linux\OS Firmware\files\目录下的uboot、内核镜像、设备树文件、文件系统等逐一烧写到存储介质(启动介质)中。
ucl2.xml文件讲解
xml文件中会根据不同的板卡类型,选择不同的LIST,主要讲解EMMC版本的烧录流程:
(一)将引导镜像加载到DDR
在文件中查找<LIST name="eMMC" desc="Choose eMMC as media">
  1. <LIST name="eMMC" desc="Choose eMMC as media">

  2.         <CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_emmc.imx" ifdev="MX6ULL">Loading U-boot</CMD>

  3.         <CMD state="BootStrap" type="load" file="firmware/zImage_emmc" address="0x80800000"

  4.                 loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>

  5.         <CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"

  6.                 loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Initramfs.</CMD>

  7.         <CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb" address="0x83000000"

  8.                 loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>

  9.         <CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
复制代码
可以看到先是加载了Profiles\Linux\OS Firmware\firmware目录下的u-boot-imx6ul%lite%%6uluboot%_emmc.imx也就是固件下的u-boot-imx6ull14x14evk_emmc.imx文件。
这两个名称是如何定义的呢?在mfgtoos的根目录下的mx6ull-4gemmc-512mddr-qt5.6.vbs和cfg.ini文件中有相关定义,可以右键使用文本格式打开这两个文件进行查看。
cfg.ini文件如下:
  1. [profiles]

  2. chip = Linux



  3. [platform]

  4. board = SabreSD



  5. [LIST]

  6. name = SDCard



  7. [variable]

  8. board = sabresd

  9. mmc = 0

  10. sxuboot=sabresd

  11. sxdtb=sdb

  12. 7duboot=sabresd

  13. 7ddtb=sdb

  14. 6uluboot=14x14ddr3arm2

  15. 6uldtb=14x14-ddr3-arm2

  16. 6ulldtb=14x14-ddr3-arm2

  17. ldo=

  18. plus=

  19. lite=l

  20. initramfs=fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot

  21. seek = 1

  22. sxnor=qspi2

  23. 7dnor=qspi1

  24. 6ulnor=qspi1

  25. nor_part=0
复制代码
可以看到,lite=l,6uluboot=14x14ddr3arm2,lite的定义没问题是l,但是6uluboot的定义也不是14x14evk呀,别着急看下一个文件。
mx6ull-8gemmc-512mddr-qt5.6.vbs:
  1. Set wshShell = CreateObject("WScript.shell")

  2. wshShell.run "mfgtool2.exe -c ""linux"" -l ""eMMC"" -s ""board=sabresd"" -s ""mmc=1"" -s ""6uluboot=14x14evk"" -s ""6uldtb=14x14-evk"""

  3. Set wshShell = Nothing
复制代码
能看到这里又重新定义了6uluboot的名称,在ucl2.xml文件中使用%lite%和%6uluboot%来引用这两个变量。所以u-boot-imx6ul%lite%%6uluboot%_emmc.imx就是u-boot-imx6ull14x14evk_emmc.imx文件。
这样芯片就会自动解析uboot然后对DDR进行初始化,引导固件中的uboot就开始运行了。
接下来就是将Profiles\Linux\OS Firmware\firmware目录下的zImage_emmc加载到DDR的“0x80800000”地址,命令如下:
  1. <CMD state="BootStrap" type="load" file="firmware/zImage_emmc" address="0x80800000"

  2. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>
复制代码
然后是加载虚拟文件系统,将Profiles\Linux\OS Firmware\firmware目录下的fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot加载到DDR的“0x83800000”,%initramfs%的定义在上文的cfg.ini文件中可以找到。这个虚拟文件系统又叫rmadisk,是将内存的一块地址虚拟成硬盘来使用,断电后是不会保存的。
  1. <CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"

  2. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Initramfs.</CMD>
复制代码
然后加载设备树文件,将Profiles\Linux\OS Firmware\firmware目录下的zImage-imx6ull-14x14-evk-emmc.dtb加载到DDR的“0x83000000”,最后jump命令跳转到虚拟文件系统中。
  1. <CMD state="BootStrap" type="load" file="firmware/zImage-imx6ul%lite%-%6uldtb%-emmc.dtb" address="0x83000000"

  2. loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>

  3. <CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>
复制代码
(二)EMMC分区,进入到虚拟文件系统后就可以对EMMC进行分区了。
先是将Profiles\Linux\OS Firmware\下的mksdcard.sh.tar包发送到了虚拟文件系统中。
  1. <!-- create partition -->

  2.         <CMD state="Updater" type="push" body="send" file="mksdcard.sh.tar">Sending partition shell</CMD>
复制代码
然后使用tar命令将压缩包解压:
  1. <CMD state="Updater" type="push" body="$ tar xf $FILE "> Partitioning...</CMD>
复制代码
最后执行mksdcard.sh对mmcblk1进行格式化和分区操作。%mmc%在上文中的mx6ull-8gemmc-512mddr-qt5.6.vbs文件中有定义。
  1. <CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>
复制代码
接下来看一下mksdcard.sh中是如何进行格式化和分区的,在windows上解压mksdcard.sh.tar并打开mksdcard.sh脚本:
  1. #!/bin/sh



  2. # partition size in MB

  3. BOOT_ROM_SIZE=10



  4. # wait for the SD/MMC device node ready

  5. while [ ! -e $1 ]

  6. do

  7. sleep 1

  8. echo “wait for $1 appear”

  9. done



  10. # call sfdisk to create partition table

  11. # destroy the partition table

  12. node=$1

  13. dd if=/dev/zero of=${node} bs=1024 count=1



  14. sfdisk --force ${node} << EOF

  15. ${BOOT_ROM_SIZE}M,500M,0c

  16. 600M,,83

  17. EOF
复制代码
先是循环检测虚拟文件系统中/dev/mmcblk1节点是否注册成功,$1就是传进来的第一个参数/dev/mmcblk1。
  1. # wait for the SD/MMC device node ready

  2. while [ ! -e $1 ]

  3. do

  4. sleep 1

  5. echo “wait for $1 appear”

  6. done
复制代码
如果识别到了mmcblk1设备,就使用dd命令将EMMC的前1KB的空间清0,EMMC的前1KB空间保存的是它的分区表信息,所以在正常使用情况下千万不能执行如下操作。
  1. # call sfdisk to create partition table

  2. # destroy the partition table

  3. node=$1

  4. dd if=/dev/zero of=${node} bs=1024 count=1
复制代码
接下来就是使用sfdisk命令对EMMC进行分区操作。
  1. sfdisk --force ${node} << EOF

  2. ${BOOT_ROM_SIZE}M,500M,0c

  3. 600M,,83

  4. EOF
复制代码
0c为fat32格式,83为ext3格式,其中10-500M为fat32格式,使用来存储镜像的分区。600M之后的空间都为ext3格式的分区,是给文件系统来用的。在开发板的命令行执行df -h命令即可看到这些分区,如下:
  1. root@ELF1:~# df -h

  2. Filesystem      Size     Used    Avail   Use%  Mounted on

  3. /dev/root        6.5G    746M    5.5G   12%    /

  4. devtmpfs        89M     4.0K    89M    1%     /dev

  5. tmpfs           40K      0       40K    0%     /mnt/ .psplash

  6. tmpfs            249M   140K  249M   1%   /run

  7. tmpfs            249M   140K  249M   1%   /var/volatile

  8. /dev/mmcblk1p1  500M   12M   488M   3%   /run/media/mmcblk1p1
复制代码
(三)格式化和烧录
uboot分区格式化和烧录,先是清除了mmcblk1偏移量768之后的8k字节,此位置存放的是uboot的环境变量。
  1. <!-- burn uboot -->

  2.         <CMD state="Updater" type="push" body="$ dd if=/dev/zero of=/dev/mmcblk%mmc% bs=1k seek=768 conv=fsync count=8">clear u-boot arg</CMD>
复制代码
然后使能mmcblk1boot0的写操作,将Profiles\Linux\OS Firmware\files目录下的u-boot.imx烧写到mmcblk1boot0分区。
  1. <!-- access boot partition -->

  2.         <CMD state="Updater" type="push" body="$ echo 0 > /sys/block/mmcblk%mmc%boot0/force_ro">access boot partition 1</CMD>

  3.         <CMD state="Updater" type="push" body="send" file="files/ u-boot.imx" ifdev="MX6ULL">Sending u-boot.bin</CMD>

  4.         <CMD state="Updater" type="push" body="$ dd if=$FILE of=/dev/mmcblk%mmc%boot0 bs=512 seek=2">write U-Boot to sd card</CMD>

  5.         <CMD state="Updater" type="push" body="$ echo 1 > /sys/block/mmcblk%mmc%boot0/force_ro"> re-enable read-only access </CMD>

  6.         <CMD state="Updater" type="push" body="$ mmc bootpart enable 1 1 /dev/mmcblk%mmc%">enable boot partion 1 to boot</CMD>
复制代码
接下来是格式化FAT32分区,并烧写zImage、logo图片和dtb文件,同样的先是检测/dev下有没有mmcblk1p1节点,使用mkfs.vfat命令将分区格式化为fat格式,再使用mdir命令创建挂载目录/mnt/mmcblk1p1,最后使用mount命令/dev下的mmcblk1p1挂载到新建的目录上。
  1. <!-- create fat partition -->

  2.         <CMD state="Updater" type="push" body="$ while [ ! -e /dev/mmcblk%mmc%p1 ]; do sleep 1; echo "waiting..."; done ">Waiting for the partition ready</CMD>

  3.         <CMD state="Updater" type="push" body="$ mkfs.vfat /dev/mmcblk%mmc%p1">Formatting rootfs partition</CMD>

  4.         <CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p1"/>

  5.         <CMD state="Updater" type="push" body="$ mount -t vfat /dev/mmcblk%mmc%p1 /mnt/mmcblk%mmc%p1"/>
复制代码
有了挂载目录,就可以将Profiles\Linux\OS Firmware\files目录下的镜像烧录到EMMC了,其实就是一个拷贝的操作。
先是拷贝Profiles\Linux\OS Firmware\files目录的zImage文件到EMMC。
  1. <!-- burn zImage -->

  2.         <CMD state="Updater" type="push" body="send" file="files/zImage">Sending kernel zImage</CMD>

  3.         <CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/zImage">write kernel image to sd card</CMD>

  4.         <CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/zImagebak">write kernel image to sd card</CMD>
复制代码
然后是logo图片,
  1. <!-- burn logo -->

  2.         <CMD state="Updater" type="push" body="send" file="files/logo.bmp">Sending logo bmp</CMD>

  3.         <CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/logo.bmp">write logo bmp to sd card</CMD>
复制代码
然后是dtb文件,再使用umount命令将挂载目录卸载掉。
  1. <!-- burn dtb -->

  2.         <CMD state="Updater" type="push" body="send"         <CMD state="Updater" type="push" body="send" file="files/imx6ull-elf1-emmc.dtb" ifdev="MX6ULL">Sending Device Tree file</CMD>

  3.         <CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/imx6ull-elf1-emmc.dtb" ifdev="MX6ULL">write device tree to sd card</CMD>

  4.         <CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p1">Unmounting vfat partition</CMD>
复制代码
最后是格式化ext3分区并烧录文件系统,与fat分区是同样的操作,先是使用mkfs.ext3命令将分区格式化为ext3格式,然后使用mkdir命令创建挂载分区目录/mnt/mmcblk1p2,并将分区挂载到目录上。
  1. <!-- burn rootfs -->

  2.         <CMD state="Updater" type="push" body="$ mkfs.ext3 -F -E nodiscard /dev/mmcblk%mmc%p2">Formatting rootfs partition</CMD>

  3.         <CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p2"/>

  4.         <CMD state="Updater" type="push" body="$ mount -t ext3 /dev/mmcblk%mmc%p2 /mnt/mmcblk%mmc%p2"/>
复制代码
有了挂载目录,就可以将Profiles\Linux\OS Firmware\files下的文件系统压缩包rootfs.tar.bz2和模块驱动压缩包modules.tar.bz2解压到挂载目录中了,解压之后使用umount命令卸载挂载目录。
  1. <CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mmcblk%mmc%p2" file="files/rootfs.tar.bz2" ifdev="MX6UL MX7D MX6ULL">Sending and writting rootfs</CMD>

  2.         <CMD state="Updater" type="push" body="frf">Finishing rootfs write</CMD>

  3.         <CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mmcblk%mmc%p2" file="files/modules.tar.bz2" ifdev="MX6UL MX7D MX6ULL">Sending and writting modules</CMD>

  4.         <CMD state="Updater" type="push" body="frf">Finishing modules software write</CMD>

  5.         <CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p2">Unmounting rootfs partition</CMD>

  6.         <CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>
复制代码
(四)烧录技巧
前面了解了整个烧录的流程,我们就可以对ucl2.xml文件进行修改来方便烧写,其中烧录文件系统是最耗时的,因为文件系统的压缩包比较大,需要完全把压缩包解压到EMMC中,如果我们想要加快烧录时间,不希望烧录文件系统,我们就可以将ucl2.xml文件中烧录文件系统的部分屏蔽掉,屏蔽语法为<!-- -->方法如下:
  1. <!-- burn rootfs -->

  2. <!--

  3. <CMD state="Updater" type="push" body="$ mkfs.ext3 -F -E nodiscard /dev/mmcblk%mmc%p2">Formatting rootfs partition</CMD>

  4. <CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p2"/>

  5. <CMD state="Updater" type="push" body="$ mount -t ext3 /dev/mmcblk%mmc%p2 /mnt/mmcblk%mmc%p2"/>

  6. <CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mmcblk%mmc%p2" file="files/rootfs-qt.tar.bz2" ifdev="MX6UL MX7D MX6ULL">Sending and writting rootfs</CMD>

  7. <CMD state="Updater" type="push" body="frf">Finishing rootfs write</CMD>

  8. <CMD state="Updater" type="push" body="pipe tar -jxv -C /mnt/mmcblk%mmc%p2" file="files/modules.tar.bz2" ifdev="MX6UL MX7D MX6ULL">Sending and writting modules</CMD>

  9. <CMD state="Updater" type="push" body="frf">Finishing modules software write</CMD>

  10. <CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p2">Unmounting rootfs partition</CMD>

  11. <CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>

  12. -->
复制代码
通过上面的学习,我们对Mfgtools工具的烧录原理已经有了充分的理解,那么我们就可以将这个工具进行修改变成自己的工具啦

回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /5 下一条



手机版|小黑屋|与非网

GMT+8, 2024-12-22 15:05 , Processed in 0.138317 second(s), 16 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.