杰理AC69xx SDK开发全指南:RISC-V音频SoC编译烧录与音频通路实战 简介杰理AC69xx系列SDK文件是一套面向嵌入式开发工程师的完整固件开发套件专为AC69xx蓝牙音频SoC芯片设计覆盖蓝牙协议栈配置、音频编解码AAC/WMA、低功耗管理及硬件外设驱动开发等核心场景适用于蓝牙音箱、TWS耳机等消费类音频产品开发。资源共554个文件涵盖95个C源码、186个头文件.h、96个目标文件.o及48个静态库.a如bluetooth_lib.a、aac_dec_lib.a、usb_lib.a等关键模块库另有PDF补丁文档、bat/sh构建脚本、示例工程apps_soundbox及蓝牙配置工具bt_config_tools_2.1.0.4包体25.56MB结构清晰、开箱即用。已有13252人学习下载开发者可直接复用驱动框架、参考标准音频盒实现逻辑、快速掌握AC69xx芯片的SDK工程组织方式与蓝牙配置流程并通过补丁说明及时升级固件稳定性。1. 杰理AC69xx系列SDK文件不是“拿来就能跑”的压缩包而是嵌入式音频开发的钥匙串你手头刚拿到一份标着“杰理AC6925B_SDK_V4.3.0.18.zip”的压缩包解压后看到上百个文件夹、上千行Makefile、一堆带“.a”后缀的静态库和满屏英文注释的头文件——第一反应可能是“这到底该从哪编译main函数在哪为什么连个LED闪烁例程都找不到”这不是你的问题。杰理AC69xx系列SDK覆盖AC692x/AC693x/AC695x等主流音频SoC本质上不是面向通用MCU开发者的“开箱即用”工具链而是一套深度耦合硬件IP、音频通路与BLE协议栈的垂直集成开发包。它不提供标准CMSIS层抽象不兼容Keil MDK或IAR默认工程模板它的“main”藏在app_main.c里但真正启动逻辑由ROM里的Bootloader接管它的UART打印要先调uart_init()再配printf重定向否则串口永远静默。这套SDK的核心价值在于把蓝牙音频TWS主从同步、ANC参数下发、本地播放MP3/WAV解码器绑定DAC通路、电源管理休眠唤醒电流20μA这些高频踩坑模块封装成可配置的API组合。适合两类人一是正在量产TWS耳机/便携音箱的嵌入式团队需要快速复用杰理方案降低BOM成本二是想深入理解低功耗音频SoC软硬协同机制的进阶开发者——如果你只打算用它点个灯、读个ADC那真不如换STM32。2. 搭建可编译环境从Windows到Linux交叉工具链的三道关卡杰理官方仅提供Windows下基于Keil uVision5的工程模板但实际量产项目中90%以上的固件团队会切换到LinuxGCC环境——原因很现实CI流水线集成、脚本化烧录、多人协作时Makefile依赖更可控。这里不讲Keil怎么点按钮只说如何在Ubuntu 22.04上让AC69xx SDK真正跑起来。2.1 安装杰理定制GCC工具链非arm-none-eabi-gcc杰理AC69xx采用自研RISC-V内核非ARM Cortex-M其SDK必须使用杰理提供的gcc_riscv32_elf工具链。官方SDK包内tools/gcc/目录下有gcc_riscv32_elf_linux.tar.gzLinux版和gcc_riscv32_elf_win.zipWindows版。切记不要用riscv64-unknown-elf-gcc替代杰理内核是32位RISC-V且指令集有裁剪无浮点单元部分原子指令被禁用。# 解压到/opt/jieeli_gcc/ sudo tar -zxvf gcc_riscv32_elf_linux.tar.gz -C /opt/ # 添加环境变量写入~/.bashrc echo export PATH/opt/gcc_riscv32_elf/bin:$PATH ~/.bashrc echo export RISCV_TOOLCHAIN/opt/gcc_riscv32_elf ~/.bashrc source ~/.bashrc # 验证 riscv32-unknown-elf-gcc --version # 正确输出应含jieeli字样例如riscv32-unknown-elf-gcc (jieeli-gcc-10.2.0) 10.2.0提示如果riscv32-unknown-elf-gcc命令报错“no such file or directory”大概率是动态库缺失。运行ldd $(which riscv32-unknown-elf-gcc)检查libstdc.so.6等依赖用apt install libstdc6 libgcc1补全。这是杰理工具链打包时未做静态链接导致的经典玄学问题。2.2 SDK目录结构解析绕过project/目录的陷阱新手常误以为project/文件夹是工程根目录直接cd进去make——结果报错No rule to make target all。真相是AC69xx SDK采用“双层工程结构”。目录路径作用是否可直接编译sdk/核心驱动、中间件、协议栈源码audio/,ble/,pmu/等❌ 不可直接编译仅为引用project/官方示例集合demo_ble_hid/,demo_mp3_player/❌ 仅为模板缺Makefile主入口makefile/真正的构建中枢含Makefile.common、Makefile.rules及芯片型号定义✅ 必须从此处启动正确做法进入makefile/目录用make命令指定目标芯片和应用。例如编译AC6925B的BLE HID示例cd makefile/ # 查看可用目标会列出所有project下的demo make help # 编译AC6925B的HID demo关键TARGET_CHIP必须与SDK版本匹配 make TARGET_CHIPAC6925B APP_NAMEdemo_ble_hid # 输出固件位于out/AC6925B_demo_ble_hid/AC6925B_demo_ble_hid.binTARGET_CHIP参数必须严格匹配SDK支持列表makefile/Makefile.chip中定义常见值包括AC6925B、AC6936B、AC6956A。填错会导致链接阶段找不到rom_code.a杰理ROM代码库而失败。2.3 头文件与库路径的隐式绑定AC69xx SDK不通过-I显式声明所有头文件路径而是依赖makefile/Makefile.common中预设的INC_PATHS变量。若你新增自定义驱动如扩展SPI Flash需手动在对应demo的Makefile中追加# 在project/demo_ble_hid/Makefile中添加 INC_PATHS $(SDK_ROOT)/drivers/spi_flash LIB_PATHS $(SDK_ROOT)/lib/spi_flash LIBS spi_flash否则编译时会提示fatal error: spi_flash.h: No such file or directory。这个设计让SDK看起来“自动包含”实则把路径管理黑盒化了——血泪经验每次新增模块先查makefile/Makefile.common里的INC_PATHS默认值再决定是改全局还是局部。3. 烧录与调试J-Link不认AC69xx用杰理专用烧录器的底层逻辑杰理AC69xx芯片不支持标准SWD/JTAG协议官方烧录器如JieLi Flash Download Tool本质是USB转UART 自定义Bootloader通信协议。这意味着J-Link、ST-Link等通用调试器无法直连AC69xx串口助手发AT指令无效Bootloader不响应AT只认二进制帧烧录失败时芯片不会变砖但会卡在ROM Bootloader等待超时约3秒之后自动跳转APP——这点比某些国产MCU友好。3.1 Linux下命令行烧录脱离GUI工具杰理提供flash_tool命令行工具位于tools/flash_tool/支持Ubuntu/MacOS。其核心是flash_tool可执行文件 config.ini配置文件。配置要点; config.ini 关键参数说明 [COMMON] chip AC6925B ; 必须与TARGET_CHIP一致 baudrate 115200 ; 实测最高稳定波特率921600易丢帧 port /dev/ttyUSB0 ; USB转串口设备名用ls /dev/ttyUSB*确认 [FLASH] flash_size 2048 ; 单位KBAC6925B内置2MB Flash erase_all 1 ; 1全片擦除0仅擦写区推荐首次用1烧录命令需root权限访问串口sudo ./flash_tool -c config.ini -f out/AC6925B_demo_ble_hid/AC6925B_demo_ble_hid.bin # 成功日志含Download success! 和 Reset chip注意若提示Cant open serial port检查串口权限sudo usermod -a -G dialout $USER然后重新登录终端。这是Linux下最常翻车的一步。3.2 UART打印调试重定向printf到串口的四步法AC69xx SDK默认关闭所有printf输出为省电需手动启用。以demo_ble_hid为例在project/demo_ble_hid/app_main.c中找到app_main()函数在app_start()调用前插入串口初始化uart_init(0, 115200, 8, 1, 0); // UART0, 115200bps, 8N1启用printf重定向SDK已提供printf_init()printf_init(); // 此函数将printf绑定到UART0在任意位置加调试打印printf(APP STARTED! heap:%d\r\n, get_free_heap_size());关键点printf_init()必须在uart_init()之后调用否则输出乱码。这是因为printf_init()内部会调用uart_putchar()而后者依赖UART寄存器已配置完成。4. 避坑指南AC69xx SDK开发中5个高频翻车现场现象、原因、解决方案按真实调试记录整理拒绝理论空谈。4.1 现象编译通过但烧录后LED不亮串口无任何输出原因out/xxx.bin是原始二进制镜像但AC69xx要求烧录带Header的加密镜像。官方flash_tool会在烧录时自动添加Header含校验和、起始地址等若你用其他工具如stm32flash直接烧xxx.bin芯片无法识别。解决严格使用杰理flash_tool烧录或用SDK自带tools/mkimage.py生成Header镜像python tools/mkimage.py -i out/AC6925B_demo_ble_hid/AC6925B_demo_ble_hid.bin -o out/with_header.bin -c AC6925B4.2 现象BLE连接成功但手机APP收不到HID报告Report ID0x01原因AC69xx的HID服务描述符HID Service Descriptor需在ble_hogp_server.c中手动配置hid_report_map数组且长度必须与HID_REPORT_MAP_LEN宏一致。SDK默认hid_report_map是空数组导致Descriptor无效。解决在project/demo_ble_hid/src/ble_hogp_server.c中替换hid_report_map为实际HID Report Descriptor十六进制字节数组并更新HID_REPORT_MAP_LENconst u8 hid_report_map[] {0x05, 0x01, 0x09, 0x06, 0xA1, 0x01, /* ...省略具体Descriptor */ }; #define HID_REPORT_MAP_LEN (sizeof(hid_report_map))4.3 现象MP3播放时音质断续DAC输出有“咔哒”声原因AC69xx的DAC驱动需严格匹配采样率。SDK中audio_dac.c默认配置为44.1kHz若MP3解码器输出48kHz数据如某些第三方解码库未做重采样会导致缓冲区溢出。解决在app_audio.c中调用dac_set_sample_rate()前确认解码器输出采样率// 假设解码器输出48kHz dac_set_sample_rate(SAMPLE_RATE_48000); // 并确保DAC缓冲区大小适配dac_set_buffer_size(4096); // 48kHz需≥4096字节4.4 现象低功耗模式下pmu_enter_sleep()唤醒后系统死机原因AC69xx进入Deep Sleep时RAM部分内容会掉电丢失。SDK默认将heap放在SRAM中唤醒后malloc返回NULL。但更隐蔽的是中断向量表IVT必须驻留在Retention RAM否则唤醒中断无法触发。解决在startup_ac69xx.s中确认.vector段链接到RETENTION_RAM.vector : { *(.vector) } RETENTION_RAM并在pmu_enter_sleep()前调用pmu_set_retention_ram()保留关键变量区域。4.5 现象修改app_config.h中的TWS_MASTER_ROLE为0后TWS耳机无法组队原因AC69xx的TWS主从角色切换不仅依赖宏定义还需烧录不同的EFUSE配置。TWS_MASTER_ROLE0仅控制软件逻辑但硬件EFUSE中TWS_MODE位地址0x1000_0004必须为1才能启用从机模式。解决用杰理efuse_tool烧录EFUSE危险操作仅首次配置./efuse_tool -p /dev/ttyUSB0 -w 0x10000004 -v 0x00000001 # 烧录后需整片擦除再烧APP否则EFUSE锁死5. 音频通路实战从MIC输入到DAC输出的端到端信号流拆解AC69xx SDK最值得深挖的不是BLE协议栈而是其音频子系统——它把模拟前端AFE、数字信号处理器DSP、编解码器Codec和接口I2S/PCM全部封装成可插拔模块。理解这个通路才能真正驾驭降噪、混音、ASR唤醒等高级功能。5.1 音频数据流的四级路由AC69xx的音频处理不是线性管道而是分层路由架构层级模块关键API作用L1: AFE层mic_analog.cmic_analog_init(),mic_analog_gain_set()配置MIC偏置电压、PGA增益0~42dB抗混叠滤波L2: ADC层adc_dmic.cadc_dmic_start(),adc_dmic_set_rate()选择DMIC/PDM输入设置采样率8/16/32/44.1/48kHzL3: DSP层dsp_core.cdsp_enable_module(),dsp_set_param()加载ANC算法、EQ滤波器、AGC参数需预编译.dspbin文件L4: DAC层dac_i2s.cdac_i2s_start(),dac_i2s_set_format()配置I2S主从模式、位宽16/24bit、LRCK极性典型场景TWS左耳采集语音 → ANC降噪 → 蓝牙回传 → 右耳DAC播放。代码骨架如下// 1. 初始化MIC通道左耳 mic_analog_init(MIC_CH0, MIC_BIAS_2P5V); adc_dmic_start(ADC_MIC0, SAMPLE_RATE_16000); // 2. 加载ANC DSP模块需提前编译好anc.dspbin dsp_load_bin(anc.dspbin); dsp_enable_module(DSP_MODULE_ANC); // 3. 启动DAC右耳 dac_i2s_start(DAC_I2S0, SAMPLE_RATE_16000); dac_i2s_set_format(I2S_FORMAT_STANDARD, 16, I2S_LRCK_POL_LOW); // 4. 数据搬运ADC输出→DSP输入→DAC输入由DMA自动完成 // SDK已内置dma_link_adc_to_dsp_to_dac()函数无需手动memcpy5.2 ANC参数实时下发的底层机制ANC主动降噪不是固定算法而是依赖麦克风频响、喇叭频响、耳道声学模型的动态参数。AC69xx SDK通过dsp_set_param()实现参数热更新但参数ID必须与DSP固件中定义的PARAM_ID严格对应。例如参数ID十六进制名称作用典型值0x0001ANC_FIR_COEFFFIR滤波器系数数组长度1280x0002ANC_LPF_CUTOFF低通截止频率0x000004B01200Hz0x0003ANC_GAIN_DB降噪增益0x0000001E30dB下发代码u16 anc_gain 0x0000001E; dsp_set_param(0x0003, anc_gain, sizeof(anc_gain)); // 注意参数值必须是u16/u32类型不能传float血泪经验参数ID填错不会报错但ANC完全失效。建议用SDK自带tools/dsp_param_viewer.py解析.dspbin文件导出所有合法ID列表。5.3 调试音频通路的三把尺子当声音异常时不用猜用这三步定位查ADC数据在adc_dmic_callback()中打印ADC采样值前10个void adc_dmic_callback(u16 *data, u16 len) { for(int i0; i10 ilen; i) { printf(ADC[%d]%d , i, data[i]); // 正常应为±2000范围的波动值 } }若全为0或恒定值说明MIC硬件或AFE配置错误。查DSP输出启用DSP调试日志需在dsp_core.c中取消注释#define DSP_DEBUG_LOG观察dsp_process()是否被调用、处理延迟是否超限5ms会丢帧。查DAC波形用示波器接DAC输出引脚看是否有稳定正弦波。若无波形检查dac_i2s_start()返回值是否为0失败返回非0以及I2S时钟是否正常用逻辑分析仪测BCLK/LRCK。我习惯在每次音频功能迭代后用手机录音APP录下DAC输出再用Audacity做频谱分析——看48kHz采样率下是否存在镜像频谱说明重采样失败看1kHz单音是否纯净判断ANC是否引入谐波失真。这种土办法比看日志快十倍。希望帮到你。本文还有配套的精品资源点击获取