API GUIDE / ADC / OVERVIEW
G32S10 ADC API 概述
模块概述:本文档定义 G32S10 SDK ADC 模块的正式接口,覆盖以下两层:
1. 文档范围
本文档定义 G32S10 SDK ADC 模块的正式接口,覆盖以下两层:
HAL ADC:面向应用、BSP和驱动上层的功能级接口LL ADC:面向寄存器与位操作的低层接口
补充说明:
LL层不返回状态码;需要返回寄存器值或数据时返回
uint32_t。HAL层负责参数校验、状态管理、中断/DMA编排和超时处理。
本文档以当前 SDK 源码为准,主要核对文件如下:
| 类型 | 路径 |
|---|---|
| HAL 公开接口 | code/include/drivers/g32s10/adc/hal_adc.h |
| HAL 实现 | code/drivers/g32s10/adc/hal_adc.c |
| LL 公开接口 | code/include/drivers/g32s10/adc/ll_adc.h |
| 寄存器定义 | code/include/drivers/g32s10/adc/adc_regs.h |
| 构建配置 | code/drivers/g32s10/adc/Kconfig |
| HAL 示例 | code/examples/hal/ |
| LL 示例 | code/examples/ll/adc_seq_example.c |
当文档描述与头文件、实现或 Kconfig 不一致时,以当前源码为准;硬件能力中未能在 SDK 源码内直接确认的数值,应结合芯片 SPEC 阅读。
2. 分层关系
分层职责如下:
HAL ADC封装初始化、序列配置、启动停止、轮询、中断、DMA侧控制、AWD和寄存器dump
维护参数合法性、模块级状态、活跃序列mask和统一返回码
提供便于上层使用的解包数据结构、回调注册和错误查询接口
LL ADC提供寄存器位级访问入口
不维护软件状态,不做复杂业务语义判断
公开接口均为
static inline,首参数为adc_regs_t *adcxadc_regs.h定义ADC基地址、寄存器结构体布局、通道数量、序列长度和位域mask
2.1 编译与运行前置条件
ADC HAL/LL 不负责板级时钟、引脚复用和 SoC 中断资源。直接使用本模块前,应用、BSP 或板级代码需要完成以下准备:
| 项目 | 责任方 | 说明 |
|---|---|---|
CONFIG_DRIVER_ADC | 应用配置 | 编译 ADC 驱动;该选项会自动选择 CONFIG_DRIVER_DMA。 |
| ADC 模块时钟与门控 | CPM/板级 | 访问寄存器前使能对应 SADC0/SADC1 时钟和门控。HAL 初始化不会配置 CPM。 |
| 模拟输入引脚 | GPIO/板级 | 将所选通道对应的引脚配置为 ADC 模拟输入功能;具体引脚和功能号由板级设计决定。 |
| SoC IRQ | PLIC/中断框架 | 使用 *_it() 或 DMA 完成中断时,应用必须注册并使能 IRQ_SADC0 或 IRQ_SADC1,中断服务程序调用 hal_adc_irq_handler()。 |
| systick 时间基准 | 应用/OS | hal_adc_poll_for_conversion() 以及使用微秒/毫秒超时的应用代码依赖 SDK systick。 |
| DMA 控制器 | CPM/DMA HAL | DMA 模式需要 DMA 控制器时钟、合法 descriptor 存储和调用方持有的目标缓冲区。HAL 负责 ADC 侧 cache 维护。 |
| Debug helper | 应用配置 | hal_adc_regs_dump() 需要同时开启 CONFIG_SDK_ENABLE_DEBUG_HELPERS 和 CONFIG_ADC_ENABLE_DEBUG_HELPERS,否则保留符号但返回 IM_ERR_UNSUPPORTED。 |
轮询模式下可不使用 ADC IRQ;DMA 模式是否使用完成中断取决于应用选择普通 start 还是 *_it() 接口。
3. 资源模型与公开类型
3.1 ADC 硬件能力摘要
| 项目 | 说明 |
|---|---|
| 分辨率 | 12 bit,转换结果有效位为 [11:0]。 |
| 采样率 | 最大 2 Msps。 |
| ADC工作时钟 | 最大 30 MHz |
| 通道 | SPEC描述模拟输入通道为 ADC_IN0 ~ ADC_IN7。寄存器存在部分预留扩展位,HAL默认只开放 0~7。 |
| 转换序列 | 支持 SEQ0、SEQ1、SEQ2 三个用户自定义转换序列。 |
| SEQ0 | 最多 4 次转换,仅支持寄存器触发,不支持DMA和连续模式,结果存储在 seq0_dr[2]。 |
| SEQ1 | LL层当前开放最多 8 次转换,支持寄存器/TCU/PWM0/PWM1触发,支持FIFO、DMA、延时扫描、连续转换、组连续转换;寄存器高8次转换暂隐藏。 |
| SEQ2 | 最多 8 次转换,支持寄存器/TCU/PWM0/PWM1触发,支持FIFO、DMA、延时扫描,不支持连续模式。 |
| 模拟看门狗 | 支持每个通道高/低阈值检测,支持中断和PWM急停FAIL输出屏蔽控制。 |
| 冲突处理 | 支持序列优先级和 BREAK_MD,用于处理高/低优先级序列触发冲突。 |
3.2 HAL 返回状态约定
HAL层普通可失败接口统一返回SDK公共错误码类型:
error_code_t
常用返回值如下:
| 返回值 | 说明 |
|---|---|
IM_OK | 操作成功。 |
IM_ERR_INVALID_PARAM | 参数为空、实例非法、越界或模式组合非法。 |
IM_ERR_BUSY | 指定序列或ADC资源忙。 |
IM_ERR_TIMEOUT | 轮询等待超时。 |
IM_ERR_NOT_READY | 轮询检测到硬件错误、数据未就绪或内部流程未完成。 |
IM_ERR_UNSUPPORTED | 当前配置不支持该操作,例如非软件触发序列调用软件start接口。 |
3.3 数据准备条件
typedef enum {
HAL_ADC_DRT_SEQUENCE_END = 0,
HAL_ADC_DRT_GROUP_END = 1,
HAL_ADC_DRT_FIFO_GE_1 = 2,
HAL_ADC_DRT_FIFO_GE_4 = 3,
HAL_ADC_DRT_FIFO_GE_8 = 4,
HAL_ADC_DRT_FIFO_GE_16 = 5,
HAL_ADC_DRT_CUSTOM = 7,
} hal_adc_drt_t;说明:
SEQ0只支持HAL_ADC_DRT_SEQUENCE_END和HAL_ADC_DRT_CUSTOM。HAL_ADC_DRT_GROUP_END仅对SEQ1连续组模式有效。FIFO阈值触发仅对
SEQ1、SEQ2有效。
HAL 枚举值与 LL 写寄存器时使用的编码并不完全相同,调用 LL 接口时不要直接套用 HAL 数值:
| HAL类型 | HAL_ADC_DRT_* 值 | ll_adc_seq0_data_ready_type_set() | ll_adc_seq1/2_data_ready_type_set() |
|---|---|---|---|
HAL_ADC_DRT_SEQUENCE_END | 0 | 0 | 0 |
HAL_ADC_DRT_GROUP_END | 1 | 不支持 | 1 |
HAL_ADC_DRT_FIFO_GE_1/4/8/16 | 2/3/4/5 | 不支持 | 2/3/4/5 |
HAL_ADC_DRT_CUSTOM | 7 | 1 | 7 |
LL函数只负责写入编码,不校验sequence与模式的组合是否有效;例如编码值1可由SEQ2的LL接口写入,但HAL不支持SEQ2组结束模式。
3.4 HAL 错误标志
typedef enum {
HAL_ADC_ERROR_NONE = 0U,
HAL_ADC_ERROR_INVALID_PARAM = (1UL << 0U),
HAL_ADC_ERROR_EOC_TIMEOUT = (1UL << 1U),
HAL_ADC_ERROR_DATA_OVERRUN = (1UL << 2U),
HAL_ADC_ERROR_EVENT_OVERRUN = (1UL << 3U),
HAL_ADC_ERROR_PHY_EOC = (1UL << 4U),
HAL_ADC_ERROR_DMA = (1UL << 5U),
} hal_adc_error_t;说明:
错误枚举值是bit flag,可按位或写入
hal_adc_handle_t.error_code。统一start路径中的DMA handle打开或传输启动失败时,HAL会记录
HAL_ADC_ERROR_DMA。普通HAL参数检查失败时直接返回
IM_ERR_INVALID_PARAM,当前实现不会因该次调用把HAL_ADC_ERROR_INVALID_PARAM锁存到error_code。hal_adc_error_get()在hadc或其instance无效时返回HAL_ADC_ERROR_INVALID_PARAM,这一返回值是无效handle的结果,不代表发生了已锁存的参数错误。
4. 当前实现约束与行为说明
4.1 通道和序列长度
| 序列 | 最大转换次数 | 通道范围 | 说明 |
|---|---|---|---|
SEQ0 | 4 | 0~7 | 软件触发,数据在 seq0_dr[2]。 |
SEQ1 | 8 | 0~7 | LL层当前开放rank 0~7,支持FIFO/DMA/连续/组连续。 |
SEQ2 | 8 | 0~7 | 支持FIFO/DMA/延时扫描。 |
4.2 模式组合
| 配置项 | SEQ0 | SEQ1 | SEQ2 |
|---|---|---|---|
| 软件触发 | 支持 | 支持 | 支持 |
| TCU触发 | 不支持 | 支持 | 支持 |
| PWM0触发 | 不支持 | 支持 | 支持 |
| PWM1触发 | 不支持 | 支持 | 支持 |
| 延时扫描 | 不支持 | 支持 | 支持 |
| 连续转换 | 不支持 | 支持 | 不支持 |
| 组连续转换 | 不支持 | 支持 | 不支持 |
| DMA | 不支持 | 支持 | 支持 |
| FIFO | 不支持 | 深度16 | 深度16 |
4.3 AWD 阈值
| 参数 | 约束 |
|---|---|
channel | 0~7。 |
low_threshold | 0~0x0FFF。 |
high_threshold | 0~0x0FFF。 |
| 阈值关系 | 必须 low_threshold <= high_threshold,HAL参数校验不满足时返回 IM_ERR_INVALID_PARAM。 |
low_flags | bit07对应通道07低阈值触发;建议使用 HAL_ADC_AWD_CHANNEL_FLAG()。 |
high_flags | bit07对应通道07高阈值触发;建议使用 HAL_ADC_AWD_CHANNEL_FLAG()。 |
4.4 配置修改时机与资源所有权
HAL 不会在所有配置接口中统一检查“所有序列均已停止”。调用方必须根据下表保证时序:
| 接口或资源 | HAL 当前检查 | 调用方责任 |
|---|---|---|
hal_adc_sequence_config() | 检查目标sequence的HAL active、DMA active和硬件busy状态 | 仅在该sequence空闲时重新配置。 |
hal_adc_start() / hal_adc_start_multi() | 检查目标sequence active、硬件busy、软件触发和DMA状态 | 不应重复启动仍在活动的sequence。 |
hal_adc_clock_config() | 只校验分频范围,不检查序列忙状态 | 在修改ADC转换/延时时钟前停止所有相关序列。 |
hal_adc_priority_config() | 只校验优先级和break参数,不检查序列忙状态 | 在修改抢占配置前停止所有相关序列。 |
hal_adc_soc_extra_cycle_config() | 校验离散编码,不检查序列忙状态 | SPEC要求任一序列运行期间不得修改 SOC_EXT_CYCLE。 |
ll_adc_soc_extra_cycle_set() | 不校验编码和序列忙状态 | 调用方只能传入合法离散编码,并保证所有序列已停止。 |
hal_adc_sequence_unstorage_config() | 不检查目标sequence是否活动 | 先停止目标SEQ1/SEQ2,再修改storage mask。 |
dma_buffer / dma_desc | 配置阶段校验地址、长度、对齐和descriptor约束 | 存储始终由调用方持有,生命周期必须覆盖DMA配置、运行和停止阶段。 |
IRQ_SADC0 / IRQ_SADC1 | HAL只处理ADC寄存器中断 | PLIC、CPU中断入口/退出和IRQ生命周期由BSP或中断框架负责。 |
5. 示例程序与使用方式
5.1 示例程序索引与接入方式
ADC示例只位于 code/examples。这些文件不会自动编译进主固件,应用需要将选定的 .c 文件显式加入自身构建目标;示例用于说明调用方式,不属于与HAL/LL同等级的稳定二进制接口。
| 示例 | 层级 | 调用入口 | 覆盖内容 |
|---|---|---|---|
adc_polling_example.c | HAL | example_adc_sample_run()、example_adc_sample_run_on() | 单通道采样、SEQ0/SEQ1/SEQ2轮询、多序列启动。 |
hal_adc_dma_example.c | HAL | example_hal_adc_dma_run() | SEQ1/SEQ2循环DMA、ADC DMA完成中断和回调。 |
hal_adc_dma_loop_example.c | HAL | example_hal_adc_dma_loop_run()、example_hal_adc_dma_loop_soak_get_default_config()、example_hal_adc_dma_loop_soak_run() | 多轮DMA、停止后重启和长时间运行观察;SADC时钟由调用方配置。 |
tcu_trig_adc_example.c | HAL | example_tcu_trig_adc0_run()、example_tcu_trig_adc1_run() | SEQ1 TCU外部触发,TCU channel 0 HALF/FULL输出分别触发ADC0/ADC1。 |
adc_seq_example.c | LL | example_adc_seq_sample_run() | 直接配置寄存器,完成SEQ0/SEQ1/SEQ2软件触发轮询和寄存器dump。 |
接入方式:
HAL示例需要包含
hal_adc.h并启用CONFIG_DRIVER_ADC;再按示例实际使用的功能启用GPIO、TCU、IRQ等驱动。CONFIG_DRIVER_ADC会自动选择CONFIG_DRIVER_DMA;示例本身不调用CPM HAL,SADC时钟由调用方准备。LL示例需要包含
ll_adc.h,不需要链接ADC HAL。示例未提供独立公共头文件时,应用应显式把示例
.c加入构建目标,并在应用侧声明需要调用的入口函数;不要同时编译和包含同一个.c文件,避免重复定义。调用示例前完成2.1节中的时钟、引脚、IRQ、systick和模拟信号准备。不同示例覆盖的前置条件不同,以各文件头部说明为准。
本文列出的 ADC HAL/LL 示例都不配置CPM,SADC源时钟和门控由板级代码或调用方预先建立;示例中的GPIO配置只负责把目标GPIOC引脚切到function 0。
5.2 单通道轮询采样
hal_adc_handle_t hadc0;
uint32_t value;
error_code_t ret;
ret = hal_adc_handle_init(&hadc0, ADC0);
if (ret != IM_OK) {
return ret;
}
hadc0.init.adc_clk_div = 2U;
hadc0.init.soc_extra_cycle = (uint8_t)HAL_ADC_SOC_EXTRA_CYCLE_0;
ret = hal_adc_init(&hadc0);
if (ret != IM_OK) {
return ret;
}
ret = hal_adc_channel_value_get(&hadc0, 0U, &value, 1000000U);