API GUIDE / SPI / HAL

G32S10 SPI HAL 接口

HAL 层接口:重要边界:

1. 分层关系与文件组织

APPLICATION  SPI Middleware / Advanced Driver  总线抽象、设备访问或直接使用 HAL
↓
PIN CONTROL  GPIO pinmux  选择 SPI 信号引脚与复用功能
INTERRUPT  SoC IRQ request / routing  把 SPI 中断接入统一中断分发
↓  平台资源就绪后进入 SPI 数据通路
HAL  HAL SPI  控制、FIFO、IRQ 源与 DMA 请求语义
↓
LL  LL SPI  寄存器访问与字段级控制
↓
HARDWARE REGISTERS  SPI0 / SPI1 Registers  实例地址、寄存器布局与位域定义
层次负责内容不负责内容
Platform/ApplicationGPIO pinmux、控制器选择、SoC IRQ 申请和路由SPI 寄存器细节和 HAL 内部状态
HAL SPICPM module clock/gate、参数校验、寄存器组合、FIFO、状态、控制器 IRQ source、DMA request 语义和 callback 分发SoC im_irq_request()、板级 pinmux、完整传输状态机和 timeout
LL SPI寄存器位级读写参数保护、软件状态、传输流程和并发保护

重要边界:

  • hal_spi_init() 要求平台已准备 GPIO pinmux;HAL 配置并使能对应 CPM module clock/gate,但保持 SPI 控制器 disabled。

  • hal_spi_irq_config() 只控制 SPI 模块内部中断源,不申请或使能 SoC IRQ。

  • hal_spi_dma_request_config() 只维护 DMA request 语义,不申请 DMA 通道,也不通过 TIE/RIE 模拟 DMA enable。

  • HAL 只记录 TX underrun 和 RX overrun 等硬件错误,不表达完整传输的 busy、timeout 或完成状态机。

1.1 Kconfig

选项默认值说明
DRIVER_SPIn编译 G32S10 SPI HAL,并选择 CPM 依赖
SPI_ENABLE_DEBUG_HELPERSn构建 hal_spi_regs_dump();需要同时开启全局 debug helper

仅使用 HAL 时启用:

CONFIG_DRIVER_SPI=y

2. 硬件能力与资源模型

2.1 串行时钟

规格书定义:

SPI_CLK = module_clock_hz / (2 * (CGV + 1))

hal_spi_init() 在 config.module_clock_parent 非 0 时使用该父时钟,否则使用 HAL_SPI_MODULE_CLOCK_PARENT;在 config.module_clock_hz 非 0 时请求该频率,否则请求 HAL_SPI_MODULE_CLOCK_HZ。随后 HAL 尝试读取 CPM module clock,回读失败或返回 0 时使用刚请求的 module clock 作为有效值。CGV 范围为 0x00..0xFF,hal_spi_handle_t.module_clock_hz 和 actual_clock_hz 分别保存用于计算的有效 module clock 与计算得到的 SPI clock。

CGV = 0 表示 module clock 二分频,不表示不分频。例如 module clock 为 60 MHz 时,CGV = 0 得到 30 MHz SPI clock。

HAL 根据有效 module clock 计算 CGV;若所需 divider 超出字段编码范围,则将 CGV 饱和到字段边界,并通过 actual_clock_hz 记录最终 SPI clock。

3. 公共宏和返回状态

3.1 HAL 公开宏

