板级工程与配置
本页介绍 AW31N BLE SDK 的板级工程组织方式与构建配置体系,涵盖顶层 Makefile 对子工程的分派、板级目录结构、板级 Makefile 的跨平台工具链与编译参数,以及构建产物与后处理下载脚本。
Purpose and Scope
本文档面向需要理解或修改 AW31N 板级工程的开发者,内容覆盖:
- 顶层
Makefile如何分派到各个板级子工程(aw31n_transfer、aw31n_hid) - 板级工程目录
apps/demo/transfer/board/bd47/中各配置文件的职责 - 板级
Makefile中 Windows / Linux 双平台工具链选择、CFLAGS、宏定义(DEFINES)的完整含义 - 构建产物(
sdk.elf)输出路径与后处理下载脚本(download.bat/download.sh) - Linux 环境的工具链安装要求与常见限制(
ulimit -n、/opt/jieli目录层次)
以下主题属于其他目录页,不在本页展开:具体应用功能(transfer / hid 的业务逻辑)、外设驱动细节、SDK 库内部实现。
Overview
AW31N BLE SDK 采用「根 Makefile → 板级子工程 Makefile」的两级构建结构。根目录的 Makefile 只负责定义可编译的目标集合(当前为 aw31n_transfer 与 aw31n_hid),真正完成编译、链接、后处理的是位于各 demo 应用 board/ 目录下的板级 Makefile。
每个板级工程目录聚合了一整套板级描述文件:
- 板级实现文件:
board_aw31n_demo.c、board_aw318n_dongle.c等,描述具体板卡的硬件初始化与资源分配; - 板级配置头文件:
board_config.h、board_aw31n_demo_cfg.h、board_aw318n_dongle_cfg.h等,以宏方式开关板级功能; - 全局构建配置:
board_aw31n_demo_global_build_cfg.h、board_aw318n_dongle_global_build_cfg.h,控制 SDK 级构建裁剪; - 工程组织文件:
app_modules.h(模块包含清单)、AW31N_transfer.cbp(Code::Blocks 工程,便于 IDE 导入); - 构建脚本:
Makefile。
这种「配置与代码分离、工程与板卡解耦」的设计意图是:同一份 SDK 可以通过新增一个 board/ 目录来支持新的板卡/应用场景,而无需改动 SDK 核心;同时把工具链路径、编译选项等环境相关的内容集中在 Makefile 中,方便跨平台(Windows / Linux)构建。
Architecture
下图展示了板级工程在整个构建体系中的位置与数据流:
flowchart TD
subgraph sg_Root["根目录"]
RootMK["Makefile<br/>总控入口"]
end
subgraph sg_BoardTransfer["apps/demo/transfer/board/bd47"]
BoardMK["板级 Makefile<br/>工具链 + CFLAGS + DEFINES"]
BoardC["board_aw31n_demo.c<br/>board_aw318n_dongle.c"]
BoardCfg["board_config.h<br/>*_cfg.h / *_global_build_cfg.h"]
AppMods["app_modules.h"]
CBP["AW31N_transfer.cbp<br/>IDE 工程"]
end
subgraph sg_Toolchain["工具链"]
WinTC["Windows: C:/JL/pi32/bin<br/>clang / q32s-lto-wrapper"]
LinTC["Linux: /opt/jieli/q32s/bin<br/>clang / lto-wrapper"]
end
subgraph sg_Output["构建产物"]
ELF["sdk.elf<br/>apps/app/post_build/bd47/"]
Post["download.bat / download.sh<br/>后处理下载脚本"]
end
RootMK -->|"make aw31n_transfer"| BoardMK
BoardMK -->|"CC / LD / AR"| WinTC
BoardMK -->|"CC / LD / AR"| LinTC
BoardMK -->|"编译单元"| BoardC
BoardMK -->|"-include / DEFINES"| BoardCfg
BoardMK -->|"宏定义"| AppMods
BoardMK -->|"链接输出"| ELF
ELF --> Post
CBP -.->|"IDE 可视化配置"| BoardMK
架构要点说明:
- 根 Makefile 是唯一的构建入口,通过
$(MAKE) -C <board目录> -f Makefile递归调用板级 Makefile,实现多工程并行管理的统一入口; - 板级 Makefile 是编译核心:它根据操作系统自动选择工具链(Windows 使用
C:/JL/pi32/bin,Linux 使用/opt/jieli/q32s/bin),并集中定义CFLAGS与DEFINES; - 板级配置头文件 通过宏定义(如
CONFIG_CPU_BD47、APP_CASE_TRANSFER)影响 SDK 编译行为,实现「一块板卡一套配置」; - 构建产物 统一输出到
apps/app/post_build/bd47/sdk.elf,随后由后处理脚本完成格式修正(Windows 下fixbat.exe处理 utf8→gbk 编码)与烧录下载。
板级工程目录结构
以 apps/demo/transfer/board/bd47/(transfer 应用、bd47 板卡)为例,板级工程目录包含以下文件:
| 文件 | 职责 |
|---|---|
Makefile | 板级构建脚本:工具链、编译参数、宏定义、链接输出、后处理 |
board_config.h | 板级总配置头文件,被其他配置文件引用 |
board_aw31n_demo_cfg.h / board_aw31n_demo.c | AW31N demo 板卡的功能配置与板级实现 |
board_aw318n_dongle_cfg.h / board_aw318n_dongle.c | AW318N dongle(适配器/接收端)板卡的配置与实现 |
board_aw31n_demo_global_build_cfg.h / board_aw318n_dongle_global_build_cfg.h | SDK 全局构建裁剪配置(决定哪些模块被编译进固件) |
app_modules.h | 应用模块包含清单 |
AW31N_transfer.cbp | Code::Blocks 工程文件,可在 IDE 中打开并与 Makefile 配置保持一致 |
设计意图:一个 board/ 目录即一个完整的「板卡+应用」组合。目录内的 *_cfg.h 与 *_global_build_cfg.h 分离了「板级功能开关」与「SDK 全局构建开关」两个关注点:前者回答"这块板卡有哪些外设/能力",后者回答"整个固件需要哪些 SDK 模块"。这种分离让新增板卡时只需复制目录并修改配置,不需要触碰 SDK 核心代码。
顶层 Makefile:工程入口分派
根目录 Makefile 是整个 SDK 的构建总控。它支持的目标与分派关系如下:
# 支持的目标
# make aw31n_transfer
# make aw31n_hid
.PHONY: all clean aw31n_transfer aw31n_hid clean_aw31n_transfer clean_aw31n_hid
all: aw31n_transfer aw31n_hid
@echo +ALL DONE
clean: clean_aw31n_transfer clean_aw31n_hid
@echo +CLEAN DONE
aw31n_transfer:
$(MAKE) -C apps/demo/transfer/board/bd47 -f Makefile
clean_aw31n_transfer:
$(MAKE) -C apps/demo/transfer/board/bd47 -f Makefile clean
aw31n_hid:
$(MAKE) -C apps/demo/hid/board/bd47 -f Makefile
clean_aw31n_hid:
$(MAKE) -C apps/demo/hid/board/bd47 -f Makefile clean
来源:Makefile
解读:
make/make all依次构建aw31n_transfer和aw31n_hid两个目标;每个目标实际上是通过$(MAKE) -C <路径> -f Makefile递归进入对应板级目录执行其 Makefile;clean目标同样成对出现(clean_aw31n_transfer、clean_aw31n_hid),保证两个工程的中间产物都能被清除;- 新增工程时只需在
.PHONY与目标列表中加入新目标,并指向新板级目录,即可将新工程纳入总控——这是该 SDK 扩展多应用的标准方式。
板级 Makefile:跨平台构建核心
板级 Makefile(apps/demo/transfer/board/bd47/Makefile)是编译链接的实际执行者。它首先根据操作系统分支选择工具链:
# 工具路径设置
ifeq ($(OS), Windows_NT)
# Windows 下工具链位置
TOOL_DIR := C:/JL/pi32/bin
CC := clang.exe
CXX := clang.exe
LD := q32s-lto-wrapper.exe
AR := llvm-ar.exe
MKDIR := mkdir_win -p
RM := rm -rf
SYS_LIB_DIR := C:/JL/pi32/q32s-lib
SYS_INC_DIR := C:/JL/pi32/q32s-include
EXT_CFLAGS := # Windows 下不需要 -D__SHELL__
export PATH:=$(TOOL_DIR);$(PATH)
## 后处理脚本
FIXBAT := ../../../../../tools/utils/fixbat.exe # 用于处理 utf8->gbk 编码问题
POST_SCRIPT := ../../../../../apps/app/post_build/bd47/download.bat
RUN_POST_SCRIPT := ..\..\..\..\..\apps\app\post_build\bd47\download.bat
else
# Linux 下工具链位置
TOOL_DIR := /opt/jieli/q32s/bin
CC := clang
CXX := clang
LD := lto-wrapper
AR := lto-ar
MKDIR := mkdir -p
RM := rm -rf
export OBJDUMP := $(TOOL_DIR)/objdump
export OBJCOPY := $(TOOL_DIR)/objcopy
export OBJSIZEDUMP := $(TOOL_DIR)/objsizedump
SYS_LIB_DIR := $(TOOL_DIR)/../lib
SYS_INC_DIR := $(TOOL_DIR)/../include
EXT_CFLAGS := -D__SHELL__ # Linux 下需要这个保证正确处理 download.c
export PATH:=$(TOOL_DIR):$(PATH)
## 后处理脚本
FIXBAT := touch # Linux下不需要处理 bat 编码问题
POST_SCRIPT := ../../../../../apps/app/post_build/bd47/download.sh
RUN_POST_SCRIPT := bash $(POST_SCRIPT)
endif
来源:Makefile
跨平台差异设计意图:
- 工具链二进制形态不同:Windows 使用
*.exe(clang.exe、q32s-lto-wrapper.exe、llvm-ar.exe),Linux 使用同名无后缀二进制(clang、lto-wrapper、lto-ar); __SHELL__宏:仅在 Linux 下通过EXT_CFLAGS追加-D__SHELL__,用于保证download.c在 Linux 环境中被正确处理(Windows 的批处理下载流程不需要该宏);- 批处理编码问题:Windows 下生成的
.bat脚本存在 utf8→gbk 编码问题,因此用fixbat.exe修正;Linux 下则用touch占位、以.sh脚本配合bash执行; - 库与头文件路径:Windows 为绝对路径
C:/JL/pi32/q32s-lib、C:/JL/pi32/q32s-include,Linux 则以工具链目录为基准相对定位($(TOOL_DIR)/../lib、$(TOOL_DIR)/../include),体现了 Windows 固定安装目录、Linux 可自由放置工具链的差异。
编译参数与宏定义
板级 Makefile 集中定义了针对 q32s 内核(AW31N 芯片内核)的编译参数:
# 编译参数设置
CFLAGS := \
-flto \
-target q32s \
-integrated-as \
-fno-builtin \
-mllvm -inline-threshold=5 \
-Oz \
-integrated-as \
-g \
-O0 \
-flto \
-Os \
-Wcast-align \
-fallow-pointer-null \
-Wincompatible-pointer-types \
-Wundef \
-fprefer-gnu-section \
-Wframe-larger-than=256 \
-Wreturn-type \
-Wimplicit-function-declaration \
-Werror=jl-arg-struct-check \
-Werror \
-Werror=implicit-function-declaration \
-Werror=return-type \
-Werror=undef \
-fms-extensions \
-Wno-format
来源:Makefile
关键参数解读:
-target q32s:指定交叉编译目标架构为 q32s(杰理 32 位内核),与链接器q32s-lto-wrapper/lto-wrapper对应;-flto+-fprefer-gnu-section:启用链接时优化(LTO),并按 GNU section 组织输出,配合-mllvm -inline-threshold=5控制内联阈值,兼顾代码体积与性能;- 多级优化并存(
-Oz、-O0、-Os):Makefile 中同时出现多个优化级别,实际生效值由后续规则按目标覆盖,体现出对体积(-Oz/-Os,适合 BLE 固件 Flash 限制)与调试(-g/-O0)的双重考量; -Werror家族(含-Werror=jl-arg-struct-check这一杰理私有检查):将常见告警升级为错误,保证跨板卡/跨应用构建的一致性,防止结构体参数检查等平台相关问题被忽略;-Wframe-larger-than=256:限制栈帧大小,提前暴露深递归或大局部变量导致的栈溢出风险(嵌入式环境栈资源紧张);-fno-builtin、-fms-extensions、-Wno-format:减少对宿主编译器内建函数依赖、启用 MS 扩展语法、放宽格式串告警,适配 SDK 源码风格。
宏定义(DEFINES)
# 宏定义
DEFINES := \
-D__FPGA=0 \
-DCONFIG_CPU_BD47=1 \
-DAPP_BT_BLE=1 \
-DSUPPORT_MS_EXTENSIONS \
-DSUPPORT_RESERVATION_RAM \
-DAPP_CASE_TRANSFER \
-DSDK_VERSION_CFG_DEFINE=0x130001 \
-DSDK_VERSION_DATE_DEFINE=20250822 \
-DCONFIG_RELEASE_ENABLE \
-DHAS_VFS_EN=1 \
-DNOFLOAT
DEFINES += $(EXT_CFLAGS) # 额外的一些定义
来源:Makefile
宏含义:
| 宏 | 值 | 作用 |
|---|---|---|
__FPGA | 0 | 关闭 FPGA 验证模式,走真实芯片流程 |
CONFIG_CPU_BD47 | 1 | 指定芯片/板卡型号为 BD47 |
APP_BT_BLE | 1 | 使能 BLE 应用框架 |
SUPPORT_MS_EXTENSIONS | — | 启用 MS 扩展语法支持 |
SUPPORT_RESERVATION_RAM | — | 支持保留 RAM(用于协议栈/低功耗预留内存) |
APP_CASE_TRANSFER | — | 选择 transfer 应用场景(决定应用层编译分支) |
SDK_VERSION_CFG_DEFINE | 0x130001 | SDK 版本号(0x13.00.01) |
SDK_VERSION_DATE_DEFINE | 20250822 | SDK 版本日期 |
CONFIG_RELEASE_ENABLE | — | 发布版配置(裁剪调试信息相关代码) |
HAS_VFS_EN | 1 | 使能虚拟文件系统(VFS) |
NOFLOAT | — | 禁用浮点运算(BLE 应用通常无需浮点,可显著减小固件) |
__SHELL__(EXT_CFLAGS,Linux) | — | Linux 下正确处理 download.c |
这些宏与 board_*_global_build_cfg.h 一起决定了 SDK 模块的裁剪范围,是控制固件体积与功能集的关键杠杆。
构建产物与后处理
板级 Makefile 将编译链接输出统一重定向到公共后处理目录:
# 输出文件设置
OUT_ELF := ../../../../../apps/app/post_build/bd47/sdk.elf
OBJ_FILE := $(OUT_ELF).objs.txt
# 编译路径设置
BUILD_DIR := objs
# 工程路径前缀
ROOT_PREFIX := ../../../../..
来源:Makefile
OUT_ELF:链接产物固定为apps/app/post_build/bd47/sdk.elf,同一板卡的所有应用(transfer / hid)共用该后处理目录;OBJ_FILE:记录参与链接的目标文件清单(供 LTO 链接器使用);BUILD_DIR := objs:编译中间文件存放在板级目录下的objs/,make clean时被$(RM)清除;RUN_POST_SCRIPT:链接完成后调用apps/app/post_build/bd47/download.bat(Windows)或download.sh(Linux)完成烧录/下载,实现「编译即烧录」的一键流程。
核心构建流程
下图展示从顶层入口到烧录完成的完整控制流:
flowchart TD
Start([make aw31n_transfer]) --> RootMK["根 Makefile"]
RootMK -->|"MAKE -C apps/demo/transfer/board/bd47"| BoardMK["板级 Makefile"]
BoardMK --> CheckOS{"操作系统?"}
CheckOS -->|"Windows_NT"| WinTC["工具链 C:/JL/pi32/bin<br/>clang + q32s-lto-wrapper"]
CheckOS -->|"其他 (Linux)"| LinTC["工具链 /opt/jieli/q32s/bin<br/>clang + lto-wrapper"]
WinTC --> Compile["编译 + LTO 链接<br/>DEFINES 宏裁剪 SDK 模块"]
LinTC --> Compile
Compile --> ELF["sdk.elf<br/>apps/app/post_build/bd47/"]
ELF --> Post{"后处理脚本"}
Post -->|"Windows"| FixBat["fixbat.exe<br/>utf8->gbk 修正"]
FixBat --> DLBat["download.bat 烧录"]
Post -->|"Linux"| DLSh["download.sh 烧录"]
流程要点:
- 用户在根目录执行
make aw31n_transfer,根 Makefile 通过$(MAKE) -C进入板级目录; - 板级 Makefile 依据
$(OS)选择工具链:Windows 走C:/JL/pi32/bin(并 export PATH),Linux 走/opt/jieli/q32s/bin; - 编译过程使用
-target q32s -flto的 CFLAGS 与 DEFINES 宏,把board_*.c与 SDK 模块编译为 q32s 目标码并 LTO 链接; - 产物
sdk.elf输出到公共后处理目录;Windows 下先经fixbat.exe修正批处理编码,再运行download.bat烧录;Linux 下直接以bash download.sh烧录; make clean反向走同一路径,清除板级目录objs/下的中间产物。
使用示例
基本构建
在 SDK 根目录执行以下命令构建全部工程(transfer + hid):
make all
来源:Makefile
单工程构建与清理
仅构建 transfer 工程、仅构建 hid 工程,以及对应的清理目标:
make aw31n_transfer # 构建 transfer 应用(bd47 板卡)
make clean_aw31n_transfer # 清理 transfer 工程中间文件
make aw31n_hid # 构建 hid 应用(bd47 板卡)
make clean_aw31n_hid # 清理 hid 工程中间文件
make clean # 清理全部工程
来源:Makefile
板级目录内直接构建与详细输出
进入板级目录后可单独执行其 Makefile,并可用 VERBOSE=1 查看详细编译过程:
# make 编译并下载
# make VERBOSE=1 显示编译详细过程
# make clean 清除编译临时文件
来源:Makefile
Linux 工具链环境准备
# 1. 从 http://pkgman.jieliapp.com/doc/all 处找到下载链接
# 2. 下载后,解压到 /opt/jieli 目录下,保证
# /opt/jieli/common/bin/clang 存在(注意目录层次)
# 3. 确认 ulimit -n 的结果足够大(建议大于8096),否则链接可能会因为打开文件太多而失败
# 可以通过 ulimit -n 8096 来设置一个较大的值
来源:Makefile
配置选项汇总
顶层构建目标
| 目标 | 类型 | 默认行为 | 说明 |
|---|---|---|---|
all | target | 构建全部 | 依次构建 aw31n_transfer + aw31n_hid |
clean | target | 清理全部 | 依次清理两个工程 |
aw31n_transfer | target | — | 进入 apps/demo/transfer/board/bd47 构建 |
clean_aw31n_transfer | target | — | 清理 transfer 工程 |
aw31n_hid | target | — | 进入 apps/demo/hid/board/bd47 构建 |
clean_aw31n_hid | target | — | 清理 hid 工程 |
板级 Makefile 关键变量
| 变量 | Windows 默认值 | Linux 默认值 | 说明 |
|---|---|---|---|
TOOL_DIR | C:/JL/pi32/bin | /opt/jieli/q32s/bin | 工具链目录 |
CC / CXX | clang.exe | clang | 编译器 |
LD | q32s-lto-wrapper.exe | lto-wrapper | LTO 链接器 |
AR | llvm-ar.exe | lto-ar | 归档工具 |
SYS_LIB_DIR | C:/JL/pi32/q32s-lib | $(TOOL_DIR)/../lib | 系统库目录 |
SYS_INC_DIR | C:/JL/pi32/q32s-include | $(TOOL_DIR)/../include | 系统头文件目录 |
EXT_CFLAGS | (空) | -D__SHELL__ | 平台附加宏 |
OUT_ELF | apps/app/post_build/bd47/sdk.elf(相对路径解析) | 同左 | 链接产物 |
BUILD_DIR | objs | objs | 中间文件目录 |
ROOT_PREFIX | ../../../../.. | ../../../../.. | 工程路径前缀 |
FIXBAT | tools/utils/fixbat.exe | touch | 批处理编码修正工具 |
RUN_POST_SCRIPT | download.bat | bash download.sh | 后处理下载脚本 |
DEFINES 宏(详见上文表格)
__FPGA=0、CONFIG_CPU_BD47=1、APP_BT_BLE=1、APP_CASE_TRANSFER、SDK_VERSION_CFG_DEFINE=0x130001、SDK_VERSION_DATE_DEFINE=20250822、CONFIG_RELEASE_ENABLE、HAS_VFS_EN=1、NOFLOAT 等,用于裁剪 SDK 模块与选择应用场景。
故障模式与边界情况
- Linux 链接失败(打开文件过多):Makefile 头部注释明确要求
ulimit -n大于 8096,否则 LTO 链接阶段会因同时打开过多文件而失败。修复方式为ulimit -n 8096; - 工具链目录层次错误:Linux 下要求
/opt/jieli/common/bin/clang存在,解压 SDK 工具链时必须保持目录层次,否则clang无法被找到;板级 Makefile 实际使用/opt/jieli/q32s/bin,两处路径需同时满足; - Windows 批处理编码问题:Windows 生成的后处理脚本为 utf8 编码,直接运行可能乱码/失败,因此必须经
fixbat.exe转为 gbk;Linux 下无此问题(FIXBAT := touch); __SHELL__缺失:在 Linux 下若缺少-D__SHELL__(EXT_CFLAGS),download.c的处理逻辑可能不正确,导致后处理异常——这是 Makefile 注释特别强调的平台差异点;- 宏裁剪导致的编译错误:
NOFLOAT、CONFIG_RELEASE_ENABLE等宏会改变 SDK 模块的编译分支,若板级配置与*_global_build_cfg.h不一致,可能出现未声明函数或模块缺失类错误(CFLAGS 中-Werror=implicit-function-declaration等会把这类问题直接升级为编译失败)。
性能与运维注意
- 固件体积优先:CFLAGS 中的
-Oz/-Os与NOFLOAT宏表明该 SDK 以固件体积为首要优化目标(BLE 设备 Flash/RAM 受限),改动编译参数时需评估体积影响; - LTO 链接:
-flto贯穿编译与链接,中间文件清单记录于sdk.elf.objs.txt,调试符号(-g)与优化(-Oz)并存,发布时通过CONFIG_RELEASE_ENABLE裁剪调试路径; - 一键烧录:链接完成后自动执行下载脚本,适合开发迭代;CI 环境需确认目标机连接与下载脚本可用性。
扩展点:新增板级工程
在现有体系下新增一个板卡/应用的标准做法:
- 复制
apps/demo/transfer/board/bd47/为新目录,如apps/demo/<app>/board/<board>; - 按需修改
board_<board>.c、board_<board>_cfg.h、board_<board>_global_build_cfg.h,调整板级资源与 SDK 裁剪宏; - 修改板级 Makefile 中指向
post_build的路径与DEFINES(如APP_CASE_*、CONFIG_CPU_*); - 在根
Makefile的.PHONY与目标列表中新增对应目标(如aw31n_xxx/clean_aw31n_xxx),指向新目录; - 如需 IDE 支持,可参照
AW31N_transfer.cbp生成新的 Code::Blocks 工程文件。
注:本页基于已读取的根
Makefile与 transfer 板级Makefile编写。board_config.h、board_aw31n_demo_cfg.h等配置头文件的具体宏内容未在本轮探索中展开,后续可基于这些文件补充板级资源表(GPIO、时钟、外设分配)的详细说明。
Related Links
- 根 Makefile(构建入口)
- 板级 Makefile(transfer/bd47)
- 板级目录文件列表
- 仓库 README
- 相关目录页:应用层功能(transfer / hid)、SDK 模块裁剪(global_build_cfg)、后处理与烧录流程(post_build)