硬件:Xilinx Zynq-7000 SoC ZC706
版本:vivado2015.4
目的:同一路SPI自发自收
工程分为PS和PL两部分。PL属于硬件连接。
(SPI外部设备开发请参考《基于ZYNQ PS-SPI的Flash驱动开发》)
PL部分
添加SPI0
配置SPI0
配置为Master模式。MOSI为Output,MOSO为Input
约束管脚
参考datasheet
set_property PACKAGE_PIN H14 [get_ports SPI0_SCLK_O]
set_property IOSTANDARD LVCMOS18 [get_ports SPI0_SCLK_O]
set_property PACKAGE_PIN J14 [get_ports SPI0_MOSI_O]
set_property IOSTANDARD LVCMOS18 [get_ports SPI0_MOSI_O]
set_property PACKAGE_PIN J15 [get_ports SPI0_MISO_I]
set_property IOSTANDARD LVCMOS18 [get_ports SPI0_MISO_I]
set_property PACKAGE_PIN J16 [get_ports SPI0_SS_O]
set_property IOSTANDARD LVCMOS18 [get_ports SPI0_SS_O]
硬件回环连接
MOSI连接MISO
PS部分
SPI控制器的FIFO模块,发送数据后,数据暂存在FIFO,实验通过读取FIFO来验证。
实验过程
1:发送数据WriteBuffer[1024]={1,2,3,4,5,6,7,8,9,0}
2:接收数据ReadBuffer并打印
3:通过打印观察,验证ReadBuffer和WriteBuffer内容是否一致
#include "xparameters.h"
#include "xspips.h"
#include "xil_printf.h"
#include "sleep.h"
XSpiPs Spi0, Spi1;
#define SpiPs_RecvByte(BaseAddress) \
(u8)XSpiPs_In8((BaseAddress) + XSPIPS_RXD_OFFSET)
#define SpiPs_SendByte(BaseAddress, Data) \
XSpiPs_Out8((BaseAddress) + XSPIPS_TXD_OFFSET, (Data))
int spi0_init();
void spi0_one_write();
void SpiRead(int ByteCount);
void SpiWrite(u8 *Sendbuffer, int ByteCount);
unsigned char ReadBuffer[1024];
unsigned char WriteBuffer[1024]={1,2,3,4,5,6,7,8,9,0};
int main(void) {
int Status;
int i,j;
int value;
xil_printf("SPI Selftest Example \r\n");
Status = spi0_init();
if (Status != XST_SUCCESS) {
xil_printf("SPI Selftest Example Failed\r\n");
return XST_FAILURE;
}
for (i = 0; i < 6; i++)
{
SpiWrite(WriteBuffer,10);
SpiRead(10);
//xil_printf("read back \n");
for (j = 0; j < 10; j++ )
{
xil_printf("%d,",ReadBuffer[j]);
}
xil_printf("\n");
memset(ReadBuffer, 0x00, 1024);
sleep(1);
}
xil_printf("Successfully ran SPI Selftest Example\r\n");
return XST_SUCCESS;
}
void SpiRead(int ByteCount)
{
int Count;
u32 StatusReg;
StatusReg = XSpiPs_ReadReg(Spi0.Config.BaseAddress,
XSPIPS_SR_OFFSET);
/*
* Polling the Rx Buffer for Data
*/
do{
StatusReg = XSpiPs_ReadReg(Spi0.Config.BaseAddress,
XSPIPS_SR_OFFSET);
}while(!(StatusReg & XSPIPS_IXR_RXNEMPTY_MASK));
/*
* Reading the Rx Buffer
*/
for(Count = 0; Count < ByteCount; Count++){
ReadBuffer[Count] = SpiPs_RecvByte(
Spi0.Config.BaseAddress);
}
}
void SpiWrite(u8 *Sendbuffer, int ByteCount)
{
u32 StatusReg;
int TransCount = 0;
StatusReg = XSpiPs_ReadReg(Spi0.Config.BaseAddress,
XSPIPS_SR_OFFSET);
while ((ByteCount > 0) &&
(TransCount < XSPIPS_FIFO_DEPTH)) {
SpiPs_SendByte(Spi0.Config.BaseAddress,
*Sendbuffer);
Sendbuffer++;
++TransCount;
ByteCount--;
}
/*
* Wait for the transfer to finish by polling Tx fifo status.
*/
do {
StatusReg = XSpiPs_ReadReg(
Spi0.Config.BaseAddress,
XSPIPS_SR_OFFSET);
} while ((StatusReg & XSPIPS_IXR_TXOW_MASK) == 0);
}
int spi0_init() {
int Status;
XSpiPs_Config *SpiConfig;
/*
* Initialize the SPI device.
*/
SpiConfig = XSpiPs_LookupConfig(XPAR_XSPIPS_0_DEVICE_ID);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize(&Spi0, SpiConfig, SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build.
*/
Status = XSpiPs_SelfTest(&Spi0);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
xil_printf("%s self test succ\r\n", __func__);
Status = XSpiPs_SetOptions(&Spi0, XSPIPS_MASTER_OPTION);
if (Status != XST_SUCCESS) {
xil_printf("%s XSpiPs_SetOptions fail\n", __func__);
return XST_FAILURE;
}
Status = XSpiPs_SetClkPrescaler(&Spi0, XSPIPS_CLK_PRESCALE_64);
if (Status != XST_SUCCESS) {
xil_printf("%s XSpiPs_SetClkPrescaler fail\n", __func__);
return XST_FAILURE;
}
XSpiPs_Enable(&Spi0);
xil_printf("spi 0 config finish\n");
return XST_SUCCESS;
}
测试
输出日志
SPI Selftest Example
spi0_init self test succ
spi 0 config finish
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
1,2,3,4,5,6,7,8,9,0,
Successfully ran SPI Selftest Example