SPI

概述

Ameba 系列产品支持摩托罗拉的 SPI 接口,能够进行高效的四线全双工通信。

功能特性

  • 支持主机或从机操作模式

  • 独立的中断屏蔽功能

  • 支持硬件/软件片选

  • 可编程特性

    • 支持动态控制串行接口频率(主机模式有效)

    • 可配置的数据帧大小(4~16 bits)

    • 可配置的时钟极性和相位

    • 可编程延迟采样时间(主机模式有效)

  • 传输模式

    • 发送和接收

    • 仅发送

    • 仅接收

  • 操作模式

    • 轮询模式

    • 中断模式

    • DMA 模式

串行时钟频率

接口频率(fsclk_out)支持

  • 主机模式:支持高达 50MHz。

  • 从机模式:支持最高 25MHz。

注意

支持从机超频模式

  • 前提条件:与之通信的主机需支持延迟采样机制

  • 延迟采样机制:以双方规定的下降沿采样数据为例,图中展示了标准采样边沿与延迟采样机制的对比

  • 理论极限:50 MHz

    ../../_images/spi_master_sample_delay.svg

    主机延迟采样机制

分频机制

  • 核心公式fsclk_out = fssi_clk/div

    其中: fssi_clk 时钟源为 PLL

  • 约束条件

    • 分频系数 div 仅支持偶数值

    • 实际输出频率为离散值,这意味输出的 fsclk_out 可能与期望值存在偏差。

注意

Bootloader 阶段配置 PLL 的输出会影响 SPI 串行时钟频率。调整 PLL 输出的方法请参考 ameba_bootcfg

例如,SPI 目标 工作时钟 ( fssi_clk ) 为 100MHz。在 PLL 设定为 524MHz 时,SPI 实际 工作时钟只有 86.67MHz。此时, fsclk_out 最大只有 43.3MHz,无法达到期望的最大值 50MHz。

引脚复用配置策略

接口频率与引脚配置如下表所示:

配置模式

主设备频率

从设备频率

专用引脚

50 MHz

25 MHz

全矩阵引脚

25 MHz

12.5 MHz

备注

关于专用引脚与全矩阵引脚的区别,请参考 功能复用 介绍。

工作模式

根据需要,可配置 SPI 工作在以下三种模式:

轮询模式

这是最基础的工作模式。CPU 通过轮询 SPI 的状态寄存器,然后根据需要读写 FIFO 缓冲区,以实现数据的收发。

适用对实时性要求较低的小规模数据传输。

中断模式

当满足配置的触发条件时,SPI 硬件会发送中断信号通知 CPU 处理相关事务。

该方式无需频繁轮询,使得 CPU 占用率降低。

中断响应延迟导致的数据传输异常

若 CPU 因为 OS 临界区等原因,无法及时响应中断,可能会引发 FIFO Overflow/Underflow 问题:

  • 发送响应延迟

    因未及时填充 TX FIFO,SPI 工作在不同角色下引发的问题如下:

    • 主设备:

      • FIFO 变空引发 CS 引脚拉高,导致数据传输中断。

    • 从设备:

      • FIFO 变空触发 Underflow 事件,此时 MISO 线路上数据无效。

      • 主设备对此无感,继续采样 MISO 从而可能收到错误数据。

  • 接收响应延迟

    因未及时读取 RX FIFO,导致 FIFO Overflow:

    • 影响:硬件暂停接收新数据。

    • 结果:软件接收的数据不完整。

DMA 模式

通过 SPI 与 DMA 握手机制,由 DMA 控制器负责数据传输,减轻 CPU 的处理负担。

适用于需处理大量数据的应用,如音视频流处理、大数据传输等情境。

备注

有关使用 DMA 模式传输的注意事项,请参考 DMA 和缓存 介绍。

应用示例

SDK 提供了两类功能示例,帮助开发者了解和使用 SPI 功能:

  • mbed 示例

    • 路径:{SDK}\example\peripheral\mbed\SPI\{demo}

    • 展示如何在 mbed 环境中实现 SPI 控制。

  • raw 示例

    • 路径:{SDK}\example\peripheral\raw\SPI\{demo}

    • 展示如何在无抽象层的情况下直接控制 SPI。

以下是对 raw 示例功能的简要说明:

备注

要了解示例支持的芯片,请查看示例路径下的 README.md 文件。

Raw API

SPI Exported Types

struct SPI_DevTable

SPI Dev table Structure Definition.

Public Members

SPI_TypeDef *SPIx

SPI peripheral base address

u32 Tx_HandshakeInterface

GDMA TX handshake interface number

u32 Rx_HandshakeInterface

GDMA RX handshake interface number

IRQn_Type IrqNum

SPI interrupt request number

struct SSI_InitTypeDef

SPI Init Structure Definition.

Public Members

u32 SPI_DmaRxDataLevel

Specifies the DMA receive data level. The dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or above this field value+1,and RDMAE=1. For Amebaz, the value range of this parameter should be 0 to 63,because the depth of Rx FIFO is 64.

