API GUIDE / AIC / API OVERVIEW
AIC API 概述
1. 文档范围
本文档定义 G32S10 AIC 的 LL(Low Level)和 HAL(Hardware Abstraction Layer) 正式接口,面向板级音频驱动、Audio middleware、测试代码和需要直接控制 AIC 的 集成代码。
本文档以当前 SDK 源码为准:
| 类型 | 路径 |
|---|---|
| 寄存器定义 | code/include/drivers/g32s10/aic/aic_regs.h |
| LL 接口 | code/include/drivers/g32s10/aic/ll_aic.h |
| HAL 接口 | code/include/drivers/g32s10/aic/hal_aic.h |
| LL/HAL 实现 | code/drivers/g32s10/aic/hal_aic.c |
| Kconfig | code/drivers/g32s10/aic/Kconfig |
| CMake | code/drivers/g32s10/aic/CMakeLists.txt |
补充说明:
- LL 接口是直接寄存器访问 helper,不校验实例和参数,要求调用方保证寄存器时钟、 pinmux 和运行状态合法。
- HAL 接口负责实例校验、AIC 状态、FIFO 阈值、复位等待、中断分发和寄存器配置。
- HAL 不管理 pinmux、外部 codec、PDMA channel、PCM buffer 或 descriptor。
- AIC 的 Audio middleware 接口见
G32S10 Audio MID 正式接口文档。
2. 分层关系与依赖
Application / Audio Core / Board
|
v
HAL AIC
|
v
LL AIC
|
v
AIC Registers
|
+---- CPM AIC gate / CGU I2S TX/RX
+---- Board pinmux
+---- External codec or internal codec
+---- PDMA channel (owned outside HAL)
HAL 层职责:
- 初始化 caller-owned
hal_aic_handle_t。 - 管理 AIC module gate 和可选 SoC I2S CGU clocks。
- 配置 4-wire/6-wire、外部/内部 codec、TX/RX clock role。
- 配置 I2S/MSB format、sample width、signedness、channel 和 endian。
- 执行硬件 reset 并等待 FIFO reset 完成。
- 管理 TX/RX/LOOP FIFO 阈值、状态、flush 和错误标志。
- 管理 playback/capture/loop callback 和 IRQ 分发。
- 提供 DMA data-port 地址;DMA channel 和 descriptor 由上层管理。
主要依赖:
| 依赖 | 用途 |
|---|---|
DRIVER_CPM |
HAL_CPM_ID_GATE_AIC、I2S TX/RX CGU |
| IRQ/PLIC | 上层注册 AIC IRQ 并调用 hal_aic_irq_handler() |
| Board pinmux | MCLK、BCLK、LRCK、DI、DO 引脚 |
| External codec | 由 BSP 控制 reset、I2C 和 DAI format |
| DMA middleware | 使用 hal_aic_fifo_data_address_get() 得到的 FIFO 地址 |
3. 构建配置与文件组织
最小配置:
CONFIG_DRIVER_CPM=y
CONFIG_DRIVER_AIC=y
DRIVER_AIC 自动选择 DRIVER_CPM。
| 文件 | 说明 |
|---|---|
aic_regs.h |
唯一 AIC 实例、寄存器布局、基地址和位域宏 |
ll_aic.h |
全部 inline 寄存器 helper |
hal_aic.h |
类型、handle、callback 和 HAL API |
hal_aic.c |
时钟、配置、复位、FIFO、状态和 IRQ 实现 |
Kconfig |
DRIVER_AIC |
CMakeLists.txt |
AIC 组件构建规则 |
应用或 BSP 包含:
#include "hal_aic.h"
需要直接访问寄存器时再包含:
#include "ll_aic.h"
4. 实例与资源所有权
G32S10 当前只有一个 AIC 实例:
#define AIC ((aic_regs_t *)(uintptr_t)AIC_IOBASE)
| 资源 | 所有者 |
|---|---|
| AIC 寄存器块 | SoC |
| AIC/FIFO 配置状态 | hal_aic_handle_t |
| AIC module gate | hal_aic_init() / hal_aic_deinit() |
| I2S TX/RX CGU | hal_aic_clock_enable() / hal_aic_clock_disable() |
| pinmux | BSP |
| AIC IRQ 注册 | 上层 |
| PDMA channel/descriptor/buffer | Audio middleware 或调用方 |
| 外部 codec 控制 | BSP/codec driver |
hal_aic_handle_t 必须由调用方分配并保持到 deinit 完成。不得复制一个正在使用的
handle。
5. 寄存器映射
基地址宏为 AIC_IOBASE。
| 偏移 | 寄存器 | 访问 | 主要用途 |
|---|---|---|---|
0x000 |
AICFR |
RW | enable、master/slave、reset、codec route、时钟线模式、FIFO 阈值 |
0x004 |
AICCR |
RW | playback/capture/loop enable、DMA、IRQ、数据格式、flush |
0x010 |
I2SCR |
RW | I2S/MSB、LR order、packed LR swap |
0x014 |
AICSR |
RW | FIFO level、service 和 error flags |
0x01C |
I2SSR |
RO | I2S BSY/TBSY/RBSY/CHBSY |
0x030 |
I2SDIV |
RW | I2S IDV/DV divider |
0x034 |
AICDR |
RW | playback TX / capture RX data port |
0x038 |
AICLR |
RO | loop FIFO data port |
0x03C |
AICTFLR |
RW | loop FIFO threshold |
FIFO 深度:
| FIFO | 深度 |
|---|---|
| TX | 64 entries |
| RX | 64 entries |
| LOOP | 32 entries |
6. 关键运行模型
6.1 Stream
hal_aic_stream_t 的值是按位标志:
| 值 | 方向 | Data/FIFO |
|---|---|---|
HAL_AIC_STREAM_PLAYBACK |
DAC/TX | AICDR + TX FIFO |
HAL_AIC_STREAM_CAPTURE |
ADC/RX | AICDR + RX FIFO |
HAL_AIC_STREAM_LOOP |
TX reference | AICLR + LOOP FIFO |
虽然枚举值可组合,HAL 的 start/stop 每次只接受一个 stream。
6.2 LOOP reference path
HAL_AIC_STREAM_LOOP 提供播放参考数据:
playback PCM -> TX FIFO -> codec
|
+-> LOOP FIFO -> AICLR
hal_aic_stream_start(..., HAL_AIC_STREAM_LOOP, mode) 使能 ETFL,并设置
LOOP FIFO 的 DMA request。LOOP 读取的是 TX FIFO 的数字副本,不经过扬声器、空气和
麦克风。
主要资源:
| 项目 | 值 |
|---|---|
| FIFO | LOOP FIFO,32 entries |
| 数据端口 | AICLR |
| 阈值 | AICTFLR.TFLTH |
| 状态 | AICSR.TFLL/TFLS/TFLOR |
| DMA request | HAL_DMA_REQUEST_AIC_RX_LOOPBACK |
使用约束:
- LOOP 与 playback 使用相同的 format、sample width、rate 和 channel。
- playback 必须已经启动,LOOP 才能获得有效数据。
- LOOP 使用独立 PCM buffer,不能与 playback/capture 共享 ring。
- HAL 只负责 AIC FIFO 和 request;DMA buffer、channel 和 cache 由 Audio middleware 管理。
6.3 Transfer mode
| 模式 | AIC 侧动作 |
|---|---|
HAL_AIC_TRANSFER_POLLING |
只开 stream,数据由 CPU 轮询 FIFO |
HAL_AIC_TRANSFER_INTERRUPT |
开对应 FIFO service IRQ |
HAL_AIC_TRANSFER_DMA |
开对应 DMA request |
HAL 不创建 DMA channel,也不搬运 descriptor。DMA 模式下,外部 DMA 必须先就绪。
6.4 4-wire 与 6-wire
4-wire:
TX 和 RX 共用 TX clock source。
设置采样率时 TX/RX divider 同步更新。
默认要求 playback/capture clock role 相同。ICOD LOOP 参考通路的合法组合是
external TX 作为共享时钟 master、internal RX 作为 slave。
6-wire:
TX 和 RX 使用独立时钟。
只允许 external codec。
设置采样率时只更新目标方向的 divider。
内部 codec 模式要求对应方向为 HAL_AIC_CLOCK_SLAVE。
6.5 Clock role
| HAL role | 含义 |
|---|---|
HAL_AIC_CLOCK_MASTER |
AIC 输出 BIT_CLK/LRCK |
HAL_AIC_CLOCK_SLAVE |
AIC 接收外部 codec/FPGA 提供的 BIT_CLK/LRCK |
hal_aic_clock_enable() 始终同时准备 TX/RX CGU,但实际 divider 由
hal_aic_clock_set_sample_rate() 按 wire mode 更新。生成 MCLK 为:
MCLK = sample_rate_hz * 256
启用 CONFIG_CPM_ENABLE_STUB=y 时,HAL 不写 CGU,外部必须提供音频时钟。真实 SoC
板通常不应启用 CPM stub。
6.6 Reset
hal_aic_reset() 触发 AIC 核心 reset:
- playback 等待 TX FIFO reset 位清零。
- capture 等待 RX FIFO reset 位清零。
- LOOP 根据 master 配置等待对应 FIFO。
- 调用前必须有 BIT_CLK 和有效的微秒时基。
- 非 stub CPM 下,reset 期间临时把 TX/RX 切成 master,以产生内部时钟。
- reset 成功会清除 FIFO error,并把 handle 置回 READY。
- reset 失败会把 handle 置 ERROR,并记录
HAL_AIC_ERROR_RESET_TIMEOUT。 - 硬件 reset 保留
AICFR和I2SDIV,但会使 frame format/stream 配置失效。
6.7 FIFO threshold
hal_aic_fifo_threshold_configure() 使用实际 entry 数,且必须为偶数:
| Stream | 可用值 |
|---|---|
| PLAYBACK | 0, 2, 4, ..., 62 |
| CAPTURE | 2, 4, ..., 64 |
| LOOP | 2, 4, ..., 32 |
配置 threshold 不会自动开启 IRQ、DMA 或 stream。
7. 常见错误与检查项
| 现象 | 检查项 |
|---|---|
hal_aic_init() 失败 |
CONFIG_DRIVER_CPM、AIC gate、时钟树 |
clock_enable() 返回 NOT_READY |
是否已 init 和 configure connection |
clock_set_sample_rate() 失败 |
CGU parent、divider 能否产生 fs*256 |
| reset timeout | BIT_CLK/LRCK 是否运行、pinmux、CPM stub、clock role |
| stream start busy | 同一方向是否已 active |
| DMA 无请求 | hal_aic_stream_start(..., DMA)、FIFO threshold、外部 PDMA |
| 采到全零 | DI pinmux、外部 codec clock/data、codec ADC path |
| 放音无声 | DO pinmux、codec DAI、codec enable、功放 enable |
| capture overrun | 上层读取不及时、FIFO threshold 或 CPU 阻塞 |
| playback underrun | TX FIFO 未预填、DMA 供数过慢 |
| I2S/MSB 不启动 | FIRSTCHN_LEFT、复位顺序、clock role |
8. 推荐约束
- 普通板级音频优先使用 HAL,不要直接展开 LL 初始化序列。
- 任何 reset 前必须保证 BIT_CLK 可用。
- 运行中不得修改 PRESCALE、wire mode、codec route、frame format 等 reset-sensitive 或格式相关字段。
- 同一寄存器的 LL read-modify-write 与 ISR 访问必须串行化。
- DMA buffer、descriptor 和 cache 维护不归 AIC HAL 管理。
- callback 内只允许 FIFO 操作、清状态和唤醒任务,不得执行阻塞型 codec I2C。