杰理 SDK 文档中心
首页
首页
  • 项目概览

    • AD23N SDK 概述与芯片平台
    • 工程结构与模块划分
  • 快速开始

    • 开发环境搭建与工具链
    • 编译构建指南
    • 烧录与固件升级工具
  • 应用框架与产品工作流

    • 应用入口与模式调度
    • 音乐播放应用
    • MIDI 解码与键盘演奏
    • 录音应用
    • LINEIN 与扩音应用
    • USB 从设备应用
    • 待机、软关机与空闲检测
    • 公共 UI 与 LED 显示
  • 音频子系统

    • 音频解码器框架
    • 音频编码器框架
    • 音效算法库
    • 音频管理与输出通路
  • 存储与文件系统

    • 文件系统层
    • NOR Flash 与虚拟机存储
    • 设备与设备管理
  • 系统服务与运行时

    • 消息机制与事件分发
    • 按键扫描与输入处理
    • 电源管理与低功耗控制
    • 定时器与系统任务
  • 外设驱动与平台

    • CPU 平台与启动流程
    • USB 协议栈与主机/设备驱动
    • SPI 与通用外设接口
  • 固件升级与构建工具

    • 固件升级机制
    • 编译后处理与镜像打包
    • 构建系统与命令行工具

构建系统与命令行工具

本页介绍 AD23N SDK 的构建系统:以 sdk/Makefile 为核心的 GNU Make + clang/LLVM 交叉编译体系,以及配套的命令行工具(make_prompt.bat、后处理脚本、烧录工具等),覆盖 Windows/Linux 双平台下的编译、链接、后处理与固件产出全流程。

Purpose and Scope

本页面向需要编译、调试或扩展 AD23N 固件工程的开发者,系统性地说明:

  • 三种构建入口:Code::Blocks IDE、Makefile 命令行、VS Code 任务
  • sdk/Makefile 的内部机制:平台分支、工具链定位、编译参数、宏定义、头文件路径、源文件清单
  • 命令行辅助工具:make_prompt.bat、fixbat.exe、post_build 下载脚本
  • 构建产物(sdk.elf)与后处理流程
  • 常见失败模式(工具链缺失、ulimit 不足、编码问题)与扩展方法

以下内容不属于本页范围,请参见对应页面:固件烧录与 USB 升级工具的详细操作(烧录与升级)、SDK 应用工程结构(应用与示例)、环境搭建的下载链接清单(环境搭建)。本页聚焦于"构建系统本身"这一主题边界。

概述

AD23N SDK 采用 Makefile + clang/LLVM 交叉编译工具链 作为命令行构建体系,目标 CPU 架构为 pi32v2(内核版本 r3v2,即 SH59 平台)。仓库源码与预编译库文件(lib.a)配合编译,最终生成 ELF 固件并经由后处理脚本烧录到目标板。

与多数嵌入式 SDK 不同,该构建体系具备以下设计特点:

  1. 单一 Makefile 双平台适配:通过 ifeq ($(OS), Windows_NT) 分支,同一份 sdk/Makefile 同时支持 Windows(C:/JL/pi32/bin 工具链)与 Linux(/opt/jieli/pi32v2/bin 工具链),平台差异集中在工具链路径与后处理脚本上。
  2. LTO 全程序优化:编译参数固定启用 -flto(链接期优化),配合 lto-wrapper / pi32v2-lto-wrapper.exe 链接器,实现跨编译单元的内联与裁剪;同时用 -Oz 优先优化代码体积,契合 Flash 容量受限的 MCU 场景。
  3. 功能宏驱动裁剪:约 40 个 -D 宏定义(如 HAS_MP3_DECODER、HAS_UPDATE_EN)作为功能开关,决定解码器、编码器、文件系统等模块是否编入固件。
  4. 编译后处理链:编译完成后通过平台对应的脚本(download.bat / download.sh)执行固件后处理与下载,Windows 下还需 fixbat.exe 解决 UTF-8→GBK 编码问题。

用户可根据使用场景选择入口:Windows 桌面用户推荐 Code::Blocks;熟悉命令行的用户推荐 make 命令(经由 make_prompt.bat 进入环境);VS Code 用户可直接使用预配置任务。

架构

下图展示构建系统的整体架构与数据流:

flowchart TD
    subgraph sg_Entry["构建入口层"]
        CB["Code::Blocks IDE<br/>(AD23N_mbox_flash.cbp)"]
        CLI["命令行 make<br/>(make_prompt.bat 环境)"]
        VSC["VS Code 任务<br/>(Ctrl+Shift+B)"]
    end

    subgraph sg_Make["构建核心层"]
        MK["sdk/Makefile"]
        subgraph sg_Platform["平台分支 ifeq(OS, Windows_NT)"]
            WIN["Windows 工具链<br/>C:/JL/pi32/bin"]
            LIN["Linux 工具链<br/>/opt/jieli/pi32v2/bin"]
        end
        CFG["编译参数 CFLAGS / DEFINES / INCLUDES"]
        SRC["源文件清单 c_SRC_FILES"]
    end

    subgraph sg_Toolchain["工具链层 (pi32v2)"]
        CC["clang (编译)"]
        LD["lto-wrapper (链接)"]
        AR["llvm-ar / lto-ar (归档)"]
    end

    subgraph sg_Output["产出与后处理层"]
        ELF["sdk.elf<br/>(app/post_build/sh59/)"]
        FIX["fixbat.exe<br/>(UTF-8→GBK)"]
        POST["download.bat / download.sh<br/>后处理+下载"]
    end

    CB --> MK
    CLI --> MK
    VSC --> MK
    MK --> CFG
    MK --> SRC
    MK --> WIN
    MK --> LIN
    CFG --> CC
    SRC --> CC
    WIN --> CC
    LIN --> CC
    CC --> LD
    AR --> LD
    LD --> ELF
    ELF --> POST
    ELF --> FIX
    FIX --> POST
    POST -->|"固件烧录"| TARGET["目标板 (AD23N 系列)"]

各组件职责说明:

  • 构建入口层:三种入口最终都归结为对 Makefile 的调用。Code::Blocks 通过 .cbp 工程间接调用同一套编译参数;VS Code 任务封装了 make 命令。
  • 构建核心层:sdk/Makefile 是唯一的事实来源,负责平台探测、工具链路径拼接、编译参数组装、源文件枚举与构建规则。
  • 平台分支:Windows 与 Linux 的工具链目录、链接器名称、系统库/头文件目录、EXT_CFLAGS、后处理脚本均在此分支中差异化设置(见下文实现解析)。
  • 工具链层:clang 负责将 C 源码编译为 LLVM IR(配合 -flto),lto-wrapper 在链接期完成跨单元优化并生成最终 ELF,llvm-ar/lto-ar 处理静态库归档。
  • 产出与后处理层:链接产物 sdk.elf 输出到 app/post_build/sh59/,随后 fixbat.exe(仅 Windows)修正批处理脚本编码,最后 download.bat/download.sh 执行后处理并触发下载。

该架构的核心设计意图是把平台差异收敛到 Makefile 的分支变量中:上层入口与编译参数不感知平台,工具链切换只需修改一处分支,从而保证双平台构建行为一致。

构建核心:sdk/Makefile 实现解析

sdk/Makefile 是整个构建系统的核心,文件头注释即定义了主要目标:

# make 编译并下载
# make VERBOSE=1 显示编译详细过程
# make clean 清除编译临时文件

Source: sdk/Makefile

平台分支与工具链定位

Makefile 通过 ifeq ($(OS), Windows_NT) 区分 Windows 与 Linux 平台。这一分支决定了工具链目录、编译器/链接器名称、系统库目录、后处理脚本等全部平台相关变量:

ifeq ($(OS), Windows_NT)
# Windows 下工具链位置
TOOL_DIR := C:/JL/pi32/bin
CC    := clang.exe
CXX   := clang.exe
LD    := pi32v2-lto-wrapper.exe
AR    := llvm-ar.exe
MKDIR := mkdir_win -p
RM    := rm -rf

SYS_LIB_DIR := C:/JL/pi32/pi32v2-lib/r3
SYS_INC_DIR := C:/JL/pi32/pi32v2-include
EXT_CFLAGS  := # Windows 下不需要 -D__SHELL__
export PATH:=$(TOOL_DIR);$(PATH)

