海思3536 NAND扩容实战:从硬件升级到双系统引导参数调整

📅 发布时间:2026/7/6 14:16:06 👁️ 浏览次数:
海思3536 NAND扩容实战:从硬件升级到双系统引导参数调整
1. 硬件升级后的第一道坎为什么系统“看不见”新空间大家好我是老张一个在嵌入式圈子里摸爬滚打了十多年的老工程师。最近在做一个海思Hi3536的项目硬件同事兴冲冲地告诉我“老张板子的NAND Flash从256MB升级到1GB了空间管够” 我一开始也挺高兴但一上电就傻眼了——系统启动后df -h命令一看根文件系统还是那可怜的235MB多出来的那700多MB空间就像凭空消失了一样系统压根不认。如果你也遇到了同样的问题别慌这太正常了。这就像你给电脑换了一块1TB的新硬盘但如果不分区、不格式化系统里显示的依然是原来那块小硬盘的容量。对于嵌入式Linux系统尤其是海思这种双系统架构的芯片这个过程要更精细一些。它不仅仅是物理硬件的更换更是一场涉及烧写工具、引导程序、内核参数和文件系统的“协同作战”。简单来说想让海思3536识别并利用这1GB的NAND我们需要完成两个核心动作第一告诉烧写工具Hitool新的“地图”怎么画也就是修改分区表把主文件系统的分区划到900MB第二告诉系统的“开机向导”U-Boot按照新地图来引导系统这涉及到一系列环境变量的调整。整个过程环环相扣一步错轻则系统无法启动重则可能把原有数据搞丢。下面我就把自己踩过的坑和总结出来的详细步骤掰开揉碎了分享给大家保证你跟着做就能成功。2. 绘制新蓝图在Hitool中修改分区表拿到硬件升级后的板子第一步不是急着烧系统而是先规划好这块1GB NAND的“土地”如何使用。海思3536默认是双系统架构一个主系统Master控制A17核心一个从系统Slave控制A7和多媒体单元。我们通常用主系统来引导从系统应用程序也放在主系统的文件系统里。原来的256MB NAND分区大概是这样的最前面是1MB的boot区放U-Boot接着是4MB的kernel区放内核然后是235MB的rootfs区主系统根文件系统剩下的空间留给从系统。现在容量变成了1GB我们目标是把主系统的rootfs扩大到900MB其他分区大小暂时不变但位置会后移。操作步骤找到并编辑分区表文件打开你的Hitool工具找到工程配置里关于NAND分区表的设置。这个可能是一个独立的配置文件比如partition.xml也可能是工具里的一个表格。原始文章里没有给出具体文件名这通常是项目相关的。你需要找到定义hinand分区的那部分。修改主文件系统分区大小将对应rootfs或者你命名的类似主文件系统分区的size字段从原来的235M修改为900M。这里有个关键点分区大小通常需要按块Block或擦除块Erase Block大小对齐海思NAND通常按1MB对齐比较安全所以设置900M是没问题的。确认其他分区偏移由于rootfs分区变大了它之后的所有分区也就是从系统的boot、kernel、rootfs它们的起始偏移地址都会发生改变。在Hitool的分区表里你通常只需要关心大小系统或工具会自动计算后续分区的起始地址。但我们必须心里有数因为下一步调整U-Boot时会用到这些新地址。计算很简单新从系统boot起始地址 1M(boot) 4M(kernel) 900M(rootfs) 905M。修改完Hitool的分区表意味着烧写工具知道了新布局。你可以用这个新配置将编译好的900MB大小的根文件系统镜像和其他镜像烧写到板子的正确位置。但是烧写成功只是完成了“数据写入”系统启动时能否正确找到这些数据还得看U-Boot的“导航”设置。3. 调整系统导航仪详解U-Boot关键环境变量烧写完成重启开发板在串口中断U-Boot的启动过程通常快速敲回车或空格键我们就进入了U-Boot的命令行界面。这里是整个扩容实战的核心战场。我们需要修改几个至关重要的环境变量它们相当于系统启动的“导航指令”。先来看看扩容前针对256MB NAND的典型设置和原始文章一致setenv bootargs mem512M consolettyAMA0,115200 root/dev/mtdblock2 rootfstypeyaffs2 mtdpartshinand:1M(boot),4M(kernel),235M(rootfs) setenv bootcmd nand read 0x42000000 0x100000 0x400000;bootm 0x42000000 setenv slave_autostart 1 setenv slave_bootcmd nand read 0x81000000 0xF000000 0x80000;nand read 0x82000000 0xF100000 0x400000;nand read 0x83000000 0xF500000 0x600000;bootm 0x81000000 0x82000000 0x83000000 setenv slave_bootargs mem96M consolettyAMA0,115200 saveenv逐条拆解与修改3.1 主系统引导参数bootargs与bootcmdbootargs这是传递给Linux内核的命令行参数。mem512M指定DDR内存大小。consolettyAMA0,115200指定控制台串口。root/dev/mtdblock2指定根文件系统在MTD块设备中的索引。mtdblock2对应的是mtdparts中定义的第三个分区索引从0开始即rootfs。扩容后它仍然是第三个分区所以这个值不需要改。rootfstypeyaffs2根文件系统类型。mtdpartshinand:1M(boot),4M(kernel),900M(rootfs)这是需要修改的关键将rootfs的大小从235M改为900M。这个参数告诉内核NAND的实际分区布局。bootcmd这是U-Boot自动执行的启动命令。nand read 0x42000000 0x100000 0x400000从NAND的偏移地址0x100000即1MB处读取0x400000即4MB大小的数据到内存地址0x42000000。这里读的是kernel分区。由于kernel分区大小和位置在boot分区之后没有改变所以这行命令不需要修改。bootm 0x42000000从内存地址启动内核。所以主系统的修改很简单几乎只动了bootargs中的mtdparts一行。3.2 从系统引导参数slave_bootcmd这是本次修改的难点和重点。因为主系统的rootfs从235M扩大到了900M导致后面所有从系统分区的起始地址都向后“推移”了。扩容前从系统分区起始地址十进制slave_boot: 240Mslave_kernel: 241Mslave_rootfs: 245M扩容后新的起始地址计算slave_boot: 1M 4M 900M 905Mslave_kernel: 905M 1M 906M(假设slave_boot为1M)slave_rootfs: 906M 4M 910M(假设slave_kernel为4M)接下来需要把十进制转换成十六进制因为U-Boot的nand read命令使用十六进制地址。905M 的十六进制905 * 1024 * 1024 949288960 字节。计算其十六进制更简单的方法是使用计算器或U-Boot的printenv配合简单运算。这里直接给出结果与原始文章有差异原始文章的计算结果似乎有误我们以正确计算为准905M ≈ 0x38900000这是更常见的对齐表示。实际上精确计算905 * 0x100000 0x38900000。906M ≈ 0x38A00000910M ≈ 0x38E00000因此新的slave_bootcmd应该修改为setenv slave_bootcmd nand read 0x81000000 0x38900000 0x80000; nand read 0x82000000 0x38A00000 0x400000; nand read 0x83000000 0x38E00000 0x600000; bootm 0x81000000 0x82000000 0x83000000注意这里读取的大小0x80000,0x400000,0x600000需要与你实际烧写的从系统镜像大小一致如果从系统镜像也变了这里也要相应调整。3.3 最终修改与保存将上述所有修改整合在U-Boot命令行中依次执行slave_autostart和slave_bootargs保持不变setenv bootargs mem512M consolettyAMA0,115200 root/dev/mtdblock2 rootfstypeyaffs2 mtdpartshinand:1M(boot),4M(kernel),900M(rootfs) setenv bootcmd nand read 0x42000000 0x100000 0x400000;bootm 0x42000000 setenv slave_autostart 1 setenv slave_bootcmd nand read 0x81000000 0x38900000 0x80000;nand read 0x82000000 0x38A00000 0x400000;nand read 0x83000000 0x38E00000 0x600000;bootm 0x81000000 0x82000000 0x83000000 setenv slave_bootargs mem96M consolettyAMA0,115200 saveenv执行saveenv后输入reset重启板子理论上系统应该能引导进入新的900MB根文件系统了。4. 踩坑记录YAFFS2文件系统的兼容性问题按照上面的步骤操作完满怀期待地重启结果系统卡住了或者内核报错提示类似“Current hardware config, pagesize:4096, ecctype:24bits/1K”或者“请检查当前单板Flash与烧写分区中的Flash类型是否一致”的信息。别急这个问题我踩过根源在于文件系统镜像与物理Flash参数不匹配。YAFFS2文件系统镜像在制作时是紧密依赖底层NAND Flash硬件参数的主要包括页大小Page Size和OOB/ECC类型。原来的256MB Flash和新的1GB Flash即使都是NAND它们的页大小、块大小、ECC配置也可能不同。你用为旧Flash制作的YAFFS2镜像烧写到新Flash上启动时内核按照新Flash的参数去挂载自然就对不上号导致挂载失败。解决方案是用与新Flash匹配的参数重新制作YAFFS2根文件系统镜像。确定新Flash的参数最准确的方法是查阅1GB NAND Flash的数据手册Datasheet找到Page Size和ECC要求。也可以询问硬件工程师。常见的组合可能是2KB页大小4bit ECC/512字节或者4KB页大小24bit ECC/1KB即错误信息里提示的。使用正确的制作工具和参数海思SDK里通常会提供mkyaffs2image工具或者你需要自己编译一个。关键是在制作镜像时传入正确的参数。例如原始文章中给出的命令./mkyaffs2image610 rootfs_glibc_master rootfs_glibc_2k_4bit_zmj_1g.yaffs2 2 4这个命令中2可能代表页大小是2KB4可能代表ECC位宽是4位。如果你的新Flash是4KB页、24位ECC/1KB那么参数很可能需要改变具体要参考你所使用的mkyaffs2image工具的帮助说明。切勿盲目套用参数。重新烧写用新制作好的YAFFS2镜像在Hitool中替换掉原来的根文件系统镜像重新烧写。这个过程告诉我们嵌入式开发中硬件、驱动、文件系统、引导程序是一个紧密耦合的整体。任何一环的变更都可能需要其他环节的同步调整。5. 系统验证与排错指南完成所有修改和烧写后如何确认扩容成功了呢这里有一套验证和排错的组合拳。验证步骤U-Boot阶段验证重启进入U-Boot使用printenv命令仔细核对修改后的bootargs、mtdparts和slave_bootcmd中的地址是否正确。还可以使用nand info查看U-Boot识别到的NAND总容量是否为1GB。内核启动阶段验证系统启动时观察内核日志串口输出。重点关注MTD子系统的初始化信息它会打印出检测到的NAND信息以及解析mtdparts参数后创建的分区表。你应该能看到类似“Creating 3 MTD partitions on hinand:”的日志并且第三个分区rootfs的大小显示为900MB左右。系统运行时验证成功进入Linux系统后执行以下命令cat /proc/mtd查看MTD分区信息。确认rootfs对应的分区通常是mtd2大小是否正确。df -h查看挂载的文件系统使用情况。挂载点为/的文件系统其总大小应该接近900MB。mount查看根文件系统的挂载参数确认类型是yaffs2并且来自正确的MTD块设备如/dev/mtdblock2。常见排错思路系统无法启动卡在U-Boot检查bootcmd命令特别是nand read的源地址和目标地址是否正确读取的数据长度是否超过镜像实际大小或分区大小。内核panic无法挂载根文件系统检查bootargs中的root参数指定的设备号是否正确/dev/mtdblock2。重点检查YAFFS2镜像兼容性问题如上节所述。检查mtdparts参数是否与Hitool烧写时的分区布局、以及内核中Flash驱动支持的命名这里是hinand完全一致。从系统无法启动主系统起来了但从系统没起来。检查slave_autostart是否为1并检查slave_bootcmd中的每一个地址。最可能出错的就是地址计算。务必反复核对十进制到十六进制的转换。可以用U-Boot的cp命令先尝试读取一小段数据到内存再用md命令查看内容确认是否读到了有效数据如从系统的U-Boot魔数。容量显示不对如果df -h显示容量还是旧的但cat /proc/mtd显示新容量可能是文件系统本身如yaffs2在挂载时没有完全占用整个MTD分区。尝试重新制作并烧写文件系统镜像。整个海思3536的NAND扩容就像一次精密的器官移植手术。硬件是新的“器官”分区表是新的“血管图”U-Boot环境变量是“神经连接指令”而文件系统则是“血液供给”。只有每一步都准确无误系统这个“生命体”才能在新硬件上焕发活力。希望我这篇结合了大量实战细节和踩坑经验的文章能帮你顺利完成这次升级。