14. 制作USB烧录包

本章旨在让用户熟悉MFGtool工具,制作属于自己的usb烧录包。

14.1. MFGtool工具简介

MFGTool工具是NXP官方推荐的一个使用USB OTG来升级镜像的软件工具,它是NXP针对i.MX系列处理器专门使用的烧录工具,可以用来升级linux, 单独烧录某一系统分区,独立地烧录spi flash、 nor flash、sd card、nand flash,emmc等, 只需简单的配置就可以使用该工具将编译好的文件系统和镜像文件烧录到开发板上,使用起来非常方便。

14.2. MFGtool工具的工作原理

简单来说MFGtool工具的烧录步骤分为两个阶段:BurnStarp和Updater。第一阶段是烧录前的准备工作,配置设备USB的vid和pid,来选择烧录的设备。 第二阶段是MFGtools开始烧录到结束烧录的过程,这个阶段的烧录过程是严格根据ucl2.xml文件来处理的,实际上是将bootloader加载到ddr(RAM), 然后在运行时将编译好的文件系统和镜像文件烧录到开发板上,烧录的位置由用户指定,可以是sd card、nand flash,emmc等。

14.3. MFGtool工具的目录结构

MFGtool工具目录如下图所示:

未找到图片
  • Document :存放了与该工具相关的文档。

  • Driver :为Windows 32位和64位操作系统的驱动。

  • Profiles :存放镜像文件。

  • cfg.ini :配置文件。

  • MfgTool2.exe :mfgtool工具,默认使用cfg.ini中的配置。

  • Mfgtool2-imx6ull-eMMC.vbs :mmc烧录脚本。

  • Mfgtool2-imx6ull-nand.vbs :nand烧录脚本。

  • Mfgtool2-imx6ull-SDCard.vbs :sd烧录脚本。

对于MFGtool工具目录下的其他文件以及文件夹,无需理会。

14.3.1. cfg.ini配置文件

cfg.ini配置文件内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
[profiles]
chip = Linux

[platform]
board = sabresd

[LIST]
#name = NAND Flash
name = eMMC
#name = SDCard

[variable]

board = sabresd
mmc = 1
sxuboot=sabresd
sxdtb=sdb
7duboot=sabresd
7ddtb=sdb
6uluboot=14x14evk
6uldtb=14x14-evk
ldo=
plus=
lite=l
initramfs=fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot

nand=nand
nanddtb=gpmi-weim
part_uboot=0
part_rootfs=1


files_dir = release
my_zImage=zImage
my_uboot=u-boot-mmc.imx

my_rootfs=rootfs.tar

my_dtb=imx6ull-mmc-npi.dtb

以上定义了一些变量,这些变量用于ucl2.xml文件,当打开MfgTool2.exe时,会解析ucl2.xml文件,使用cfg.ini中定义的变量。

  • Profiles :表示要使用Profiles目录下哪个文件夹的内容进行烧录。

如以上配置使用“mfgtools-release/profiles/Linux/OS Firmware/ucl2.xml”目录下的ucl2.xml配置烧录。

  • platform :开发板名字,目前没有作用,可以忽略。

  • list :表示使用“mfgtools-release/profiles/CHIP_PROFILE/OS Firmware/ucl2.xml”文件中的哪个list配置进行烧录。

1
2
3
4
5
6
<LIST name="SDCard"
….
<LIST name="eMMC"
….
<LIST name="NAND Flash"
….
  • variable :variable中是一些环境变量,在list列表配置中会引用的环境变量。

例如,initramfs=fsl-image-mfgtool-initramfs-imx_mfgtools.cpio.gz.u-boot,在“mfgtools-release/profiles/CHIP_PROFILE/OS Firmware/ucl2.xml”文件中会被 <CMD state=“BootStrap” type=“load” file=“firmware/%initramfs%” address=”0x83800000”…引用,其引用的方式为“%…%”,在两个百分号(%)之间,通过变量initramfs进行传递。

因此,通过修改cfg.ini配置文件可以很方便的指定烧录介质,系统分区,内核、uboot、文件系统、设备树名字等。

14.3.2. Mfgtool2-xxx.vbs脚本

可右击Mfgtool2-xxx.vbs脚本,通过记事本方式打开,查看脚本内容。

其中,Mfgtool2-imx6ull-eMMC.vbs内容如下:

1
2
3
Set wshShell = CreateObject("WScript.shell")
wshShell.run "mfgtool2.exe -c ""linux"" -l ""eMMC"" -s ""mmc=1"" -s ""my_uboot=u-boot-mmc.imx"" -s ""my_dtb=imx6ull-mmc-npi-lite.dtb"" "
Set wshShell = Nothing

其中,Mfgtool2-imx6ull-nand.vbs内容如下:

1
2
3
Set wshShell = CreateObject("WScript.shell")
wshShell.run "mfgtool2.exe -c ""linux"" -l ""NAND Flash"" -s ""my_uboot=u-boot-nand.imx"" -s ""my_dtb=imx6ull-nand-npi-lite.dtb""  "
Set wshShell = Nothing