## 后处理脚本
FIXBAT          := tools/utils/fixbat.exe # 用于处理 utf8->gbk 编码问题
POST_SCRIPT     := app/post_build/sh59/download.bat
RUN_POST_SCRIPT := app\\post_build\\sh59\\download.bat
else
# Linux 下工具链位置
TOOL_DIR := /opt/jieli/pi32v2/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/r3
SYS_INC_DIR := $(TOOL_DIR)/../include
EXT_CFLAGS  := -D__SHELL__ # Linux 下需要这个保证正确处理 download.c
export PATH:=$(TOOL_DIR):$(PATH)

## 后处理脚本
FIXBAT          := touch # Linux下不需要处理 bat 编码问题
POST_SCRIPT     := app/post_build/sh59/download.sh
RUN_POST_SCRIPT := bash $(POST_SCRIPT)
endif

Source: sdk/Makefile

设计意图解读:

  • 工具链目录差异:Windows 工具链默认安装在 C:/JL/pi32,Linux 默认在 /opt/jieli/pi32v2(对应 Makefile 头部注释中"解压到 /opt/jieli 目录"的安装指引)。二者目录层次命名不同,因此系统库与头文件目录也分别推导。
  • EXT_CFLAGS 的差异:Windows 分支为空,Linux 分支为 -D__SHELL__。注释说明该宏用于保证 Linux 下正确编译 download.c(后处理下载程序),是平台相关源码适配的开关。
  • FIXBAT 的巧妙替代:Windows 下是 fixbat.exe(将生成的 bat 脚本从 UTF-8 转 GBK 以兼容 cmd.exe),Linux 下直接替换为 touch(空命令),无需额外工具即可保持构建脚本统一。
  • 环境变量注入:通过 export PATH:=$(TOOL_DIR);$(PATH)(Windows 用分号、Linux 用冒号)将工具链目录前置注入 PATH,使后续调用 clang、lto-wrapper 时无需完整路径。

工具链变量随后统一拼上 TOOL_DIR 前缀:

CC  := $(TOOL_DIR)/$(CC)
CXX := $(TOOL_DIR)/$(CXX)
LD  := $(TOOL_DIR)/$(LD)
AR  := $(TOOL_DIR)/$(AR)
# 输出文件设置
OUT_ELF   := app/post_build/sh59/sdk.elf
OBJ_FILE  := $(OUT_ELF).objs.txt
# 编译路径设置
BUILD_DIR := objs

Source: sdk/Makefile

编译参数(CFLAGS)与功能宏(DEFINES)

编译参数面向 pi32v2 架构固定生成,核心选项包括目标架构、LTO、体积优化与调试信息:

CFLAGS := \
	-target pi32v2 \
	-mcpu=r3v2 \
	-integrated-as \
	-flto \
	-Wuninitialized \
	-Wno-invalid-noreturn \
	-fno-common \
	-integrated-as \
	-Oz \
	-g \
	-flto \
	-fallow-pointer-null \
	-fprefer-gnu-section \
	-Wno-shift-negative-value \
	-Wundef \

Source: sdk/Makefile

关键选项说明:

选项作用设计意图
-target pi32v2 -mcpu=r3v2指定交叉编译目标架构与 CPU 内核将 clang 从宿主编译器变为 pi32v2 交叉编译器
-flto启用链接期优化跨编译单元内联/裁剪,配合 lto-wrapper 链接器
-Oz优先优化代码尺寸MCU Flash 容量受限,体积优先于速度
-g生成调试信息支持后续 GDB/反汇编调试
-fprefer-gnu-section偏好 GNU section 布局配合链接脚本做段级裁剪
-fno-common禁止 common 段合并避免多文件同名全局变量意外合并

功能宏 DEFINES 是固件功能的"总开关",约 40 项,覆盖芯片平台、外设、解码器、编码器与文件系统:

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 \
	-DHAS_FATFS_EN \
	-DHAS_FREEFS_EN \
	-DSIMPLE_FATFS_ENABLE=0 \
	-DSYS_VM_EN=0 \
	-DHAS_MP3_ENCODER \
	-DHAS_UMP3_ENCODER \
	-DHAS_A_ENCODER \
	-DHAS_SIMPLE_DEC_MODE \
	-DHAS_MUSIC_MODE \
	-DNOFLOAT \

DEFINES += $(EXT_CFLAGS) # 额外的一些定义

Source: sdk/Makefile

