第三章 SDK编译与烧录:从源码到板子跑起来
说实话,很多刚入行的朋友觉得编译烧录就是敲几个命令的事。嗯,表面上看确实如此。但我在海思平台折腾了这么多年,可以负责任地告诉你——这里面的坑,一个比一个深。今天我就把SDK编译与烧录的全流程掰开揉碎了讲给你听。
3.1 SDK源码获取:别找错地方
海思的SDK一般通过两种方式获取:
- 官方渠道:海思官网的开发者专区,需要注册企业账号
- 板卡厂商:买开发板时配套的光盘或网盘链接
我个人习惯优先用板卡厂商提供的版本。为什么?因为官方SDK有时候跟具体板子的硬件配置有出入,厂商会做适配。我曾经遇到过官方SDK编译出来的内核,在某个开发板上网口死活不通,折腾了两天才发现是PHY芯片的驱动没适配好。
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.squashfs或rootfs.ext4等文件。这就是你要烧录到板子上的文件系统镜像。
3.4 分区表配置:别让板子变砖
分区表配置,是烧录前最重要的一步。海思芯片的Flash分区一般长这样:
| 分区名 | 起始地址 | 大小 | 内容 |
|---|---|---|---|
| boot | 0x00000000 | 1MB | uboot |
| kernel | 0x00100000 | 8MB | 内核镜像 |
| rootfs | 0x00900000 | 64MB | 文件系统 |
| app | 0x04900000 | 剩余空间 | 应用程序 |
这个表通常在SDK的tools/pc/uboot_tools/目录下,以.xml或.cfg文件形式存在。
所以我的习惯是:先编译完所有镜像,看看每个文件的实际大小,再回头调整分区表。确保每个分区至少留出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。
3.6 验证与调试:烧录完不等于完事
烧录完成后,重启板子。如果一切顺利,你会看到uboot启动,然后加载内核,最后进入文件系统。但现实往往没那么美好。
常见问题:
- uboot启动卡住:检查串口波特率是否匹配,一般是115200
- 内核panic:多半是设备树配置不对,或者驱动没编进去
- 文件系统挂载失败:检查分区地址和文件系统类型是否匹配
我记得有一次,内核启动后报VFS: Unable to mount root fs,查了半天发现是文件系统格式选错了。我编译的是squashfs,但内核配置里没开这个文件系统的支持。重新编译内核后就好了。
嗯,到这里,SDK编译与烧录的全流程就讲完了。说白了,这步就是搭积木——把uboot、内核、文件系统这三块积木拼好,然后通过烧录工具塞进板子。每一步都有坑,但只要你按照流程来,多试几次,总能跑起来。
下一章我会讲设备树配置,那是让内核认识你板子硬件的关键一步。到时候见。