其中,Mfgtool2-imx6ull-SDCard.vbs内容如下:

1
2
3
Set wshShell = CreateObject("WScript.shell")
wshShell.run "mfgtool2.exe -c ""linux"" -l ""SDCard"" -s ""mmc=0"" -s ""my_uboot=u-boot-mmc.imx"" -s ""my_dtb=imx6ull-mmc-npi-lite.dtb"" "
Set wshShell = Nothing

以上是使用VBScript编写的脚本,其主要作用是调用mfgtool2.exe工具,并为该工具传递一系列参数来执行特定的操作。

说明如下:

  • Set wshShell = CreateObject(“WScript.shell”) :创建了一个WScript.shell对象的实例,并将其赋值给变量wshShell,用于与操作系统的Shell进行交互。

  • wshShell.run :用于执行外部程序。

  • mfgtool2.exe :是要执行的可执行程序。

  • -c “linux” : 指定cfg.ini配置文件中的[profiles] chip为linux。

  • -l “”SDCard”” :指定cfg.ini配置文件中的[LIST] name为SDCard。

  • -s “”mmc=0”” :指定cfg.ini配置文件中的[variable] mmc为0。

  • -s “”my_uboot=u-boot-mmc.imx”” :指定指定cfg.ini配置文件中的[variable] my_uboot为u-boot-mmc.imx。

  • Set wshShell = Nothing :释放该对象所占用的系统资源,避免内存泄漏。

因此,通过vbs脚本,可以在打开mfgtool2.exe时指定修改不同的参数而区分eMMC、nand以及SDCard版本,而不需要修改cfg.ini配置文件。

14.3.3. ucl2.xml配置文件

ucl2.xml配置文件位于mfgtools-release/profiles/Linux/OS Firmware/目录下,截取SDCard部分内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<UCL>
<CFG>
    <!-- 支持的设备-->
    <STATE name="BootStrap" dev="MX6ULL" vid="15A2" pid="0080"/>
    <STATE name="Updater"   dev="MSC" vid="066F" pid="37FF"/>
</CFG>


    <!-- 烧录介质-->
<LIST name="SDCard" desc="Choose SD Card as media">

    <!-- 烧录第一阶段。加载uboot、内核、initiramfs文件系统、设备树到RAM上运行-->
    <CMD state="BootStrap" type="boot" body="BootStrap" file ="firmware/u-boot-imx6ul%lite%%6uluboot%_sd.imx" ifdev="MX6ULL">Loading U-boot</CMD>
    <CMD state="BootStrap" type="load" file="firmware/zImage_sd" address="0x80800000"
        loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Kernel.</CMD>
    <CMD state="BootStrap" type="load" file="firmware/%initramfs%" address="0x83800000"
        loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6SL MX6SX MX7D MX6UL MX6ULL">Loading Initramfs.</CMD>
    <CMD state="BootStrap" type="load" file="firmware/imx6ull-14x14-sd.dtb" address="0x83000000"
        loadSection="OTH" setSection="OTH" HasFlashHeader="FALSE" ifdev="MX6ULL">Loading device tree.</CMD>


    <CMD state="BootStrap" type="jump" > Jumping to OS image. </CMD>

    <!-- 通过mksdcard.sh脚本格式化并创建分区-->
    <!-- create partition -->
    <CMD state="Updater" type="push" body="send" file="mksdcard.sh.tar">Sending partition shell</CMD>
    <CMD state="Updater" type="push" body="$ tar xf $FILE "> Partitioning...</CMD>
    <CMD state="Updater" type="push" body="$ sh mksdcard.sh /dev/mmcblk%mmc%"> Partitioning...</CMD>

    <!-- 烧录第二阶段。烧录uboot、内核、文件系统、设备树到存储-->
    <!-- 烧录uboot 选择uboot的路径-->
    <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>
    <!-- access boot partition -->
    <CMD state="Updater" type="push" body="send" file="%files_dir%/%my_uboot%" ifdev="MX6ULL">Sending u-boot.bin</CMD>
    <CMD state="Updater" type="push" body="$ dd if=$FILE of=/dev/mmcblk%mmc% bs=1k seek=1 conv=fsync">write U-Boot to sd card</CMD>

    <!-- 格式化和挂载boot分区 -->
    <CMD state="Updater" type="push" body="$ while [ ! -e /dev/mmcblk%mmc%p1 ]; do sleep 1; echo \"waiting...\"; done ">Waiting for the partition ready</CMD>
    <CMD state="Updater" type="push" body="$ mkfs.vfat -F 32 /dev/mmcblk%mmc%p1">Formatting rootfs partition</CMD>
    <CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p1"/>
    <CMD state="Updater" type="push" body="$ mount -t vfat /dev/mmcblk%mmc%p1 /mnt/mmcblk%mmc%p1"/>

    <!-- 烧录zImage 选择zImage的路径 -->
    <CMD state="Updater" type="push" body="send" file="%files_dir%/%my_zImage%">Sending kernel zImage</CMD>
    <CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/%my_zImage%">write kernel image to sd card</CMD>

    <!-- 烧录dtb 选择dtb的路径 -->
    <CMD state="Updater" type="push" body="send" file="%files_dir%/%my_dtb%" ifdev="MX6ULL">Sending Device Tree file</CMD>
    <CMD state="Updater" type="push" body="$ cp $FILE /mnt/mmcblk%mmc%p1/%my_dtb%" ifdev="MX6ULL">write device tree to sd card</CMD>

    <!-- 同步并卸载boot分区 -->
    <CMD state="Updater" type="push" body="$ sleep 1">delay</CMD>
    <CMD state="Updater" type="push" body="$ sync">Sync...</CMD>
    <CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p1">Unmounting vfat partition</CMD>

    <!-- 格式化并挂载文件系统分区 -->
    <CMD state="Updater" type="push" body="$ mkfs.ext4 -F -E nodiscard /dev/mmcblk%mmc%p2">Formatting rootfs partition</CMD>
    <CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p2"/>
    <CMD state="Updater" type="push" body="$ mount -t ext4 /dev/mmcblk%mmc%p2 /mnt/mmcblk%mmc%p2"/>

    <!-- 烧录rootfs -->
    <CMD state="Updater" type="push" body="pipe tar -xv -C /mnt/mmcblk%mmc%p2" file="%files_dir%/%my_rootfs%" ifdev="MX6UL MX7D MX6ULL">Sending and writting rootfs</CMD>
    <CMD state="Updater" type="push" body="frf">Finishing rootfs write</CMD>

    <!-- 拷贝modules到rootfs -->
    <CMD state="Updater" type="push" body="send" file="%files_dir%/modules.tar.bz2" ifdev="MX6ULL">Sending modules file</CMD>
    <CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p2/lib/modules"/>
    <CMD state="Updater" type="push" body="$ tar jxf $FILE -C /mnt/mmcblk%mmc%p2/lib/modules/" ifdev="MX6ULL">tar modules file</CMD>
    <CMD state="Updater" type="push" body="$ sleep 1">delay</CMD>
    <CMD state="Updater" type="push" body="$ sync">Sync...</CMD>

    <CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p2">Unmounting rootfs partition</CMD>
    <CMD state="Updater" type="push" body="$ echo Update Complete!">Done</CMD>