u32 SPI_DmaTxDataLevel

Specifies the DMA transmit data level. The dma_tx_req is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value,and TDMAE=1. For Amebaz, the value range of this parameter should be 0 to 63,because the depth of Rx FIFO is 64.

u32 SPI_RxThresholdLevel

Specifies the receive FIFO threshold level. This Parameter controls the level of entries(or above) at which the receive FIFO controller triggers an interrupt.When the number of receive FIFO entries is greater than or equal to this value +1,the receive FIFO full interrupt is triggered. For Amebaz, the value range of this parameter should be 0 to 63,because the depth of Rx FIFO is 64.

u32 SPI_TxThresholdLevel

Specifies the transmit FIFO threshold level. This Parameter controls the level of entries (or below) at which the transmit FIFO controller triggers an interrupt.When the number of transmit FIFO entries is less than or equal to this value,the transmit FIFO empty interrupt is triggered. For Amebaz, the value range of this parameter should be 0 to 63,because of the depth of Rx FIFO is 64.

u32 SPI_SlaveSelectEnable

Set the slave select enable flag. This Parameter controls which slave to be selected by master,each bit in SER register corresponds to a slave select line(ss_x_n) from spi master. The default value of this parameter is 0,and one slave is selected.if more slaves to be selected, you may use SW way to do this.And this parameter is used only when the device is master.

u32 SPI_ClockDivider

Specifies the SPI Baud Rate. The value of sclk_out equals to ssi_clk devides the value of this parameter The LSB for this field is always set to 0 and is unaffected by a write operation,which ensures an even value is held.

u32 SPI_DataFrameNumber

Specifies the number of data frames master wants to receive . When TMOD=10 or TMOD=11,Ctrl1 register uses this value to set the number of data frames to be continuous received. The value of this parameter should be set to the number of data frames that to be received minus one.And this parameter is used only when the device is master.

u32 SPI_DataFrameFormat

Selects which serial protocol transfers the data . This parameter can be a value of SPI Frame Format.

u32 SPI_DataFrameSize

Selects the data frame length . This parameter can be a value of SPI Data Frame Size. Need to right-justify transmit data before writing into the transmit FIFO The transmit logic ignores the upper unused bits when transmitting the data.

u32 SPI_InterruptMask

Specifies which interrupt to be enable. Each bit in this parameter corresponds to a specific interrupt.

u32 SPI_Role

Specifies the role of SPI device. This parameter can be a value of SPI Role.

u32 SPI_SclkPhase

Specifies the serial clock phase. When SPI_SclkPhase = 0, data are captured on the first edge of the serial clock. When SPI_SclkPhase = 1, the serial clock starts toggling one cycle after the slave select line is activated, and data are captured on the second edge of the serial clock. This parameter can be a value of SPI Clock Phase. Valid when the frame format(FRF) is set to Motorola SPI.

u32 SPI_SclkPolarity

Specifies the serial clock polarity. When SPI_SclkPolarity = 0, the serial clock remains low when idle. When SPI_SclkPolarity = 1, the serial clock remains high when idle. This parameter can be a value of SPI Clock Polarity. Valid when the frame format(FRF) is set to Motorola SPI.

u32 SPI_TransferMode

Selects the mode of transfer for serial communication. This parameter can be a value of SPI Transfer Mode. This transfer mode is only valid when the DW_apb_ssi is configured as a master device.

SPI Exported Constants

SPI DMA Control

/* DMA disabled for SPI. */
#define SSI_NODMA (0)

/* RX DMA channel enabled. */
#define SSI_RXDMA_ENABLE (1)

/* TX DMA channel enabled. */
#define SSI_TXDMA_ENABLE (2)

/* Both TX and RX DMA enabled. */
#define SSI_TRDMA_ENABLE (3)

SPI Data Frame Size

/* 4-bit data frame size. */
#define DFS_4_BITS (3)

/* 5-bit data frame size. */
#define DFS_5_BITS (4)

/* 6-bit data frame size. */
#define DFS_6_BITS (5)

/* 7-bit data frame size. */
#define DFS_7_BITS (6)

/* 8-bit data frame size. */
#define DFS_8_BITS (7)

/* 9-bit data frame size. */
#define DFS_9_BITS (8)

/* 10-bit data frame size. */
#define DFS_10_BITS (9)

/* 11-bit data frame size. */
#define DFS_11_BITS (10)

/* 12-bit data frame size. */
#define DFS_12_BITS (11)

/* 13-bit data frame size. */
#define DFS_13_BITS (12)

/* 14-bit data frame size. */
#define DFS_14_BITS (13)

/* 15-bit data frame size. */
#define DFS_15_BITS (14)

/* 16-bit data frame size. */
#define DFS_16_BITS (15)

SPI FIFO Depth

/* SPI transmit FIFO depth in entries. */
#define SSI_TX_FIFO_DEPTH (64)

/* SPI receive FIFO depth in entries. */
#define SSI_RX_FIFO_DEPTH (64)

SPI Frame Format

