杰理 SDK 文档中心
首页
首页
  • SDK 概述与快速开始

    • SDK 概览与 AC791N 芯片平台
    • 环境搭建与编译指南
    • 烧录与固件升级
    • 工程结构导览
  • 产品方案应用

    • WiFi 摄像头方案
    • WiFi IPC 可视对讲方案
    • WiFi 故事机方案
    • 扫码枪 HID 方案
    • 开发板示例工程
  • 公共应用组件

    • 语音识别 ASR 引擎
    • LLM 与 AI 语音助手接入
    • 摄像头传感器驱动
    • UI 显示框架与驱动
    • USB 主机与设备栈
    • 文件系统与存储管理
    • 系统服务与外设管理
    • 生产测试与射频工具
  • 蓝牙协议栈

    • 经典蓝牙 BR/EDR
    • BLE 低功耗蓝牙
    • 蓝牙 Mesh 网络
    • 蓝牙扩展协议(RCSP/广播/无线麦克风)
  • WiFi 与网络协议栈

    • WiFi 驱动与网络模式
    • lwIP TCP/IP 协议栈
    • 网络安全与加密库
    • 应用层网络协议
    • 流媒体与音视频传输
    • 云平台接入 SDK
    • P2P 远程访问与设备互联
  • 芯片平台与驱动

    • wl82 平台与硬件加速
    • 外设驱动框架
    • 平台配置与固件打包工具
  • 媒体与音频引擎

    • 音频编解码与音源
    • 音效处理引擎
    • 视频与图像处理
  • 操作系统与运行时

    • 实时操作系统与 POSIX 层
    • C/C++ 运行时库
  • 开发资源与文档

    • 文档与规格书
    • 公共示例工程
    • UI 资源工程与打包
    • SDK 辅助工具与脚本

wl82 平台与硬件加速

wl82(AC791N)是杰理(Jieli)AIoT SDK 中的 WiFi SoC 平台。本页介绍其平台启动流程、内存/链接布局、芯片寄存器映射,以及 WL82 专属的硬件加速能力(硬件 FFT 等),并说明平台相关的差异化配置与预编译库结构。

Purpose and Scope

本页覆盖 wl82 平台在 fw-AC79_AIoT_SDK 中的完整软件视图:

  • 平台引导与初始化流程(cpu/wl82/setup.c 中的 setup_arch())
  • 内存布局与链接脚本(SDRAM 运行与 SFC 运行的两种链接方案)
  • 芯片 SFR 寄存器映射(include_lib/driver/cpu/wl82/asm/WL82.h)
  • 硬件加速能力:硬件 FFT(JL_HW_FFT_V、vc_hw_fft())及平台差异化算法开关
  • 预编译库(cpu/wl82/liba/)与加载工具(wl82loader.bin)

下列主题属于其他页面,不在本页展开:WiFi 协议栈与吞吐率/功耗调优细节(参见芯片平台手册及 doc/stuff/ 下的评估文档)、具体应用层业务(音频、网络协议栈如 mqtt/coap 等各自的 wl82 工程配置)。

概述

wl82 平台以 AC791N 芯片为核心,是一颗集成 WiFi、音频(Audio Server)、AI 语音(ai_server)与蓝牙控制器的 SoC。在 SDK 中,wl82 的软件栈由以下层次构成:

  1. 平台启动层:cpu/wl82/setup.c 的 setup_arch() 完成看门狗、时钟、中断、调试串口、复位原因、CRC 互斥锁与 IO 锁存等早期初始化,并打印芯片 ID 与各内存段大小。
  2. 链接/内存层:cpu/wl82/sdk_ld_sdram.c(代码从 SDRAM 运行)与 cpu/wl82/sdk_ld_sfc.c(代码从 SPI Flash 直接执行,XIP)两种链接方案,统一复用 driver/cpu/wl82/ 下的 media_text.ld、system.ld、system_data.ld 片段,并提供 lib_wl82_rf_version 等版本符号。
  3. 寄存器抽象层:WL82.h 按高速(hsb)、低速(lsb)、蓝牙/无线(bt)与端口(port)四类总线定义 SFR 基地址,并以 JL_xxx_TypeDef 结构体 + JL_xxx 宏的方式暴露外设(如 JL_SFC 串行 Flash 控制器、JL_SFCENC 加密引擎)。
  4. 硬件加速层:针对 CONFIG_CPU_WL82,SDK 启用硬件 FFT 版本 4(JL_HW_FFT_V = 4),apps/common/jl_math/jl_fft.c 通过 vc_hw_fft() 调用硬件 FFT 加速 1024/512 点实数变换;同时开启新的啸叫移频算法(howling_freshift_PLATFORM = 1)。
  5. 库与工具层:cpu/wl82/liba/ 存放 cpu.a、audio_server.a、btstack.a、ai_server.a 等预编译库;cpu/wl82/tools/ 提供 wl82loader.bin 加载固件。

