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_HIGH shadow 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 边界更新。典型流程:

  1. 写一个或多个可更新参数。
  2. 写 AUDIO_UPDATE.UPDATE=1。
  3. 需要确认完成时轮询 AUDIO_ST.BUSY。
  4. 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 参数。

需要区分两层行为:

  1. PWMA 硬件/HAL 支持 DMA 运行中通过 AUDIO_UPDATE 应用新音量。
  2. 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. 推荐约束

  1. 普通音频应用通过 Audio middleware 使用 PWMA,不直接管理 PDMA descriptor。
  2. 修改 PRESCALE 前停止 waveform。
  3. 所有 shadow 配置变更后调用 hal_pwma_apply_update()。
  4. 运行中修改音量时禁止同时修改 PRESCALE/AUDIO_TH。
  5. hal_pwma_start() 会开启 DMA request,CPU 模式需要显式关闭。
  6. callback 内只能做状态处理和唤醒,不得执行阻塞 I/O。
  7. 设备树/Kconfig 的 module clock 必须与实际 CPM 频率一致;计算载波时应使用 hal_pwma_get_module_clock_hz() 返回的实际值。