宏值说明
HAL_SPI_INSTANCE_COUNT2UHAL 支持的控制器数量
HAL_SPI_FIFO_DEPTH128UTX/RX FIFO 深度
HAL_SPI_BITS_PER_WORD_MIN2U最小帧长
HAL_SPI_BITS_PER_WORD_MAX32U最大帧长
HAL_SPI_CLOCK_DIVIDER_MAX0xFFUCGV 最大值
HAL_SPI_HARDWARE_CHIP_SELECT_NONE0xFFFFFFFFU不使用硬件 CS
HAL_SPI_HARDWARE_CHIP_SELECT_MAX0x1U最大硬件 CS 编号
HAL_SPI_INTERVAL_TIME_MAX0x7FFFUIVLTM 最大值
HAL_SPI_INTERVAL_FRAME_COUNT_MAX0x7UICC 最大字段值
HAL_SPI_RECEIVE_COUNT_MAX0xFFFFURCNT 最大值
HAL_SPI_DEFAULT_CLOCK_HZ1000000UHAL 默认请求时钟
HAL_SPI_MODULE_CLOCK_PARENTHAL_CPM_ID_CLK_SCLK_A默认 CPM module clock 父源
HAL_SPI_MODULE_CLOCK_HZ80000000UHAL init 默认请求的 CPM module clock
HAL_SPI_DEFAULT_MODULE_CLOCK_HZHAL_SPI_MODULE_CLOCK_HZHAL_SPI_MODULE_CLOCK_HZ 的兼容别名

4. 公开类型

4.1 HAL 枚举类型

4.1.1 协议格式

枚举值说明
HAL_SPI_FRAME_FORMAT_SPI0Motorola SPI
HAL_SPI_FRAME_FORMAT_SSP1TI SSP;不允许 2 bit frame
HAL_SPI_FRAME_FORMAT_NM12National Microwire 1
HAL_SPI_FRAME_FORMAT_NM23National Microwire 2

4.1.2 Endian

枚举说明
HAL_SPI_ENDIAN_MSB_FIRSTMSB first
HAL_SPI_ENDIAN_MSB_FIRST_BYTE_SWAPMSB first 并交换 byte
HAL_SPI_ENDIAN_LSB_FIRSTLSB first
HAL_SPI_ENDIAN_LSB_FIRST_BYTE_SWAPLSB first 并交换 byte

4.1.3 CPOL、CPHA 和 CS

类型枚举说明
hal_spi_clock_polarity_tLOW / HIGHSPI clock 空闲电平
hal_spi_clock_phase_tFIRST_EDGE / SECOND_EDGE第一个边沿采样或驱动
hal_spi_cs_active_level_tACTIVE_LOW / ACTIVE_HIGHCS 有效电平

4.1.4 状态、错误、IRQ 和 DMA

类型成员
hal_spi_status_tTX half empty、RX half full、TX underrun、RX overrun、END、BUSY、TX full、RX empty
hal_spi_error_tTX underrun、RX overrun
hal_spi_irq_source_tTX threshold、RX threshold、TX underrun、RX overrun、END
hal_spi_dma_request_tTX、RX
hal_spi_callback_id_tTX ready、RX ready、ERROR、END

IRQ mask 与 DMA request mask 是独立语义。PDMA request 由 DMA 控制器 request source 选择,DMA 使用方不应通过 TIE/RIE 模拟 DMA enable。

4.2 hal_spi_config_t 默认值和约束

| 字段 | HAL 默认值 | 约束/说明 | | --- | --- | --- | --- | | instance | SPI0 | 必须为 SPI0/SPI1 | | clock_hz | 1 MHz | init 配置中 0 表示默认 1 MHz | | bits_per_word | 8 | 2..32 | | frame_format | SPI | SPI/SSP/NM1/NM2 | | clock_polarity | LOW | SPI 格式有效 | | clock_phase | FIRST_EDGE | SPI 格式有效 | | tx_endian | MSB first | 四种模式之一 | | rx_endian | MSB first | 四种模式之一 | | hardware_chip_select | 0 | SPI1 不支持硬件 CS1 | | hardware_cs_active_level | active low | 使用硬件 CS 时生效 | | continue_on_tx_underrun | false | SSP 不允许 true | | interval_enable | false | true 时 interval_time 必须非零 | | interval_count_32k | false | interval 使用 32K 计数时钟 | | interval_keep_cs | false | interval gap 是否保持 CS | | interval_time | 0 | 0..0x7FFF | | interval_frame_count | 0 | ICC 原始值 0..7;实际每组帧数为值 + 1 | | loopback | false | 内部回环 | | tx_threshold | 1 | TTRG 原始值 0..15 | | rx_threshold | 1 | RTRG 原始值 0..15;传输层可以在空闲时通过 HAL 接口调整 | | module_clock_parent | 0 | 0 表示使用 HAL_SPI_MODULE_CLOCK_PARENT;init 后保存实际选择的父源 | | module_clock_hz | 0 | 0 表示使用 HAL_SPI_MODULE_CLOCK_HZ;init 后保存请求频率 |