宏分组解读:

  • 平台类:FPGA=0(非 FPGA 验证)、CPU_SH59=1(SH59 内核)、ROM_SECURE_BOOT(安全启动)
  • 外设类:AUDIO_ADC_EN、SPEAKER_EN、AUX_EN、ENCODER_EN、HAS_EXT_FLASH_EN、HAS_SDMMC_EN、HAS_HW_SRC_MODULE=1
  • 解码器类:HAS_UMP3_DECODER、HAS_MP3_ST_DECODER、HAS_WAV_DECODER、HAS_F1A_DECODER(含 HAS_MAX_F1A_NUMBER=2 数量上限)、HAS_MIDI_DECODER、HAS_MIDI_KEYBOARD_DECODER、HAS_A_DECODER
  • 编码器类:HAS_MP3_ENCODER、HAS_UMP3_ENCODER、HAS_A_ENCODER
  • 音效类:HAS_VOICE_PITCH_EN(变调)、HAS_VOICE_CHANGER_EN(变声)、HAS_PCM_EQ_FLOAT_EN(浮点 EQ)、HAS_ANS_EN(降噪)、HAS_SPEED_EN(变速)、HAS_ECHO_EN(混响)、HOWLING_EN(啸叫抑制)
  • 文件系统类:HAS_NORFS_EN、HAS_FATFS_EN、HAS_FREEFS_EN、SIMPLE_FATFS_ENABLE=0、SYS_VM_EN=0
  • 系统类:HAS_USB_EN=0(USB 关闭)、HAS_UPDATE_EN=1(升级使能)、HAS_SIMPLE_DEC_MODE、HAS_MUSIC_MODE、NOFLOAT(禁用浮点运算)

NOFLOAT 与 CFLAGS 中的 -DNOFLOAT 呼应,提示该固件配置为定点运算模式(F1A 解码器通常需要)。修改这些宏即可裁剪/增配固件功能,但需同步确认对应源文件已列入 c_SRC_FILES。

头文件搜索路径与源文件清单

INCLUDES 定义了约 70 个头文件搜索目录,覆盖应用层(app/src/mbox_flash/...)、BSP 层(app/bsp/...)、预编译库头文件(include_lib/...)与系统头文件($(SYS_INC_DIR)):

INCLUDES := \
	-Iapp/src \
	-Iapp/bsp/common \
	-Iapp/bsp/common/fs \
	-Iapp/bsp/common/iic_soft \
	-Iapp/bsp/common/eeprom \
	-Iapp/bsp/common/msg \
	-Iapp/bsp/common/file_operate \
	-Iapp/bsp/common/api_mg \
	-Iapp/bsp/common/key \
	-Iapp/bsp/common/power_manage \
	-Iapp/bsp/common/norflash \
	-Iapp/bsp/common/spi_soft \
	-Iapp/bsp/common/reserved_area \
	-Iapp/bsp/common/uart_update \
	-Iapp/bsp/common/vm \
	-Iapp/bsp/cpu/sh59 \
	-Iapp/bsp/cpu/sh59/spi \
	-Iapp/bsp/cpu/sh59/wdt \
	-Iapp/bsp/cpu/sh59/audio \
	-Iapp/bsp/lib \
	-Iapp/bsp/modules \
	-Iapp/bsp/modules/timer \
	-Iapp/bsp/start/sh59 \
	-Iapp/post_build/sh59 \
	-Iinclude_lib \
	-Iinclude_lib/common \
	-Iinclude_lib/cpu/sh59 \
	-Iinclude_lib/cpu \
	-Iinclude_lib/fs \
	-Iinclude_lib/msg \
	-Iinclude_lib/fs/sydf \
	-Iinclude_lib/dev_mg \
	-Iinclude_lib/audio \
	-Iinclude_lib/sdmmc \
	-Iinclude_lib/update \
	-Iinclude_lib/decoder \
	-Iinclude_lib/decoder/list \
	-Iinclude_lib/encoder \
	-Iinclude_lib/encoder/list \
	-Iinclude_lib/device \
	-Iinclude_lib/ex_mcu \
	-Iinclude_lib/agreement \
	-Iinclude_lib/remain_output \
	-Iapp/src/mbox_flash \
	-Iapp/src/mbox_flash/sh59 \
	-Iapp/src/mbox_flash/common \
	-Iapp/src/mbox_flash/common/ui \
	-Iapp/src/mbox_flash/simple_decode \
	-Iapp/src/mbox_flash/linein \
	-Iapp/src/mbox_flash/loudspeaker \
	-Iapp/src/mbox_flash/idle \
	-Iapp/src/mbox_flash/record \
	-Iapp/src/mbox_flash/midi_dec \
	-Iapp/src/mbox_flash/midi_keyboard \
	-Iapp/src/mbox_flash/softoff_app \
	-Iapp/src/mbox_flash/usb_slave \
	-Iapp/src/mbox_flash/music \
	-Iinclude_lib/ans \
	-Iapp/bsp/common/speaker \
	-Iinclude_lib/speaker \
	-Iapp/bsp/common/vo_pitch \
	-Iinclude_lib/vo_pitch \
	-Iinclude_lib/vo_changer \
	-Iapp/bsp/modules/midi \
	-Iapp/bsp/modules/midi/pi32v2_lto_r3v2 \
	-Iapp/bsp/common/bt_common \
	-I$(SYS_INC_DIR) \

