SPI
概述
SPI ( Serial Peripheral Interface, 串行外围设备接口)是一种高速,全双工,同步的通信总线 常规只占用四根线,可节约芯片管脚和 PCB 的布局省空间 常见的集成这种协议的芯片有 EEPROM , FLASH , AD 转换器等
优点:
支持全双工
支持高速
协议支持字长不限于 8bit ,可根据应用特点灵活选择消息字长
硬件连接简单
缺点:
相比 IIC 多两根线
没有寻址机制,只能靠片选选择不同设备
没有从设备接受 ACK ,主设备对于发送成功与否不得而知
SPI 传输距离较短
SPI 一主多从拓扑结构
SPI 总线包含以下 4 条逻辑线:
SCK : Serial Clock 串行时钟信号,由主机发给从机
MOSI : Master Output Slave Input 主发从收信号
MISO : Master Input Slave Output 主收从发信号
SS/CS : Slave Select 片选信号,由主机发送
WQ7036A/AX 内置两个 SPI master 控制器 WQ7036A/AX 作为主机,向从机发送命令或数据,从机端接收主机端发送的数据
SPI 架构图
功能特性
单收、单发和收发并行模式
四线全双工和三线半双工通信
主机从机模式配置
时钟极性( CPOL )和时钟相位( CPHA )可配
时钟分频倍数可配
传输数据大小可配
SPI DMA 接口支持使用链表收/发数据
SPI 中断接口
工作模式
SPI 支持四种传输模式,可以通过寄存器 SPICR1 中的 CPOL 和 CPHA 位设置:
CPOL , 即 Clock Polarity 时钟极性,决定在总线空闲时, SCK 信号线上的电平为高或低
1 : 时钟低电平时有效, SCK 信号线在空闲时为高电平
0 : 时钟高电平时有效, SCK 信号线在空闲时为低电平
CPHA ,即 Clock Phase 时钟相位,定义 SPI 数据传输的两种基本模式:
1 : 在时钟偶数( 2 , 4 , 6 , ... , 16 )边沿(包括上下边沿)进行数据采样
0 : 在时钟奇数( 1 , 3 , 5 , ... , 15 )边沿(包括上下边沿)进行数据采样
SPI 通讯要求主从设备必须配置相同的传输模式
注意事项一:
当 CPHA = 0 且 CPOL = 0 时, DW_apb_ssi 主设备在开始连续串行传输的每个新数据帧之前切换从选择输出( ss_0_n )
而当 CPHA = 1 且 CPOL = 1 时, DW_apb_ssi 主设备在开始连续串行传输之前拉低从选择输出( ss_0_n )即可
故当用户需要使用 CPHA = 0 且 CPOL = 0 此模式时, 如果用户配置 CS ,交由驱动去控制,那 auto_cs 需设为 false , 如果用户为控制多个 SPI 从设备,那用户需自己手动拉低从选择输出( ss_0_n ), 来保证数据连续传输
注意事项二:
因为 SPI 的频率是在 DCORE 主频上分频的,故需要注意 DCORE 的主频必须大于或等于设置的 SPI 频率的四倍,且注意将运行 核频率也适配于设置的 SPI 频率(推荐运行核主频设置成大于或等于设置的 SPI 频率的四倍)。
如果 DCORE 的主频小于设置的 SPI 频率的四倍,则可能出现 SPI CLK 波形异常的问题; 如果运行核频率不适配于设置的 SPI 频率,则可能出现 SPI 大数据包传输时异常终止的问题。
资源依赖
SPI
DMA
用法流程
初始化
wq_spi_init()配置并打开
wq_spi_open()poll 方式先写后读
wq_spi_poll_transfer()poll 方式双工同时读写
wq_spi_poll_duplex_transfer()DMA 方式先写后读
wq_spi_dma_transfer()DMA 方式双工同时读写
wq_spi_dma_duplex_transfer()
注:如果需要 DMA 方式读写,需要在调用传输函数调用 wq_dma_init()
参考示例
examples/spi_demo
API 介绍
Typedefs
-
typedef struct wq_spi_gpio_cfg wq_spi_gpio_cfg_t
-
typedef struct wq_spi_cfg wq_spi_cfg_t
-
typedef struct wq_spi_transfer wq_spi_transfer_t
-
typedef void (*wq_spi_dma_callback)(const void *param)
SPI dma done callback func Invoke when dma transfer is done.
Enums
Functions
-
WQ_RET wq_spi_init(WQ_SPI_PORT port)
This function is to initialize SPI module.
- 参数:
port -- is the SPI port.
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL Bad param.
WQ_RET_AGAIN Repeated call.
-
WQ_RET wq_spi_deinit(WQ_SPI_PORT port)
This function is to deinitialize SPI module.
- 参数:
port -- is the SPI port.
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL Bad param.
WQ_RET_BUSY There is a unfinash transmition.
-
WQ_RET wq_spi_open(WQ_SPI_PORT port, const wq_spi_cfg_t *cfg, const wq_spi_gpio_cfg_t *gpio_cfg)
This function is to open SPI.
- 参数:
port -- is the SPI port.
cfg -- is configuration of the SPI.
gpio_cfg -- is configuration of the SPI gpio.
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL Bad param.
WQ_RET_AGAIN Repeated call.
WQ_RET_NOT_READY spi not init.
WQ_RET_BUSY gpio claim fail. /There is a unfinash transmition.
WQ_RET_NOSUPP frequency of dcore is less than four times that of spi.
-
WQ_RET wq_spi_close(WQ_SPI_PORT port)
This function is to close the SPI module.
备注
If this function is called when there is an unfinash dma transfer, then after running this function, even if the return value is WQ_RET_OK, the spi may still be in the stop dma transfer. The spi is not really shut down until the dma stop is complete.
- 参数:
port -- is the SPI port.
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL spi not open.
WQ_RET_NOT_READY spi cfg frequency is 0.
-
WQ_RET wq_spi_gpio_config(WQ_SPI_PORT port, const wq_spi_gpio_cfg_t *gpio_cfg)
Config spi gpio.
- 参数:
port -- is the SPI port
gpio_cfg -- is the GPIO config
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL Bad param.
WQ_RET_BUSY gpio claim fail.
-
WQ_RET wq_spi_dma_config(WQ_SPI_PORT port)
Config spi dma.
备注
This function Can be called after wq_spi_init and wq_spi_open and before wq_spi_dma_transfer or wq_spi_dma_duplex_transfer. However, if you do not mind that the time to call this function is extra in wq_spi_dma_transfer or wq_spi_dma_duplex_transfer for the first time after an spi port is open, you do not need to call this function separately in advance.
- 参数:
port -- is the SPI port
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL Bad param.
WQ_RET_NOT_READY spi not init or not open.
-
WQ_RET wq_spi_poll_transfer(WQ_SPI_PORT port, uint8_t *outbuf, size_t outbuf_len, uint8_t *inbuf, size_t inbuf_len)
This function is to config for using the spi tx and rx by poll mode.(send then receive data)
- 参数:
port -- is the SPI port.
outbuf -- is the data buff need to transfer to the peri.
outbuf_len -- is the out buff length.
inbuf -- is the data buff need to read from the peri.
inbuf_len -- is the in buff length.
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL Bad param.
WQ_RET_NOT_READY spi not open.
WQ_RET_BUSY spi have a unfinash transfer.
WQ_RET_FAIL spi transfer fail.
-
WQ_RET wq_spi_dma_transfer(WQ_SPI_PORT port, uint8_t *outbuf, size_t outbuf_len, uint8_t *inbuf, size_t inbuf_len, wq_spi_dma_callback cb)
This function is to config for using the spi dma tx and rx.(send then receive data)
- 参数:
port -- is the SPI port.
outbuf -- is the data buff need to transfer to the peri.
outbuf_len -- is the out buff length.
inbuf -- is the data buff need to read from the peri.
inbuf_len -- is the in buff length.
cb -- spi transfer done callback
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL Bad param.
WQ_RET_NOT_READY spi not open.
WQ_RET_BUSY spi have a unfinash transfer.
WQ_RET_NOMEM no memory to save spi dma transfer cfg.
-
WQ_RET wq_spi_poll_duplex_transfer(WQ_SPI_PORT port, uint8_t *outbuf, size_t outbuf_len, uint8_t *inbuf, size_t inbuf_len)
This function is to config for using the spi tx and rx by poll mode using duplex mode.(send and receive data simultaneously)
- 参数:
port -- is the SPI port.
outbuf -- is the data buff need to transfer to the peri.
outbuf_len -- is the out buff length.
inbuf -- is the data buff need to read from the peri.
inbuf_len -- is the in buff length.
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL Bad param.
WQ_RET_NOT_READY spi not open.
WQ_RET_BUSY spi have a unfinash transfer.
WQ_RET_FAIL spi transfer fail.
-
WQ_RET wq_spi_dma_duplex_transfer(WQ_SPI_PORT port, uint8_t *outbuf, size_t outbuf_len, uint8_t *inbuf, size_t inbuf_len, wq_spi_dma_callback cb)
This function is to config for using the spi dma tx and rx using duplex mode.(send and receive data simultaneously)
- 参数:
port -- is the SPI port.
outbuf -- is the data buff need to transfer to the peri.
outbuf_len -- is the out buff length.
inbuf -- is the data buff need to read from the peri.
inbuf_len -- is the in buff length.
cb -- spi transfer done callback
- 返回:
WQ_RET_OK Success.
WQ_RET_INVAL Bad param.
WQ_RET_NOT_READY spi not open.
WQ_RET_BUSY spi have a unfinash transfer.
WQ_RET_NOMEM no memory to save spi dma transfer cfg.
-
struct wq_spi_gpio_cfg
Public Members
-
WQ_GPIO_ID clk
SPI clk gpio
-
WQ_GPIO_ID cs
-
WQ_GPIO_ID mosi
SPI mosi gpio
-
WQ_GPIO_ID miso
SPI miso gpio
-
bool auto_cs
Is SPI cs auto, If auto_cs is set to false, driver control cs pin
-
WQ_GPIO_ID clk
-
struct wq_spi_cfg
Public Members
-
WQ_SPI_DFRAME_SIZE dframe_size
SPI dframe size
-
WQ_SPI_CLK_MODE clk_mode
SPI clk mode
-
uint32_t frequency
SPI frequency
备注
The DCORE frequency must be four times greater than this value, The frequency of the running core must also match this value.
-
uint32_t dummy_data
spi sends dummy_data while receiving data:
1) spi transfer data using mode of sending then receiving data and inbuf_len is not 0
2) spi transfer data using mode of sending and receiving data simultaneously and outbuf_len is greater than inbuf_len
备注
When dframe_size = WQ_SPI_DFRAME_SIZE_8, the lower 8 bits of dummy_data are valid. When dframe_size = WQ_SPI_DFRAME_SIZE_16, the lower 16 bits of dummy_data are valid.
-
WQ_SPI_DFRAME_SIZE dframe_size
-
struct wq_spi_transfer