API GUIDE / PWMA / API OVERVIEW
PWMA API 概述
1. 文档范围
本文档定义 G32S10 PWMA 的 LL(Low Level)和 HAL(Hardware Abstraction Layer) 正式接口,面向板级音频驱动、Audio middleware、测试代码和需要直接操作 PWMA 的 集成代码。
本文档以当前 SDK 源码为准:
| 类型 | 路径 |
|---|---|
| 寄存器定义 | code/include/drivers/g32s10/pwma/pwma_regs.h |
| LL 接口 | code/include/drivers/g32s10/pwma/ll_pwma.h |
| HAL 接口 | code/include/drivers/g32s10/pwma/hal_pwma.h |
| HAL 实现 | code/drivers/g32s10/pwma/hal_pwma.c |
| Kconfig | code/drivers/g32s10/pwma/Kconfig |
| CMake | code/drivers/g32s10/pwma/CMakeLists.txt |
补充说明:
- LL 接口是直接寄存器 helper,不校验实例、clock、state 或参数。
- HAL 接口负责参数校验、CPM 时钟、配置、状态、软件 update 和 IRQ 分发。
- HAL 不管理外部 PDMA channel、descriptor、PCM buffer 或功放 GPIO。
- PWMA Audio middleware 接口见
G32S10 Audio MID 正式接口文档。
2. 分层关系与依赖
Application / Audio Core / Board
|
v
HAL PWMA
|
v
LL PWMA
|
v
PWMA Registers
|
+---- CPM CGU_PWMA + PWMA gate
+---- Board pinmux / output pin
+---- External PDMA channel
+---- Amplifier enable GPIO
HAL 层职责:
- 初始化 caller-owned
hal_pwma_handle_t。 - 配置 CPM PGWA module clock 和 gate。
- 配置 PCM signedness、endian、precision、sample format。
- 配置 PRESCALE、AUDIO_TH 和 CPU-mode HIGH threshold。
- 配置 initial/idle level、volume、DMA request 和 interrupt mask。
- 触发
AUDIO_UPDATE。 - 提供 start/stop、FIFO clear、first-wave clear 和 soft reset。
- 提供状态、module clock、DMA data address、callback 和 IRQ。
HAL 不负责:
- 创建外部 DMA channel。
- 读取或写入 PCM ring。
- 配置功放 enable GPIO。
- 自动维护
AUDIO_HIGHshadow value。 - 自动把 PWM 载波频率与采样率绑定;板级/middleware 负责选择参数。
3. 构建配置
最小配置:
CONFIG_DRIVER_CPM=y
CONFIG_DRIVER_PWMA=y
DRIVER_PWMA 自动选择 DRIVER_CPM。
可选调试配置:
CONFIG_SDK_ENABLE_DEBUG_HELPERS=y
CONFIG_PWMA_ENABLE_DEBUG_HELPERS=y
启用后 hal_pwma_regs_dump() 才执行寄存器 dump;否则返回
IM_ERR_UNSUPPORTED。
默认不会读取 DMA_DATA 寄存器。确需 dump 时定义:
#define HAL_PWMA_DUMP_READ_DMA_DATA 1U
该寄存器是 PCM 输入数据路径的一部分,正常调试不应读取。
4. 实例与资源所有权
G32S10 当前只有一个 PWMA 实例:
#define PWMA ((pwma_regs_t *)(uintptr_t)PWMA_IOBASE)
| 资源 | 所有者 |
|---|---|
| PWMA 寄存器块 | SoC |
| PWMA CPM CGU/gate | hal_pwma_init() / hal_pwma_deinit() |
| PWMA 配置和 callback | hal_pwma_handle_t |
| output pinmux | BSP |
| PDMA channel/descriptor | Audio middleware 或调用方 |
| speaker enable GPIO | BSP |
5. 寄存器映射
基地址宏为 PWMA_IOBASE。
| 偏移 | 寄存器 | 访问 | 用途 |
|---|---|---|---|
0x000 |
AUDIO_CON |
RW | data type、endian、levels、precision、format、DMA/COUNT enable、prescaler |
0x004 |
AUDIO_UPDATE |
WO | 应用 CPU-mode shadow parameter |
0x008 |
AUDIO_ST |
R,FST_WAVE W1C | BUSY、FST_WAVE、DMA_FE、AUDIO_WORK |
0x00C |
AUDIO_INT_MASK |
RW | DMA FIFO empty / first-wave interrupt mask |
0x010 |
AUDIO_TH |
RW | PWM period count |
0x014 |
AUDIO_HIGH |
RW | CPU-mode high-level count |
0x018 |
DMA_DATA |
RW | DMA PCM input port |
0x01C |
AUDIO_VOLUME |
RW | volume direction + gain |
0x020 |
SOFT_RESET |
RW | low-active software reset |
0x024 |
SOFT_RESET_STATUS |
R/W1C | low-active reset status;写 1 清除状态 |
6. 时序与数据模型
6.1 Prescaler 和载波
PWMA module clock 为 f_pwma。AUDIO_CON.PRESCALE 的原始值 P=0..255 表示分频:
f_divided = f_pwma / (P + 1)
AUDIO_TH 的计数值为 TH,硬件有效周期长度为 TH - 1 个分频时钟:
f_carrier = f_divided / (TH - 1)
TH = round(f_divided / f_carrier) + 1
因此 AUDIO_TH 必须大于等于 2。HAL 对该边界做参数检查。
PRESCALE 属于运行时不可随意改变的时序参数。改变 prescaler 前应先停止波形输出,
再重新配置并 apply update。
6.2 CPU 模式
CPU 模式使用:
AUDIO_TH = period count
AUDIO_HIGH = high-level count
两者的相对关系形成占空比。软件写入新的 AUDIO_HIGH shadow 值后调用
AUDIO_UPDATE,然后可轮询 AUDIO_ST.BUSY,BUSY 清零表示更新完成。
6.3 DMA 模式
DMA 模式通过 DMA_DATA 接收 PCM-style sample,硬件根据 sample 和 AUDIO_TH
计算每个 PWM period 的 high-level count。此时 AUDIO_HIGH 寄存器的值不是当前
每个样本的占空比。
输入格式由以下字段共同决定:
| 字段 | 值 |
|---|---|
DATA_TYPE |
0=unsigned,1=signed |
ENDIAN |
0=little-endian,1=big-endian |
PRECISION |
0=8-bit,1=16-bit |
FORMAT |
8k、16k、32k、44.1k、48k |
6.4 Software update
AUDIO_UPDATE 用于请求 shadow register 在 waveform 边界更新。典型流程:
- 写一个或多个可更新参数。
- 写
AUDIO_UPDATE.UPDATE=1。 - 需要确认完成时轮询
AUDIO_ST.BUSY。 - BUSY 清零后再写下一组 shadow 参数。
hal_pwma_init() 在所有配置完成后自动执行一次 update。
6.5 音量和方向
AUDIO_VOLUME:
bit[8] VOLUME_DOWN
bit[7:4] coarse gain,约 6.02 dB 一档
bit[3:0] fine gain,约 0.5 dB 一档
DOWN=0 为放大方向,DOWN=1 为衰减方向。fine 在衰减方向下按相反顺序参与计算,
因此不能把 8-bit GAIN 当作线性音量值。
运行中修改音量时,可以调用:
hal_pwma_configure_volume(&handle, &volume);
hal_pwma_apply_update(&handle);
HAL 当前不禁止在 ACTIVE 状态调用这些接口,但业务必须串行化访问,并避免同时修改 其他 shadow 参数。
需要区分两层行为:
- PWMA 硬件/HAL 支持 DMA 运行中通过
AUDIO_UPDATE应用新音量。 im_pwma_adapter_param_set()和board_audio_set_pwma_param()管理持久板级 policy,当前实现要求 PWMA 处于 RESET,运行中会返回IM_ERR_BUSY。
因此运行中动态音量应使用 HAL 的 hal_pwma_configure_volume() 和
hal_pwma_apply_update();持久参数仍使用 adapter/BSP 接口。
7. 常见错误与检查项
| 现象 | 检查项 |
|---|---|
| init 返回 INVALID_PARAM | AUDIO_TH 是否至少为 2、各字段位宽是否合法 |
| 无输出 | PWMA clock/gate、pinmux、speaker enable、CNT_EN |
| 输出固定电平 | INIT_LEVEL、IDLE_LEVEL、DMA 数据、precision/signedness |
| 载波频率不对 | module clock、PRESCALE、AUDIO_TH |
| 有载波但无音频 | DMA_EN、外部 PDMA、DMA_DATA、sample/format |
| underrun/重复尾音 | 外部 PDMA 提前停止、ring 未持续供数 |
| 音量不生效 | 是否写了 AUDIO_UPDATE |
| update 卡住 | BUSY 是否清零、是否在 waveform 运行中写入非法 prescale |
| 停止后仍有输出 | hal_pwma_stop() 只关 CNT_EN,后续按流程清 DMA/FIFO/CLR |
| soft reset 后配置全失效 | 重新执行 hal_pwma_init() |
| IRQ 只触发一次 | handler 会 mask source,需要重新 unmask |
8. 推荐约束
- 普通音频应用通过 Audio middleware 使用 PWMA,不直接管理 PDMA descriptor。
- 修改 PRESCALE 前停止 waveform。
- 所有 shadow 配置变更后调用
hal_pwma_apply_update()。 - 运行中修改音量时禁止同时修改 PRESCALE/AUDIO_TH。
hal_pwma_start()会开启 DMA request,CPU 模式需要显式关闭。- callback 内只能做状态处理和唤醒,不得执行阻塞 I/O。
- 设备树/Kconfig 的 module clock 必须与实际 CPM 频率一致;计算载波时应使用
hal_pwma_get_module_clock_hz()返回的实际值。