/* Motorola SPI frame format. */
#define FRF_MOTOROLA_SPI (0)

SPI Role

/* SPI operates as slave device. */
#define SSI_SLAVE (0)

/* SPI operates as master device. */
#define SSI_MASTER (1)

SPI Clock Phase

/* Clock toggles in middle of first data bit. */
#define SCPH_TOGGLES_IN_MIDDLE (0)

/* Clock toggles at start of first data bit. */
#define SCPH_TOGGLES_AT_START (1)

SPI Clock Polarity

/* Inactive serial clock polarity is low. */
#define SCPOL_INACTIVE_IS_LOW (0)

/* Inactive serial clock polarity is high. */
#define SCPOL_INACTIVE_IS_HIGH (1)

SPI Slave Select Toggle Phase

/* Slave select does not toggle between frames. */
#define SPI_SS_NOT_TOGGLE (0)

/* Slave select toggles between successive frames. */
#define SPI_SS_TOGGLE (1)

SPI Transfer Mode

/* Transmit and receive mode. */
#define TMOD_TR (0)

/* Transmit only mode. */
#define TMOD_TO (1)

/* Receive only mode. */
#define TMOD_RO (2)

SPI Exported Functions

u32 SPI_GetINTConfig(SPI_TypeDef *spi_dev)

Get SPIx interrupt mask configuration.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

The current interrupt mask register value, which can be a combination of:

  • SPI_BIT_TXEIM

  • SPI_BIT_TXOIM

  • SPI_BIT_RXUIM

  • SPI_BIT_RXOIM

  • SPI_BIT_RXFIM

  • SPI_BIT_MSTIM_FAEIM

  • SPI_BIT_TXUIM

  • SPI_BIT_SSRIM

备注

When a bit is 1, the corresponding interrupt is enabled; otherwise, it is disabled.

u32 SSI_Busy(SPI_TypeDef *spi_dev)

Check if SPIx is busy.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

SPIx busy status value:

  • 1: Busy

  • 0: Not Busy

void SSI_Cmd(SPI_TypeDef *spi_dev, u32 NewStatus)

Enable or disable SPIx peripheral.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • NewStatus --

    This parameter can be one of the following values:

    • ENABLE

    • DISABLE

u32 SSI_GetDataFrameNumber(SPI_TypeDef *spi_dev)

Get SPIx data frame number.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Data frame number

u32 SSI_GetDataFrameSize(SPI_TypeDef *spi_dev)

Get SPIx data frame size.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Data frame size in bits (value range: 4-16).

u32 SSI_GetIsr(SPI_TypeDef *spi_dev)

Get SPIx Interrupt Status.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Current interrupt status, each bit of this value represents one interrupt status:

bit 7 : SSRIS SS_N Rising Edge Detect Interrupt Status. (valid when device is slave)

  • 0 : ssi_ssr_intr interrupt not active after masking

  • 1 : ssi_ssr_intr interrupt is active after masking

bit 6 : TXUIS Transmit FIFO Under Flow Interrupt Status. (valid when device is slave)

  • 0 : ssi_txu_intr interrupt is not active after masking

  • 1 : ssi_txu_intr interrupt is active after masking

bit 5 : FAEIS Frame Alignment Interrupt Status. (valid when device is slave)

  • 0 : ssi_fae_intr interrupt not active after masking

  • 1 : ssi_fae_intr interrupt is active after masking

bit 5 : MSTIS Multi-Master Contention Interrupt Status. (valid when device is master)

  • 0 : ssi_mst_intr interrupt not active after masking

  • 1 : ssi_mst_intr interrupt is active after masking

bit 4 : RXFIS Receive FIFO Full Interrupt Status.

  • 0 : ssi_rxf_intr interrupt is not active after masking

  • 1 : ssi_rxf_intr interrupt is full after masking

bit 3 : RXOIS Receive FIFO Overflow Interrupt Status.

  • 0 : ssi_rxo_intr interrupt is not active after masking

  • 1 : ssi_rxo_intr interrupt is active after masking

bit 2 : RXUIS Receive FIFO Underflow Interrupt Status.

  • 0 : ssi_rxu_intr interrupt is not active after masking

  • 1 : ssi_rxu_intr interrupt is active after masking

bit 1 : TXOIS Transmit FIFO Overflow Interrupt Status.

  • 0 : ssi_txo_intr interrupt is not active after masking

  • 1 : ssi_txo_intr interrupt is active after masking

bit 0 : TXEIS Transmit FIFO Empty Interrupt Status.

  • 0 : ssi_txe_intr interrupt is not active after masking

  • 1 : ssi_txe_intr interrupt is active after masking

u32 SSI_GetRawIsr(SPI_TypeDef *spi_dev)

Get SPIx Raw Interrupt Status.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Current raw interrupt status, each bit of this value represents one raw interrupt status:

bit 7 : SSRIR SS_N Rising Edge Detect Interrupt Status. (valid when device is slave)

  • 0 : ssi_ssr_intr interrupt not active after masking

  • 1 : ssi_ssr_intr interrupt is active after masking

