API GUIDE / SPI Slave / OVERVIEW

G32S10 SPI Slave API 概述

模块概述:本文档描述 G32S10 SPI_SLV 模块当前 SDK 中对外提供的 HAL 层与 LL 层正式接口, 包括公开类型、接口行为、参数约束、返回值约定、寄存器语义、典型使用流程以及当前 实现限制。

1. 文档范围

本文档描述 G32S10 SPI_SLV 模块当前 SDK 中对外提供的 HAL 层与 LL 层正式接口, 包括公开类型、接口行为、参数约束、返回值约定、寄存器语义、典型使用流程以及当前 实现限制。

本文档基于以下文件编写:

  • code/include/drivers/g32s10/spi_slv/spi_slv_regs.h

  • code/include/drivers/g32s10/spi_slv/ll_spi_slv.h

  • code/include/drivers/g32s10/spi_slv/hal_spi_slv.h

  • code/drivers/g32s10/spi_slv/hal_spi_slv.c

2. 分层关系

APPLICATION  Application / BSP / Middleware  业务代码、板级支持与示例入口
↓
HAL  SPI_SLV HAL  模块级配置、状态管理与硬件访问
↓
LL  SPI_SLV LL  寄存器访问与字段级控制
↓
HARDWARE REGISTERS  SPI_SLV Registers  实例地址、寄存器布局与位域定义
层级文件职责
寄存器定义spi_slv_regs.h定义寄存器结构体、实例宏和位域宏
LL 层ll_spi_slv.h提供寄存器字段级静态内联访问,不维护软件状态
HAL 层头文件hal_spi_slv.h定义 HAL 公开宏、类型、句柄和函数原型
HAL 层实现hal_spi_slv.c完成参数检查、模块时钟管理、复位、FIFO、IRQ 和回调处理

HAL 面向应用、BSP 和 middleware 使用;LL 面向寄存器级控制、底层适配和调试使用。 通常应优先使用 HAL。直接使用 LL 时,调用方必须自行保证实例、参数、时序和并发访问 合法。

3. 资源模型与公开类型

3.1 模块实例与基地址

当前 HAL/LL 支持两个 SPI_SLV 实例。

实例基地址宏基地址
SPI_SLV0SPI_SLV0_IOBASE0x100CC000
SPI_SLV1SPI_SLV1_IOBASE0x1000E000

spi_slv_regs.h 中提供如下实例宏:

#define SPI_SLV0  ((spi_slv_regs_t *)(uintptr_t)SPI_SLV0_IOBASE)
#define SPI_SLV1  ((spi_slv_regs_t *)(uintptr_t)SPI_SLV1_IOBASE)

3.2 硬件能力摘要

项目说明
实例数量2,SPI_SLV0 和 SPI_SLV1
角色SPI 从机,只能响应外部主机提供的 CS 和 SCLK
数据通道单线、双线、四线;实际可用通道还取决于 BSP 引脚复用
帧位宽4 至 32 bit
FIFO 深度TX 128 entry,RX 128 entry;每个 entry 通过 32 bit 数据寄存器访问
传输计数RX/TX 各有一个 32 bit 总帧数/剩余帧数寄存器
中断RX/TX 阈值、空/满和 FIFO 错误状态汇总为模块聚合 IRQ
DMARX_RDFLAG 可产生 RX DMA 请求,TX_WRFLAG 可产生 TX DMA 请求
环回支持内部环回,但从机仍不能自行产生 CS 和 SCLK

3.3 状态标志

hal_spi_slv_status_get() 返回由 hal_spi_slv_status_flag_t 组成的逻辑 bitmask。

状态bit说明
HAL_SPI_SLV_STATUS_TX_READ_FLAG0TX read flag
HAL_SPI_SLV_STATUS_TX_WRITE_FLAG1TX write flag
HAL_SPI_SLV_STATUS_TX_READ_EMPTY_ERR2TX FIFO 读空错误
HAL_SPI_SLV_STATUS_TX_WRITE_FULL_ERR3TX FIFO 写满错误
HAL_SPI_SLV_STATUS_TX_EMPTY4TX FIFO 空
HAL_SPI_SLV_STATUS_TX_FULL5TX FIFO 满
HAL_SPI_SLV_STATUS_RX_READ_FLAG6RX read flag
HAL_SPI_SLV_STATUS_RX_WRITE_FLAG7RX write flag
HAL_SPI_SLV_STATUS_RX_READ_EMPTY_ERR8RX FIFO 读空错误
HAL_SPI_SLV_STATUS_RX_WRITE_FULL_ERR9RX FIFO 写满错误
HAL_SPI_SLV_STATUS_RX_EMPTY10RX FIFO 空
HAL_SPI_SLV_STATUS_RX_FULL11RX FIFO 满
HAL_SPI_SLV_STATUS_IRQ12模块聚合 IRQ 待处理

HAL 状态 bit 与 SSLVCTRL[24:13] 的原始位位置不同。需要寄存器原始位时使用ll_spi_slv_get_raw_status();应用侧应使用 HAL 状态定义。

3.4 HAL 返回值约定

返回值SPI_SLV HAL 中的典型含义
IM_OK操作成功
IM_ERR_INVALID_PARAM句柄、实例、输出指针、枚举、bitmask 或配置范围非法
IM_ERR_BUSY重复初始化、TX FIFO 已满,或设置传输计数时 RX/TX 已使能
IM_ERR_NOT_READYRX FIFO 为空,或复位所需系统 tick 尚未初始化
IM_ERR_TIMEOUT等待硬件复位完成超过内部超时
IM_ERR_UNSUPPORTED寄存器 dump 功能未编译