架构

flowchart TD
    subgraph sg_App["应用层 (apps/)"]
        AudioConfig["audio_config.c<br/>平台差异化配置"]
        JLMath["jl_math/jl_fft.c<br/>FFT 计算"]
        AppMain["app_config.h / 应用入口"]
    end

    subgraph sg_Platform["wl82 平台层 (cpu/wl82/)"]
        Setup["setup.c<br/>setup_arch()"]
        LinkSdram["sdk_ld_sdram.c<br/>SDRAM 链接"]
        LinkSfc["sdk_ld_sfc.c<br/>SFC 链接"]
        Debug["debug.c / iic.c"]
        Key["key/ 按键检测<br/>adc/ctmu/irflt/plcnt/rdec"]
        Libs["liba/ 预编译库<br/>cpu.a / audio_server.a / btstack.a"]
    end

    subgraph sg_Hw["硬件抽象层 (include_lib/driver/cpu/wl82/)"]
        WL82H["asm/WL82.h<br/>SFR 寄存器映射"]
        Lds["media_text.ld / system.ld<br/>system_data.ld"]
    end

    subgraph sg_HwAccel["硬件加速"]
        HWFFT["硬件 FFT 引擎<br/>JL_HW_FFT_V = 4"]
        SFCEngine["SFC 加密引擎<br/>JL_SFCENC"]
    end

    subgraph sg_Silicon["AC791N 芯片"]
        CPU["CPU 核"]
        SFC["SPI Flash 控制器"]
        RAM["SDRAM / RAM0 / CACHE_RAM"]
    end

    AppMain --> Setup
    AudioConfig -->|"CONFIG_CPU_WL82"| Setup
    JLMath -->|"vc_hw_fft()"| HWFFT
    Setup --> WL82H
    LinkSdram --> Lds
    LinkSfc --> Lds
    WL82H --> SFC
    WL82H --> CPU
    HWFFT --> CPU
    SFCEngine --> SFC
    Libs --> CPU
    Key --> WL82H
    Setup --> RAM
    SFC --> RAM

架构说明: 应用层通过 CONFIG_CPU_WL82 编译开关与平台层交互:audio_config.c 决定是否启用硬件 FFT 及选择算法版本,jl_fft.c 在应用侧直接驱动硬件 FFT 引擎。平台层 setup_arch() 读取 WL82.h 暴露的寄存器完成初始化,并通过链接脚本(sdk_ld_sdram.c/sdk_ld_sfc.c + *.ld 片段)决定代码与数据在 SDRAM、SFC、RAM0、CACHE_RAM 中的落位。预编译库(cpu.a 等)封装了芯片底层驱动,向应用提供标准 API。

平台启动流程:setup_arch()

wl82 平台的早期初始化全部集中在 cpu/wl82/setup.c 的 setup_arch() 中,它是 SDK 从汇编启动跳转到 C 世界后的第一个平台相关入口。其执行顺序即硬件上电后的依赖顺序:

void setup_arch()
{
    /*wdt_close();*/
    wdt_init(0xc);

    clk_early_init();

    interrupt_init();

#ifdef CONFIG_DISABLE_P3_FSPG_CON
    p33_tx_1byte(P3_FSPG_CON, 0);
#endif

#ifdef CONFIG_DEBUG_ENABLE
    extern void debug_uart_init();
    debug_uart_init();
#ifdef __LOG_ENABLE
    log_early_init(10 * 1024);
#endif
#endif

    system_reset_reason_get();
    ...
}

Source: setup.c

各步骤的设计意图:

步骤函数/宏作用与原因
看门狗wdt_init(0xc)最先打开看门狗,防止后续初始化卡死无人知晓;wdt_close() 被注释,说明生产环境要求看门狗常开
时钟clk_early_init()在访问任何外设前配置 PLL/分频,setup_arch() 末尾打印 sys_clk / sdram_clk / hsb_clk / lsb_clk / sfc_clk 用于核对
中断interrupt_init()建立中断向量表与控制器基础配置,之后外设驱动才能安全注册中断
P3 电源域CONFIG_DISABLE_P3_FSPG_CON + p33_tx_1byte()可选的省电配置:通过 P33 接口关闭 P3 域的 FSPG(Flash 电源门控)连接
调试串口CONFIG_DEBUG_ENABLE + debug_uart_init()尽早可用,后续所有 puts/printf 才有输出通道
早期日志__LOG_ENABLE + log_early_init(10 * 1024)分配 10KB 早期日志缓冲,保证启动阶段日志不丢
复位原因system_reset_reason_get()在日志系统就绪后立即记录复位原因(上电/看门狗/低电压等),便于现场定位

初始化完成后,setup_arch() 打印芯片信息与内存规划:

printf("\n   WL82(AC791N) CHIP_ID: 0x%x  setup_arch %s %s", JL_INTEST->CHIP_ID, __DATE__, __TIME__);
...
printf("\nSDRAM_SIZE = %d, DATA_SIZE = %d,BSS_SIZE = %d,REMAIN_SIZE = %d", ...);
printf("\nRAM_SIZE = %d,DATA_SIZE = %d,BSS_SIZE = %d,REMAIN_SIZE = %d", ...);
printf("\nCACHE_RAM_SIZE = %d,DATA_SIZE = %d, BSS_SIZE = %d,REMAIN_SIZE = %d", ...);
printf("\nHEAP_SIZE = %d", (u32)&HEAP_END - (u32)&HEAP_BEGIN);

Source: setup.c

这些符号(SDRAM_SIZE、RAM0_SIZE、CACHE_RAM_SIZE、HEAP_END/HEAP_BEGIN 等)由链接脚本定义,setup_arch() 通过 extern 声明读取,是"链接脚本向运行时代码传递内存规划"的典型机制——启动日志因此能直接反映当前工程的链接配置是否合理。

收尾部分完成三项关键注册:

extern void code_movable_init(void);
code_movable_init();       // 可搬移代码段(movable code)初始化
debug_init();              // 调试子系统(含按键/命令行等)初始化
__crc16_mutex_init();      // CRC16 硬件加速器的互斥锁初始化
p33_io_latch_init();       // P33 IO 锁存初始化

Source: setup.c

其中 code_movable_init() 与链接脚本中的 movable_text.ld 配合——允许把不常执行的代码段搬到外部存储,节省内部 RAM;__crc16_mutex_init() 说明硬件 CRC16 加速器被多个模块共享,需要互斥保护(详见"并发与一致性"一节)。

内存布局与链接脚本

wl82 平台支持两种运行形态,分别对应两个链接入口:

  • SDRAM 运行:cpu/wl82/sdk_ld_sdram.c —— 代码/常量从 SPI Flash 加载到 SDRAM 后执行,适合大工程(音频、AI 全功能)。
  • SFC 运行(XIP):cpu/wl82/sdk_ld_sfc.c —— 代码直接在 SPI Flash 上执行(execute-in-place),配合 media_text.ld 将媒体热点代码搬入 RAM,适合资源受限场景。