bit 6 : TXUIR Transmit FIFO Under Flow Interrupt Status. (valid when device is slave)

  • 0 : ssi_txu_intr interrupt is not active after masking

  • 1 : ssi_txu_intr interrupt is active after masking

bit 5 : FAEIR Frame Alignment Interrupt Status. (valid when device is slave)

  • 0 : ssi_fae_intr interrupt not active after masking

  • 1 : ssi_fae_intr interrupt is active after masking

bit 5 : MSTIR Multi-Master Contention Raw Interrupt Status.(valid when device is master)

  • 0 : ssi_mst_intr interrupt not active prior to masking

  • 1 : ssi_mst_intr interrupt is active prior to masking

bit 4 : RXFIR Receive FIFO Full Raw Interrupt Status.

  • 0 : ssi_rxf_intr interrupt is not active prior to masking

  • 1 : ssi_rxf_intr interrupt is full prior to masking

bit 3 : RXOIR Receive FIFO Overflow Raw Interrupt Status.

  • 0 : ssi_rxo_intr interrupt is not active prior to masking

  • 1 : ssi_rxo_intr interrupt is active prior to masking

bit 2 : RXUIR Receive FIFO Underflow Raw Interrupt Status.

  • 0 : ssi_rxu_intr interrupt is not active prior to masking

  • 1 : ssi_rxu_intr interrupt is active prior to masking

bit 1 : TXOIR Transmit FIFO Overflow Raw Interrupt Status.

  • 0 : ssi_txo_intr interrupt is not active prior to masking

  • 1 : ssi_txo_intr interrupt is active prior to masking

bit 0 : TXEIR Transmit FIFO Empty Raw Interrupt Status.

  • 0 : ssi_txe_intr interrupt is not active prior to masking

  • 1 : ssi_txe_intr interrupt is active prior to masking

u32 SSI_GetRxCount(SPI_TypeDef *spi_dev)

Get SPIx the number of valid entries in receive FIFO.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

The number of valid entries in receive FIFO.Value range:0-64.

u32 SSI_GetSlaveEnable(SPI_TypeDef *spi_dev)

Get which slave is selected.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Each bit of this value which is set to 1 corresponds to the slave being selected.

备注

Valid only when the device is configured as a master.

u32 SSI_GetStatus(SPI_TypeDef *spi_dev)

Get SPIx transfer status.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Current transfer status, each bit of this value represents one transfer status:

bit 5 : TXE Transmission Error.(valid when device is slave)

  • 0 : No Error

  • 1 : Transmission error

bit 4 : RFF Receive FIFO Full.

  • 0 : Receive FIFO is not full

  • 1 : Receive FIFO is full

bit 3 : RFNE Receive FIFO Not Empty.

  • 0 : Receive FIFO is empty

  • 1 : Receive FIFO is not empty

bit 2 : TFE Transmit FIFO Empty.

  • 0 : Transmit FIFO is not empty

  • 1 : Transmit FIFO is empty

bit 1 : TFNF Transmit FIFO Not Full.

  • 0 : Transmit FIFO is full

  • 1 : Transmit FIFO is not full

bit 0 : BUSY SSI Busy Flag.

  • 0 : idle or disable

  • 1 : active transferring data

u32 SSI_GetTxCount(SPI_TypeDef *spi_dev)

Get SPIx the number of valid entries in transmit FIFO.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

The number of valid entries in transmit FIFO.Value range:0-64.

void SSI_INTConfig(SPI_TypeDef *spi_dev, u32 SSI_IT, u32 newState)

Mask or unmask SPIx interrupt.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • SSI_IT --

    This parameter can be one of the following values or mixed:

    • SPI_BIT_TXEIM

    • SPI_BIT_TXOIM

    • SPI_BIT_RXUIM

    • SPI_BIT_RXOIM

    • SPI_BIT_RXFIM

    • SPI_BIT_MSTIM_FAEIM

    • SPI_BIT_TXUIM

    • SPI_BIT_SSRIM

  • newState --

    This parameter can be one of the following values:

    • ENABLE

    • DISABLE

备注

BIT_IMR_TXUIM, BIT_IMR_SSRIM are for Slave only.

void SSI_Init(SPI_TypeDef *spi_dev, SSI_InitTypeDef *SSI_InitStruct)

Initialize the SPI registers according to the specified parameters in SSI_InitStruct.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • SSI_InitStruct -- Pointer to a SSI_InitTypeDef structure that contains the configuration information for the SPI peripheral.

bool SSI_RXGDMA_Init(u8 Index, GDMA_InitTypeDef *GDMA_InitStruct, void *CallbackData, IRQ_FUN CallbackFunc, u8 *pRxData, u32 Length)

Init and Enable SPI RX GDMA.

参数:
  • Index -- 0 or 1.

  • GDMA_InitStruct -- Pointer to a GDMA_InitTypeDef structure that contains the configuration information for the GDMA peripheral.

  • CallbackData -- GDMA callback data.

  • CallbackFunc -- GDMA callback function.

  • pRxData -- Rx Buffer.

  • Length -- Rx Count.

