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 的软件栈由以下层次构成:
- 平台启动层:
cpu/wl82/setup.c的setup_arch()完成看门狗、时钟、中断、调试串口、复位原因、CRC 互斥锁与 IO 锁存等早期初始化,并打印芯片 ID 与各内存段大小。 - 链接/内存层:
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等版本符号。 - 寄存器抽象层:
WL82.h按高速(hsb)、低速(lsb)、蓝牙/无线(bt)与端口(port)四类总线定义 SFR 基地址,并以JL_xxx_TypeDef结构体 +JL_xxx宏的方式暴露外设(如JL_SFC串行 Flash 控制器、JL_SFCENC加密引擎)。 - 硬件加速层:针对
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)。 - 库与工具层:
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:
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 装载 |
| SDRAM | SDRAM_SIZE | 主运行内存,放 data/bss/heap |
| 内部 RAM0 | RAM0_SIZE | 低延迟关键数据 |
| Cache RAM | CACHE_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,容纳复数结果) |
real | 1 表示实数变换 |
same | 1 表示原位运算(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 配置明文/密文区
流程要点:
- 看门狗最先打开,保证"死也要死得明白"——任何后续卡死都会被复位并留下复位原因;
- 时钟 → 中断 → 调试串口的顺序保证后续日志与驱动可安全运行;
- 链接脚本符号(
text_size、SDRAM_SIZE等)在此处被读取打印,作为链接配置的自检输出; code_movable_init()之后,应用层才可使用 movable 段优化;- 硬件加速(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_V | int 常量 | 4(WL82)/ 3(其他) | 硬件 FFT 引擎版本,算法层据此选择寄存器序列 |
JLA_HW_FFT | int 常量 | 0(软件 FFT) | 置 1 启用硬件模块 FFT,置 0 使用软件 FFT |
howling_freshift_PLATFORM | int 常量 | 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个 intreal(int):1 表示实数变换same(int):1 表示原位运算(输入输出同一缓冲)
返回: int(状态码,0 表示成功)
链接脚本导出符号
| 符号 | 类型 | 说明 |
|---|---|---|
SDRAM_SIZE / RAM0_SIZE / CACHE_RAM_SIZE | u32 | 各内存段总大小 |
text_size / data_size / bss_size | u32 | 代码/数据/BSS 段大小 |
HEAP_BEGIN / HEAP_END | u32 | 堆边界,差值即堆大小 |
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 读路径经过解密引擎,会带来额外延迟;仅对需要防抄板的段启用加密,头部保留明文便于引导。
扩展点
- 平台差异化常量:在
apps/common/audio_music/audio_config.c的#ifdef CONFIG_CPU_WL82分支中添加新的平台能力常量(如算法版本、硬件特性标志),应用层统一读取,避免#ifdef蔓延。 - 链接脚本片段:在
driver/cpu/wl82/*.ld中新增段定义(如自定义加速数据段),sdk_ld_sdram.c/sdk_ld_sfc.c即可按条件包含;新增符号(如lib_wl82_xxx_version)可仿照lib_wl82_rf_version导出供运行时查询。 - 寄存器宏模式:新增外设时在
WL82.h中按JL_xxx_TypeDef+JL_xxx_BASE/JL_xxx模式声明,保持与现有 SFC/SFCENC 一致的访问风格。 - 硬件加速封装:仿照
vc_hw_fft的static int xxx(int *in, int cfg, ...)+always_inline形态封装其他硬件引擎(如加解密、音频编解码加速),上层算法通过薄封装调用,方便在无硬件平台回落软件实现。 - 预编译库替换:
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可核对射频固件版本。