两个入口都通过 #include 复用 driver/cpu/wl82/ 下的链接片段:

#include "driver/cpu/wl82/media_text.ld"
...
#include "driver/cpu/wl82/system.ld"
...
#include "driver/cpu/wl82/system_data.ld"

Sources:

  • sdk_ld_sdram.c
  • sdk_ld_sfc.c

SDRAM 方案还会按 CONFIG_BT_ENABLE、CONFIG_DYNAMIC_SDRAM_ONOFF_ENABLE 等开关条件性地包含蓝牙与动态 SDRAM 电源管理相关段。链接脚本中同样导出版本符号供运行时查询:

lib_wl82_rf_version

Source: sdk_ld_sdram.c

lib_wl82_rf_version 与 lib_wifi_version、lib_httpcli_version 并列,说明射频固件版本是平台运行时可观测信息,常用于产测与版本比对。

内存段划分:

段链接符号说明
代码+常量text_size从 Flash/SFC 装载
SDRAMSDRAM_SIZE主运行内存,放 data/bss/heap
内部 RAM0RAM0_SIZE低延迟关键数据
Cache RAMCACHE_RAM_SIZE媒体/缓存热点数据
堆HEAP_BEGIN/HEAP_END动态内存

这种"多级内存 + 条件链接"的布局是 AC79 系列 SoC 资源管理的核心:内部 RAM 有限,热点代码与数据必须显式分配到 CACHE_RAM/RAM0,其余落入 SDRAM。

芯片寄存器映射(WL82.h)

include_lib/driver/cpu/wl82/asm/WL82.h 是 wl82 平台访问芯片寄存器的统一入口。它把 AC791N 的 SFR 空间按总线域划分:

#define psfr_base          0x50000                // port
#define hsfr_base          0x40000                // hsb
#define bsfr_base          0x20000                // bt; wire less
#define lsfr_base          0x10000                // lsb
#define map_adr(grp, adr)  ((64 * grp + adr) * 4) // grp(0x0-0xff), adr(0x0-0x3f)

Source: WL82.h

  • hsb(0x40000):高速总线外设——SFC、DMA、加密引擎、显示等;
  • lsb(0x10000):低速总线外设——定时器、UART、IIC 等;
  • bt(0x20000):蓝牙/无线相关寄存器;
  • port(0x50000):IO 端口。

外设寄存器采用"结构体 + 宏"模式暴露。以 SPI Flash 控制器为例:

typedef struct {
    ___RW ___u32(CON);
    ___WO ___u32(BAUD);
    ___WO ___u32(CODE);
    ___WO ___u32(BASE_ADR);
} JL_SFC_TypeDef;

#define JL_SFC_BASE   (hsfr_base + map_adr(0x02, 0x00))
#define JL_SFC        ((JL_SFC_TypeDef *)JL_SFC_BASE)

Source: WL82.h

___RW/___RO/___WO 宏控制 volatile 属性,___u8/___u16/___u32 宏在字段间插入保留字节/半字,保证结构体字段与硬件寄存器地址严格对齐。setup_arch() 中打印的 sfc_clk = hsb_clk / (JL_SFC->BAUD + 1) 正是通过 JL_SFC 指针读取分频寄存器计算得出。

紧随 SFC 定义的是 SFC 加密引擎(硬件加速的一环):

typedef struct {
    ___RW ___u8(CON);
    ___RW ___u16(KEY);
    ___WO ___u32(UNENC_ADRH);
    ___WO ___u32(UNENC_ADRL);
    ___WO ___u32(LENC_ADRH);
    ___WO ___u32(LENC_ADRL);
} JL_SFCENC_TypeDef;
#define JL_SFCENC ((JL_SFCENC_TypeDef *)JL_SFCENC_BASE)

Source: WL82.h

UNENC_ADR(未加密区)与 LENC_ADR(加密区)各含高/低地址寄存器,允许 Flash 中一段区域明文、一段区域密文,这是量产固件"头部明文 + 主体加密"方案的寄存器基础。

硬件加速:FFT 与算法差异化