返回:

The result of RX GDMA initialization:

  • TRUE: RX GDMA initialization successful

  • FALSE: RX GDMA initialization failed

u32 SSI_ReadData(SPI_TypeDef *spi_dev)

Read data from SPIx receive FIFO .

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Data received from SPI receive FIFO.

u32 SSI_Readable(SPI_TypeDef *spi_dev)

Determine SPIx Receive FIFO is empty or not.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Receive FIFO is empty or not:

  • 1: Not Empty

  • 0: Empty

u32 SSI_ReceiveData(SPI_TypeDef *spi_dev, void *RxData, u32 Length)

Receive data from rx FIFO.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • RxData -- Buffer to save data read from SPI FIFO.

  • Length -- Number of data to be read.

返回:

Transfer len

u32 SSI_SendData(SPI_TypeDef *spi_dev, void *TxData, u32 Length, u32 Role)

Send data to tx FIFO.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • TxData -- Buffer to be written to Tx FIFO.

  • Length -- Number of data to be written.

  • Role -- SSI_MASTER or SSI_SLAVE.

返回:

Transfer len

void SSI_SetBaudDiv(SPI_TypeDef *spi_dev, u32 ClockDivider)

Set SPIx clock divider.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • ClockDivider -- Even value between 2 and 65534. And Fsclk_out=Fssi_clk/ClockDivider.

备注

Valid only when the device is configured as a master. And The LSB is always set to 0,and is unaffected by a write operation.

void SSI_SetDataFrameSize(SPI_TypeDef *spi_dev, u32 DataFrameSize)

Set SPIx data frame size.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • DataFrameSize --

    This parameter can be one of the following values:

    • DFS_4_BITS

    • DFS_5_BITS

    • DFS_6_BITS

    • DFS_7_BITS

    • DFS_8_BITS

    • DFS_9_BITS

    • DFS_10_BITS

    • DFS_11_BITS

    • DFS_12_BITS

    • DFS_13_BITS

    • DFS_14_BITS

    • DFS_15_BITS

    • DFS_16_BITS

void SSI_SetDataSwap(SPI_TypeDef *spi_dev, u32 SwapStatus, u32 newState)

Set or reset SPIx data swap bit.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • SwapStatus --

    This parameter can be one of the following values or mixed:

    • SPI_BIT_TXBYTESWAP

    • SPI_BIT_TXBITSWAP

    • SPI_BIT_RXBYTESWAP

    • SPI_BIT_RXBITSWAP

  • newState --

    This parameter can be one of the following values:

    • ENABLE

    • DISABLE

void SSI_SetDmaEnable(SPI_TypeDef *spi_dev, u32 newState, u32 Mask)

Enable or disable SPIx TDMA and RDMA .

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • newState --

    This parameter can be one of the following values:

    • ENABLE

    • DISABLE

  • Mask --

    This parameter can be one of the following values or mixed:

    • SPI_BIT_TDMAE

    • SPI_BIT_RDMAE

void SSI_SetDmaLevel(SPI_TypeDef *spi_dev, u32 TxLevel, u32 RxLevel)

Set SPIx DMA TxLevel and RxLevel.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • TxLevel -- Transmit FIFO Threshold level.Value range: 0 to 63. The dma_tx_req is generated when the number of valid data entries in the transmit FIFO is equal to or below this field value.

  • RxLevel -- Receive FIFO Threshold level.Value range: 0 to 63. The dma_rx_req is generated when the number of valid data entries in the receive FIFO is equal to or above this field value + 1.

void SSI_SetIsrClean(SPI_TypeDef *spi_dev, u32 InterruptStatus)

Clear SPIx interrupt status.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • InterruptStatus -- The value of current interrupt status .

void SSI_SetReadLen(SPI_TypeDef *spi_dev, u32 DataFrameNumber)

Set SPIx the number of data frame to be received.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • DataFrameNumber -- The number of data frames that to be received.

备注

Valid only when the device is configured as a master in TMOD_RO mode

void SSI_SetRole(SPI_TypeDef *spi_dev, u32 role)

Set SPIx as Master or Slave.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • role --

    This parameter can be one of the following values:

    • SSI_MASTER

    • SSI_SLAVE

void SSI_SetRxFifoLevel(SPI_TypeDef *spi_dev, u32 RxThresholdLevel)

Set SPIx Rx FIFO threshold level.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • RxThresholdLevel -- Rx FIFO Threshold Level.Value range: 0 to 63. When the number of receive FIFO entries is greater than or equal to this value + 1, the receive FIFO full interrupt is triggered.

void SSI_SetSSTogglePhase(SPI_TypeDef *spi_dev, u32 TogglePhase)

Set SPI SS Toggle Phase.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • TogglePhase --

    This parameter can be one of the following values:

    • SPI_SS_NOT_TOGGLE , means SPI support continuous transfer when spi_cph=0

    • SPI_SS_TOGGLE, means SPI does not support continuous transfer when spi_cph=0 and SS(CS) needs break.