Source: sdk/Makefile

路径组织遵循三层结构:

  1. app/ 层:应用与 BSP 源码目录,app/src/mbox_flash 为小音箱应用代码,app/bsp/common 为平台无关驱动(key、msg、norflash、fs、vm 等),app/bsp/cpu/sh59 为 SH59 CPU 相关驱动(spi、wdt、audio),app/bsp/modules 为外设模块(timer、midi)。
  2. include_lib/ 层:预编译库(lib.a)对应的公开头文件,按功能分子目录(decoder、encoder、fs、update、device 等),这是"Release 版 SDK 配合 lib.a 编译"模式的接口层。
  3. $(SYS_INC_DIR) 层:工具链自带的系统头文件。

c_SRC_FILES 列出需要编译的全部 .c 文件,覆盖解码器(decoder_api、mp3_standard_api、ump3_api、wav_api、f1a_api、midi_api 等)、编码器(a_encoder、mp3_encoder、ump3_encoder)、文件系统(fat、free_fs、nor_fs、sydf、vfs)、按键、消息、NOR Flash 等:

c_SRC_FILES := \
	app/bsp/common/config/lib_power_config.c \
	app/bsp/common/decoder/decoder_api.c \
	app/bsp/common/decoder/decoder_msg_tab.c \
	app/bsp/common/decoder/decoder_point.c \
	app/bsp/common/decoder/eq.c \
	app/bsp/common/decoder/list/a_api.c \
	app/bsp/common/decoder/list/f1a_api.c \
	app/bsp/common/decoder/list/f1x_parsing.c \
	app/bsp/common/decoder/list/midi_api.c \
	app/bsp/common/decoder/list/midi_ctrl_api.c \
	app/bsp/common/decoder/list/mp3_standard_api.c \
	app/bsp/common/decoder/list/ump3_api.c \
	app/bsp/common/decoder/list/wav_api.c \
	app/bsp/common/decoder/mp_io.c \
	app/bsp/common/decoder/sine_play.c \
	app/bsp/common/encoder/encoder_api.c \
	app/bsp/common/encoder/list/a_encoder.c \
	app/bsp/common/encoder/list/mp3_encoder.c \
	app/bsp/common/encoder/list/ump3_encoder.c \
	app/bsp/common/fs/fat/fat_resource.c \
	app/bsp/common/fs/free_fs/free_fs.c \
	app/bsp/common/fs/free_fs/free_fs_resource.c \
	app/bsp/common/fs/nor_fs/nor_fs_resource.c \
	app/bsp/common/fs/sydf/sydf_resource.c \
	app/bsp/common/fs/vfs.c \
	app/bsp/common/fs/vfs_fat.c \
	app/bsp/common/fs/vfs_resource.c \
	app/bsp/common/key/key.c \
	app/bsp/common/key/key_drv_ad.c \
	app/bsp/common/key/key_drv_io.c \
	app/bsp/common/key/key_matrix.c \
	app/bsp/common/msg/msg.c \
	app/bsp/common/norflash/norflash.c \
	...

Source: sdk/Makefile

设计意图:源文件清单以"模块化平铺"方式维护,新增功能模块时需同时修改三处——INCLUDES(头文件路径)、DEFINES(功能宏)与 c_SRC_FILES(源文件)。这种显式枚举虽然冗长,但让每个固件版本的内容完全可审计,避免了通配符隐式引入未预期代码。

核心构建流程

下图展示一次完整的 make 调用从入口到固件产出的执行时序:

sequenceDiagram
    participant Dev as 开发者
    participant Make as make (Makefile)
    participant CC as clang (pi32v2)
    participant LD as lto-wrapper
    participant Post as post_build 脚本
    participant Board as 目标板

    Dev->>Make: make -j4 (或 make VERBOSE=1 -j4)
    activate Make
    Make->>Make: 检测平台 ifeq(OS, Windows_NT)
    Make->>Make: 组装 CFLAGS/DEFINES/INCLUDES
    loop 每个 .c 文件 (c_SRC_FILES)
        Make->>CC: clang -target pi32v2 -flto -Oz -c file.c
        CC-->>Make: LLVM IR 目标文件
    end
    Make->>LD: lto-wrapper 链接 (含 SYS_LIB_DIR/lib.a)
    LD-->>Make: app/post_build/sh59/sdk.elf
    Make->>Post: 调用 download.bat / download.sh
    alt Windows
        Post->>Post: fixbat.exe 转换 UTF-8→GBK
    end
    Post->>Board: 后处理并下载固件
    Board-->>Post: 完成
    Post-->>Make: 返回
    deactivate Make
    Make-->>Dev: 构建完成

关键步骤说明:

  1. 平台探测:Make 首先根据 OS 变量选择 Windows/Linux 分支,确定工具链路径与后处理脚本。这一步决定后续所有命令的实际形式(clang.exe vs clang、; vs : 路径分隔符)。
  2. 参数组装:CFLAGS、DEFINES、INCLUDES 在 Makefile 解析期拼接为完整命令行,DEFINES += $(EXT_CFLAGS) 把平台附加宏并入。
  3. 并行编译:-j4 让 make 并行编译 c_SRC_FILES 中的源文件;每个文件经 clang 以 -flto 模式产出 LLVM IR 中间目标文件(输出目录 BUILD_DIR := objs)。
  4. LTO 链接:lto-wrapper 读取所有 IR 目标文件与系统库(SYS_LIB_DIR 下的 lib.a),执行链接期优化后生成 OUT_ELF := app/post_build/sh59/sdk.elf。Linux 下此步骤对文件描述符数量敏感,故 Makefile 头部注释特别提示 ulimit -n 需大于 8096。
  5. 后处理与下载:RUN_POST_SCRIPT 执行 download.bat(Windows)或 bash download.sh(Linux)。Windows 下生成的 bat 脚本先经 fixbat.exe 做 UTF-8→GBK 编码转换,避免 cmd.exe 中文乱码;Linux 下 FIXBAT := touch 为空操作。
  6. 烧录:后处理脚本连接目标板完成固件下载,构建结束。

命令行工具与辅助脚本

make_prompt.bat — Windows 命令行环境入口

README 指示 Windows 用户先"双击 sdk/make_prompt.bat 打开命令行环境",再执行 make -j4。该脚本的作用是建立与 Makefile 一致的环境(将工具链目录 C:/JL/pi32/bin 注入 PATH),确保在普通 cmd 窗口中输入 make、clang 等命令即可被解析。它本质上是对"工具链环境初始化"的封装,与 Makefile 内部的 export PATH 形成双保险。

fixbat.exe — bat 脚本编码修正工具

位于 tools/utils/fixbat.exe,仅 Windows 分支使用。由于 Makefile 与源码以 UTF-8 编码保存,而 Windows cmd.exe 默认使用 GBK 代码页,直接执行会中文乱码或命令解析错误。fixbat.exe 在下载脚本执行前将其转为 GBK,保证 download.bat 正确运行。Linux 分支用 touch 占位,保持 Makefile 变量引用结构一致。

后处理脚本 — download.bat / download.sh

平台各有一个后处理脚本,路径均为 app/post_build/sh59/:

平台脚本触发方式
Windowsdownload.batapp\\post_build\\sh59\\download.bat
Linuxdownload.shbash $(POST_SCRIPT)

脚本负责编译后的固件后处理(如格式封装、校验)与下载。Linux 分支的 EXT_CFLAGS := -D__SHELL__ 正是为了让与下载相关的 download.c 在 Linux 下能正确编译——README 也提示"Linux 下 Makefile 命令行编译(需要重写 download_bat.c 脚本适配 Linux 环境)",说明下载逻辑的源码实现(download_bat.c)本身是平台相关的。

烧录工具(外部工具)

