第三章 SDK编译与烧录:从源码到板子跑起来

说实话,很多刚入行的朋友觉得编译烧录就是敲几个命令的事。嗯,表面上看确实如此。但我在海思平台折腾了这么多年,可以负责任地告诉你——这里面的坑,一个比一个深。今天我就把SDK编译与烧录的全流程掰开揉碎了讲给你听。

3.1 SDK源码获取:别找错地方

海思的SDK一般通过两种方式获取:

  • 官方渠道:海思官网的开发者专区,需要注册企业账号
  • 板卡厂商:买开发板时配套的光盘或网盘链接

我个人习惯优先用板卡厂商提供的版本。为什么?因为官方SDK有时候跟具体板子的硬件配置有出入,厂商会做适配。我曾经遇到过官方SDK编译出来的内核,在某个开发板上网口死活不通,折腾了两天才发现是PHY芯片的驱动没适配好。

注意:拿到SDK后第一件事——检查MD5校验值。我见过有人下载到一半断网,结果编译到半夜才发现文件损坏,那叫一个崩溃。

3.2 顶层Makefile解析:读懂海思的编译框架

解压SDK后,你会看到一个顶层的Makefile。别急着敲make,先花10分钟看看它的结构。

# 海思SDK顶层Makefile典型结构
all: prepare kernel rootfs uboot

prepare:
    @echo "Checking toolchain..."
    # 检查交叉编译链是否存在

kernel:
    $(MAKE) -C $(KERNEL_DIR) ARCH=arm CROSS_COMPILE=$(CROSS)

rootfs:
    $(MAKE) -C $(ROOTFS_DIR)

uboot:
    $(MAKE) -C $(UBOOT_DIR)

clean:
    rm -rf $(OUTPUT_DIR)/*

你看,它把整个编译流程分成了四个阶段:准备环境、编译内核、制作文件系统、编译uboot。每个阶段都是独立的,可以单独执行。

这里有个小技巧——我一般先执行make prepare,看看环境有没有问题。如果直接make all,万一中间某个环节报错,排查起来很麻烦。

3.3 内核与文件系统编译:两个关键步骤

3.3.1 内核编译

海思芯片的内核编译,说白了就是配置+编译两步。但配置这一步,学问很大。

# 进入内核目录
cd kernel/

# 使用默认配置
make ARCH=arm hi3559av100_defconfig

# 或者手动配置
make ARCH=arm menuconfig

# 编译内核
make ARCH=arm CROSS_COMPILE=arm-himix200-linux- -j4

你可能会问:用默认配置不行吗?行,但不够。我在项目中遇到过,默认配置没开某个SPI驱动,结果外接的传感器死活读不到数据。后来进menuconfig翻了半天才找到。

我的建议:第一次编译先用默认配置,确保流程走通。然后根据你的硬件需求,逐步裁剪或增加功能。别一上来就全选,编译时间长得够你喝三杯咖啡。

3.3.2 文件系统编译

文件系统这块,海思SDK通常提供两种选择:

  • Busybox:轻量级,适合资源受限的场景
  • Buildroot:功能更全,但体积也大

我个人更倾向于Buildroot。为什么?因为它能自动处理依赖关系。用Busybox时,我曾经手动添加一个网络工具,结果漏了某个库文件,板子上跑起来直接段错误。排查了整整一个下午。

# Buildroot编译示例
cd buildroot/
make hi3559av100_defconfig
make

编译完成后,会在output/images/目录下生成rootfs.squashfsrootfs.ext4等文件。这就是你要烧录到板子上的文件系统镜像。

3.4 分区表配置:别让板子变砖

分区表配置,是烧录前最重要的一步。海思芯片的Flash分区一般长这样:

分区名 起始地址 大小 内容
boot 0x00000000 1MB uboot
kernel 0x00100000 8MB 内核镜像
rootfs 0x00900000 64MB 文件系统
app 0x04900000 剩余空间 应用程序

这个表通常在SDK的tools/pc/uboot_tools/目录下,以.xml.cfg文件形式存在。

血的教训:我曾经在配置分区时,把kernel分区大小写小了,结果编译出来的内核镜像放不进去。更惨的是,uboot启动时会去固定地址加载内核,地址对不上,板子直接变砖。最后只能拆Flash用编程器重刷。

所以我的习惯是:先编译完所有镜像,看看每个文件的实际大小,再回头调整分区表。确保每个分区至少留出20%的余量。

3.5 烧录工具使用:把镜像写进板子

海思官方提供的烧录工具叫HiTool,也有用fastboot的。我重点讲HiTool,因为它更常用。

3.5.1 准备工作

  • 板子通过串口线连接电脑
  • 板子进入烧录模式(一般是上电时按住某个按键)
  • 打开HiTool,选择对应的芯片型号

3.5.2 烧录步骤

1. 选择烧录方式:串口或网口
   - 串口:速度慢,但稳定,适合调试
   - 网口:速度快,但需要先配置IP

2. 加载分区表文件(就是刚才说的.xml)

3. 逐个加载镜像文件:
   - uboot -> boot分区
   - uImage -> kernel分区
   - rootfs.squashfs -> rootfs分区

4. 点击"烧录",等待进度条走完

这里有个细节——烧录uboot时,如果板子原来的uboot已经坏了,串口烧录可能不成功。我遇到过这种情况,最后是用SD卡启动一个最小系统,再通过它来烧录Flash。

小技巧:第一次烧录成功后,记得备份整个Flash。用HiTool的"读取"功能,把Flash内容全部读出来保存。万一以后板子变砖,直接恢复就行,省得重新编译。

3.6 验证与调试:烧录完不等于完事

烧录完成后,重启板子。如果一切顺利,你会看到uboot启动,然后加载内核,最后进入文件系统。但现实往往没那么美好。

常见问题:

  • uboot启动卡住:检查串口波特率是否匹配,一般是115200
  • 内核panic:多半是设备树配置不对,或者驱动没编进去
  • 文件系统挂载失败:检查分区地址和文件系统类型是否匹配

我记得有一次,内核启动后报VFS: Unable to mount root fs,查了半天发现是文件系统格式选错了。我编译的是squashfs,但内核配置里没开这个文件系统的支持。重新编译内核后就好了。

嗯,到这里,SDK编译与烧录的全流程就讲完了。说白了,这步就是搭积木——把uboot、内核、文件系统这三块积木拼好,然后通过烧录工具塞进板子。每一步都有坑,但只要你按照流程来,多试几次,总能跑起来。

下一章我会讲设备树配置,那是让内核认识你板子硬件的关键一步。到时候见。