备注

SS Toggle function is valid only for master.

void SSI_SetSampleDelay(SPI_TypeDef *spi_dev, u32 SampleDelay)

Set SPIx Rx Sample Delay. support from AZ BCUT.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • SampleDelay -- The number of ssi_clk cycles that to be delayed.

备注

The max clk delay cycle is 4.

void SSI_SetSclkPhase(SPI_TypeDef *spi_dev, u32 SclkPhase)

Set SPIx clock phase.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • SclkPhase --

    This parameter can be one of the following values:

    • SCPH_TOGGLES_AT_START

    • SCPH_TOGGLES_IN_MIDDLE

void SSI_SetSclkPolarity(SPI_TypeDef *spi_dev, u32 SclkPolarity)

Set SPIx clock polarity.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • SclkPolarity --

    This parameter can be one of the following values:

    • SCPOL_INACTIVE_IS_HIGH

    • SCPOL_INACTIVE_IS_LOW

void SSI_SetSlaveEnable(SPI_TypeDef *spi_dev, u32 SlaveIndex)

Enable slave select.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • SlaveIndex -- The index of slave to be selected.

备注

Valid only when the device is configured as a master.

void SSI_SetTxFifoLevel(SPI_TypeDef *spi_dev, u32 TxThresholdLevel)

Set SPIx Tx FIFO threshold level.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • TxThresholdLevel -- Tx FIFO Threshold Level.Value range: 0 to 63. When the number of transmit FIFO entries is less than or equal to this value, the transmit FIFO empty interrupt is triggered.

u32 SSI_SlaveErrRecovery(SPI_TypeDef *spi_dev)

Perform FAE (Frame Alignment Error) recovery for SPI.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Recovery result:

  • TRUE: FAE error was detected and recovery performed.

  • FALSE: No FAE error detected.

备注

When a FAE error is detected, SSI_EN is reset to recover the peripheral.

void SSI_SlaveOutputEnable(SPI_TypeDef *spi_dev, u32 Status)

Set slave output enable.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • Status -- Where Status can be ENABLE or DISABLE.

备注

Valid only when the device is configured as a slave.

void SSI_StructInit(SSI_InitTypeDef *SSI_InitStruct)

Fill each SSI_InitStruct member with its default value.

参数:
  • SSI_InitStruct -- Pointer to a SSI_InitTypeDef structure which will be initialized.

bool SSI_TXGDMA_Init(u32 Index, PGDMA_InitTypeDef GDMA_InitStruct, void *CallbackData, IRQ_FUN CallbackFunc, u8 *pTxData, u32 Length)

Init and Enable SPI TX GDMA.

参数:
  • Index -- 0 or 1.

  • GDMA_InitStruct -- Pointer to a GDMA_InitTypeDef structure that contains the configuration information for the GDMA peripheral.

  • CallbackData -- GDMA callback data.

  • CallbackFunc -- GDMA callback function.

  • pTxData -- Tx Buffer.

  • Length -- Tx Count.

返回:

The result of TX GDMA initialization:

  • TRUE: TX GDMA initialization successful

  • FALSE: TX GDMA initialization failed

void SSI_WriteData(SPI_TypeDef *spi_dev, u32 value)

Write data to SPIx transmit FIFO.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

  • value -- The data value that is to be transmitted .

u32 SSI_Writeable(SPI_TypeDef *spi_dev)

Determine whether SPIx transmit FIFO is full or not.

参数:
  • spi_dev -- Where spi_dev can be SPI0_DEV or SPI1_DEV.

返回:

Transmit FIFO is full or not:

  • 1: Not Full

  • 0: Full

RTL8721Dx:

Not supported.

Mbed API

MBED_SPI Exported Types

Enumeration Type

enum ChipSelect

SPI chip select index.

Values:

/* Chip select 0. */
CS_0 = 0

/* Chip select 1. */
CS_1 = 1

/* Chip select 2. */
CS_2 = 2

/* Chip select 3. */
CS_3 = 3

/* Chip select 4. */
CS_4 = 4

/* Chip select 5. */
CS_5 = 5

/* Chip select 6. */
CS_6 = 6

/* Chip select 7. */
CS_7 = 7
enum MBED_SPI_IDX

SPI device index enumeration.

Values:

/* SPI0 peripheral index. */
MBED_SPI0 = 0xF0

/* SPI1 peripheral index. */
MBED_SPI1 = 0xF1
enum SPI_SCLK_IDLE_LEVEL

SPI serial clock idle level.

Values:

/* SCLK is low when SPI is inactive. */
SPI_SCLK_IDLE_LOW = 0

/* SCLK is high when SPI is inactive. */
SPI_SCLK_IDLE_HIGH = 2
enum SPI_SCLK_TOGGLE_MODE

SPI serial clock toggle mode.

Values:

/* SCLK toggles at middle of first data bit. */
SPI_SCLK_TOGGLE_MIDDLE = 0

