4. SDK编译与烧录:全量编译、模块编译、分区烧录、EMMC与SPI Flash烧录方法

这一章,咱们聊聊SDK的编译和烧录。说实话,这是很多新手朋友最容易卡住的地方。我自己刚接触海思平台那会儿,也在这上面栽过跟头——编译出来烧进去,板子死活起不来,最后发现是分区表没搞对。嗯,咱们今天就把这些坑一个个填平。

4.1 全量编译:从零开始构建整个系统

全量编译,说白了就是把整个SDK从头到尾编译一遍。我个人的习惯是,拿到一个新板子或者新SDK版本时,先做一次全量编译,确保环境没问题。

操作其实很简单,进入SDK根目录,执行:

make clean
make all

这里要注意,第一次编译时间会比较长,大概20到40分钟,取决于你电脑的性能。我建议你泡杯咖啡,或者去活动活动。

我的小技巧: 编译前先检查一下交叉编译链是否配置正确。运行 arm-himix200-linux-gcc --version,如果能正常显示版本号,说明环境没问题。

全量编译会生成哪些东西?主要有这几个:

  • u-boot:引导加载程序,负责初始化硬件并加载内核
  • 内核镜像:Linux内核,通常叫uImage或zImage
  • 文件系统:rootfs,包含所有应用程序和库
  • 设备树:描述硬件信息的.dtb文件

我在项目中遇到过一个问题:全量编译后烧录进去,网络死活不通。查了半天,发现是设备树里网口引脚配置和实际板子对不上。所以啊,全量编译虽然方便,但硬件相关的配置一定要仔细核对。

4.2 模块编译:只改哪里编哪里

全量编译太慢了,对吧?尤其是你只改了一行代码,却要等半小时。这时候模块编译就派上用场了。

海思SDK支持单独编译各个模块。比如你只改了内核驱动:

make kernel

只改uboot:

make uboot

只改文件系统:

make rootfs

你想想看,这样是不是快多了?一般模块编译只需要1到5分钟。

注意: 模块编译不会自动处理依赖关系。比如你改了内核配置,只编译内核是不够的,还得重新生成设备树。我建议你养成习惯:改了什么模块,就把相关的模块都编译一遍。

还有一种情况,你只改了某个应用程序。这时候连模块编译都嫌麻烦,可以直接在SDK的app目录下单独编译:

cd ./osdrv/app/your_app
make clean
make

编译出来的二进制文件,通过NFS或者scp直接传到板子上测试就行。这样做的好处是快,坏处是——嗯,你得自己管理版本,别搞混了。

4.3 分区烧录:搞清楚你的板子怎么分区

分区烧录,这是最容易出问题的地方。我曾经因为分区表写错,把一块板子搞成砖,折腾了一天才救回来。

Hi3559A的存储分区一般是这样划分的:

分区名称 起始地址 大小 内容
boot 0x0 1MB uboot
env 0x100000 128KB uboot环境变量
kernel 0x120000 8MB 内核镜像
rootfs 0x920000 剩余空间 文件系统

烧录的时候,你可以选择全量烧录,也可以只烧某个分区。比如只更新内核:

# 在uboot命令行下
tftp 0x82000000 uImage
nand erase 0x120000 0x800000
nand write 0x82000000 0x120000 0x800000

这里我解释一下:0x82000000是内存地址,用来临时存放从tftp下载的数据。0x120000是内核分区的起始地址,0x800000是大小(8MB)。

核心要点: 分区烧录的关键是地址要对。烧之前一定要确认分区表,最好用 printenv 命令查看uboot的环境变量,里面通常有分区信息。

4.4 EMMC与SPI Flash烧录方法

Hi3559A支持两种存储介质:EMMC和SPI Flash。这两种的烧录方法不太一样,我分别说说。

4.4.1 SPI Flash烧录

SPI Flash容量小(通常16MB到64MB),速度慢,但启动简单。适合做小批量或者原型验证。

烧录SPI Flash,我推荐用海思的烧录工具HiTool。操作步骤:

  1. 板子进入烧录模式(一般是按住某个按键再上电)
  2. 打开HiTool,选择芯片型号Hi3559A
  3. 选择烧录方式为SPI
  4. 加载各个分区的镜像文件
  5. 点击烧录,等待完成

用命令行烧录也可以,但说实话,HiTool更直观。我刚开始用命令行烧SPI Flash时,参数搞错了好几次,后来就老老实实用工具了。

4.4.2 EMMC烧录

EMMC容量大(4GB到64GB),速度快,是量产时的首选。但EMMC烧录比SPI Flash复杂一些。

EMMC烧录有两种方式:

  • fastboot方式:板子进入fastboot模式,通过USB烧录
  • uboot方式:板子启动到uboot,通过tftp或USB烧录

我个人更推荐fastboot方式,因为它速度快,而且支持分区烧录。操作步骤:

# 在PC端执行
fastboot flash boot u-boot-hi3559a.bin
fastboot flash kernel uImage
fastboot flash rootfs rootfs.squashfs
fastboot reboot
避坑指南: 我曾经遇到过一个问题——用fastboot烧录EMMC时,烧到一半提示"data transfer error"。查了半天,发现是USB线质量不好,导致数据传输出错。换了一根好线就解决了。所以啊,烧录时别用那种几块钱的USB线。

还有一种情况,板子已经起不来,uboot也进不去。这时候只能用串口烧录,也就是通过HiTool的串口模式。虽然慢(大概几十KB/s),但至少能把板子救回来。

4.5 我的经验总结

说了这么多,我总结几条实用经验:

  • 第一次烧录:建议全量烧录,确保所有分区都是最新的
  • 日常开发:用模块编译+分区烧录,省时间
  • 量产阶段:用EMMC+fastboot,效率最高
  • 救砖:用串口烧录,虽然慢但可靠

最后提醒一句:烧录前一定要备份原始镜像。我见过太多人把板子搞成砖,然后找不到原始镜像,只能重新下载SDK编译。那个时间成本,啧啧,够你喝好几杯咖啡了。

好了,这一章就到这里。下一章咱们聊聊系统启动流程和调试技巧,到时候我会分享一些我踩过的坑,保证让你少走弯路。