4.3 hal_spi_handle_t

分区字段说明
配置快照instance、configinit 成功后只读
内部状态error_codesticky 的 HAL 硬件错误位
内部状态irq_enable_mask当前 HAL IRQ source mask
内部状态dma_request_mask当前 HAL DMA request 语义 mask
内部状态actual_clock_hz实际 SPI clock
内部状态module_clock_hzHAL 用于分频计算的有效 SPI module clock
内部状态callback slots / user_data通过注册接口维护
内部状态is_initializedHAL 生命周期标志

应用不应直接写入 HAL handle 内部状态。

5. HAL 接口规范

5.1 HAL 实现边界

HAL 是无 timeout、无完整 transfer busy 状态机的硬件积木层。它保留硬件相关错误 TX_UNDERRUN 和 RX_OVERRUN,但不表达上层传输的 BUSY/ERROR/TIMEOUT 状态机。

HAL init 不处理 GPIO pinmux、SoC IRQ request 或 DMA 通道打开;SPI 实例固定对应的 CPM module clock/gate 由 HAL 管理。

5.2 初始化与生命周期

接口原型摘要行为
hal_spi_config_struct_initvoid (...config)填充 HAL 默认配置
hal_spi_initerror_code_t (handle, config)配置并使能 CPM clock/gate,配置寄存器并保持 disabled,初始化 no-op callbacks
hal_spi_deiniterror_code_t (handle)关闭 IRQ/DMA 语义、disable、flush,并关闭 CPM clock/gate
hal_spi_enableerror_code_t (handle)使能控制器
hal_spi_disableerror_code_t (handle)禁用控制器

hal_spi_init() 的时钟和寄存器配置顺序为:

  1. 根据 SPI0/SPI1 取得固定的 CPM module clock、gate 和默认 parent。

  2. 按配置选择 parent 并设置请求的 module clock,enable module clock 和 gate;回读有效时更新缓存,否则保留请求值。

  3. 根据请求 SPI clock 和缓存的有效 module clock 计算 CGV。

  4. disable SPI 和所有内部 IRQ source。

  5. 选择新 TX FIFO empty 判定模式。

  6. 配置接收、RCNT、endian、loopback 和硬件 CS。

  7. 配置协议、位宽、CPHA/CPOL、threshold、interval 和 CGV。

  8. 保持 SPI disabled,等待传输层准备 FIFO/RCNT/IRQ/DMA 后 enable。

5.3 时钟

error_code_t hal_spi_set_clock(hal_spi_handle_t *handle,
                               uint32_t clock_hz);
  • clock_hz 必须非零;当请求不能被 CGV 精确表达时,应通过 actual_clock_hz 获取最终 SPI clock。

  • 只能在 SPI disabled、传输空闲时调用;控制器 enabled 时返回 IM_ERR_BUSY。

  • HAL 使用 handle 中缓存的有效 module clock 计算并更新 CGV,不要求 CPM 再次提供频率回读。

  • config.clock_hz 和 actual_clock_hz 更新;module_clock_hz 保持初始化时的有效 module clock 不变。

5.4 FIFO