/* SCLK toggles at start of first data bit. */
SPI_SCLK_TOGGLE_START = 1
enum SpiIrq

SPI interrupt event type.

Values:

/* SPI receive interrupt. */
SpiRxIrq

/* SPI transmit interrupt. */
SpiTxIrq

Structure Type

typedef void (*spi_irq_handler)(uint32_t id, SpiIrq event)

Typedef function pointer to point SPI interrupt handler.

typedef struct spi_s spi_t

SPI object type, defined as struct spi_s.

MBED_SPI Exported Constants

/* Enable SPI DMA RX channel. */
#define SPI_DMA_RX_EN (1<<0)

/* Enable SPI DMA TX channel. */
#define SPI_DMA_TX_EN (1<<1)

/* SPI state: idle and ready. */
#define SPI_STATE_READY 0x00

/* SPI state: receive operation in progress. */
#define SPI_STATE_RX_BUSY (1<<1)

/* SPI state: transmit operation in progress. */
#define SPI_STATE_TX_BUSY (1<<2)

MBED_SPI Exported Functions

void spi_bus_tx_done_irq_hook(spi_t *obj, spi_irq_handler handler, uint32_t id)

Register SPI bus Tx done interrupt handler if needed.

参数:
  • obj -- SPI object defined in application software.

  • handler -- Interrupt bus Tx done callback function.

  • id -- Interrupt bus Tx done callback parameter.

int spi_busy(spi_t *obj)

Get SPI busy state.

参数:
  • obj -- SPI object defined in application software.

返回:

Current busy state.

void spi_disable(spi_t *obj)

Disable SPI device clock.

参数:
  • obj -- SPI object defined in application software.

void spi_enable(spi_t *obj)

Enable SPI device clock.

参数:
  • obj -- SPI object defined in application software.

void spi_flush_rx_fifo(spi_t *obj)

SPI device to flush Rx FIFO.

参数:
  • obj -- SPI object defined in application software.

void spi_format(spi_t *obj, int bits, int mode, int slave)

Set SPI format, including DFS, Phase, Polarity and Role.

参数:
  • obj -- SPI object defined in application software.

  • bits -- Data frame size, which can be 4~16.

  • mode --

    This parameter can be one of the following values:

    • 0: [Polarity,Phase]=[0,0].

    • 1: [Polarity,Phase]=[0,1].

    • 2: [Polarity,Phase]=[1,0].

    • 3: [Polarity,Phase]=[1,1].

  • slave --

    This parameter can be one of the following values:

    • 0: Configure SPI as the master.

    • 1: Configure SPI as the slave.

void spi_free(spi_t *obj)

Deinitialize the SPI device, including interrupt, DMA, and SPI peripheral.

参数:
  • obj -- SPI object defined in application software.

void spi_frequency(spi_t *obj, int hz)

Set SPI baudrate.

参数:
  • obj -- SPI master object defined in application software.

  • hz -- Baudrate for SPI bus in units of Hz.

注意

Baudrate to be set should be less than or equal to half of the SPI IpClk.

void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)

Initialize the SPI device, including clock, function, interrupt and SPI registers.

参数:
  • obj -- SPI object defined in application software.

  • mosi -- MOSI PinName according to pinmux spec.

  • miso -- MISO PinName according to pinmux spec.

  • sclk -- SCLK PinName according to pinmux spec.

  • ssel -- CS PinName according to pinmux spec.

注意

Remember to set obj->spi_index to MBED_SPI0 or MBED_SPI1 before calling spi_init.

void spi_irq_hook(spi_t *obj, spi_irq_handler handler, uint32_t id)

Register SPI interrupt handler if needed.

参数:
  • obj -- SPI object defined in application software.

  • handler -- SPI Interrupt callback function.

  • id -- SPI Interrupt callback parameter.

int32_t spi_master_read_stream(spi_t *obj, char *rx_buffer, uint32_t length)

Master SPI receives data of target length under interrupt mode.

参数:
  • obj -- SPI master object defined in application software.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be read.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

int32_t spi_master_read_stream_dma(spi_t *obj, char *rx_buffer, uint32_t length)

Master SPI receives data of target length under DMA mode.

参数:
  • obj -- SPI master object defined in application software.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be read.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

备注

DMA or Interrupt mode can be used to TX dummy data

int spi_master_write(spi_t *obj, int value)

Master SPI sends one frame.

参数:
  • obj -- SPI master object defined in application software.

  • value -- Data to be transmitted.

返回:

Data received from slave SPI.

int32_t spi_master_write_read_stream(spi_t *obj, char *tx_buffer, char *rx_buffer, uint32_t length)

Master SPI sends and receives data of target length under interrupt mode.

参数:
  • obj -- SPI master object defined in application software.

  • tx_buffer -- Buffer to be written to Tx FIFO.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be sent and receive.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

int32_t spi_master_write_read_stream_dma(spi_t *obj, char *tx_buffer, char *rx_buffer, uint32_t length)

Master SPI sends and receives data of target length under DMA mode.

