工程结构与模块划分
本页介绍 fw-AD23N_GP-MCU_SDK 仓库的顶层目录结构、sdk/ 主目录的模块划分(应用层 / 板级支持 / 预编译库)、构建系统与模块裁剪机制,帮助开发者快速定位代码、理解各模块职责并掌握如何启停功能模块。
Purpose and Scope
本页是仓库级(overview)导航页面,回答三个问题:
- 代码在哪里 —— 仓库顶层
sdk/、doc/与各模块目录的组织方式; - 每个模块做什么 ——
app/(应用层)、include_lib/(头文件与预编译库)、tools/(构建工具)的职责边界; - 如何裁剪与构建 ——
Makefile中工具链配置、编译参数与-D宏定义如何决定最终固件包含哪些功能。
以下内容不属于本页范围,请参阅对应页面:环境搭建与编译/烧录流程(Build 相关页面)、mbox_flash 应用的功能细节(应用页面)、芯片规格与硬件资料(doc/ 目录对应页面)。
Overview
fw-AD23N_GP-MCU_SDK 是杰理科技(Jieli-Tech)为 AD23N 系列芯片提供的通用 MCU SDK 固件程序,面向语音玩具、小音箱与通用 MCU 三类应用场景。芯片内置 NPU 神经网络加速、双发射 DSP(288MHz,含 FPU)、184KB 片上 SRAM,支持多种音频解码(.a/.b/.e、.f1a/.f1b/.f1c、UMP3、MP3、WAV)、MIDI 播放、三路并发解码与多种音效算法(ANS 降噪、变速、ECHO 混响、变调、变声、浮点 PCM EQ)。
仓库采用 "源码 + 预编译库 + 构建脚本" 的典型嵌入式 SDK 布局:应用代码以源码形式开放(sdk/app/),而底层驱动、解码器、算法等以头文件(API 声明)+ 预编译静态库(lib.a) 形式提供(sdk/include_lib/),最终由顶层 Makefile(或 Code::Blocks 工程)调用杰理交叉编译工具链完成编译、链接与后处理烧录。
该布局的设计意图在于:隐藏芯片底层实现细节、保持 API 稳定,同时开放应用层供客户二次开发。因此绝大多数日常开发工作发生在 app/ 目录,而功能裁剪(使能/禁用解码器、外设、算法)通过 Makefile 中的宏开关完成,无需改动库内部代码。
Architecture
flowchart TD
subgraph sg_Top["仓库顶层 (fw-AD23N)"]
README["README.md / README-en.md"]
LICENSE["LICENSE"]
PDF["AD23N_SDK_发布版本信息.pdf"]
DOC["doc/ 文档与硬件资料"]
SDK["sdk/ SDK 主目录"]
end
subgraph sg_SDK["sdk/ 主目录"]
APP["app/ 应用层源码"]
INCLIB["include_lib/ 头文件 + 预编译库"]
TOOLS["tools/ 编译工具与脚本"]
MK["Makefile 顶层构建"]
CBP["AD23N_mbox_flash.cbp"]
PROMPT["make_prompt.bat"]
end
subgraph sg_APP["app/ 应用层"]
SRC["src/mbox_flash 应用入口"]
BSP["bsp/ 板级支持包"]
PB["post_build/ 编译后处理"]
end
subgraph sg_INC["include_lib/ 模块库"]
M1["cpu / decoder / encoder / audio"]
M2["device / dev_mg / fs / msg"]
M3["ans / pcm_eq_float / vo_changer / vo_pitch"]
M4["update / power / common / liba"]
end
README --> SDK
DOC --> SDK
PDF --> README
SDK --> APP
SDK --> INCLIB
SDK --> TOOLS
SDK --> MK
SDK --> CBP
APP --> SRC
APP --> BSP
APP --> PB
INCLIB --> M1
INCLIB --> M2
INCLIB --> M3
INCLIB --> M4
架构说明:
- 顶层由
sdk/(代码主体)、doc/(SDK 手册、用户手册、硬件资料、选型表等 PDF)与若干说明文件(README、LICENSE、发布版本信息)组成。doc/目录的具体内容见 README.md。 sdk/主目录是构建的根目录,同时存在三种构建入口:Makefile(命令行,Windows/Linux 通用)、AD23N_mbox_flash.cbp(Code::Blocks IDE 工程)、make_prompt.bat(Windows 下打开预配置命令行环境)。app/应用层是客户二次开发的主战场:src/mbox_flash/为小音箱/音频播放应用入口,bsp/为板级支持包,post_build/存放编译后处理(固件打包/烧录)脚本。include_lib/模块库以目录为单位划分功能域:解码器(decoder)、编码器(encoder)、音频(audio)、设备驱动(device)、设备管理(dev_mg)、文件系统(fs)、消息机制(msg)、音效算法(ans、pcm_eq_float、vo_changer、vo_pitch)、固件升级(update)、电源管理(power),以及预编译库本体(liba)。
顶层目录详解
仓库根目录的文件与目录如下(来自 README.md 五、工程结构):
| 路径 | 类型 | 职责 |
|---|---|---|
sdk/ | 目录 | SDK 主目录,包含全部源码、头文件、预编译库与构建脚本 |
doc/ | 目录 | 文档中心:AD23N 硬件资料、SDK 手册、用户手册、选型表、烧录工具文档 |
README.md / README-en.md | 文件 | 中/英文使用说明(概述、环境搭建、快速开始、工程结构、编译、烧录、FAQ) |
LICENSE | 文件 | 开源许可证 |
AD23N_SDK_发布版本信息.pdf | 文件 | SDK 各 Release 版本的变更记录 |
jl_ad_chip.png | 文件 | 芯片系列差异图(README 内嵌) |
sdk/ 主目录
sdk/ 是构建与开发的根目录,包含三个核心目录和三个构建入口文件:
| 路径 | 类型 | 职责 |
|---|---|---|
app/ | 目录 | 应用层代码:src/(应用入口源码)、bsp/(板级支持包)、post_build/(编译后处理脚本与工具) |
include_lib/ | 目录 | 头文件与预编译库:cpu、decoder、encoder、audio、device、dev_mg、common、fs、msg、ans、pcm_eq_float、vo_changer、vo_pitch、update、power、liba |
tools/ | 目录 | 编译工具与脚本:make_prompt.bat(Windows 编译命令行入口)、utils/(make、rm 等工具集) |
Makefile | 文件 | 顶层 Makefile,命令行构建的唯一入口 |
AD23N_mbox_flash.cbp | 文件 | Code::Blocks 工程文件(当前唯一应用工程,覆盖小音箱/语音玩具/MIDI 琴) |
make_prompt.bat | 文件 | Windows 下双击即可打开带工具链 PATH 的命令行环境 |
工程入口的官方说明见 README.md 4.2 工程入口:当前 SDK 仅包含 AD23N_mbox_flash.cbp 一个工程,适用于 AD23N 全系列芯片。
app/ 应用层
src/mbox_flash/—— 小音箱/音频播放应用入口,支持音乐播放(.a/.b/.e、.f1a/.f1b/.f1c、UMP3、MP3、WAV)、MIDI 演奏、录音(编码)、USB Device、LINEIN、扩音等功能;适用领域为语音玩具、AI 语音交互、故事机、学习机、MIDI 乐器。bsp/—— 板级支持包(Board Support Package),承载具体开发板的引脚、时钟、外设初始化等板级适配代码。post_build/—— 编译后处理:sh59/download.bat(Windows)与sh59/download.sh(Linux)负责链接产物sdk.elf的后续处理与烧录,Makefile 通过POST_SCRIPT变量引用它们(见 Makefile L30-L33)。
include_lib/ 模块库
include_lib/ 以"一个功能域一个目录"的方式组织头文件,其目录即模块边界:
| 目录 | 功能域 |
|---|---|
cpu/ | CPU 平台头文件(寄存器、平台抽象) |
decoder/ | 解码器 API(.a/.b/.e、f1a/f1b/f1c、UMP3、MP3、WAV、MIDI 等) |
encoder/ | 编码器 API(录音编码) |
audio/ | 音频链路 API(DAC/ADC/I2S/PDM/SRC 等) |
device/ | 设备驱动头文件(Flash、SDMMC、USB 等) |
dev_mg/ | 设备管理(设备枚举、挂载、切换) |
common/ | 公共头文件(基础类型、宏、工具函数) |
fs/ | 文件系统(SydFs/NorFs/FreeFs/FATFS) |
msg/ | 消息机制(事件/消息队列) |
ans/ | ANS 降噪算法 |
pcm_eq_float/ | 浮点 PCM EQ 算法 |
vo_changer/ | 变声算法 |
vo_pitch/ | 变调算法 |
update/ | 固件升级 |
power/ | 电源管理(低功耗/软关机 <3µA) |
liba/ | 预编译静态库本体(lib.a) |
该目录结构在 README.md 工程结构 中逐项列出。预编译库需配合对应命名规则的
lib.a才能正确链接,这也是仓库说明中强调"需配合对应命名规则的库文件进行编译"的原因(见 README.md L60)。
构建系统与模块裁剪机制
工具链与平台差异
Makefile 在同一份文件中同时支持 Windows 与 Linux,通过 $(OS) 判断当前平台并切换工具链路径、命令名与后处理脚本(见 Makefile L14-L56):
| 项目 | Windows | Linux |
|---|---|---|
| 工具链目录 | C:/JL/pi32/bin | /opt/jieli/pi32v2/bin |
| 编译器 | clang.exe | clang |
| 链接器 | pi32v2-lto-wrapper.exe | lto-wrapper |
| 归档器 | llvm-ar.exe | lto-ar |
| 系统库 | C:/JL/pi32/pi32v2-lib/r3 | $(TOOL_DIR)/../lib/r3 |
| 系统头文件 | C:/JL/pi32/pi32v2-include | $(TOOL_DIR)/../include |
| 额外宏 | 无 | -D__SHELL__(保证 download.c 正确处理) |
| 后处理脚本 | app/post_build/sh59/download.bat | app/post_build/sh59/download.sh |
设计意图:嵌入式固件构建通常与特定工具链版本强绑定,将平台差异收敛到 Makefile 顶部的条件分支中,可让同一份源码在两个平台上产出一致的固件;-D__SHELL__ 的差异则说明 download.c 这类工具代码需要按宿主平台区分行为。
编译参数与产物
核心编译参数(Makefile L62-L84):
# 输出文件设置
OUT_ELF := app/post_build/sh59/sdk.elf
OBJ_FILE := $(OUT_ELF).objs.txt
# 编译路径设置
BUILD_DIR := objs
# 编译参数设置
CFLAGS := \
-target pi32v2 \
-mcpu=r3v2 \
-integrated-as \
-flto \
-Wuninitialized \
-Wno-invalid-noreturn \
-fno-common \
-Oz \
-g \
-fallow-pointer-null \
-fprefer-gnu-section \
-Wno-shift-negative-value \
-Wundef
要点解读:
- 目标架构:
-target pi32v2 -mcpu=r3v2是杰理 32 位 DSP 核(pi32v2 架构、r3v2 内核)的交叉编译目标; - LTO:
-flto开启链接时优化,配合pi32v2-lto-wrapper链接器,让编译单元间可以做全局优化(对 SRAM 仅 184KB 的嵌入式芯片,代码密度至关重要); - 体积优先:
-Oz以代码尺寸最小化为优化目标,符合 Flash 空间受限的 MCU 场景; - 产物路径:链接输出
sdk.elf直接落在app/post_build/sh59/下,便于后处理脚本就地处理;中间文件(.o、.objs.txt)集中在objs/,make clean只需删除该目录。
模块使能:DEFINES 宏开关
Makefile 用一组 -D 宏定义来裁剪固件功能(Makefile L91-L120):
# 宏定义
DEFINES := \
-DFPGA=0 \
-DCPU_SH59=1 \
-DAUDIO_ADC_EN=1 \
-DROM_SECURE_BOOT \
-DSPEAKER_EN \
-DHAS_VOICE_PITCH_EN \
-DHAS_VOICE_CHANGER_EN \
-DHAS_PCM_EQ_FLOAT_EN \
-DAUX_EN \
-DENCODER_EN \
-DHAS_UMP3_DECODER \
-DHAS_MP3_ST_DECODER \
-DHAS_WAV_DECODER \
-DHAS_F1A_DECODER \
-DHAS_MAX_F1A_NUMBER=2 \
-DHAS_MIDI_DECODER \
-DHAS_MIDI_KEYBOARD_DECODER \
-DHAS_A_DECODER \
-DHAS_ANS_EN \
-DHAS_SPEED_EN \
-DHAS_EXT_FLASH_EN \
-DHAS_USB_EN=0 \
-DHAS_SDMMC_EN \
-DHAS_HW_SRC_MODULE=1 \
-DHAS_UPDATE_EN=1 \
-DHAS_ECHO_EN \
-DHOWLING_EN \
-DHAS_NORFS_EN
设计意图:这是 SDK 的模块裁剪总开关。预编译库 lib.a 内含所有功能的实现,但具体哪些被编译进固件、占用多少 SRAM/Flash,由这些宏在编译期决定。例如:
-DHAS_USB_EN=0关闭 USB 设备功能(当前 mbox_flash 工程不需要 USB);-DHAS_MAX_F1A_NUMBER=2限制 f1a 解码器最多 2 路实例;-DHAS_UPDATE_EN=1开启固件升级能力;-DROM_SECURE_BOOT启用安全启动。
开发者新增/裁剪功能时,优先修改此处的宏,而不是改动 include_lib/ 内的库代码。
构建流程
flowchart LR
subgraph sg_Src["输入"]
A["app/src 应用源码"]
B["include_lib 头文件"]
C["liba/ 预编译库 lib.a"]
D["工具链 clang (pi32v2)"]
end
subgraph sg_Build["构建过程 (sdk/ 目录)"]
E["CFLAGS 交叉编译 -flto -Oz"]
F["pi32v2-lto-wrapper 链接"]
G["sdk.elf 链接产物"]
H["post_build 后处理脚本"]
end
subgraph sg_Out["输出"]
I["固件烧录 (USB 升级工具)"]
end
A --> E
B --> E
D --> E
E --> F
C --> F
F --> G
G --> H
H --> I
对应到实际命令(在 sdk/ 目录下执行,见 README.md 七、编译指南):
| 目标 | 命令 |
|---|---|
| 编译 | make -j4 |
| 显示编译详情 | make VERBOSE=1 -j4 |
| 清理临时文件 | make clean |
| IDE 编译 | 打开 AD23N_mbox_flash.cbp → Build(Ctrl+F9) |
| VS Code 编译 | Ctrl+Shift+B 选择编译任务 |
配置选项
以下配置项位于 sdk/Makefile(DEFINES 宏与工具链变量),是构建期可调的核心开关:
| 配置项 | 类型 | 默认值(本工程) | 说明 |
|---|---|---|---|
FPGA | int | 0 | 是否为 FPGA 验证平台(0=量产芯片) |
CPU_SH59 | int | 1 | 目标 CPU 平台(SH59 = AD23N 系列) |
AUDIO_ADC_EN | int | 1 | 音频 ADC 使能 |
ROM_SECURE_BOOT | bool | 定义 | 安全启动 |
SPEAKER_EN | bool | 定义 | 喇叭/Class-D 功放使能 |
HAS_VOICE_PITCH_EN | bool | 定义 | 变调算法使能 |
HAS_VOICE_CHANGER_EN | bool | 定义 | 变声算法使能 |
HAS_PCM_EQ_FLOAT_EN | bool | 定义 | 浮点 PCM EQ 使能 |
AUX_EN | bool | 定义 | AUX/线路输入使能 |
ENCODER_EN | bool | 定义 | 编码器(录音)使能 |
HAS_UMP3_DECODER | bool | 定义 | UMP3 解码器使能 |
HAS_MP3_ST_DECODER | bool | 定义 | MP3 解码器使能 |
HAS_WAV_DECODER | bool | 定义 | WAV 解码器使能 |
HAS_F1A_DECODER | bool | 定义 | f1a 解码器使能 |
HAS_MAX_F1A_NUMBER | int | 2 | f1a 最大并发实例数 |
HAS_MIDI_DECODER | bool | 定义 | MIDI 解码使能 |
HAS_MIDI_KEYBOARD_DECODER | bool | 定义 | MIDI 键盘(演奏)使能 |
HAS_A_DECODER | bool | 定义 | .a/.b/.e 解码器使能 |
HAS_ANS_EN | bool | 定义 | ANS 降噪使能 |
HAS_SPEED_EN | bool | 定义 | 变速播放使能 |
HAS_EXT_FLASH_EN | bool | 定义 | 外置 Flash 使能 |
HAS_USB_EN | int | 0 | USB 设备功能(本工程关闭) |
HAS_SDMMC_EN | bool | 定义 | SD/MMC 卡使能 |
HAS_HW_SRC_MODULE | int | 1 | 硬件 SRC 重采样模块 |
HAS_UPDATE_EN | int | 1 | 固件升级使能 |
HAS_ECHO_EN | bool | 定义 | ECHO 混响使能 |
HOWLING_EN | bool | 定义 | 啸叫抑制使能 |
HAS_NORFS_EN | bool | 定义 | NorFs 文件系统使能 |
TOOL_DIR | 路径 | Win: C:/JL/pi32/bin;Linux: /opt/jieli/pi32v2/bin | 交叉工具链目录 |
OUT_ELF | 路径 | app/post_build/sh59/sdk.elf | 链接产物路径 |
BUILD_DIR | 路径 | objs | 中间文件目录 |
EXT_CFLAGS | 字符串 | Linux: -D__SHELL__ | 平台附加宏 |
使用示例
示例一:Windows 下启动命令行构建环境
# 双击 sdk/make_prompt.bat,或手动执行:
cd sdk
make_prompt.bat
# 编译
make -j4
# 显示编译详情
make VERBOSE=1 -j4
来源:README.md 4.4 方式二:Makefile 命令行
示例二:Linux 下配置工具链与编译
# 1. 下载工具链并解压到 /opt/jieli,确保 /opt/jieli/pi32/bin/clang 存在
# 2. 增大文件描述符上限,避免链接失败
ulimit -n 8096
# 3. 进入工程目录编译
cd sdk
make -j4
示例三:平台分支式工具链选择
ifeq ($(OS), Windows_NT)
TOOL_DIR := C:/JL/pi32/bin
CC := clang.exe
LD := pi32v2-lto-wrapper.exe
...
POST_SCRIPT := app/post_build/sh59/download.bat
else
TOOL_DIR := /opt/jieli/pi32v2/bin
CC := clang
LD := lto-wrapper
EXT_CFLAGS := -D__SHELL__
POST_SCRIPT := app/post_build/sh59/download.sh
endif
失败模式、边界情况与并发注意点
- 工具链路径不匹配:Windows 使用
C:/JL/pi32/bin,Linux 使用/opt/jieli/pi32v2/bin。若工具链未安装到约定路径,make会因找不到clang直接失败;务必先完成 环境搭建。 - Linux 下文件描述符耗尽:LTO 链接需要打开大量中间文件,官方建议
ulimit -n大于 8096,否则链接阶段报"Too many open files"(见 Makefile L10-L11)。 __SHELL__宏差异:Linux 下必须定义-D__SHELL__才能正确处理download.c;Windows 下不需要。移植构建脚本时漏掉该宏会导致后处理行为异常。- bat 编码问题:Windows 下用
fixbat.exe处理 utf8→gbk 编码,Linux 下无需处理(FIXBAT := touch)——跨平台脚本移植时不要照搬工具链。 - 预编译库配套:
include_lib/liba/的lib.a需与 SDK 版本、芯片型号(CPU_SH59)及命名规则匹配,混用会导致链接符号缺失或运行异常。 - 并行编译:
make -j4默认并行度 4;LTO 阶段会重新调用编译器,多任务下内存占用较高,小内存开发机可降为make -j2或-j1。 - 烧录依赖外部工具:固件烧录依赖 USB 升级工具/生产烧写工具(需单独申请获取),构建成功 ≠ 可以烧录,详见 README.md 3.3。
扩展点
- 新增应用工程:在
app/src/下新建应用目录(如mbox_flash),参考现有工程组织main入口与模块初始化代码;若使用 IDE,则仿照AD23N_mbox_flash.cbp新建.cbp工程文件;若使用命令行,确认Makefile的源文件收集规则能覆盖新目录。 - 功能裁剪:编辑
Makefile的DEFINES,按需开/关解码器、外设与算法宏(例如将-DHAS_USB_EN=0改为1以启用 USB Device),无需改动库代码。 - 后处理/烧录扩展:修改
app/post_build/sh59/下的download.bat/download.sh,可扩展固件打包、签名、量产烧录等步骤;POST_SCRIPT与RUN_POST_SCRIPT变量是挂接点。 - 板级适配:新开发板优先修改
app/bsp/(引脚、时钟、外设初始化),保持应用层src/与芯片库不变。