硬件 FFT 引擎(V4)

wl82 平台在音频/信号处理上最重要的硬件加速是 FFT 引擎。apps/common/audio_music/audio_config.c 按平台编译开关选择硬件 FFT 版本:

#ifdef CONFIG_CPU_WL82
const int JL_HW_FFT_V = 4;
#else
const int JL_HW_FFT_V = 3;
#endif

Source: audio_config.c

设计意图:JL_HW_FFT_V 是硬件 FFT 引擎的版本号,驱动/算法层据此选择对应的寄存器操作序列。WL82 的引擎版本为 4,高于其他平台的 3——说明 AC791N 的 FFT 硬件核有演进(可能支持更大点数或更快的蝶形运算),平台差异化通过这一个常量收敛,避免算法代码散落 #ifdef。

同时,同一文件还定义了软件 FFT 的开关(供非 WL82 平台或其他算法路径使用):

const int JLA_HW_FFT = 0; //置1使用硬件模块FFT, 置0使用软件模块FFT

Source: audio_config.c

vc_hw_fft():硬件 FFT 调用点

apps/common/jl_math/jl_fft.c 中,实数 FFT 最终通过 vc_hw_fft() 送入硬件引擎:

__attribute__((always_inline))
static int vc_hw_fft(int *coef_in, int blockbit, int *coef_out, int real, int same)
{
    ...
}

Source: jl_fft.c

调用形态(1024 点实数 FFT,支持原位运算):

vc_hw_fft(datain, 10, dataout, 1, datain == dataout ? 1 : 0);
memcpy(out, dataout, sizeof(int) * 1026);

Source: jl_fft.c

参数语义:

参数含义
coef_in输入系数缓冲(实数序列)
blockbit变换点数对数:10 → 1024 点,9 → 512 点
coef_out输出缓冲(N+2 个 int,容纳复数结果)
real1 表示实数变换
same1 表示原位运算(datain == dataout)

find_pow(fft_N) 动态计算点数对数,说明该封装支持任意 2 的幂点数,而 1024/512 是音频算法的常见规模。硬件 FFT 相比软件 FFT 的收益在于:蝶形运算由专用逻辑完成,CPU 仅在启动/收尾时参与,可显著降低 EQ、混响、频谱分析等模块的 CPU 占用。

平台差异化算法开关

除 FFT 外,CONFIG_CPU_WL82 还驱动其他算法差异化:

#ifdef CONFIG_CPU_WL82
const int howling_freshift_PLATFORM = 1;
#endif

Source: audio_config.c

howling_freshift_PLATFORM = 1 表明 WL82 平台启用新版啸叫抑制移频算法——这通常与芯片更强的运算能力或新的 DSP 指令相关,使算法团队可以在不改动应用代码的情况下按平台切换实现。

核心流程:从复位到应用就绪

sequenceDiagram
    participant ROM as ROM/启动代码
    participant Setup as setup_arch()<br/>(cpu/wl82/setup.c)
    participant CLK as 时钟/中断子系统
    participant DBG as 调试子系统
    participant SFC as SFC/Flash 控制器
    participant APP as 应用层

    ROM->>Setup: 跳转 C 入口
    Setup->>Setup: wdt_init(0xc) 开看门狗
    Setup->>CLK: clk_early_init() 配置 PLL/分频
    Setup->>CLK: interrupt_init() 建立中断
    Note over Setup,SFC: CONFIG_DISABLE_P3_FSPG_CON 时关闭 P3 电源域
    Setup->>DBG: debug_uart_init() + log_early_init(10KB)
    Setup->>Setup: system_reset_reason_get() 记录复位原因
    Setup->>SFC: 读取 JL_SFC->BAUD 计算 sfc_clk 并打印
    Setup->>Setup: 打印 CHIP_ID / 内存段大小 / HEAP_SIZE
    Setup->>Setup: code_movable_init() 搬移可搬移代码
    Setup->>Setup: __crc16_mutex_init() + p33_io_latch_init()
    Setup->>APP: 返回,进入应用初始化(含硬件 FFT 服务)
    APP->>SFC: 需加密时经 JL_SFCENC 配置明文/密文区