接口主要返回说明
hal_spi_fifo_flushIM_OKflush TX/RX,并清 TUNDR、ROVER、END
hal_spi_fifo_writeIM_ERR_BUSYTX full 时不写,否则写一个 32 bit frame word
hal_spi_fifo_readIM_ERR_NOT_READYRX empty 时不读,否则读一个 word
hal_spi_fifo_level_getIM_OK返回 TX count、RX count 和 TX free space
hal_spi_threshold_configIM_ERR_INVALID_PARAM配置原始 TTRG/RTRG 0..15,并更新快照
hal_spi_receive_count_configIM_ERR_INVALID_PARAM0 禁用 RCNT;1..0xFFFF 配置并使能

5.5 状态

error_code_t hal_spi_status_get(const hal_spi_handle_t *handle,
                                uint32_t *status_out);

error_code_t hal_spi_status_clear(hal_spi_handle_t *handle,
                                  uint32_t status_mask);

status_get 单次读取 SSISR,映射为 HAL_SPI_STATUS_*。status_clear 只对 TUNDR、ROVER 和 END 执行 clear;level 类型的 TX/RX threshold 状态不能靠 clear 接口消除。

5.6 IRQ

error_code_t hal_spi_irq_config(hal_spi_handle_t *handle,
                                uint32_t irq_enable_mask);

error_code_t hal_spi_callback_register(hal_spi_handle_t *handle,
                                       hal_spi_callback_id_t callback_id,
                                       hal_spi_callback_t callback);

error_code_t hal_spi_user_data_set(hal_spi_handle_t *handle,
                                   void *user_data);

void hal_spi_irq_handler(hal_spi_handle_t *handle);

说明:

  • irq_config 接收 HAL_SPI_IRQ_* mask;0 表示 mask 所有 SPI 内部 IRQ source。

  • callback 传 NULL 会恢复 HAL 默认 no-op callback。

  • user_data 由四类 callback 共享。

  • handler 先处理并 clear TUNDR/ROVER,再分发 RX/TX level callback,最后处理并 clear END。

  • handler 不 request、enable、disable 或 release SoC IRQ。

5.7 DMA 辅助

error_code_t hal_spi_dma_request_config(hal_spi_handle_t *handle,
                                        uint32_t request_mask);

error_code_t hal_spi_tx_dma_address_get(const hal_spi_handle_t *handle,
                                        uintptr_t *address_out);

error_code_t hal_spi_rx_dma_address_get(const hal_spi_handle_t *handle,
                                        uintptr_t *address_out);

hal_spi_dma_request_config() 记录 TX/RX DMA request 语义,不打开 DMA channel,也不切换 TIE/RIE。TX/RX 地址接口当前都返回 SSIDR 地址。

5.8 Debug dump

error_code_t hal_spi_regs_dump(const hal_spi_handle_t *handle);

仅当 CONFIG_SDK_ENABLE_DEBUG_HELPERS 和 CONFIG_SPI_ENABLE_DEBUG_HELPERS 同时启用时输出 SPI 寄存器;否则返回 IM_ERR_UNSUPPORTED。dump 跳过读取会消耗 RX FIFO 数据的 SSIDR,也跳过只写的 SSITLOAD。

6. 行为约束与规格书流程

6.1 软件配置流程对齐

规格书要求在使能 SPI 前完成 GPIO、时钟、IRQ mask、错误清除、FIFO flush、协议、时钟、阈值、帧宽、interval 和 RCNT 等配置。

当前分层关系如下:

规格书步骤负责方
GPIO pinmuxBSP/平台
CPM module clock/gateHAL init/deinit
SoC IRQ request/enableHAL 上层调用方
SPI 内部 IRQ sourceHAL hal_spi_irq_config()
清 TUNDR/ROVER/END 和 flush FIFOHAL 接口及上层传输流程
SPI serial clock、协议、位宽、intervalHAL init/hal_spi_set_clock()
RCNT 和传输期 thresholdHAL 上层调用方
FIFO CPU/DMA 搬运HAL 上层调用方
enable/disableHAL 上层调用方通过 HAL 接口控制

hal_spi_init() 完成静态配置后保持控制器 disabled。上层应在 FIFO、RCNT、IRQ 或 DMA 等传输资源准备完成后再调用 hal_spi_enable()。