ElfBoard ELF 1板卡OTG烧写与分区方案优化指南

1. ElfBoard ELF 1板卡OTG烧写基础原理

在嵌入式系统开发中,OTG(On-The-Go)烧写是一种常用的固件烧录方式,它通过USB接口实现开发板与主机之间的高速数据传输。ElfBoard ELF 1板卡采用的MfgTool工具是NXP提供的专业烧录工具,其工作流程可以分为以下几个关键阶段:

首先,开发板上电后,内部的boot ROM代码会初始化USB外设,将板卡枚举为HID设备。这个阶段是硬件层面的自动处理,开发者无需干预。当MfgTool检测到HID设备后,会建立连接并开始解析预置的uboot镜像,利用其中的内存配置信息对开发板的DDR进行初始化。

DDR初始化完成后,工具会按照ucl2.xml脚本的指令,将firmware目录下的uboot镜像、内核镜像、设备树以及ramfs加载到DDR内存的指定地址。这个过程涉及精确的内存地址分配:

  • 内核镜像(zImage)加载到0x80800000
  • 虚拟文件系统(ramfs)加载到0x83800000
  • 设备树(dtb)加载到0x83000000

系统启动后会重新枚举USB为MSC设备,此时传输速度大幅提升。MfgTool继续执行ucl2.xml中的命令,将files目录下的完整系统镜像烧写到存储介质中。这个设计巧妙利用了USB协议的不同工作模式,既保证了初始连接的可靠性,又确保了大数据量传输的效率。

2. 分区表修改的核心步骤

2.1 理解默认分区方案

ElfBoard ELF 1的默认分区方案由mksdcard.sh脚本定义,主要包含两个分区:

${BOOT_ROM_SIZE}M,500M,0c # FAT32格式的boot分区 600M,,83 # EXT3格式的rootfs分区

这种设计将前10MB保留给uboot,500MB FAT32分区用于存放内核、设备树等启动文件,剩余空间作为根文件系统。但在实际项目中,我们经常需要调整这个布局。

2.2 修改分区脚本

要增加新的分区,需要编辑mksdcard.sh脚本中的sfdisk命令部分。例如增加一个512MB的数据分区:

sfdisk --force ${node} << EOF ${BOOT_ROM_SIZE}M,500M,0c 600M,512M,83 1200M,,83 EOF

这个修改创建了三个分区:

  1. 保持原有的500MB FAT32分区(0c类型)
  2. 新增512MB的EXT3分区(83类型)作为数据存储
  3. 剩余空间仍作为根文件系统分区

注意:分区大小需要根据实际存储介质容量调整,确保总和不超过设备容量。EMMC通常会有少量保留空间,建议保留至少2%的未分配空间。

2.3 更新烧录流程

分区脚本修改后,需要在ucl2.xml中添加对新分区的处理。在原有的rootfs烧录步骤前插入:

<!-- 格式化并挂载data分区 --> <CMD state="Updater" type="push" body="$ mkfs.ext3 -F /dev/mmcblk%mmc%p3">Formatting data partition</CMD> <CMD state="Updater" type="push" body="$ mkdir -p /mnt/mmcblk%mmc%p3"/> <CMD state="Updater" type="push" body="$ mount -t ext3 /dev/mmcblk%mmc%p3 /mnt/mmcblk%mmc%p3"/> <!-- 可在此添加data分区初始化内容 --> <CMD state="Updater" type="push" body="$ echo "Data Partition" > /mnt/mmcblk%mmc%p3/README"/> <CMD state="Updater" type="push" body="$ umount /mnt/mmcblk%mmc%p3"/>

3. 分区方案设计实践

3.1 典型多分区配置

对于工业应用,推荐以下分区方案:

1. uboot : 1MB (原始保留区域) 2. uboot-env : 1MB (环境变量存储) 3. boot : 128MB (FAT32,内核和设备树) 4. recovery : 128MB (EXT3,恢复系统) 5. data : 512MB (EXT4,应用数据) 6. rootfs : 剩余空间 (EXT4,主系统)

对应的sfdisk命令为:

dd if=/dev/zero of=${node} bs=1024 count=1 sfdisk --force ${node} << EOF ,1M,83 ,1M,83 ,128M,0c ,128M,83 ,512M,83 ,,83 EOF

3.2 分区挂载配置

修改根文件系统中的/etc/fstab文件,添加自动挂载项:

/dev/mmcblk1p3 /data ext4 defaults,noatime 0 2 /dev/mmcblk1p4 /recovery ext4 ro,noauto 0 2

3.3 动态分区调整技巧

对于需要灵活调整分区的场景,可以采用以下方法:

  1. 使用parted工具替代sfdisk:
parted -s ${node} mklabel gpt parted -s ${node} mkpart primary fat32 1MiB 129MiB parted -s ${node} mkpart primary ext4 129MiB 257MiB parted -s ${node} mkpart primary ext4 257MiB 769MiB parted -s ${node} mkpart primary ext4 769MiB 100%
  1. 在烧录脚本中添加分区校验逻辑:
# 检查分区是否创建成功 while [ ! -e /dev/mmcblk%mmc%p4 ]; do sleep 1 echo "等待分区初始化..." done

4. 常见问题与解决方案

4.1 分区未正确识别

现象:系统启动后无法找到新增分区 排查步骤:

  1. 检查内核启动日志:dmesg | grep mmcblk
  2. 确认分区表信息:fdisk -l /dev/mmcblk1
  3. 验证文件系统类型:blkid /dev/mmcblk1p*

常见原因:

  • 分区表未正确写入 → 增加sync命令确保写入完成
  • 内核不支持文件系统 → 检查内核配置中的文件系统支持选项

4.2 烧录过程卡死

现象:烧录到新分区步骤时工具无响应 解决方法:

  1. 降低传输速度:在ucl2.xml的push命令中添加sleep 1间隔
  2. 检查USB连接质量,更换高质量数据线
  3. 增加超时检测机制:
<CMD state="Updater" type="push" body="timeout 60 dd if=$FILE of=/dev/mmcblk%mmc%p3 bs=4M">

4.3 分区大小计算错误

精确计算分区大小的公式:

实际可用空间 = (总块数 - 1) * 块大小 - 2 * 块大小

建议在脚本中添加计算校验:

TOTAL_SIZE=$(blockdev --getsize64 /dev/mmcblk1) REQUIRED_SIZE=$(( (128 + 128 + 512) * 1024 * 1024 )) if [ $TOTAL_SIZE -lt $REQUIRED_SIZE ]; then echo "错误:存储空间不足" exit 1 fi

5. 高级应用技巧

5.1 保留分区配置

对于需要频繁修改分区的场景,可以采用以下策略:

  1. 将分区表信息单独保存到文件中:
sfdisk -d /dev/mmcblk1 > partition_table.backup
  1. 烧录时直接应用备份:
<CMD state="Updater" type="push" body="send" file="config/partition_table.backup"> <CMD state="Updater" type="push" body="$ sfdisk /dev/mmcblk%mmc% < $FILE">

5.2 动态分区挂载

在系统启动脚本中实现智能挂载:

# 检查分区是否存在 if [ -b /dev/mmcblk1p3 ]; then # 检查文件系统完整性 fsck.ext4 -p /dev/mmcblk1p3 # 动态创建挂载点 mkdir -p /data mount /dev/mmcblk1p3 /data fi

5.3 安全擦除技术

对于需要安全擦除的场景,可以在分区前执行:

<CMD state="Updater" type="push" body="$ blkdiscard -f /dev/mmcblk%mmc%"> <CMD state="Updater" type="push" body="$ echo -e 'o\nn\np\n1\n\n+128M\nn\np\n2\n\n+128M\nw' | fdisk /dev/mmcblk%mmc%">

在实际项目中,我曾遇到一个案例:客户需要在同一块板卡上支持两种不同的应用场景。通过设计灵活的分区方案,我们实现了:

  • 前128MB存放公共内核和基础驱动
  • 中间512MB作为场景A的专用分区
  • 剩余空间用于场景B的系统 这种设计减少了30%的存储空间需求,同时提高了系统切换效率。关键点在于精确计算每个分区的最小需求,并在ucl2.xml中添加智能检测逻辑。