K230 SDK 编译流程分析:目录结构、Makefile 入口与 Buildroot 集成

2026-03-27

K230 是嘉楠科技基于玄铁 C908 双核的 RISC-V AI 视觉 SoC。本文分析 K230 SDK 的编译流程,覆盖目录布局、Makefile 入口、Buildroot 集成方式以及最终输出产物。


SDK 目录结构

K230 SDK 顶层目录布局如下:

k230_sdk/
├── Makefile                  # 顶层入口,核心编译驱动
├── configs/                  # defconfig(如 k230_evb_defconfig)
├── board/                    # 板级配置文件、设备树、启动脚本
│   └── k230/
│       ├── env.env           # U-Boot 环境变量
│       └── genimage.cfg      # 镜像打包配置
├── buildroot-ext/            # BR2_EXTERNAL 扩展目录
│   ├── Config.in             # 顶层 Kconfig 入口
│   ├── external.mk           # 顶层 make 入口
│   ├── package/              # 自定义 package(AI 库、驱动、应用)
│   └── configs/              # Buildroot defconfig
├── src/
│   ├── little/               # 小核(Linux + Buildroot)
│   │   └── buildroot/        # Buildroot 源码(submodule)
│   ├── big/                  # 大核(RT-Thread 或裸机)
│   │   └── rtsmart/          # RT-Smart 源码
│   └── uboot/                # U-Boot 源码
├── tools/                    # 镜像打包、烧录工具
└── output/                   # 编译产物目录
    ├── images/               # 最终镜像
    └── build/                # 中间产物

K230 采用双核异构架构:小核运行 Linux(Buildroot 构建),大核运行 RT-Smart(实时操作系统),两者通过共享内存 + mailbox 通信。


Makefile 入口分析

顶层 Makefile 的核心逻辑如下:

# 加载 defconfig,确定 ARCH、CROSS_COMPILE 等变量
include $(BR2_CONFIG)

# 小核编译:调用 Buildroot
little:
	$(MAKE) -C src/little/buildroot \
		BR2_EXTERNAL=$(SDK_ROOT)/buildroot-ext \
		O=$(OUTPUT)/little \
		$(LITTLE_DEFCONFIG)
	$(MAKE) -C src/little/buildroot \
		O=$(OUTPUT)/little

# 大核编译:调用 RT-Smart
big:
	$(MAKE) -C src/big/rtsmart \
		CROSS_COMPILE=$(RISCV_BIG_CROSS) \
		O=$(OUTPUT)/big

# U-Boot 编译
uboot:
	$(MAKE) -C src/uboot \
		CROSS_COMPILE=$(RISCV_CROSS) \
		k230_evb_defconfig
	$(MAKE) -C src/uboot CROSS_COMPILE=$(RISCV_CROSS)

# 打包镜像
image: little big uboot
	python3 tools/gen_image.py \
		--config board/k230/genimage.cfg \
		--output output/images/sysimage-sdcard.img

编译顺序:ubootbig(RT-Smart)→ little(Buildroot/Linux)→ image(打包)。

顶层 make 不加参数时默认执行 all,等价于完整编译并打包。可单独执行 make little 仅编译小核部分。


Buildroot 集成方式

BR2_EXTERNAL 机制

K230 SDK 通过 Buildroot 的 BR2_EXTERNAL 机制将 SDK 特有 package 和配置注入 Buildroot,而不修改 Buildroot 主线源码。

BR2_EXTERNAL 目录须包含以下固定文件:

buildroot-ext/
├── Config.in        # 必须:声明 source "$BR2_EXTERNAL_K230_PATH/package/.../Config.in"
├── external.mk      # 必须:include 所有自定义 package 的 .mk 文件
└── external.desc    # 必须:描述此 BR2_EXTERNAL 的 name 和 desc

external.desc 示例:

name: K230
desc: Canaan K230 SDK external tree

Buildroot 在调用时通过 O= 指定独立输出目录,源码树与产物分离,支持多配置并存。

自定义 package 示例

以 K230 AI 推理库 k230_nncase_runtime 为例,package 目录结构:

buildroot-ext/package/k230_nncase_runtime/
├── Config.in
└── k230_nncase_runtime.mk

Config.in

config BR2_PACKAGE_K230_NNCASE_RUNTIME
	bool "k230_nncase_runtime"
	help
	  nncase runtime library for K230 KPU inference.

k230_nncase_runtime.mk

K230_NNCASE_RUNTIME_VERSION = 1.0.0
K230_NNCASE_RUNTIME_SITE = $(SDK_ROOT)/src/little/nncase
K230_NNCASE_RUNTIME_SITE_METHOD = local

define K230_NNCASE_RUNTIME_BUILD_CMDS
	$(MAKE) -C $(@D) CROSS_COMPILE=$(TARGET_CROSS)
endef

define K230_NNCASE_RUNTIME_INSTALL_TARGET_CMDS
	$(INSTALL) -D -m 0755 $(@D)/libnncase.so $(TARGET_DIR)/usr/lib/
endef

$(eval $(generic-package))

编译输出产物

完整编译后,output/images/ 目录包含:

文件 说明
sysimage-sdcard.img SD 卡完整镜像(含分区表、U-Boot、内核、rootfs)
u-boot.bin U-Boot 二进制
Image / Image.gz Linux 内核镜像
k230-evb.dtb 设备树 blob
rootfs.ext4 小核 Linux rootfs(ext4)
rtsmart.img 大核 RT-Smart 镜像
env.bin U-Boot 环境变量二进制

sysimage-sdcard.img 的分区布局(典型配置):

Offset 0       : MBR 分区表
Partition 1    : U-Boot(raw,不格式化)
Partition 2    : U-Boot env
Partition 3    : Linux 内核 + DTB(FAT32)
Partition 4    : rootfs(ext4)

常用编译命令

# 完整编译(首次或 clean 后)
make CONF=k230_evb_defconfig

# 仅编译小核(Linux + Buildroot)
make little

# 仅重新打包镜像(不重编代码)
make image

# 单独重编某个 Buildroot package
make -C src/little/buildroot O=$(pwd)/output/little k230_nncase_runtime-rebuild

# 清理输出
make clean

# 烧录 SD 卡镜像(Linux 主机)
sudo dd if=output/images/sysimage-sdcard.img of=/dev/sdX bs=4M status=progress

感谢阅读!