ACPU 使用指南
1. ACPU 概述
SF32LB57x 与 SF32LB58x 系列采用三核架构:HCPU(高性能计算)、ACPU 以及 LCPU(低功耗任务,如 BLE 和传感器数据处理)。完整的架构说明请参考 HAL 索引。
ACPU 在不同芯片系列中的角色不同:
芯片系列 |
ACPU 角色 |
|---|---|
SF32LB57x |
音频和图形处理 |
SF32LB58x |
Audio DSP 处理 |
ACPU 运行独立的固件镜像(基于 RT-Thread),作为 HCPU 工程的子工程构建,启动时由二级 boot 加载到 ACPU RAM 中。HCPU 与 ACPU 之间通过基于 Mailbox 的核间 IPC Queue 通信。
1.1 典型应用场景
音频编解码卸载:opus 编解码器运行在 ACPU 上,例如
example/multimedia/audio/opus。语音 3A 处理:ACPU 任务
ACPU_TASK_audio_3a_open/uplink/downlink/close完成 3A 处理。图形渲染:EPIC 渲染列表在 ACPU 上执行(
ACPU_TASK_epic_rl),例如example/rt_device/gpu/render_list_mode。自定义计算任务:用户自定义任务由
acpu_main()分发执行,例如example/multicore/acpu_task。
1.2 HCPU 与 ACPU 的交互方式
HCPU 通过
acpu_run_task()发起任务,该调用为阻塞式,ACPU 完成任务后返回。ACPU 在
acpu_main()中接收任务并执行,通过acpu_send_result()回传结果。底层传输为 IPC Queue(双向队列
sys_get_ha_ipc_queue/sys_get_ah_ipc_queue),配合信号量同步。
API 细节见 第 4 章。
2. 使能与配置
支持 ACPU 的工程由两部分组成:HCPU 工程和 ACPU 子工程(见 第 3 章)。两个工程各有独立的配置,均通过 menuconfig 修改。
2.1 在 HCPU 工程中使能 ACPU
在 project/hcpu 目录下,使用板名启动 menuconfig:
sdk.py menuconfig --board=ec-lb587
在 menuconfig 界面中:
打开 SiFli Built-in Components → ACPU Control Framework(
USING_ACPU_CTRL_FWK)。该选项会自动选中 On-chip Peripherals → ACPU(BSP_USING_ACPU)和 IPC Queue(USING_IPC_QUEUE)。(可选)在 SiFli Built-in Components → ACPU Control Framework 下打开 Enable Caller(
ACPU_CALLER_ENABLED,HCPU 侧默认开启),允许 ACPU 代码调用 HCPU 服务(内存分配、控制台输出)。
按 D 键将最小配置保存到 proj.conf。
说明:
BSP_USING_ACPU仅在 SF32LB57x 和 SF32LB58x 芯片上可用(customer/boards/Kconfig_drv)。--board不带核后缀时默认按 HCPU 配置:ec-lb587与ec-lb587_hcpu等价。
2.2 配置 ACPU 工程
ACPU 子工程有独立的配置。在 project/acpu 目录下,使用带 _acpu 后缀的板名启动 menuconfig(使 menuconfig 使用 ACPU 核的板级配置):
sdk.py menuconfig --board=ec-lb587_acpu
打开 SiFli Built-in Components → ACPU Control Framework(USING_ACPU_CTRL_FWK,IPC Queue 会自动选中)。
2.3 功能相关选项
功能 |
HCPU 工程( |
ACPU 工程( |
|---|---|---|
EPIC 双核渲染列表模式 |
On-chip Peripherals → EPIC → Using epic render list API → EPIC Render List API Mode,选择 Using epic render list API in dual core HCPU mode( |
相同路径,选择 Using epic render list API in dual core ACPU mode( |
ACPU 上的 opus 编解码 |
– |
Third-Party Components → libopus( |
ACPU 调用 HCPU 服务(内存分配、控制台输出) |
见 2.1 第 2 步 |
– |
EPIC 双核选项会自动选择 USING_ACPU_CTRL_FWK(customer/boards/Kconfig_drv)。EPIC Render List API Mode 的选择项依赖核,因此 HCPU 与 ACPU 两侧需分别在各自工程的 menuconfig 会话(带 _hcpu / _acpu 后缀)中选择对应的双核模式。完整的 EPIC 使能 ACPU 工程配置可参考 example/acpu/project/proj.conf。
3. 工程创建、编译与烧录
ACPU 运行独立的固件镜像。在 SDK 中,ACPU 工程作为 HCPU 工程的子工程管理,并与 HCPU 工程一起编译。
3.1 工程结构
以 example/multicore/acpu_task 为例:
example/multicore/acpu_task/
├── project/hcpu/ # HCPU 工程
├── project/acpu/ # ACPU 子工程
├── src/acpu/ # ACPU 应用代码
└── src/hcpu/ # HCPU 应用代码
3.2 添加 ACPU 子工程
在 HCPU 工程的 SConstruct.py 中调用 AddChildProj,并指定 core="ACPU" 添加 ACPU 子工程(example/multicore/acpu_task/project/hcpu/SConstruct.py):
acpu_proj_path = os.path.join(proj_path, '../acpu')
acpu_proj_name = 'acpu'
AddChildProj(acpu_proj_name, acpu_proj_path, False, core="ACPU")
3.3 编译与烧录
在 project/hcpu 目录下,使用板名编译(仅基于 SF32LB57x/SF32LB58x 的开发板支持 ACPU,例如 ec-lb583、ec-lb587):
scons --board=ec-lb587
编译产物生成在 build_ec-lb587 目录下,使用以下命令烧录镜像:
build_ec-lb587/download.bat
板名带 _hcpu 后缀时可以省略,因为默认编译 HCPU 核(例如 ec-lb587 与 ec-lb587_hcpu 均使用 HCPU 配置)。
3.4 ACPU 镜像加载
ACPU 镜像存放在 Flash 中,启动时由二级 boot 加载到 ACPU RAM:
Flash 表中将 ACPU 镜像映射到
DFU_FLASH_HCPU_EXT2分区。例如,生成的ftab.c将镜像放在 Flash 地址0x69100000,并设置xip_base = 0x20200000,对应 ACPU 指令空间的 0 地址:
RT_USED const struct sec_configuration sec_config =
{
.magic = SEC_CONFIG_MAGIC,
.ftab[DFU_FLASH_HCPU_EXT2] = {.base = 0x69100000, .size = 0x0007C000, .xip_base = 0x20200000, .flags = 0},
.imgs[DFU_FLASH_IMG_IDX(DFU_FLASH_HCPU_EXT2)] = {.length = 0x00000AE4, .blksize = 512, .flags = DFU_FLAG_AUTO},
};
启动时,二级 boot 将 ACPU 镜像从 Flash 拷贝到 ACPU RAM(
example/boot_loader/project/sf32lb58x_v2/board/main.c中的boot_images函数):
/* load extended img if present, such as ACPU img */
if (g_sec_config->imgs[DFU_FLASH_IMG_IDX(DFU_FLASH_HCPU_EXT2)].length != FLASH_UNINIT_32)
{
dfu_boot_img_in_flash(DFU_FLASH_HCPU_EXT2);
}
example/acpu是供其他工程引用的通用 ACPU 工程模板,修改它会影响到所有引用该模板的工程。
4. 通信与 API 使用
完整 API 定义在 middleware/include/acpu_ctrl.h(Doxygen 参考:acpu_ctrl API)。两个核之间的传输基于 Mailbox 之上的 IPC Queue(见 IPC Queue 和 Mailbox)。
4.1 HCPU 侧 API
函数 |
说明 |
|---|---|
|
初始化框架:创建 HCPU→ACPU 的 IPC Queue 并给 ACPU 上电。通过 |
|
向 ACPU 发送任务并阻塞等待任务完成。返回 ACPU 的结果缓冲指针,并将错误码写入 |
|
控制 ACPU 电源域。上电通常由 |
acpu_run_task() 通过阻塞信号量实现:调用线程挂起,直到 ACPU 返回响应;若等待 1 秒超时,SDK 会触发断言(见 middleware/acpu_ctrl/acpu_ctrl.c)。
4.2 ACPU 侧 API
函数 |
说明 |
|---|---|
|
ACPU 入口函数。默认弱实现会分发预定义任务(opus、音频 3A、read/write、EPIC 渲染列表)。自定义任务时覆盖该函数(见 第 5 章)。 |
|
将任务结果回传给 HCPU,使 HCPU 挂起的 |
|
将字符串转发到 HCPU 控制台(需要 HCPU 侧开启 |
|
在 ACPU 代码中向 HCPU 申请/释放内存(需要 HCPU 侧开启 |
|
向 HCPU 发送断言通知。 |
4.3 任务 ID
任务 ID 定义在 middleware/include/acpu_ctrl.h:
宏 |
值 |
说明 |
|---|---|---|
|
0 |
无效任务 |
|
1 |
用户自定义任务 0 |
|
2 |
用户自定义任务 1 |
|
3 |
opus 编码器初始化 |
|
4 |
opus 编码器控制 |
|
5 |
opus 编码 |
|
6 |
opus 解码器初始化 |
|
7 |
opus 解码器控制 |
|
8 |
opus 解码 |
|
9 |
音频 3A 打开 |
|
10 |
音频 3A 关闭 |
|
11 |
音频 3A 下行 |
|
12 |
音频 3A 上行 |
|
13 |
读 |
|
14 |
写 |
|
15 |
EPIC 渲染列表 |
|
16 |
任务数量 |
ACPU 回调 HCPU 时使用的 HCPU 侧任务 ID:
宏 |
值 |
说明 |
|---|---|---|
|
0 |
无效任务 |
|
1 |
在 HCPU 上分配内存 |
|
2 |
在 HCPU 上释放内存 |
|
3 |
输出到 HCPU 控制台 |
4.4 注意事项与限制
任务消息(
acpu_ctrl_ipc_msg_t)通过 IPC Queue 传递参数缓冲指针和结果值。按acpu_ctrl.h中acpu_run_task()的文档说明,参数大小受ACPU_TASK_INPUT_PARAM_SIZE限制,结果长度受ACPU_TASK_OUTPUT_VAL_SIZE限制。不要在中断上下文中调用
acpu_run_task():该调用是阻塞式的,会挂起调用线程。等待 ACPU 结果期间,框架会请求
PM_SLEEP_MODE_IDLE,避免系统在调用期间进入更深睡眠状态。如果 ACPU 返回
ACPU_ERR_ASSERT,HCPU 会打印acpu assert:及 ACPU 上报的<file> <line>,并触发自身断言。ACPU 镜像必须正确烧录;否则 ACPU 不会响应,
acpu_run_task()会超时并断言。
5. 例程讲解
5.1 acpu_task:HCPU 向 ACPU 下发任务
example/multicore/acpu_task 是最小的 ACPU 例程。HCPU 注册了控制台命令 run_acpu(src/hcpu/main.c),命令中调用 acpu_run_task():
static int run_acpu(int argc, char *argv[])
{
char *s;
if (argc < 2)
{
rt_kprintf("wrong argument\n");
return -1;
}
/* config ACPU to run specified task */
s = acpu_run_task(atoi(argv[1]) + ACPU_TASK_0, NULL, 0, NULL);
LOG_I(s);
return 0;
}
MSH_CMD_EXPORT(run_acpu, "run acpu")
该调用会阻塞,直到 ACPU 完成任务。ACPU 入口 acpu_main() 在 middleware/acpu_ctrl/acpu_main.c 中有默认弱实现,可处理预定义任务 ID:任务 0/1 返回 "task_0" / "task_1",未知任务 ID 返回 "unknown task"。HCPU 随后打印返回的字符串:
msh />run_acpu 0
run_acpu 0
[I/main] task_0
msh />run_acpu 1
[I/main] task_1
msh />run_acpu 2
[I/main] unknown task
要实现自定义任务,请在 src/acpu/main.c 中定义 acpu_main(task_name, param)(例程中的 __acpu_main() 空函数仅为占位模板;对 acpu_main 的强定义会覆盖框架的默认弱实现),根据 task_name 分发任务,执行后用 acpu_send_result() 回传结果。
5.2 opus:ACPU 上的音频编解码
example/multimedia/audio/opus 将 opus 编码/解码器运行在 ACPU 上。ACPU 工程开启 CONFIG_PKG_LIB_OPUS=y,HCPU 通过 ACPU_TASK_opus_* 任务 ID 委派编解码操作,例如(src/main.c):
#if defined(USING_ACPU_CTRL_FWK)
uint8_t error_code = 1;
opus_encode_ctl_arg_t arg;
arg.st = encoder;
arg.id = 0;
acpu_run_task(ACPU_TASK_opus_encoder_ctl, &arg, sizeof(arg), &error_code);
RT_ASSERT(error_code == 0);
#else
opus_encoder_ctl(encoder, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_10_MS));
...
#endif
ACPU_TASK_opus_encode、ACPU_TASK_opus_decode 等任务的使用方式相同。
5.3 4pdm:ACPU 上的音频采集与 3A
example/multimedia/audio/4pdm 采集 4 路 PDM 音频。当 HCPU 工程设置 CONFIG_ANYKA_RUN_IN_ACPU=y 时,3A 处理通过 ACPU_TASK_audio_3a_* 任务运行在 ACPU 上,ACPU 子工程在 project/hcpu/SConstruct 中添加。
5.4 render_list_mode:ACPU 上的图形渲染
example/rt_device/gpu/render_list_mode 将 EPIC 渲染列表执行放到 ACPU。HCPU 工程设置 CONFIG_DRV_EPIC_NEW_API_DUAL_CORE_HCPU=y,并复用通用 ACPU 模板 example/acpu/project 作为子工程(该模板开启 CONFIG_DRV_EPIC_NEW_API_DUAL_CORE_ACPU=y)。渲染列表任务以 ACPU_TASK_epic_rl 下发到 ACPU。
6. 调试与常见问题
6.1 ACPU 断言
ACPU 触发断言时,会调用 acpu_send_assert(file, line) 将位置上报给 HCPU。HCPU 打印:
acpu assert:<file> <line>
并触发自身的断言(RT_ASSERT(0))。请根据上报的 ACPU 源码位置排查问题。
6.2 ACPU 日志
ACPU 代码可以使用 acpu_printf() 将字符串转发到 HCPU 控制台,这要求 HCPU 侧开启 ACPU_CALLER_ENABLED(HCPU 侧默认开启)。控制台命令 acpu on / acpu off 用于调试时打开/关闭 ACPU 电源域。
6.3 内存
二级 boot 会将 ACPU 镜像拷贝到 ACPU RAM 的
0x20200000(ACPU 指令空间的 0 地址)。板级内存映射位于
customer/boards/<board>/{hcpu,lcpu,acpu}/(例如custom_mem_map.h)。
6.4 常见问题
现象 |
可能原因 |
|---|---|
|
ACPU 镜像未烧录,或 HCPU 工程未使能 |
menuconfig 中没有 ACPU 选项 |
开发板基于 SF32LB52x/55x/56x,没有 ACPU 核 |
|
ACPU 代码在报错的文件:行位置失败 |
EPIC 渲染异常或卡死 |
HCPU 和 ACPU 两侧未同时使能 |
7. 参考链接
双核开发说明(SDK 路径:
docs/source/zh_CN/app_note/dualcore.md,SF32LB55x HCPU/LCPU)内存使用指南(SDK 路径:
docs/source/zh_CN/app_note/memory_usage.md,SF32LB55x)acpu_task例程(SDK 路径:example/multicore/acpu_task)