hal_spi_slv_init() 和 hal_spi_slv_deinit() 还会透传 CPM 接口返回的错误码。

4. 典型用法

4.1 轮询式全双工从机准备

以下代码只展示 HAL 调用顺序。BSP 引脚初始化和主机启动应由系统在相应位置完成。

hal_spi_slv_handle_t hspi_slv;
hal_spi_slv_fifo_level_t level;
uint32_t rx_word;
error_code_t ret;

ret = hal_spi_slv_handle_init(&hspi_slv, SPI_SLV1);
if (ret != IM_OK) {
    return ret;
}

hspi_slv.init.cpol = HAL_SPI_SLV_CLOCK_POLARITY_LOW;
hspi_slv.init.cpha = HAL_SPI_SLV_CLOCK_PHASE_FIRST_EDGE;
hspi_slv.init.rx_channel = HAL_SPI_SLV_CHANNEL_SINGLE;
hspi_slv.init.tx_channel = HAL_SPI_SLV_CHANNEL_SINGLE;
hspi_slv.init.rx_bitwidth = 8U;
hspi_slv.init.tx_bitwidth = 8U;

ret = hal_spi_slv_init(&hspi_slv);
if (ret != IM_OK) {
    return ret;
}

ret = hal_spi_slv_transfer_count_set(&hspi_slv, 64U, 64U);
if (ret != IM_OK) {
    goto out_deinit;
}

(void)hal_spi_slv_irq_clear(&hspi_slv);
ret = hal_spi_slv_enable(&hspi_slv, HAL_SPI_SLV_DIRECTION_TX_RX);
if (ret != IM_OK) {
    goto out_deinit;
}

/* 在主机开始 CS/SCLK 前,按 TX 可用水位写入待发 frame。 */
ret = hal_spi_slv_fifo_level_get(&hspi_slv, &level);
if ((ret == IM_OK) && (level.tx_available_count != 0U)) {
    ret = hal_spi_slv_fifo_write(&hspi_slv, 0x5AU);
}

/* 主机开始传输后,轮询 RX 水位并读取。 */
if (ret == IM_OK) {
    ret = hal_spi_slv_fifo_level_get(&hspi_slv, &level);
}
if ((ret == IM_OK) && (level.rx_fill_count != 0U)) {
    ret = hal_spi_slv_fifo_read(&hspi_slv, &rx_word);
}

(void)hal_spi_slv_disable(&hspi_slv, HAL_SPI_SLV_DIRECTION_TX_RX);
out_deinit:
(void)hal_spi_slv_deinit(&hspi_slv);
return ret;

实际轮询流程应增加超时、循环填充/读取、错误状态检查和完整帧数校验。仓库中的code/examples/hal/spi_slv_hal_example.c 提供 SPI_SLV1 与 SSI1 互收发的完整示例。

4.2 IRQ 回调配置

static void spi_slv_rx_ready(hal_spi_slv_handle_t *hspi_slv,
                             void *user_data)
{
    uint32_t word;

    (void)user_data;
    while (hal_spi_slv_fifo_read(hspi_slv, &word) == IM_OK) {
        /* 将 word 放入非阻塞软件队列。 */
    }
}

static void spi_slv_error(hal_spi_slv_handle_t *hspi_slv,
                          void *user_data)
{
    uint32_t status;

    (void)user_data;
    (void)hal_spi_slv_status_get(hspi_slv, &status);
}

(void)hal_spi_slv_callback_register(&hspi_slv,
                                    HAL_SPI_SLV_CALLBACK_RX_READY,
                                    spi_slv_rx_ready);
(void)hal_spi_slv_callback_register(&hspi_slv,
                                    HAL_SPI_SLV_CALLBACK_ERROR,
                                    spi_slv_error);

(void)hal_spi_slv_irq_config(
    &hspi_slv,
    HAL_SPI_SLV_IRQ_READ_FLAG |
        HAL_SPI_SLV_IRQ_READ_EMPTY_ERR |
        HAL_SPI_SLV_IRQ_WRITE_FULL_ERR,
    HAL_SPI_SLV_IRQ_READ_EMPTY_ERR |
        HAL_SPI_SLV_IRQ_WRITE_FULL_ERR,
    1U);

SoC IRQ 入口仍需由上层注册,并在入口中调用:

hal_spi_slv_irq_handler(&hspi_slv);

5. 使用检查表

  • BSP 已为目标实例配置 CLK、CS 和所需数据线;dual/quad 模式配置了足够的数据引脚。

  • 已在使用 HAL 前完成系统 tick 初始化,以便 HAL 硬件复位超时逻辑工作。

  • 主机和 SPI_SLV 的 CPOL、CPHA、位宽、端序及通道模式一致。

  • 在 RX/TX 均关闭时设置 RXN/TXN,并在主机开始 SCLK 前将 SPI_SLV armed。

  • FIFO 访问前检查 fill/unfill 水位,避免读空和写满。

  • HAL IRQ enable mask 与 LL 硬件 mask 的相反语义没有混用。

  • IRQ 回调只执行短小、非阻塞操作;任务间共享句柄和 FIFO 时有明确同步。

  • DMA 模式同时正确配置 request、数据寄存器地址、宽度、长度和固定外设地址。

  • 传输结束或异常退出时关闭 RX/TX,并按生命周期调用 reset 或 deinit。