编译成功后需借助外部工具将固件烧录到目标板:

  • USB 升级工具:开发阶段烧录,需目标板进入编程模式(README 提示"编译前请确保 USB 升级工具正确连接且目标板已进入编程模式")。
  • 生产烧写工具:量产/裸片烧写,由代理商提供。

使用示例

方式一:命令行 make(推荐 Linux / 进阶用户)

# Windows 用户
双击 sdk/make_prompt.bat 打开命令行环境

# 编译
make -j4

# 显示编译详情
make VERBOSE=1 -j4

Source: README.md

-j4 指定 4 路并行编译;VERBOSE=1 让 make 回显每条实际执行的编译/链接命令,用于排查参数错误或观察工具链调用细节。Makefile 头部注释还声明了 make clean 用于清除编译临时文件(objs/ 目录)。

方式二:Code::Blocks IDE(推荐 Windows 桌面用户)

# 双击打开工程文件
AD23N_mbox_flash.cbp

# 点击 Build → Build(Ctrl+F9)
# 编译成功后,使用 USB 升级工具烧录生成的固件

Source: README.md

.cbp 是 Code::Blocks 工程文件,其编译参数与 Makefile 保持一致(同一套 clang 工具链与宏定义),适合不熟悉命令行的开发者。

方式三:VS Code 任务

# 仓库已预配置 VS Code 任务
# 按 Ctrl+Shift+B 选择编译目标

Source: README.md

验证工具链安装

# 验证工具链是否安装成功
clang --version

Source: README.md

配置选项

构建系统的配置通过修改 Makefile 变量实现,主要可调项如下:

配置项类型默认值说明
TOOL_DIR路径Windows: C:/JL/pi32/bin;Linux: /opt/jieli/pi32v2/bin交叉编译工具链目录
SYS_LIB_DIR路径Windows: C:/JL/pi32/pi32v2-lib/r3;Linux: $(TOOL_DIR)/../lib/r3预编译系统库(lib.a)目录
SYS_INC_DIR路径Windows: C:/JL/pi32/pi32v2-include;Linux: $(TOOL_DIR)/../include工具链系统头文件目录
OUT_ELF路径app/post_build/sh59/sdk.elf链接产物输出路径
BUILD_DIR路径objs编译中间文件目录
CFLAGS字符串-target pi32v2 -mcpu=r3v2 -flto -Oz -g ...编译参数
DEFINES字符串约 40 个 -D 宏(见上文)功能开关宏定义
EXT_CFLAGS字符串Windows: 空;Linux: -D__SHELL__平台附加宏
FIXBAT命令Windows: tools/utils/fixbat.exe;Linux: touchbat 编码修正工具
POST_SCRIPT路径Windows: download.bat;Linux: download.sh编译后处理脚本

环境级配置(非 Makefile 变量):

配置项平台说明
PATH双平台工具链目录需在 PATH 中(Makefile 内已自动注入)
ulimit -nLinux需大于 8096,否则 LTO 链接可能因打开文件过多失败
工具链安装位置双平台Windows C:/JL/pi32、Linux /opt/jieli/pi32v2,需与 Makefile 分支一致

Make 目标参考(API Reference)

构建系统对外暴露的 Make 目标如下(依据 Makefile 头部注释与 README 使用说明):

目标等价命令行行为
默认目标(all)make -j4编译全部源文件、LTO 链接生成 sdk.elf,并执行后处理/下载
详细模式make VERBOSE=1 -j4与默认目标相同,但回显每条实际执行的命令
清理make clean清除编译临时文件(objs/ 构建目录等)

变量参数:

  • VERBOSE(整数):置 1 时打印详细编译命令,用于排查工具链调用问题。
  • -j<N>:GNU make 并行任务数,示例使用 -j4。注意 LTO 链接阶段对文件描述符数量敏感(Linux 下需 ulimit -n > 8096)。

失败模式、边界情况与并发

工具链缺失或路径不符

构建的第一步是定位 clang/lto-wrapper。若工具链未安装或安装目录与 Makefile 分支不一致(如 Windows 下不在 C:/JL/pi32,Linux 下不在 /opt/jieli/pi32v2),make 将报 command not found 或 No such file or directory。对策:按 README 指引安装杰理编译工具链,并保证目录层次(Makefile 注释强调"保证 /opt/jieli/common/bin/clang 存在(注意目录层次)");或修改 TOOL_DIR 变量适配本机路径。

