XVF3800 默认核资源使用分析(上): 16 个逻辑核,一个都没闲着

2026-10-26 14:48:50 吴昊 2

给 XVF3800 加功能(UART、自定义协议、常驻算法)之前,必须先回答一个问题:芯片还有没有核可用?本文对 v3.2.1 默认源码(main_tile0.c / main_tile1.c 的 PAR_JOBS 结构)与官方预编译的 23 个 .xe 固件逐一做 xobjdump 实测,把 16 个逻辑核、每 tile 512 KB SRAM 的账算清楚。

一句话结论:两个 tile 的 8 个逻辑核全部占满(8/8),默认固件里没有任何空闲核;UA 构建下 tile[1] 的 SRAM 只剩约 4.2 KB。要加常驻逻辑,只能复用 reserved_core 预留核,或挤占现有核的帧内空闲时间——不能「再开一个核」。


一、结论总览

项目tile[0]tile[1]
静态核需求8 / 8,占满8 / 8,占满
主要占用SHF 后处理 3 核 + 麦克风 1 核 + USB 2 核 + FreeRTOS 2 核SHF 回声消除 4 核 + 音频路由 1 核 + I2S 1 核 + 预留核 1 核 + FreeRTOS 1 核
UA 构建剩余 SRAM约 9.8 KB约 4.2 KB(非常紧张)
INT 构建剩余 SRAM约 33.5 KB约 32.4 KB

工程含义:默认固件没有任何空闲逻辑核。若要在 XVF3800 上追加功能,只能复用 reserved_core 预留核,或挤占现有核的帧内空闲时间,而不能「再开一个核」。

另一个重要发现:.xe 内每个 tile 有两个 Loadable(引导桩 + 主应用)。xobjdump --resources 汇总中 tile[0] 那几行描述的是主应用(可信);tile[1] 那 5 行(program 6104 / thread 1 …)描述的是引导桩而非主应用——它在每个固件里完全相同,所以 23 个固件数值恒定。用 xobjdump -t --resources 看分段符号表即可证实。


二、分析方法:三个 xobjdump 用法

命令作用本文档中的用途
xobjdump -t app.xe打印 ELF 符号表读每个函数的 .maxcores / .nstackwords / .maxtimers / .maxchanends,即编译器静态推导的「这个函数启动时要几个核、多少栈」
xobjdump --resources app.xe打印资源汇总报告每 tile 的栈、程序大小、剩余内存、线程数、定时器、通道端、端口
xobjdump --size app.xe打印各 loadable 段大小text/data/bss 精确字节数,用于内存推算

原理:XC 编译器对每个包含 par / PJOB 的函数都会生成 4 个绝对符号(如 main_tile0.maxcores),数值等于该函数及其子作业对资源的静态需求总和。因此「哪个任务占几个核」不必靠猜,直接读符号即可;--resources 的汇总报告也是由这些信息聚合而来。

# 资源汇总(每 tile 的栈/程序/内存/线程/定时器/通道端/端口)
xobjdump --resources application_xvf3800_ua-io48-lin.xe

# 符号表(保存到文件后检索 *.maxcores / *.nstackwords)
xobjdump -t application_xvf3800_ua-io48-lin.xe > syms.txt

# 各 loadable 的 text/data/bss 字节数
xobjdump --size application_xvf3800_ua-io48-lin.xe

三、核资源模型:16 个逻辑核怎么分

XVF3800 采用 XMOS XU316 芯片:1 个节点(node)、2 个 tile,每个 tile 8 个逻辑核(logical core / 硬件线程),合计 16 个逻辑核;每个 tile 独立 512 KB SRAM(芯片合计 1 MB)。固件把这 16 个核分成两个「世界」:

裸金属世界(Bare metal):PJOB 直接在 RTOS 之外启动的作业,独占核、不被调度打断,负责音频实时通路(麦克风、AEC、后处理、I2S、USB 底层)。

FreeRTOS 世界:由 vTaskStartScheduler() 启动的 SMP 调度器,占用固定数量的核,所有 Servicer / 控制任务在这些核上轮转。

优先级方面,XMOS 没有抢占式优先级。所谓「高优先级(HP)」是通过 SETSR(XS1_SR_QUEUE_MASK) 把线程放入队列调度组(H 组)实现的——同一组的核每 5 个处理器周期轮流获得指令发射槽,多个核协同跑同一段 DSP,帧内耗时确定可预测。其余核为普通优先级(NP),平时 waiteu 等待事件唤醒。