流程要点:

  1. 看门狗最先打开,保证"死也要死得明白"——任何后续卡死都会被复位并留下复位原因;
  2. 时钟 → 中断 → 调试串口的顺序保证后续日志与驱动可安全运行;
  3. 链接脚本符号(text_size、SDRAM_SIZE 等)在此处被读取打印,作为链接配置的自检输出;
  4. code_movable_init() 之后,应用层才可使用 movable 段优化;
  5. 硬件加速(FFT 引擎、CRC16、SFC 加密)均在初始化完成后由各子系统按需启用,其中 CRC16 通过互斥锁保护共享引擎。

使用示例

1. 平台启动自检输出(摘自 setup_arch())

工程编译并烧录后,串口日志会打印 wl82 平台的芯片与内存信息,这是排查链接配置、确认平台版本的第一现场:

printf("\n   WL82(AC791N) CHIP_ID: 0x%x  setup_arch %s %s", JL_INTEST->CHIP_ID, __DATE__, __TIME__);
printf("\nsys_clk = %d,sdram_clk = %d,hsb_clk = %d,lsb_clk = %d, sfc_clk = %d",
       clk_get("sys"), clk_get("sdram"), clk_get("hsb"), clk_get("timer"),
       clk_get("hsb") / (JL_SFC->BAUD + 1));

Source: setup.c

sfc_clk 通过读寄存器 JL_SFC->BAUD 计算,展示了"寄存器宏 + 时钟框架"的典型用法。

2. 平台差异化配置(硬件 FFT 版本)

新增 wl82 平台工程时,音频库会根据 CONFIG_CPU_WL82 自动选用正确的 FFT 硬件版本:

#ifdef CONFIG_CPU_WL82
const int JL_HW_FFT_V = 4;
#else
const int JL_HW_FFT_V = 3;
#endif

Source: audio_config.c

应用代码无需修改,只需保证编译时定义了 CONFIG_CPU_WL82(通常由 app_config.h 或工程文件按平台模板注入)。

3. 硬件 FFT 调用(1024 点实数变换)

音频算法(如频谱显示、EQ 分析)需要 FFT 时,直接走 jl_fft.c 封装,底层自动路由到硬件引擎:

vc_hw_fft(datain, 10, dataout, 1, datain == dataout ? 1 : 0);
memcpy(out, dataout, sizeof(int) * 1026);

Source: jl_fft.c

要点:blockbit=10 对应 1024 点;输出为 N+2 个 int(复数频谱布局);最后一个参数允许原位运算,节省缓冲区。

4. 寄存器访问(SFC 控制器)

驱动层通过 WL82.h 的宏访问外设寄存器,例如读取 SFC 分频配置:

#define JL_SFC_BASE   (hsfr_base + map_adr(0x02, 0x00))
#define JL_SFC        ((JL_SFC_TypeDef *)JL_SFC_BASE)
// 用法: u32 baud = JL_SFC->BAUD;  JL_SFC->CON = ...;

Source: WL82.h

配置选项

以下配置项通过编译宏/常量影响 wl82 平台行为:

配置项类型默认/取值说明
CONFIG_CPU_WL82编译宏平台工程定义标识当前编译目标为 WL82,驱动平台差异化代码分支
JL_HW_FFT_Vint 常量4(WL82)/ 3(其他)硬件 FFT 引擎版本,算法层据此选择寄存器序列
JLA_HW_FFTint 常量0(软件 FFT)置 1 启用硬件模块 FFT,置 0 使用软件 FFT
howling_freshift_PLATFORMint 常量1(WL82)是否启用新版啸叫抑制移频算法
CONFIG_DEBUG_ENABLE编译宏视工程使能调试串口初始化与调试子系统
__LOG_ENABLE编译宏视工程使能日志系统,log_early_init(10*1024) 分配 10KB 早期缓冲
CONFIG_DISABLE_P3_FSPG_CON编译宏未定义定义后通过 p33_tx_1byte(P3_FSPG_CON, 0) 关闭 P3 域 Flash 电源门控
CONFIG_BT_ENABLE编译宏视工程链接脚本条件包含蓝牙相关段
CONFIG_DYNAMIC_SDRAM_ONOFF_ENABLE编译宏视工程使能 SDRAM 动态开关(省电),影响 system_data.ld 的包含