Linux 链接期文件描述符耗尽

LTO 链接需要同时打开大量中间文件与库文件,若 ulimit -n 过小,链接阶段会失败。Makefile 头部注释明确给出建议:"确认 ulimit -n 的结果足够大(建议大于8096),否则链接可能会因为打开文件太多而失败,可以通过 ulimit -n 8096 来设置一个较大的值"。这是 Linux 平台最典型的构建失败场景之一。

bat 脚本编码问题(Windows)

cmd.exe 默认 GBK 代码页,而工程文件为 UTF-8。若不经过 fixbat.exe 转换,download.bat 可能乱码或执行异常。构建系统通过 FIXBAT 变量自动处理;若用户跳过 make 直接手动运行 download.bat,需自行保证编码正确。

平台相关源码差异

Linux 分支通过 -D__SHELL__ 让 download.c 以 shell 模式编译;README 同时指出 Linux 下"需要重写 download_bat.c 脚本适配 Linux 环境"。若在 Linux 下直接使用 Windows 版本下载逻辑,可能出现编译或执行不匹配。对策:遵循 README 的平台指引,必要时适配 download_bat.c。

并发构建注意事项

-j4 并行编译是安全的——各 .c 文件独立编译为 IR,互不依赖。但后处理/下载阶段涉及目标板连接,属于串行瓶颈;且并行度受限于工具链(LTO 链接本身会占用较多文件描述符),过高的 -j 值可能在链接期放大 ulimit 问题。建议按 README 使用 -j4。

功能宏与源文件一致性

DEFINES 与 c_SRC_FILES 必须保持一致:启用某宏(如 HAS_MIDI_DECODER)却未把对应源文件(midi_api.c)列入清单,或反之,会导致链接期符号缺失或代码冗余。由于清单是显式平铺的,排查此类问题时需交叉核对三处:DEFINES、INCLUDES、c_SRC_FILES。

性能与运维考虑

  • 构建速度:-flto 将优化推迟到链接期,首次构建时间主要消耗在 clang 编译与 lto-wrapper 链接两个阶段;增量构建时 make 依据文件时间戳跳过未变更源文件。objs/ 目录缓存中间产物,make clean 可强制全量重建。
  • 体积优先:-Oz 配合 -fprefer-gnu-section 与 LTO 裁剪,使固件体积最小化,适配小 Flash MCU;代价是运行性能非最优,对实时性敏感路径需在代码层面评估。
  • 二进制信息:-g 保留调试信息,可结合工具链的 objdump/objcopy/objsizedump(Linux 分支显式 export 这些变量)做反汇编与体积分析。
  • 固件输出位置固定:sdk.elf 固定输出到 app/post_build/sh59/,后处理脚本与烧录工具都依赖该路径,运维时勿随意更改。

扩展点

构建系统为功能扩展预留了明确的修改点:

  1. 新增源文件:将 .c 文件路径追加到 c_SRC_FILES,并在 INCLUDES 中补充其头文件目录。
  2. 新增功能宏:在 DEFINES 中添加 -D 开关,并在源码中以 #ifdef 条件编译接入;HAS_* 系列宏是现成的命名范式。
  3. 切换平台工具链:修改对应平台的 TOOL_DIR/SYS_LIB_DIR/SYS_INC_DIR,或新增 ifeq 分支(如 macOS 需自行配置交叉编译工具链)。
  4. 自定义后处理:修改 app/post_build/sh59/download.bat / download.sh,或替换 POST_SCRIPT/RUN_POST_SCRIPT 变量指向新脚本。
  5. 集成到 IDE/CI:Code::Blocks(.cbp)与 VS Code 任务均已预配置;CI 场景可直接调用 make -j4(Linux),注意在流水线中预留 ulimit -n 8096 设置。

相关链接

  • README.md 编译指南:环境搭建、工具链安装与三种编译方式完整说明
  • sdk/Makefile:构建系统核心源码
  • 杰理编译工具链下载:官方文档 / pkgman.jieliapp.com
  • USB 升级工具使用文档:forced_upgrade
  • 生产烧写工具使用文档:burner_1tuo2

说明:本页聚焦构建系统与命令行工具本身;固件烧录操作细节、SDK 应用工程结构、芯片平台差异分别属于"烧录与升级""应用与示例""支持的芯片与平台"等页面主题。

Prev
编译后处理与镜像打包