图片关键词

[图 1 两个 tile 的核面分工:tile[0] 控制・USB・后处理 8/8,tile[1] 音频算法・I2S 8/8]

需要注意:逻辑核编号由运行时按 PJOB 启动顺序分配,图中「核槽位 0—7」只表示数量与归属,不代表固定物理编号;调试时可通过 get_logical_core_id() 打印实际编号。


四、源码层的核分配

两个 tile 的入口分别是 main_tile0() 与 main_tile1(),二者都在函数尾部用一个 PAR_JOBS(...) 一次性并行启动所有裸金属作业(每个 PJOB(func, args) 占用一个或多个逻辑核),其中最后一个 PJOB 固定为 tile_common_start_rtos_app(),负责初始化平台驱动并启动 FreeRTOS 调度器。

4.1 tile[0]:控制 / USB / 后处理面

PAR_JOBS(
    PJOB(INTERRUPT_PERMITTED(pp_task), (...)),      // 3 核
    PJOB(mic_array_task, (c_mic_to_audio)),         // 1 核
    PJOB(usb_buffer, (&usb_task_args)),             // 1 核(UA)
    PJOB(wrap_XUD_Main, (...)),                     // 1 核(UA)
    PJOB(tile_common_start_rtos_app, (...))         // 2 核
);
作业(PJOB)maxcoresnstackwords优先级职责
pp_task30x506 = 5144 BH 组SHF 后处理:波束成形、噪声抑制、DOA 输出;该核同时挂接 USB EP0 SETUP 包中断回调
mic_array_task10x5A = 360 B普通4 路 PDM 麦克风采集中与抽取
usb_buffer10x3DC = 3952 B普通USB 音频端点软件缓冲、PLL 锁定检测
wrap_XUD_Main → XUD_Main10xB8 = 736 B普通lib_xud USB 设备栈底层收发
tile_common_start_rtos_app20x220 = 2176 B普通启动 FreeRTOS SMP(UA 构建 configNUM_CORES = 2),GPO/PP/USB Buffer Server、ep_proxy 等任务都在这 2 个核上

合计 = 3 + 1 + 1 + 1 + 2 = 8 核。

4.2 tile[1]:音频算法 / I2S 数据面

PAR_JOBS(
    PJOB(aec_task, (...)),                          // 4 核
    PJOB(audio_manager_task, (...)),                // 1 核
    PJOB(i2s_task, (...)),                          // 1 核
    PJOB(reserved_core, ()),                        // 1 核
    PJOB(tile_common_start_rtos_app, (...))         // 1 核
);
作业(PJOB)maxcoresnstackwords优先级职责
aec_task40x424 = 4240 BH 组SHF 回声消除(SHF_Init_AEC_split_post,4 核协同)
audio_manager_task10x20B = 2092 B普通帧调度、声道混音;post_shf_dsp() 用户钩子在此执行
i2s_task10xFA = 1000 B普通I2S 主/从收发;far_end_dsp() 用户钩子在其回调中执行
reserved_core10x6 = 24 B普通预留核:原为空转占位任务,是官方留给客户的核位
tile_common_start_rtos_app10x118 = 1120 B普通启动 FreeRTOS(configNUM_CORES = 1),全部 Servicer、usb_manager、HID 都在这 1 个核上轮转

合计 = 4 + 1 + 1 + 1 + 1 = 8 核。

图片关键词

[图 2 两个 tile 的 PJOB 树与 maxcores 推导:子作业核数相加恰好等于 8]

4.3 官方注释与实际代码的差异

app_conf.h 中的官方注释把 tile[1] 描述为「4 HP AEC + 1 NP i2s/audio + 1 NP 客户 DSP + 1 备用 + 1 NP RTOS」。但实际代码里:

  • i2s_task 与 audio_manager_task 是两个独立 PJOB(各占 1 核);

  • 「客户 DSP」位即 reserved_core;

  • 因此所谓「1 备用」在当前 8 核里并不存在——main_tile1.maxcores = 8 是静态可证的事实。

这份注释反映的是早期版本的设计意图,评估资源时请以符号表实测为准。

中篇预告:xobjdump 实测——--resources 汇总逐项解读、-t 符号表证据、tile[1] 那 5 行数字为什么是引导桩而非主应用、每 tile 512 KB 内存的推算方法。


下篇预告:UA 与 INT 构建的核心差异、数据流与核归属、工程建议、复现命令清单与常见误读澄清。

首页
产品
新闻
联系