第3章:SDK源码结构解析
拿到一块新的开发板,第一件事是什么?我个人习惯是先把它自带的SDK目录结构摸清楚。说白了,你得知道什么东西放在哪里,不然编译都找不到头文件,那可就尴尬了。
RV1126的SDK,我刚开始接触时也觉得挺复杂。但拆开来看,其实就几个核心模块。今天我就带你走一遍,把每个目录的职责讲明白。
3.1 SDK顶层目录一览
先看看SDK解压后的顶层长什么样。你执行 ls -l 会看到类似这样的结构:
rv1126_sdk/
├── kernel/ # Linux内核源码
├── u-boot/ # U-Boot引导程序
├── buildroot/ # 根文件系统构建工具
├── app/ # 应用层代码
├── docs/ # 文档
├── tools/ # 工具链和脚本
├── output/ # 编译输出目录
└── Makefile # 顶层编译入口
嗯,这里要注意:不同厂商的SDK可能会有细微差别,但核心模块基本一致。我在项目中遇到过一家厂商把 app 改名叫 customer,但内容大同小异。
3.2 kernel目录:驱动开发的主战场
作为驱动开发者,kernel 目录是你打交道最多的地方。它的结构遵循标准Linux内核布局:
kernel/
├── arch/ # 架构相关代码
│ └── arm/ # ARM架构
│ └── mach-rockchip/ # Rockchip平台代码
├── drivers/ # 设备驱动
│ ├── media/ # 多媒体驱动(摄像头、显示等)
│ ├── net/ # 网络驱动
│ ├── spi/ # SPI驱动
│ └── i2c/ # I2C驱动
├── include/ # 头文件
├── sound/ # 音频驱动
└── Makefile # 内核编译规则
你想想看,我们写驱动时,大部分时间都在 drivers/ 下折腾。比如你要写一个摄像头驱动,就去 drivers/media/ 下面找。Rockchip平台相关的代码在 arch/arm/mach-rockchip/ 里,这里面定义了芯片的引脚复用、时钟管理等底层配置。
arch/arm/mach-rockchip/ 下的 board-*.c 文件。这里面有开发板的硬件初始化代码,能帮你快速了解外设是怎么挂载的。
3.3 u-boot目录:系统启动的第一棒
U-Boot负责初始化硬件并加载内核。它的目录结构相对简单:
u-boot/
├── board/ # 板级支持包
│ └── rockchip/ # Rockchip板级代码
├── common/ # 通用功能
├── drivers/ # 驱动(串口、网络、存储等)
├── include/ # 头文件
└── configs/ # 板级配置文件
我曾经在调试一个新板子时,发现U-Boot死活起不来。查了半天,原来是 configs/ 下的配置文件里DDR参数设错了。所以,如果你遇到启动问题,先检查这里。
3.4 buildroot目录:构建你的文件系统
Buildroot是一个自动化构建工具,帮你生成根文件系统。它的结构如下:
buildroot/
├── board/ # 板级配置
├── configs/ # 默认配置
├── package/ # 软件包
│ ├── busybox/ # 基础命令
│ ├── alsa-utils/ # 音频工具
│ └── openssh/ # SSH服务
├── fs/ # 文件系统生成脚本
└── Makefile # 构建规则
说白了,你想在板子上跑什么软件,就在 package/ 下找对应的包。比如你想加个网络调试工具,就找 package/iperf/。Buildroot会自动下载源码、交叉编译、打包进文件系统。
configs/ 下,通常以 rockchip_rv1126_defconfig 命名。执行 make menuconfig 可以图形化选择你要的软件包。
3.5 app目录:用户态程序的家
app 目录存放用户态应用程序,比如多媒体测试程序、网络服务等。它的结构因项目而异,但通常包含:
app/
├── camera/ # 摄像头测试程序
├── display/ # 显示测试程序
├── network/ # 网络相关程序
└── common/ # 公共库
我建议你多看看这里的代码。很多时候,驱动写好了,怎么验证?就是靠这些app。比如你写完一个摄像头驱动,就可以用 app/camera/ 下的程序抓一帧图像看看。
3.6 编译流程概览
整个SDK的编译流程,我用一张图来展示:
编译流程其实就四步:
- 配置环境: 设置交叉编译工具链路径,执行
source envsetup.sh - 编译U-Boot: 生成
uboot.img,负责引导系统 - 编译内核: 生成
boot.img,包含内核镜像和设备树 - 构建文件系统: 生成
rootfs.img,包含所有用户态程序
你可能会问:为什么是这个顺序?因为U-Boot要先跑起来,才能加载内核;内核跑起来后,才能挂载文件系统。一环扣一环,缺一不可。
# 一键编译所有
./build.sh all
# 或者分步编译
./build.sh uboot
./build.sh kernel
./build.sh rootfs
我记得第一次编译整个SDK时,等了将近半小时。后来发现,其实可以只编译你修改的部分。比如你只改了内核驱动,那就只执行 ./build.sh kernel,能省不少时间。
3.7 输出目录说明
编译完成后,所有生成的文件都在 output/ 目录下:
output/
├── images/ # 最终镜像文件
│ ├── uboot.img
│ ├── boot.img
│ └── rootfs.img
├── kernel/ # 内核编译中间文件
├── uboot/ # U-Boot编译中间文件
└── buildroot/ # 文件系统编译中间文件
你烧录板子时,只需要 images/ 下的三个镜像文件。其他中间文件,说白了就是编译过程的副产品,平时不用管。
output/ 目录下找半天找不到镜像文件,后来发现是编译失败了。建议你每次编译完,先检查 output/images/ 下有没有生成文件,再开始烧录。
好了,SDK的目录结构和编译流程就讲到这里。你只要记住:kernel是驱动的主战场,u-boot是启动的第一棒,buildroot负责文件系统,app是验证工具。把这几个模块的关系理清楚,后面写驱动时就不会迷路了。
可可精品资料库