API 参考

void setup_arch(void)

wl82 平台早期初始化入口,由启动汇编/引导代码调用一次。完成看门狗、时钟、中断、调试串口、复位原因、movable 代码、CRC16 互斥锁与 IO 锁存初始化。

参数: 无

返回: 无

注意: 本函数在堆/标准库完全就绪前执行,应只使用早期可用服务(puts/printf、clk_get 等)。

static int vc_hw_fft(int *coef_in, int blockbit, int *coef_out, int real, int same)

调用 wl82 硬件 FFT 引擎执行变换(jl_fft.c 内部使用,always_inline)。

参数:

  • coef_in (int*):输入系数缓冲
  • blockbit (int):变换点数对数,10=1024 点、9=512 点
  • coef_out (int*):输出缓冲,实数变换需 N+2 个 int
  • real (int):1 表示实数变换
  • same (int):1 表示原位运算(输入输出同一缓冲)

返回: int(状态码,0 表示成功)

链接脚本导出符号

符号类型说明
SDRAM_SIZE / RAM0_SIZE / CACHE_RAM_SIZEu32各内存段总大小
text_size / data_size / bss_sizeu32代码/数据/BSS 段大小
HEAP_BEGIN / HEAP_ENDu32堆边界,差值即堆大小
lib_wl82_rf_version符号WL82 射频库版本标识

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

启动阶段失败模式

场景表现防护/排查
看门狗超时导致复位循环串口反复打印启动横幅先看 system_reset_reason_get() 记录的复位原因;确认 clk_early_init() 后各外设时钟是否满足要求
时钟配置错误setup_arch() 打印的 sys_clk/sdram_clk 异常,外设访问挂死核对 JL_SFC->BAUD 分频与 Flash 规格;SFC 时钟过高会导致 Flash 读失败
链接布局溢出启动打印 REMAIN_SIZE 为负数或堆过小根据 SDRAMA_SIZE/DATA/BSS/HEAP 打印调整 media_text.ld/system.ld 分段
早期日志缓冲不足启动早期日志丢失log_early_init(10 * 1024) 缓冲仅 10KB,大段打印请延后到完整日志系统就绪

边界情况

  • 原位 FFT:vc_hw_fft(datain, ..., datain == dataout ? 1 : 0) 明确支持原位运算,但 coef_out 必须预留 N+2 个 int;若调用方只分配 N 个,硬件写越界会破坏相邻内存——这是音频算法中常见的隐蔽 bug 来源。
  • 非 2 的幂点数:find_pow(fft_N) 动态换算 blockbit,说明封装只支持 2 的幂;传入非 2 的幂会得到错误的 blockbit。
  • SDRAM 动态开关:CONFIG_DYNAMIC_SDRAM_ONOFF_ENABLE 下 system_data.ld 的条件包含,意味着 SDRAM 休眠期间访问其中数据会导致总线错误,驱动必须遵循电源管理框架的"开关窗口"。

并发与一致性

  • CRC16 硬件加速器共享:setup_arch() 末尾调用 __crc16_mutex_init(),说明 CRC16 引擎是全局共享资源,多任务(如网络协议栈与文件系统同时计算校验)必须经互斥锁串行化,否则寄存器上下文互相覆盖。
  • FFT 引擎独占性:vc_hw_fft 使用硬件蝶形单元,若音频任务与频谱分析任务并发调用,需要上层保证互斥(SDK 音频框架通常以单音频线程串行化处理)。
  • P33 电源域:p33_tx_1byte(P3_FSPG_CON, 0) 通过 P33 串行接口写电源控制寄存器,该接口本身是低速串行总线,低功耗唤醒路径上对它的访问需避免与休眠流程竞争。