如果需要修改ucl2.xml配置, 烧录第一阶段的配置请不要修改, 可以修改第二阶段配置,指定要烧录的文件名称、烧录位置等。

14.3.4. mksdcard.sh脚本

mksdcard.sh文件位于mfgtools-release/profiles/Linux/OS Firmware/目录下,默认是tar压缩包——mksdcard.sh.tar,可以解压然后查看mksdcard.sh文件,脚本内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/sh

# partition size in MB
BOOT_ROM_SIZE=4

# wait for the SD/MMC device node ready
while [ ! -e $1 ]
do
sleep 1
echo “wait for $1 appear”
done

# call sfdisk to create partition table
# destroy the partition table
node=$1
dd if=/dev/zero of=${node} bs=1M count=2

sfdisk --force ${node} << EOF
${BOOT_ROM_SIZE}M,40M,0c
44M,,-
EOF

说明如下:

  • node=$1 :输入的参数是系统分区,eMMC是/dev/mmcblk1,sd是/dev/mmcblk0

  • dd if=/dev/zero of=${node} bs=1M count=2 :销毁设备上原有的分区表和uboot环境变量。

  • sfdisk –force ${node} :sfdisk是一个用于创建和修改分区表的工具,–force选项表示强制操作。

  • ${BOOT_ROM_SIZE}M,40M,0c :定义了第一个分区的信息。从BOOT_ROM_SIZE(4MB)处开始,大小为40MB,分区类型代码为0c,表示FAT32格式。此分区也即boot分区,存放内核和设备树。

  • 44M,,-:定义了第二个分区的信息。从44MB处开始,使用剩余的所有空间,分区类型代码未指定。此分区也即roofs分区,在ucl2.xml中配置格式化为ext4格式。

注意

如果要修改分区大小或者新建分区,可通过mksdcard.sh脚本修改,修改完成后需压缩回tar格式压缩包,并且压缩包名字是mksdcard.sh.tar,不是mksdcard.tar

mksdcard.sh脚本仅适用于eMMC/SD版本,不适用于nand,如果需要修改nand分区和大小,需要修改uboot环境变量、uboot配置文件、内核设备树,相对复杂,此处不作展开。

14.4. 总结

根据前面的讲解可总结以下内容:

  1. 镜像组件存放在mfgtools-release/Profiles/Linux/OS Firmware/release目录下。

  2. 镜像组件名称可通过cfg.ini和vbs脚本指定。

  3. ucl2.xml配置文件指定烧录方法,如分区格式化,烧录哪些文件,烧录到哪个位置等。

  4. mksdcard.sh文件用于配置eMMC和SD分区,可以配置分区大小或者新建分区。