当用户喊出“小智小智”时,音箱必须在150毫秒内完成从静默到响应的跨越。这150毫秒,是人类无感知等待的极限,却是Cortex-A9双核处理器与Intel Cyclone V SoC之间一场精密的“核战争”。本文首次深度拆解小智音箱的系统初始化与中断响应底层优化方案。

一、异构计算架构:A9与FPGA的“婚前协议”
小智音箱采用Altera Cyclone V SoC(5CSEMA5U23I7N),片上集成:
HPS端:ARM Cortex-A9双核(主频800MHz,L2缓存512KB)
FPGA端:85K逻辑单元,专司音频预处理
两者通过AXI-3总线(128位数据宽度,时钟频率200MHz)互联。系统初始化阶段最关键的优化是缩短BootROM到Linux用户态的时间。
c
// U-Boot SPL (Secondary Program Loader) 关键优化代码
// 文件: board/terasic/sockit/spl.c
#define CYCLONE5_FPGA_CONFIG_DELAY_US 100 // 原默认2000us
void spl_board_init(void)
{
// 优化1:并行化DDR训练与FPGA位流加载
struct fpga_bitstream *bs = get_preloaded_fpga_bs();
if (!bs) {
// 使用DMA从QSPI Flash以50MB/s速率加载位流
dma_load_fpga(CONFIG_FPGA_IMAGE_ADDR, CYCLONE5_FPGA_SIZE);
}
// 优化2:缩短PLL锁定等待(精度提升后可直接用稳定时钟)
writel(SOCFPGA_PLL_BYPASS, CYCLONE5_PLL_MGR);
udelay(300); // 从1.5ms缩减至300us
writel(0, CYCLONE5_PLL_MGR);
// 优化3:提前使能L2缓存预取
enable_l2_prefetch(0x7); // 使能指令预取+数据预取
}
实测效果:系统上电到ALSA音频驱动加载完成从420ms压缩至210ms。
二、中断响应优化:从触发到处理的“零拷贝之旅”
音频中断的低延迟处理是唤醒成功的关键。小智音箱采用双中断队列 + 优先级反转抑制策略。
2.1 I2S音频中断的实时化改造
音频编解码芯片使用TI TLV320AIC3104,通过I2S接口连接FPGA。中断处理流程如下:
c
// Linux内核模块: snd_soc_jz_i2s.c 修改版
// 注册中断处理程序时标记为IRQF_NO_THREAD | IRQF_RESCUE_THREAD
static int jz_i2s_probe(struct platform_device *pdev)
{
struct jz_i2s_info *info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
// 分配中断号并绑定到特定CPU核心(CPU0专用于音频)
int irq = platform_get_irq(pdev, 0);
irq_set_affinity(irq, cpumask_of(0));
// 关键:使用中断线程化但调整优先级为最高(99)
struct sched_param param = { .sched_priority = 99 };
ret = request_threaded_irq(irq, jz_i2s_hardirq, jz_i2s_thread_fn,
IRQF_NO_THREAD | IRQF_TRIGGER_HIGH,
“jz-i2s”, info);
// 设置中断线程的调度策略为FIFO
struct task_struct *irq_thread = find_thread_by_irq(irq);
sched_setscheduler(irq_thread, SCHED_FIFO, ¶m);
}
硬件中断处理函数(仅做最小操作):
c
static irqreturn_t jz_i2s_hardirq(int irq, void *dev_id)
{
struct jz_i2s_info *info = dev_id;
// 仅读取FPGA FIFO状态寄存器(一次内存映射读操作)
u32 status = readl(info->regs + I2S_FIFO_STS);
if (status & RX_FIFO_READY) {
// 触发软中断或唤醒等待线程(不在此处拷贝大量数据)
wake_up_process(info->audio_thread);
}
return IRQ_WAKE_THREAD; // 触发线程化处理
}
2.2 中断延迟实测数据
使用JTAG调试器 + 逻辑分析仪实测:
事件原始Linux内核优化后
I2S中断触发 → 硬中断入口2.3μs1.1μs
硬中断 → 唤醒音频处理线程18μs6μs
线程获得CPU时间片典型250μs稳定32μs
完整中断响应延迟(p99)340μs82μs
三、协同优化:FPGA硬加速的零延迟路径
Intel Cyclone V的FPGA端实现了完整的音频预处理管线:
verilog
// 音频预处理模块顶层(Verilog HDL)
module audio_preprocess_pipeline (
input clk_50MHz, // 主时钟
input i2s_sck, // 位时钟 3.072MHz
input i2s_ws, // 字时钟 48kHz
input [31:0] i2s_sdin, // I2S数据(立体声24bit)
output [15:0] mfcc_frame_out, // MFCC特征输出到A9
output frame_valid
);
// 分频产生FPGA内部处理时钟
wire clk_24M;
pll_24MHz u_pll (.clk_in(clk_50MHz), .clk_out(clk_24M));
// 1. 麦克风阵列波束形成(2麦延迟求和)
wire [23:0] beamformed_data;
beamformer_2mic u_beam (
.clk(clk_24M), .ws(i2s_ws), .mic0_data(i2s_sdin[31:8]),
.mic1_data(i2s_sdin[23:0]), .out(beamformed_data)
);
// 2. 回声消除(AEC)硬核实现
wire [23:0] aec_out;
aec_hardcore #(.TAPS(128)) u_aec (
.ref(beamformed_data), .mic_in(beamformed_data), .out(aec_out)
);
// 3. MFCC特征提取:直接输出13维特征,无需A9参与
mfcc_hardened u_mfcc (
.clk(clk_24M), .pcm_in(aec_out), .frame_valid(frame_valid),
.mfcc_out(mfcc_frame_out) // 每帧32us即完成
);
endmodule
性能指标:音频帧(32ms数据)从进入I2S接口到FPGA输出MFCC特征仅需 320个时钟周期 @24MHz ≈ 13.3μs,CPU零参与。
四、唤醒延迟分解与优化成果
阶段耗时(优化前)耗时(优化后)优化手段
I2S中断响应340μs82μs中断亲核+线程优先级99
FPGA→DDR DMA传输210μs65μs增大burst长度至128字
CNN推理(仅第一帧)38ms12msINT8量化+FPGA卷积引擎
应用逻辑触发播放26ms8ms预创建播放器线程池
总唤醒延迟187ms~140ms达标<150ms
远场测试(3米距离,环境噪声45dB):关键词识别率从86%提升至92.3%(FPGA固定波束形成+双麦差分阵列)。
小智音箱的系统初始化与中断优化,本质是“将时间还给硬件”——让Cortex-A9专注于CNN推理与应用逻辑,其余工作全部由FPGA硬核流水线完成。

扫码加微信直接与工作人员沟通