性能与运行注意事项

  • 硬件 FFT 收益:WL82 的 FFT 引擎(V4)将蝶形运算卸载到专用逻辑,1024 点实数变换仅需 CPU 搬运数据,频谱分析类应用应优先走 jl_fft.c 硬件路径而非软件 FFT(JLA_HW_FFT = 0 仅作为无硬件或调试时的回退)。
  • 多级内存分配原则:热点代码进 media_text.ld/CACHE_RAM,冷代码走 movable 段搬移到外部存储;code_movable_init() 必须在任何 movable 代码执行前调用。
  • XIP 与 SDRAM 形态选择:sdk_ld_sfc.c(XIP)省去搬运时间但 Flash 读延迟高;sdk_ld_sdram.c 一次性搬入 SDRAM,运行更快但占用 SDRAM 且启动稍慢。音频/AI 全功能工程默认选 SDRAM 形态。
  • SFC 加密开销:JL_SFCENC 的明文/密文分区使 Flash 读路径经过解密引擎,会带来额外延迟;仅对需要防抄板的段启用加密,头部保留明文便于引导。

扩展点

  1. 平台差异化常量:在 apps/common/audio_music/audio_config.c 的 #ifdef CONFIG_CPU_WL82 分支中添加新的平台能力常量(如算法版本、硬件特性标志),应用层统一读取,避免 #ifdef 蔓延。
  2. 链接脚本片段:在 driver/cpu/wl82/*.ld 中新增段定义(如自定义加速数据段),sdk_ld_sdram.c/sdk_ld_sfc.c 即可按条件包含;新增符号(如 lib_wl82_xxx_version)可仿照 lib_wl82_rf_version 导出供运行时查询。
  3. 寄存器宏模式:新增外设时在 WL82.h 中按 JL_xxx_TypeDef + JL_xxx_BASE/JL_xxx 模式声明,保持与现有 SFC/SFCENC 一致的访问风格。
  4. 硬件加速封装:仿照 vc_hw_fft 的 static int xxx(int *in, int cfg, ...) + always_inline 形态封装其他硬件引擎(如加解密、音频编解码加速),上层算法通过薄封装调用,方便在无硬件平台回落软件实现。
  5. 预编译库替换:cpu/wl82/liba/ 下的 cpu.a、audio_server.a 等为闭源库,但工程可用同名库替换(如换用 AI 语音库 aisIntlib_dual_xiaoai.a)来切换功能形态,接口保持不变。

测试与验证

  • 启动自检:setup_arch() 的内存/时钟打印是每次上电的"冒烟测试",脚本可解析 CHIP_ID、REMAIN_SIZE、HEAP_SIZE 断言链接配置符合预期。
  • FFT 正确性:jl_fft.c 同时维护软件与硬件两条路径(JLA_HW_FFT 开关),可通过对比两条路径输出验证硬件引擎,或在产测中注入已知频谱信号校验 vc_hw_fft 结果。
  • 文档化评估:仓库 doc/stuff/ 提供 WL82_WiFi吞吐率高低温测试.docx 与 WL82_WiFi场景功耗评估.docx,是平台级吞吐率与功耗验收的参考基线。
  • 加载工具:cpu/wl82/tools/ 下的 wl82loader.bin 用于产线/调试加载,配合 lib_wl82_rf_version 可核对射频固件版本。

Related Links

  • 平台启动实现 cpu/wl82/setup.c
  • SDRAM 链接脚本 cpu/wl82/sdk_ld_sdram.c
  • SFC 链接脚本 cpu/wl82/sdk_ld_sfc.c
  • 芯片寄存器定义 WL82.h
  • 平台差异化配置 audio_config.c
  • 硬件 FFT 封装 jl_fft.c
  • 平台级评估文档:WL82 WiFi 吞吐率高低温测试、WL82 WiFi 场景功耗评估
Next
外设驱动框架