参数:
  • obj -- SPI master object defined in application software.

  • tx_buffer -- Buffer to be written to Tx FIFO.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be sent and received.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

int32_t spi_master_write_stream(spi_t *obj, char *tx_buffer, uint32_t length)

Master SPI sends data of target length under interrupt mode.

参数:
  • obj -- SPI master object defined in application software.

  • tx_buffer -- Buffer to be written to Tx FIFO.

  • length -- Number of data bytes to be sent.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

int32_t spi_master_write_stream_dma(spi_t *obj, char *tx_buffer, uint32_t length)

Master SPI sends data of target length under DMA mode.

参数:
  • obj -- SPI master object defined in application software.

  • tx_buffer -- Buffer to be written to Tx FIFO.

  • length -- Number of data bytes to be sent.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

void spi_slave_flush_fifo(spi_t *obj)

Discard all data in SPI slave Tx and Rx FIFOs.

参数:
  • obj -- SPI slave object defined in application software.

int spi_slave_read(spi_t *obj)

Slave SPI receives one frame.

参数:
  • obj -- SPI slave object defined in application software.

返回:

Data received from master SPI.

int32_t spi_slave_read_stream(spi_t *obj, char *rx_buffer, uint32_t length)

Slave SPI receives data of target length under interrupt mode.

参数:
  • obj -- SPI slave object defined in application software.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be read.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

int32_t spi_slave_read_stream_dma(spi_t *obj, char *rx_buffer, uint32_t length)

Slave SPI receives data of target length under DMA mode.

参数:
  • obj -- SPI slave object defined in application software.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be read.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

int32_t spi_slave_read_stream_dma_terminate(spi_t *obj, char *rx_buffer, uint32_t length)

Slave SPI receives data of target length under DMA mode and stops if SPI bus is idle.

参数:
  • obj -- SPI slave object defined in application software.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be read.

返回:

Number of already read bytes.

int32_t spi_slave_read_stream_dma_timeout(spi_t *obj, char *rx_buffer, uint32_t length, uint32_t timeout_ms)

Slave SPI receives data of target length under DMA mode before timeout.

参数:
  • obj -- SPI slave object defined in application software.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be read.

  • timeout_ms -- Timeout waiting time in units of ms.

返回:

Number of already read bytes.

int32_t spi_slave_read_stream_terminate(spi_t *obj, char *rx_buffer, uint32_t length)

Slave SPI receives data of target length under interrupt mode and stops if SPI bus is idle.

参数:
  • obj -- SPI slave object defined in application software.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be read.

返回:

Number of data bytes already read if success or -HAL_BUSY if error happens.

int32_t spi_slave_read_stream_timeout(spi_t *obj, char *rx_buffer, uint32_t length, uint32_t timeout_ms)

Slave SPI receives data of target length under interrupt mode monitored before timeout.

参数:
  • obj -- SPI slave object defined in application software.

  • rx_buffer -- Buffer to save data read from SPI FIFO.

  • length -- Number of data bytes to be read.

  • timeout_ms -- Timeout waiting time in units of ms.

返回:

Number of already read bytes.

int spi_slave_receive(spi_t *obj)

Check if slave SPI is readable and not busy.

参数:
  • obj -- SPI slave object defined in application software.

返回:

Receive-ready state of slave SPI:

  • 1: Readable and not busy

  • 0: Not ready

void spi_slave_write(spi_t *obj, int value)

Slave SPI sends one frame.

参数:
  • obj -- SPI slave object defined in application software.

  • value -- Data to be transmitted.

int32_t spi_slave_write_stream(spi_t *obj, char *tx_buffer, uint32_t length)

Slave SPI sends data of target length under interrupt mode.

参数:
  • obj -- SPI slave object defined in application software.

  • tx_buffer -- Buffer to be written to Tx FIFO.

  • length -- Number of data bytes to be sent.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

int32_t spi_slave_write_stream_dma(spi_t *obj, char *tx_buffer, uint32_t length)

Slave SPI sends data of target length under DMA mode.

参数:
  • obj -- SPI slave object defined in application software.

  • tx_buffer -- Buffer to be written to Tx FIFO.

  • length -- Number of data bytes to be send.

返回:

Operation status:

  • HAL_OK: Success.

  • HAL_BUSY: Error.

常见问题排查

CS 信号提前拉高

  • 现象 : 在数据传输未完成时 CS 被提前拉高,导致传输中断,数据未能完整发送。

  • 可能原因 : FIFO 缓冲区未能及时填充,或由于数据流控制不当导致数据断流。

  • 解决方法 :

    • 检查 FIFO 阈值配置:确保与数据流量需求相匹配。

    • 优化中断优先级:通过提高中断优先级,减少数据填充的延迟时间。

    • 使用 DMA 模式传输:减轻 CPU 的负担并提升数据传输的稳定性。

DMA 模式少部分数据传输错误

  • 现象 :初始传输的数据可能出现少量错误,而后续的数据传输正常。

  • 原因与解决方法 :请参考 DMA 和缓存 介绍。