spips_v3_0: Added new version V3_0 and deprecated v2_0

This patch adds new version for spips driver.
support for Zynq Ultrascale Mp added in new version.

Signed-off-by: Vishnu Motghare <vishnum@xilinx.com>
This commit is contained in:
Vishnu Motghare 2014-12-09 19:47:17 +05:30 committed by Suneel Garapati
parent f45ada332c
commit 8a752fd656
20 changed files with 6496 additions and 0 deletions

View file

@ -0,0 +1,42 @@
###############################################################################
#
# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
OPTION psf_version = 2.1;
BEGIN driver spips
OPTION supported_peripherals = (ps7_spi ps8_spi pss_spi);
OPTION driver_state = ACTIVE;
OPTION copyfiles = all;
OPTION VERSION = 3.0;
OPTION NAME = spips;
END driver

View file

@ -0,0 +1,51 @@
###############################################################################
#
# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
##############################################################################
#
# Modification History
#
# Ver Who Date Changes
# ----- ---- -------- -----------------------------------------------
# 1.00a sdm 11/22/11 Created
#
##############################################################################
#uses "xillib.tcl"
proc generate {drv_handle} {
xdefine_zynq_include_file $drv_handle "xparameters.h" "XSpiPs" "NUM_INSTANCES" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_SPI_CLK_FREQ_HZ"
xdefine_zynq_config_file $drv_handle "xspips_g.c" "XSpiPs" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_SPI_CLK_FREQ_HZ"
xdefine_zynq_canonical_xpars $drv_handle "xparameters.h" "XSpiPs" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_SPI_CLK_FREQ_HZ"
}

View file

@ -0,0 +1,40 @@
/******************************************************************************
*
* Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#ifndef SPIPS_HEADER_H /* prevent circular inclusions */
#define SPIPS_HEADER_H /* by using protection macros */
#include "xil_types.h"
#include "xil_assert.h"
#include "xstatus.h"
int SpiPsSelfTestExample(u16 DeviceId);
#endif

View file

@ -0,0 +1,138 @@
###############################################################################
#
# Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# Use of the Software is limited solely to applications:
# (a) running on a Xilinx device, or
# (b) that interact with a Xilinx device through a bus or interconnect.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
# Except as contained in this notice, the name of the Xilinx shall not be used
# in advertising or otherwise to promote the sale, use or other dealings in
# this Software without prior written authorization from Xilinx.
#
###############################################################################
###############################################################################
# MODIFICATION HISTORY:
# Ver Who Date Changes
# -------- ------ -------- ------------------------------------
# 2.0 adk 12/10/13 Updated as per the New Tcl API's
##############################################################################
# Uses $XILINX_EDK/bin/lib/xillib_sw.tcl
# -----------------------------------------------------------------
# Software Project Types (swproj):
# 0 : MemoryTest - Calls basic memorytest routines from common driver dir
# 1 : PeripheralTest - Calls any existing polled_example and/or selftest
# -----------------------------------------------------------------
# -----------------------------------------------------------------
# TCL Procedures:
# -----------------------------------------------------------------
proc gen_include_files {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set inc_file_lines {xspips.h spips_header.h}
}
return $inc_file_lines
}
proc gen_src_files {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
set inc_file_lines {examples/xspips_selftest_example.c data/spips_header.h}
return $inc_file_lines
}
}
proc gen_testfunc_def {swproj mhsinst} {
return ""
}
proc gen_init_code {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
if {$swproj == 1} {
return ""
}
}
proc gen_testfunc_call {swproj mhsinst} {
if {$swproj == 0} {
return ""
}
set ipname [get_property NAME $mhsinst]
set deviceid [::hsm::utils::get_ip_param_name $mhsinst "DEVICE_ID"]
set stdout [get_property CONFIG.STDOUT [get_os]]
if { $stdout == "" || $stdout == "none" } {
set hasStdout 0
} else {
set hasStdout 1
}
set testfunc_call ""
if {${hasStdout} == 0} {
append testfunc_call "
{
int Status;
Status = SpiPsSelfTestExample(${deviceid});
}"
} else {
append testfunc_call "
{
int Status;
print(\"\\r\\n Running SpiPsSelfTestExample() for ${ipname}...\\r\\n\");
Status = SpiPsSelfTestExample(${deviceid});
if (Status == 0) {
print(\"SpiPsSelfTestExample PASSED\\r\\n\");
}
else {
print(\"SpiPsSelfTestExample FAILED\\r\\n\");
}
}"
}
return $testfunc_call
}

View file

@ -0,0 +1,21 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Driver example applications</title>
<link rel="stylesheet" type="text/css" href="../help.css">
</head>
<body bgcolor="#FFFFFF">
<h1> Example Applications for the driver spips_v2_0 </h1>
<HR>
<ul>
<li>xspips_eeprom_intr_example.c <a href="xspips_eeprom_intr_example.c">(source)</a> </li>
<li>xspips_eeprom_polled_example.c <a href="xspips_eeprom_polled_example.c">(source)</a> </li>
<li>xspips_flash_intr_example.c <a href="xspips_flash_intr_example.c">(source)</a> </li>
<li>xspips_flash_polled_example.c <a href="xspips_flash_polled_example.c">(source)</a> </li>
<li>xspips_selftest_example.c <a href="xspips_selftest_example.c">(source)</a> </li>
</ul>
<p><font face="Times New Roman" color="#800000">Copyright <20> 1995-2014 Xilinx, Inc. All rights reserved.</font></p>
</body>
</html>

View file

@ -0,0 +1,645 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xspi_eeprom_intr_example.c
*
*
* This file contains a design example using the SPI driver (XSpiPs) in
* interrupt mode and hardware device with a serial EEPROM device. The
* hardware which this example runs on must have a serial EEPROM (Microchip
* 25XX320 or 25XX160) for it to run.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00 sdm 02/27/10 First release
* 1.00 sdm 10/25/11 Updated the chip select to be used to second chip select
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xspips.h" /* SPI device driver */
#include "xscugic.h" /* Interrupt controller device driver */
#include "xil_exception.h"
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define SPI_INTR_ID XPAR_XSPIPS_0_INTR
/*
* The following constants define the commands which may be sent to the EEPROM
* device.
*/
#define WRITE_STATUS_CMD 1
#define WRITE_CMD 2
#define READ_CMD 3
#define WRITE_DISABLE_CMD 4
#define READ_STATUS_CMD 5
#define WRITE_ENABLE_CMD 6
/*
* The following constants define the offsets within a EepromBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the SPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define COMMAND_OFFSET 0 /* EEPROM instruction */
#define ADDRESS_MSB_OFFSET 1 /* MSB of address to read or write */
#define ADDRESS_LSB_OFFSET 2 /* LSB of address to read or write */
#define DATA_OFFSET 3
#define WRITE_DATA_OFFSET 3 /* Start of data to write to the EEPROM */
#define READ_DATA_OFFSET 6 /* Start of data read from the EEPROM */
/*
* The following constants specify the extra bytes which are sent to the
* EEPROM on the SPI interface, that are not data, but control information
* which includes the command and address
*/
#define OVERHEAD_SIZE 3
/*
* The following constants specify the page size and number of pages for the
* EEPROM. The page size specifies a max number of bytes that can be written
* to the EEPROM with a single transfer using the SPI driver.
*/
#define PAGE_SIZE 16
#define PAGE_COUNT 128
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the EEPROM.
*/
#define MAX_DATA PAGE_COUNT * PAGE_SIZE
#define BUFFER_SIZE MAX_DATA + READ_DATA_OFFSET
/*
* The following constant defines the slave select signal that is used to
* to select the EEPROM device on the SPI bus, this signal is typically
* connected to the chip select of the device
*/
#define EEPROM_SPI_SELECT 0x01
/**************************** Type Definitions *******************************/
/*
* The following data type is used to send and receive data to the serial
* EEPROM device connected to the SPI interface. It is an array of bytes
* rather than a structure for portability avoiding packing issues. The
* application must setup the data to be written in this buffer and retrieve
* the data read from it.
*/
typedef u8 EepromBuffer[BUFFER_SIZE];
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int SpiSetupIntrSystem(XScuGic *IntcInstancePtr,
XSpiPs *SpiInstancePtr, u16 SpiIntrId);
static void SpiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId);
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
void EepromRead(XSpiPs *SpiPtr, u16 Address, int ByteCount,
EepromBuffer Buffer);
void EepromWrite(XSpiPs *SpiPtr, u16 Address, u8 ByteCount,
EepromBuffer Buffer);
int SpiPsEepromIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
u16 SpiDeviceId, u16 SpiIntrId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that the
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XScuGic IntcInstance;
static XSpiPs SpiInstance;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing
*/
int Error;
/*
* The following variable allows a test value to be added to the values that
* are written to the EEPROM such that unique values can be generated to
* guarantee the writes to the EEPROM were successful
*/
int Test;
/*
* The following variables are used to read and write to the eeprom and they
* are global to avoid having large buffers on the stack
*/
EepromBuffer ReadBuffer;
EepromBuffer WriteBuffer;
/*****************************************************************************/
/**
*
* Main function to call the Spi Eeprom example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("SPI EEPROM Interrupt Example Test \r\n");
/*
* Run the Spi Interrupt example.
*/
Status = SpiPsEepromIntrExample(&IntcInstance, &SpiInstance,
SPI_DEVICE_ID, SPI_INTR_ID);
if (Status != XST_SUCCESS) {
xil_printf("SPI EEPROM Interrupt Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran SPI EEPROM Interrupt Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in interrupt mode . This test writes and reads data from a
* serial EEPROM.
* This part must be present in the hardware to use this example.
*
* @param IntcInstancePtr is a pointer to the GIC driver to use.
* @param SpiInstancePtr is a pointer to the SPI driver to use.
* @param SpiDeviceId is the DeviceId of the Spi device.
* @param SpiIntrId is the Spi Interrupt Id.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int SpiPsEepromIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
u16 SpiDeviceId, u16 SpiIntrId)
{
int Status;
u8 *BufferPtr;
u8 UniqueValue;
int Count;
int Page;
XSpiPs_Config *SpiConfig;
/*
* Initialize the SPI driver so that it's ready to use
*/
SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize(SpiInstancePtr, SpiConfig,
SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XSpiPs_SelfTest(SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the Spi device to the interrupt subsystem such that
* interrupts can occur. This function is application specific
*/
Status = SpiSetupIntrSystem(IntcInstancePtr, SpiInstancePtr, SpiIntrId);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the
* interrupt context when an SPI status occurs, specify a pointer to
* the SPI driver instance as the callback reference so the handler is
* able to access the instance data
*/
XSpiPs_SetStatusHandler(SpiInstancePtr, SpiInstancePtr,
(XSpiPs_StatusHandler) SpiHandler);
/*
* Set the Spi device as a master. External loopback is required.
*/
XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MASTER_OPTION |
XSPIPS_FORCE_SSELECT_OPTION);
XSpiPs_SetClkPrescaler(SpiInstancePtr, XSPIPS_CLK_PRESCALE_64);
/*
* Initialize the write buffer for a pattern to write to the EEPROM
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = 13, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
WriteBuffer[WRITE_DATA_OFFSET + Count] =
(u8)(UniqueValue + Test);
ReadBuffer[READ_DATA_OFFSET + Count] = 0xA5;
}
/*
* Assert the EEPROM chip select
*/
XSpiPs_SetSlaveSelect(SpiInstancePtr, EEPROM_SPI_SELECT);
/*
* Write the data in the write buffer to the serial EEPROM a page at a
* time
*/
for (Page = 0; Page < PAGE_COUNT; Page++) {
EepromWrite(SpiInstancePtr, Page * PAGE_SIZE, PAGE_SIZE,
&WriteBuffer[Page * PAGE_SIZE]);
}
/*
* Read the contents of the entire EEPROM from address 0, since this
* function reads the entire EEPROM it will take some amount of time to
* complete
*/
EepromRead(SpiInstancePtr, 0, MAX_DATA, ReadBuffer);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[READ_DATA_OFFSET];
for (UniqueValue = 13, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
SpiDisableIntrSystem(IntcInstancePtr, SpiIntrId);
return XST_SUCCESS;
}
/******************************************************************************
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts
* but is application specific.
*
*
* @param CallBackRef is a reference passed to the handler.
* @param StatusEvent is the status of the SPI .
* @param ByteCount is the number of bytes transferred.
*
* @return None
*
* @note None.
*
******************************************************************************/
void SpiHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
Error++;
}
}
/******************************************************************************
*
* This function reads from the serial EEPROM connected to the SPI interface.
*
* @param SpiPtr is a pointer to the SPI driver instance to use.
* @param Address contains the address to read data from in the EEPROM.
* @param ByteCount contains the number of bytes to read.
* @param Buffer is a buffer to read the data into.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void EepromRead(XSpiPs *SpiPtr, u16 Address, int ByteCount,
EepromBuffer Buffer)
{
/*
* Setup the write command with the specified address and data for the
* EEPROM
*/
Buffer[COMMAND_OFFSET] = READ_CMD;
Buffer[ADDRESS_MSB_OFFSET] = (u8)((Address & 0xFF00) >> 8);
Buffer[ADDRESS_LSB_OFFSET] = (u8)(Address & 0x00FF);
/*
* Send the read command to the EEPROM to read the specified number
* of bytes from the EEPROM, send the read command and address and
* receive the specified number of bytes of data in the data buffer
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, Buffer, &Buffer[DATA_OFFSET],
ByteCount + OVERHEAD_SIZE);
/*
* Wait for the transfer on the SPI bus to be complete before proceeding
*/
while (TransferInProgress);
}
/******************************************************************************
*
*
* This function writes to the serial EEPROM connected to the SPI interface.
* This function is not designed to be a driver to handle all
* the conditions of the EEPROM device. The EEPROM contains a 32 byte write
* buffer which can be filled and then a write is automatically performed by
* the device. All the data put into the buffer must be in the same page of
* the device with page boundaries being on 32 byte boundaries.
*
* @param SpiPtr is a pointer to the SPI driver instance to use.
* @param Address contains the address to write data to in the EEPROM.
* @param ByteCount contains the number of bytes to write.
* @param Buffer is a buffer of data to write from.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void EepromWrite(XSpiPs *SpiPtr, u16 Address, u8 ByteCount,
EepromBuffer Buffer)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 EepromStatus[2];
int DelayCount = 0;
/*
* Send the write enable command to the SEEPOM so that it can be
* written to, this needs to be sent as a seperate transfer before
* the write
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd));
/*
* Wait for the transfer on the SPI bus to be complete before proceeding
*/
while (TransferInProgress);
/*
* Setup the write command with the specified address and data for the
* EEPROM
*/
Buffer[COMMAND_OFFSET] = WRITE_CMD;
Buffer[ADDRESS_MSB_OFFSET] = (u8)((Address & 0xFF00) >> 8);
Buffer[ADDRESS_LSB_OFFSET] = (u8)(Address & 0x00FF);
/*
* Send the write command, address, and data to the EEPROM to be
* written, no receive buffer is specified since there is nothing to
* receive
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, Buffer, NULL, ByteCount + OVERHEAD_SIZE);
while (TransferInProgress);
/*
* Wait for a bit of time to allow the programming to occur as reading
* the status while programming causes it to fail because of noisy power
* on the board containing the EEPROM, this loop does not need to be
* very long but is longer to hopefully work for a faster processor
*/
while (DelayCount++ < 10000) {
}
/*
* Wait for the write command to the EEPROM to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the device to determine when it
* completes by sending a read status command and receiving the
* status byte
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, ReadStatusCmd, EepromStatus,
sizeof(ReadStatusCmd));
/*
* Wait for the transfer on the SPI bus to be complete before
* proceeding
*/
while (TransferInProgress);
/*
* If the status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((EepromStatus[1] & 0x03) == 0) {
break;
}
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system for an Spi device.
* This function is application specific since the actual system may or may not
* have an interrupt controller. The Spi device could be directly connected to
* a processor without an interrupt controller. The user should modify this
* function to fit the application.
*
* @param IntcInstancePtr is a pointer to the instance of the Intc device.
* @param SpiInstancePtr is a pointer to the instance of the Spi device.
* @param SpiIntrId is the interrupt Id for an SPI device.
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None.
*
******************************************************************************/
static int SpiSetupIntrSystem(XScuGic *IntcInstancePtr,
XSpiPs *SpiInstancePtr, u16 SpiIntrId)
{
int Status;
#ifndef TESTAPP_GEN
XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
Xil_ExceptionInit();
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
IntcInstancePtr);
#endif
/*
* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device.
*/
Status = XScuGic_Connect(IntcInstancePtr, SpiIntrId,
(Xil_ExceptionHandler)XSpiPs_InterruptHandler,
(void *)SpiInstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Enable the interrupt for the Spi device.
*/
XScuGic_Enable(IntcInstancePtr, SpiIntrId);
#ifndef TESTAPP_GEN
/*
* Enable interrupts in the Processor.
*/
Xil_ExceptionEnable();
#endif
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function disables the interrupts that occur for the Spi device.
*
* @param IntcInstancePtr is the pointer to a ScuGic driver instance.
* @param SpiIntrId is the interrupt Id for an SPI device.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void SpiDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId)
{
/*
* Disable the interrupt for the SPI device.
*/
XScuGic_Disable(IntcInstancePtr, SpiIntrId);
/*
* Disconnect and disable the interrupt for the Spi device.
*/
XScuGic_Disconnect(IntcInstancePtr, SpiIntrId);
}

View file

@ -0,0 +1,422 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xspi_eeprom_polled_example.c
**
* This file contains a design example using the SPI driver (XSpiPs) in
* polled mode and hardware device with a serial EEPROM device. The
* hardware which this example runs on must have a serial EEPROM (Microchip
* 25XX320 or 25XX160) for it to run. This example has been tested with the
* SPI EEPROM on the EP4.5 ARM processor.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- -----------------------------------------------
* 1.00 sdm 03/09/10 First release
* 1.00 sdm 10/25/11 Updated the chip select to be used to second chip select
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* EDK generated parameters */
#include "xspips.h" /* SPI device driver */
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
/*
* The following constants define the commands which may be sent to the EEPROM
* device.
*/
#define WRITE_STATUS_CMD 1
#define WRITE_CMD 2
#define READ_CMD 3
#define WRITE_DISABLE_CMD 4
#define READ_STATUS_CMD 5
#define WRITE_ENABLE_CMD 6
/*
* The following constants define the offsets within a EepromBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the SPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define COMMAND_OFFSET 0 /* EEPROM instruction */
#define ADDRESS_MSB_OFFSET 1 /* MSB of address to read or write */
#define ADDRESS_LSB_OFFSET 2 /* LSB of address to read or write */
#define DATA_OFFSET 3
#define WRITE_DATA_OFFSET 3 /* Start of data to write to the EEPROM */
#define READ_DATA_OFFSET 6 /* Start of data read from the EEPROM */
/*
* The following constants specify the extra bytes which are sent to the
* EEPROM on the SPI interface, that are not data, but control information
* which includes the command and address
*/
#define OVERHEAD_SIZE 3
/*
* The following constants specify the page size and number of pages for the
* EEPROM. The page size specifies a max number of bytes that can be written
* to the EEPROM with a single transfer using the SPI driver.
*/
#define PAGE_SIZE 16
#define PAGE_COUNT 128
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the EEPROM.
*/
#define MAX_DATA PAGE_COUNT * PAGE_SIZE
#define BUFFER_SIZE MAX_DATA + READ_DATA_OFFSET
/*
* The following constant defines the slave select signal that is used to
* to select the EEPROM device on the SPI bus, this signal is typically
* connected to the chip select of the device
*/
#define EEPROM_SPI_SELECT 0x01
/**************************** Type Definitions *******************************/
/*
* The following data type is used to send and receive data to the serial
* EEPROM device connected to the SPI interface. It is an array of bytes
* rather than a structure for portability avoiding packing issues. The
* application must setup the data to be written in this buffer and retrieve
* the data read from it.
*/
typedef u8 EepromBuffer[BUFFER_SIZE];
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
void EepromRead(XSpiPs *SpiPtr, u16 Address, int ByteCount,
EepromBuffer Buffer);
void EepromWrite(XSpiPs *SpiPtr, u16 Address, u8 ByteCount,
EepromBuffer Buffer);
int SpiPsEepromPolledExample(XSpiPs *SpiInstancePtr, u16 SpiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that the
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XSpiPs SpiInstance;
/*
* The following variable allows a test value to be added to the values that
* are written to the EEPROM such that unique values can be generated to
* guarantee the writes to the EEPROM were successful
*/
int Test;
/*
* The following variables are used to read and write to the eeprom and they
* are global to avoid having large buffers on the stack
*/
EepromBuffer ReadBuffer;
EepromBuffer WriteBuffer;
/*****************************************************************************/
/**
*
* Main function to call the Spi Eeprom example.
*
* @param None
*
* @return XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("SPI EEPROM Polled Mode Example Test \r\n");
/*
* Run the Spi Interrupt example.
*/
Status = SpiPsEepromPolledExample(&SpiInstance, SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("SPI EEPROM Polled Mode Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran SPI EEPROM Polled Mode Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in polled mode. This test writes and reads data from a
* serial EEPROM. The serial EEPROM part must be present in the hardware
* to use this example.
*
* @param SpiInstancePtr is a pointer to the Spi Instance.
* @param SpiDeviceId is the Device Id of Spi.
*
* @return XST_SUCCESS if successful else XST_FAILURE.
*
* @note
*
* This function calls functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int SpiPsEepromPolledExample(XSpiPs *SpiInstancePtr, u16 SpiDeviceId)
{
int Status;
u8 *BufferPtr;
u8 UniqueValue;
int Count;
int Page;
XSpiPs_Config *SpiConfig;
/*
* Initialize the SPI driver so that it's ready to use
*/
SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize(SpiInstancePtr, SpiConfig,
SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XSpiPs_SelfTest(SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the Spi device as a master. External loopback is required.
*/
XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MASTER_OPTION |
XSPIPS_FORCE_SSELECT_OPTION);
XSpiPs_SetClkPrescaler(SpiInstancePtr, XSPIPS_CLK_PRESCALE_64);
/*
* Initialize the write buffer for a pattern to write to the EEPROM
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = 13, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
WriteBuffer[WRITE_DATA_OFFSET + Count] =
(u8)(UniqueValue + Test);
ReadBuffer[READ_DATA_OFFSET + Count] = 0xA5;
}
/*
* Assert the EEPROM chip select
*/
XSpiPs_SetSlaveSelect(SpiInstancePtr, EEPROM_SPI_SELECT);
/*
* Write the data in the write buffer to the serial EEPROM a page at a
* time, read the data back from the EEPROM and verify it
*/
UniqueValue = 13;
for (Page = 0; Page < PAGE_COUNT; Page++) {
EepromWrite(SpiInstancePtr, Page * PAGE_SIZE, PAGE_SIZE,
&WriteBuffer[Page * PAGE_SIZE]);
EepromRead(SpiInstancePtr, Page * PAGE_SIZE, PAGE_SIZE,
ReadBuffer);
BufferPtr = &ReadBuffer[READ_DATA_OFFSET];
for (Count = 0; Count < PAGE_SIZE; Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue + Test)) {
return XST_FAILURE;
}
}
}
return XST_SUCCESS;
}
/******************************************************************************
*
* This function reads from the serial EEPROM connected to the SPI interface.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
* @param Address contains the address to read data from in the EEPROM.
* @param ByteCount contains the number of bytes to read.
* @param Buffer is a buffer to read the data into.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void EepromRead(XSpiPs *SpiPtr, u16 Address, int ByteCount,
EepromBuffer Buffer)
{
/*
* Setup the write command with the specified address and data for the
* EEPROM
*/
Buffer[COMMAND_OFFSET] = READ_CMD;
Buffer[ADDRESS_MSB_OFFSET] = (u8)((Address & 0xFF00) >> 8);
Buffer[ADDRESS_LSB_OFFSET] = (u8)(Address & 0x00FF);
/*
* Send the read command to the EEPROM to read the specified number
* of bytes from the EEPROM, send the read command and address and
* receive the specified number of bytes of data in the data buffer
*/
XSpiPs_PolledTransfer(SpiPtr, Buffer, &Buffer[DATA_OFFSET],
ByteCount + OVERHEAD_SIZE);
}
/******************************************************************************
*
*
* This function writes to the serial EEPROM connected to the SPI interface.
* This function is not designed to be a driver to handle all
* the conditions of the EEPROM device. The EEPROM contains a 32 byte write
* buffer which can be filled and then a write is automatically performed by
* the device. All the data put into the buffer must be in the same page of
* the device with page boundaries being on 32 byte boundaries.
*
* @param SpiPtr is a pointer to the SPI driver instance to use.
* @param Address contains the address to write data to in the EEPROM.
* @param ByteCount contains the number of bytes to write.
* @param Buffer is a buffer of data to write from.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void EepromWrite(XSpiPs *SpiPtr, u16 Address, u8 ByteCount,
EepromBuffer Buffer)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 EepromStatus[2];
int DelayCount = 0;
/*
* Send the write enable command to the SEEPOM so that it can be
* written to, this needs to be sent as a seperate transfer before
* the write
*/
XSpiPs_PolledTransfer(SpiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address and data for the
* EEPROM
*/
Buffer[COMMAND_OFFSET] = WRITE_CMD;
Buffer[ADDRESS_MSB_OFFSET] = (u8)((Address & 0xFF00) >> 8);
Buffer[ADDRESS_LSB_OFFSET] = (u8)(Address & 0x00FF);
/*
* Send the write command, address, and data to the EEPROM to be
* written, no receive buffer is specified since there is nothing to
* receive
*/
XSpiPs_PolledTransfer(SpiPtr, Buffer, NULL, ByteCount + OVERHEAD_SIZE);
/*
* Wait for a bit of time to allow the programming to occur as reading
* the status while programming causes it to fail because of noisy power
* on the board containing the EEPROM, this loop does not need to be
* very long but is longer to hopefully work for a faster processor
*/
while (DelayCount++ < 10000) {
}
/*
* Wait for the write command to the EEPROM to be completed, it takes
* some time for the data to be written
*/
while (1) {
/*
* Poll the status register of the device to determine when it
* completes by sending a read status command and receiving the
* status byte
*/
XSpiPs_PolledTransfer(SpiPtr, ReadStatusCmd, EepromStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop waiting,
* if a value of 0xFF in the status byte is read from the
* device and this loop never exits, the device slave select is
* possibly incorrect such that the device status is not being
* read
*/
if ((EepromStatus[1] & 0x03) == 0) {
break;
}
}
}

View file

@ -0,0 +1,976 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips_flash_intr_example.c
*
*
* This file contains a design example using the SPI driver (XSpiPs) in
* interrupt mode with a serial flash device. This examples performs
* transfers in Manual start mode using interrupts.
* The hardware which this example runs on, must have a serial flash
* for it to run. This example has been tested with SST25W080.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sg 1/30/13 First release
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* SDK generated parameters */
#include "xspips.h" /* SPI device driver */
#include "xscugic.h" /* Interrupt controller device driver */
#include "xil_exception.h"
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define SPI_INTR_ID XPAR_XSPIPS_1_INTR
/*
* The following constants define the commands which may be sent to the flash
* device.
*/
#define WRITE_STATUS_CMD 0x01
#define WRITE_CMD 0x02
#define READ_CMD 0x03
#define WRITE_DISABLE_CMD 0x04
#define READ_STATUS_CMD 0x05
#define WRITE_ENABLE_CMD 0x06
#define FAST_READ_CMD 0x0B
#define CHIP_ERASE_CMD 0x60
#define BLOCK_ERASE_64K_CMD 0xD8
#define READ_ID 0x90
/*
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the SPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define COMMAND_OFFSET 0 /* Flash instruction */
#define ADDRESS_1_OFFSET 1 /* MSB byte of address to read or write */
#define ADDRESS_2_OFFSET 2 /* Middle byte of address to read or write */
#define ADDRESS_3_OFFSET 3 /* LSB byte of address to read or write */
#define DATA_OFFSET 4 /* Start of Data for Read/Write */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast read */
#define RD_ID_SIZE 4 /* Read ID command + 3 bytes ID response */
/*
* The following constants specify the extra bytes which are sent to the
* flash on the SPI interface, that are not data, but control information
* which includes the command and address
*/
#define OVERHEAD_SIZE 4
#define UNIQUE_VALUE 0x55
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the flash.
*/
#define MAX_DATA 1024*1024
/*
* The following constant defines the slave select signal that is used to
* to select the flash device on the SPI bus, this signal is typically
* connected to the chip select of the device
*/
#define FLASH_SPI_SELECT 0x01
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
static int SpiPsSetupIntrSystem(XScuGic *IntcInstancePtr,
XSpiPs *SpiInstancePtr, u16 SpiIntrId);
static void SpiPsDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId);
void SpiPsHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount);
void FlashErase(XSpiPs *SpiPtr);
void FlashWrite(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command);
void FlashRead(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command);
int FlashReadID(void);
int SpiPsFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
u16 SpiDeviceId, u16 SpiIntrId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XScuGic IntcInstance;
static XSpiPs SpiInstance;
/*
* The following variables are shared between non-interrupt processing and
* interrupt processing such that they must be global.
*/
volatile int TransferInProgress;
/*
* The following variable tracks any errors that occur during interrupt
* processing
*/
int Error;
/*
* Write Address Location in Serial Flash.
*/
static int TestAddress;
/*
* The following variables are used to read and write to the eeprom and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[MAX_DATA + DATA_OFFSET];
/*****************************************************************************/
/**
*
* Main function to call the SPI Flash example.
*
* @param None
*
* @return
* - XST_SUCCESS if successful
* - XST_FAILURE if not successful
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("SPI FLASH Interrupt Example Test \r\n");
/*
* Run the Spi Interrupt example.
*/
Status = SpiPsFlashIntrExample(&IntcInstance, &SpiInstance,
SPI_DEVICE_ID, SPI_INTR_ID);
if (Status != XST_SUCCESS) {
xil_printf("SPI FLASH Interrupt Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran SPI FLASH Interrupt Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in interrupt mode. This function writes and reads data
* from a serial flash.
*
* @param IntcInstancePtr is a pointer to Interrupt Controller instance.
*
* @param SpiInstancePtr is a pointer to the SPI driver instance to use.
*
* @param SpiDeviceId is the Instance Id of SPI in the system.
*
* @param SpiIntrId is the Interrupt Id for SPI in the system.
*
* @param None.
*
* @return
* - XST_SUCCESS if successful
* - XST_FAILURE if not successful
*
* @note
*
* This function calls other functions which contain loops that may be infinite
* if interrupts are not working such that it may not return. If the device
* slave select is not correct and the device is not responding on bus it will
* read a status of 0xFF for the status register as the bus is pulled up.
*
*****************************************************************************/
int SpiPsFlashIntrExample(XScuGic *IntcInstancePtr, XSpiPs *SpiInstancePtr,
u16 SpiDeviceId, u16 SpiIntrId)
{
int Status;
u8 *BufferPtr;
u8 UniqueValue;
u32 Count;
XSpiPs_Config *SpiConfig;
/*
* Initialize the SPI driver so that it's ready to use
*/
SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize(SpiInstancePtr, SpiConfig,
SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XSpiPs_SelfTest(SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the Spi device to the interrupt subsystem such that
* interrupts can occur. This function is application specific
*/
Status = SpiPsSetupIntrSystem(IntcInstancePtr, SpiInstancePtr,
SpiIntrId);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Setup the handler for the SPI that will be called from the
* interrupt context when an SPI status occurs, specify a pointer to
* the SPI driver instance as the callback reference so the handler is
* able to access the instance data
*/
XSpiPs_SetStatusHandler(SpiInstancePtr, SpiInstancePtr,
(XSpiPs_StatusHandler) SpiPsHandler);
/*
* Set the SPI device as a master with manual start and manual
* chip select mode options
*/
XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MANUAL_START_OPTION | \
XSPIPS_MASTER_OPTION | XSPIPS_FORCE_SSELECT_OPTION);
/*
* Set the SPI device pre-scalar to divide by 8
*/
XSpiPs_SetClkPrescaler(SpiInstancePtr, XSPIPS_CLK_PRESCALE_8);
memset(WriteBuffer, 0x00, sizeof(WriteBuffer));
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Initialize the write buffer for a pattern to write to the flash
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue);
}
/*
* Assert the flash chip select
*/
XSpiPs_SetSlaveSelect(SpiInstancePtr, FLASH_SPI_SELECT);
/*
* Read the flash ID
*/
Status = FlashReadID();
if (Status != XST_SUCCESS) {
xil_printf("SPI FLASH Interrupt Example Read ID Failed\r\n");
return XST_FAILURE;
}
/*
* Erase the flash
*/
FlashErase(SpiInstancePtr);
/*
* Write the data in the write buffer to TestAddress in serial flash
*/
FlashWrite(SpiInstancePtr, TestAddress, MAX_DATA, WRITE_CMD);
/*
* Read the contents of the flash from TestAddress of size MAX_DATA
* using Normal Read command
*/
FlashRead(SpiInstancePtr, TestAddress, MAX_DATA, READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue)) {
return XST_FAILURE;
}
}
/*
* Set the SPI device as a master with auto start and manual
* chip select mode options
*/
XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MASTER_OPTION | \
XSPIPS_FORCE_SSELECT_OPTION);
memset(WriteBuffer, 0x00, sizeof(WriteBuffer));
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Initialize the write buffer for a pattern to write to the flash
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue);
}
/*
* Erase the flash
*/
FlashErase(SpiInstancePtr);
/*
* Write the data in the write buffer to TestAddress in serial flash
*/
FlashWrite(SpiInstancePtr, TestAddress, MAX_DATA, WRITE_CMD);
/*
* Read the contents of the flash from TestAddress of size MAX_DATA
* using Normal Read command
*/
FlashRead(SpiInstancePtr, TestAddress, MAX_DATA, READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue)) {
return XST_FAILURE;
}
}
SpiPsDisableIntrSystem(IntcInstancePtr, SpiIntrId);
return XST_SUCCESS;
}
/******************************************************************************
*
* This function is the handler which performs processing for the SPI driver.
* It is called from an interrupt context such that the amount of processing
* performed should be minimized. It is called when a transfer of SPI data
* completes or an error occurs.
*
* This handler provides an example of how to handle SPI interrupts but is
* application specific.
*
* @param CallBackRef is a reference passed to the handler.
* @param StatusEvent is the status of the SPI .
* @param ByteCount is the number of bytes transferred.
*
* @return None
*
* @note None.
*
******************************************************************************/
void SpiPsHandler(void *CallBackRef, u32 StatusEvent, unsigned int ByteCount)
{
/*
* Indicate the transfer on the SPI bus is no longer in progress
* regardless of the status event
*/
TransferInProgress = FALSE;
/*
* If the event was not transfer done, then track it as an error
*/
if (StatusEvent != XST_SPI_TRANSFER_DONE) {
Error++;
}
}
/******************************************************************************
*
*
* This function writes to the serial flash connected to the SPI interface.
* The flash contains a 256 byte write buffer which can be filled and then a
* write is automatically performed by the device. All the data put into the
* buffer must be in the same page of the device with page boundaries being on
* 256 byte boundaries.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
* @param Address contains the address to write data to in the flash.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash. SPI
* device supports only Page Program command to write data to the
* flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashWrite(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 WriteDisableCmd = { WRITE_DISABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
u32 Temp = 0;
u32 TempAddress = Address;
u8 TempBuffer[5];
if (Command == WRITE_CMD) {
for (Temp = 0; Temp < ByteCount ; Temp++, TempAddress++) {
/*
* Send the write enable command to the flash so
* that it can be written to, this needs to be sent
* as a seperate transfer before the write
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Wait for the transfer on the SPI bus to be complete before
* proceeding
*/
while (TransferInProgress);
/*
* Setup the write command with the specified address
* and data for the flash
*/
TempBuffer[COMMAND_OFFSET] = Command;
TempBuffer[ADDRESS_1_OFFSET] =
(u8)((TempAddress & 0xFF0000) >> 16);
TempBuffer[ADDRESS_2_OFFSET] =
(u8)((TempAddress & 0xFF00) >> 8);
TempBuffer[ADDRESS_3_OFFSET] =
(u8)(TempAddress & 0xFF);
TempBuffer[DATA_OFFSET] =
WriteBuffer[DATA_OFFSET + Temp];
/*
* Send the write command, address, and data to the
* flash to be written, no receive buffer is specified
* since there is nothing to receive
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, TempBuffer, NULL, 5);
while (TransferInProgress);
/*
* Wait for the write command to the flash to be ,
* completed it takes some time for the data to be
* written
*/
while (1) {
/*
* Poll the status register of the flash to
* determine when it completes, by sending
* a read status command and receiving the
* status byte
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, ReadStatusCmd,
FlashStatus, sizeof(ReadStatusCmd));
/*
* Wait for the transfer on the SPI bus
* to be complete before proceeding
*/
while (TransferInProgress);
/*
* If the status indicates the write is done,
* then stop waiting, if a value of 0xFF in
* the status byte is read from the device
* and this loop never exits, the device slave
* select is possibly incorrect such that the
* device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, &WriteDisableCmd, NULL,
sizeof(WriteDisableCmd));
/*
* Wait for the transfer on the SPI bus to be complete
* before proceeding
*/
while (TransferInProgress);
}
}
}
/******************************************************************************
*
* This function reads from the serial flash connected to the
* SPI interface.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
* @param Address contains the address to read data from in the flash.
* @param ByteCount contains the number of bytes to read.
* @param Command is the command used to read data from the flash. SPI
* device supports one of the Read, Fast Read, Dual Read and Fast
* Read commands to read data from the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashRead(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command)
{
/*
* Setup the write command with the specified address and data for the
* flash
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
/*
* Send the read command to the flash to read the specified number
* of bytes from the flash, send the read command and address and
* receive the specified number of bytes of data in the data buffer
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, WriteBuffer, ReadBuffer,
ByteCount + OVERHEAD_SIZE);
/*
* Wait for the transfer on the SPI bus to be complete before
* proceeding
*/
while (TransferInProgress);
}
/******************************************************************************
*
* This function reads serial flash ID connected to the SPI interface.
*
* @param None.
*
* @return
* - XST_SUCCESS if successful
* - XST_FAILURE if not successful
*
* @note None.
*
******************************************************************************/
int FlashReadID(void)
{
u8 Index;
u8 ByteCount = 4;
u8 SendBuffer[8];
u8 RecvBuffer[8];
SendBuffer[0] = READ_ID;
SendBuffer[1] = 0;
SendBuffer[2] = 0;
SendBuffer[3] = 0;
for(Index=0; Index < ByteCount; Index++) {
SendBuffer[4 + Index] = 0x00;
}
TransferInProgress = TRUE;
XSpiPs_Transfer(&SpiInstance, SendBuffer, RecvBuffer,
(4 + ByteCount));
while (TransferInProgress);
for(Index=0; Index < ByteCount; Index++) {
xil_printf("ID : %0x\r\n", RecvBuffer[4 + Index]);
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function erases the sectors in the serial flash connected to the
* SPI interface.
*
* @param SpiPtr is a pointer to the SPI driver component to use.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashErase(XSpiPs *SpiPtr)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
/* must send 2 bytes */
u8 WriteStatusCmd[] = { WRITE_STATUS_CMD, 0x0 };
u8 FlashStatus[2];
/*
* Send the write enable command to the flash so that it can be
* written to, this needs to be sent as a seperate transfer
* before the erase
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd));
/*
* Wait for the transfer on the SPI bus to be complete before
* proceeding
*/
while (TransferInProgress);
/*
* Wait for write enable command to the flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* Wait for the transfer on the SPI bus to be complete
* before proceeding
*/
while (TransferInProgress);
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x02) == 0x02) {
break;
}
}
/*
* Clear write protect bits using write status command to the flash
* this needs to be sent as a seperate transfer before the erase
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, WriteStatusCmd, NULL, sizeof(WriteStatusCmd));
/*
* Wait for the transfer on the SPI bus to be complete before
* proceeding
*/
while (TransferInProgress);
/*
* Check for write status command to the flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* Wait for the transfer on the SPI bus to be complete
* before proceeding
*/
while (TransferInProgress);
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x1C) == 0x0) {
break;
}
}
/*
* Send the write enable command to the flash so that it can be
* written to, this needs to be sent as a seperate transfer
* before the erase
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, &WriteEnableCmd, NULL, sizeof(WriteEnableCmd));
/*
* Wait for the transfer on the SPI bus to be complete before
* proceeding
*/
while (TransferInProgress);
/*
* Wait for write enable command to the flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* Wait for the transfer on the SPI bus to be complete
* before proceeding
*/
while (TransferInProgress);
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x02) == 0x02) {
break;
}
}
/*
* Setup the bulk erase or chip-erase command
*/
WriteBuffer[COMMAND_OFFSET] = CHIP_ERASE_CMD;
/*
* Send the bulk erase command; no receive buffer is specified
* since there is nothing to receive
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, WriteBuffer, NULL, 1);
while (TransferInProgress);
/*
* Wait for the erase command to the flash to be completed
*/
while (1) {
/*
* Poll the status register of the device to determine
* when it completes, by sending a read status command
* and receiving the status byte
*/
TransferInProgress = TRUE;
XSpiPs_Transfer(SpiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* Wait for the transfer on the SPI bus to be complete
* before proceeding
*/
while (TransferInProgress);
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
}
/*****************************************************************************/
/**
*
* This function setups the interrupt system for an Spi device.
*
* @param IntcInstancePtr is a pointer to the instance of the Intc device.
* @param SpiInstancePtr is a pointer to the instance of the Spi device.
* @param SpiIntrId is the interrupt Id for an SPI device.
*
* @return
* - XST_SUCCESS if successful
* - XST_FAILURE if not successful
*
* @note None.
*
******************************************************************************/
static int SpiPsSetupIntrSystem(XScuGic *IntcInstancePtr,
XSpiPs *SpiInstancePtr, u16 SpiIntrId)
{
int Status;
XScuGic_Config *IntcConfig; /* Instance of the interrupt controller */
Xil_ExceptionInit();
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
IntcInstancePtr);
/*
* Connect the device driver handler that will be called when an
* interrupt for the device occurs, the handler defined above performs
* the specific interrupt processing for the device.
*/
Status = XScuGic_Connect(IntcInstancePtr, SpiIntrId,
(Xil_ExceptionHandler)XSpiPs_InterruptHandler,
(void *)SpiInstancePtr);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Enable the interrupt for the Spi device.
*/
XScuGic_Enable(IntcInstancePtr, SpiIntrId);
/*
* Enable interrupts in the Processor.
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function disables the interrupts that occur for the Spi device.
*
* @param IntcInstancePtr is the pointer to an INTC instance.
* @param SpiIntrId is the interrupt Id for an SPI device.
*
* @return None.
*
* @note None.
*
******************************************************************************/
static void SpiPsDisableIntrSystem(XScuGic *IntcInstancePtr, u16 SpiIntrId)
{
/*
* Disable the interrupt for the SPI device.
*/
XScuGic_Disable(IntcInstancePtr, SpiIntrId);
/*
* Disconnect and disable the interrupt for the Spi device.
*/
XScuGic_Disconnect(IntcInstancePtr, SpiIntrId);
}

View file

@ -0,0 +1,659 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips_polled_example.c
*
*
* This file contains a design example using the SPI driver (XSpiPs) in
* polled mode with a Serial Flash device. This examples performs
* transfers in polled mode.
* The hardware which this example runs on, must have a Serial Flash
* for it to run. This example has been tested with SST25W080.
*
* @note
*
* None.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00 sg 1/30/13 First release
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* SDK generated parameters */
#include "xspips.h" /* SPI device driver */
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
/*
* The following constants define the commands which may be sent to the flash
* device.
*/
#define WRITE_STATUS_CMD 0x01
#define WRITE_CMD 0x02
#define READ_CMD 0x03
#define WRITE_DISABLE_CMD 0x04
#define READ_STATUS_CMD 0x05
#define WRITE_ENABLE_CMD 0x06
#define FAST_READ_CMD 0x0B
#define CHIP_ERASE_CMD 0x60
#define BULK_ERASE_CMD 0xC7
#define BLOCK_ERASE_64K_CMD 0xD8
#define READ_ID 0x90
#define AAI_WRITE_CMD 0xAD
/*
* The following constants define the offsets within a FlashBuffer data
* type for each kind of data. Note that the read data offset is not the
* same as the write data because the SPI driver is designed to allow full
* duplex transfers such that the number of bytes received is the number
* sent and received.
*/
#define COMMAND_OFFSET 0 /* Flash instruction */
#define ADDRESS_1_OFFSET 1 /* MSB byte of address to read or write */
#define ADDRESS_2_OFFSET 2 /* Middle byte of address to read or write */
#define ADDRESS_3_OFFSET 3 /* LSB byte of address to read or write */
#define DATA_OFFSET 4 /* Start of Data for Read/Write */
#define DUMMY_SIZE 1 /* Number of dummy bytes for fast read */
#define RD_ID_SIZE 4 /* Read ID command + 3 bytes ID response */
/*
* The following constants specify the extra bytes which are sent to the
* flash on the SPI interface, that are not data, but control information
* which includes the command and address
*/
#define OVERHEAD_SIZE 4
#define UNIQUE_VALUE 0x05
/*
* The following constants specify the max amount of data and the size of the
* the buffer required to hold the data and overhead to transfer the data to
* and from the flash.
*/
#define MAX_DATA 1024*1024
/*
* The following constant defines the slave select signal that is used to
* to select the flash device on the SPI bus, this signal is typically
* connected to the chip select of the device
*/
#define FLASH_SPI_SELECT 0x01
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
void FlashErase(XSpiPs *SpiPtr);
void FlashWrite(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command);
void FlashRead(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command);
int SpiPsFlashPolledExample(XSpiPs *SpiInstancePtr, u16 SpiDeviceId);
int FlashReadID(void);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XSpiPs SpiInstance;
/*
* Write Address Location in Serial Flash.
*/
static int TestAddress;
/*
* The following variables are used to read and write to the eeprom and they
* are global to avoid having large buffers on the stack
*/
u8 ReadBuffer[MAX_DATA + DATA_OFFSET + DUMMY_SIZE];
u8 WriteBuffer[MAX_DATA + DATA_OFFSET];
/*****************************************************************************/
/**
*
* Main function to call the SPI Flash Polled Example.
*
* @param None
*
* @return
* - XST_SUCCESS if successful
* - XST_FAILURE if not successful
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("SPI SerialFlash Polled Example Test \r\n");
/*
* Run the Spi Polled example.
*/
Status = SpiPsFlashPolledExample(&SpiInstance,SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("SPI SerialFlash Polled Example Test Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran SPI SerialFlash Polled Example Test\r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in polled mode. This function writes and reads data
* from a serial flash.
*
* @param SpiPtr is a pointer to the SPI driver instance to use.
*
* @param SpiDeviceId is the Instance Id of SPI in the system.
*
* @return
* - XST_SUCCESS if successful
* - XST_FAILURE if not successful
*
* @note
*
* If the device slave select is not correct and the device is not responding
* on bus it will read a status of 0xFF for the status register as the bus
* is pulled up.
*
*****************************************************************************/
int SpiPsFlashPolledExample(XSpiPs *SpiInstancePtr,
u16 SpiDeviceId)
{
int Status;
u8 *BufferPtr;
u8 UniqueValue;
u32 Count;
XSpiPs_Config *SpiConfig;
/*
* Initialize the SPI driver so that it's ready to use
*/
SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize(SpiInstancePtr, SpiConfig,
SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XSpiPs_SelfTest(SpiInstancePtr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Set the SPI device as a master with manual start and manual
* chip select mode options
*/
XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MANUAL_START_OPTION | \
XSPIPS_MASTER_OPTION | XSPIPS_FORCE_SSELECT_OPTION);
/*
* Set the SPI device pre-scalar to divide by 8
*/
XSpiPs_SetClkPrescaler(SpiInstancePtr, XSPIPS_CLK_PRESCALE_8);
memset(WriteBuffer, 0x00, sizeof(WriteBuffer));
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Initialize the write buffer for a pattern to write to the Flash
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue);
}
/*
* Set the flash chip select
*/
XSpiPs_SetSlaveSelect(SpiInstancePtr, FLASH_SPI_SELECT);
/*
* Read the flash Id
*/
Status = FlashReadID();
if (Status != XST_SUCCESS) {
xil_printf("SPI Flash Polled Example Read ID Failed\r\n");
return XST_FAILURE;
}
/*
* Erase the flash
*/
FlashErase(SpiInstancePtr);
TestAddress = 0x0;
/*
* Write the data in the write buffer to TestAddress in serial flash
*/
FlashWrite(SpiInstancePtr, TestAddress, MAX_DATA, WRITE_CMD);
/*
* Read the contents of the flash from TestAddress of size MAX_DATA
* using Normal Read command
*/
FlashRead(SpiInstancePtr, TestAddress, MAX_DATA, READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue)) {
return XST_FAILURE;
}
}
memset(WriteBuffer, 0x00, sizeof(WriteBuffer));
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Initialize the write buffer for a pattern to write to the Flash
* and the read buffer to zero so it can be verified after the read, the
* test value that is added to the unique value allows the value to be
* changed in a debug environment to guarantee
*/
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
WriteBuffer[DATA_OFFSET + Count] = (u8)(UniqueValue);
}
/*
* Set the SPI device as a master with auto start and manual
* chip select mode options
*/
XSpiPs_SetOptions(SpiInstancePtr, XSPIPS_MASTER_OPTION | \
XSPIPS_FORCE_SSELECT_OPTION);
/*
* Erase the flash
*/
FlashErase(SpiInstancePtr);
TestAddress = 0x0;
/*
* Write the data in the write buffer to TestAddress in serial flash
*/
FlashWrite(SpiInstancePtr, TestAddress, MAX_DATA, WRITE_CMD);
/*
* Read the contents of the flash from TestAddress of size MAX_DATA
* using Normal Read command
*/
FlashRead(SpiInstancePtr, TestAddress, MAX_DATA, READ_CMD);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and verify the data read is the data that was written
*/
BufferPtr = &ReadBuffer[DATA_OFFSET];
for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MAX_DATA;
Count++, UniqueValue++) {
if (BufferPtr[Count] != (u8)(UniqueValue)) {
return XST_FAILURE;
}
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function writes to the desired address in serial flash connected to
* the SPI interface.
*
* @param SpiPtr is a pointer to the SPI driver instance to use.
* @param Address contains the address to write data to in the flash.
* @param ByteCount contains the number of bytes to write.
* @param Command is the command used to write data to the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashWrite(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
u8 WriteDisableCmd = { WRITE_DISABLE_CMD };
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0 }; /* must send 2 bytes */
u8 FlashStatus[2];
u32 Temp = 0;
u32 TempAddress = Address;
u8 TempBuffer[5];
if (Command == WRITE_CMD) {
for (Temp = 0; Temp < ByteCount ; Temp++, TempAddress++) {
/*
* Send the write enable command to the flash so
* that it can be written to, this needs to be sent
* as a seperate transfer before the write
*/
XSpiPs_PolledTransfer(SpiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
/*
* Setup the write command with the specified address
* and data for the flash
*/
TempBuffer[COMMAND_OFFSET] = Command;
TempBuffer[ADDRESS_1_OFFSET] =
(u8)((TempAddress & 0xFF0000) >> 16);
TempBuffer[ADDRESS_2_OFFSET] =
(u8)((TempAddress & 0xFF00) >> 8);
TempBuffer[ADDRESS_3_OFFSET] =
(u8)(TempAddress & 0xFF);
TempBuffer[DATA_OFFSET] =
WriteBuffer[DATA_OFFSET + Temp];
/*
* Send the write command, address, and data to the
* flash to be written, no receive buffer is specified
* since there is nothing to receive
*/
XSpiPs_PolledTransfer(SpiPtr, TempBuffer, NULL, 5);
/*
* Wait for the write command to the flash to be ,
* completed it takes some time for the data to be
* written
*/
while (1) {
/*
* Poll the status register of the flash to
* determine when it completes, by sending
* a read status command and receiving the
* status byte
*/
XSpiPs_PolledTransfer(SpiPtr, ReadStatusCmd,
FlashStatus, sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done,
* then stop waiting, if a value of 0xFF in
* the status byte is read from the device
* and this loop never exits, the device slave
* select is possibly incorrect such that the
* device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
XSpiPs_PolledTransfer(SpiPtr, &WriteDisableCmd,
NULL, sizeof(WriteDisableCmd));
}
}
}
/******************************************************************************
*
* This function reads from the serial flash connected to the
* SPI interface.
*
* @param SpiPtr is a pointer to the SPI driver instance to use.
* @param Address contains the address to read data from in the flash.
* @param ByteCount contains the number of bytes to read.
* @param Command is the command used to read data from the flash. SPI
* device supports one of the Read, Fast Read commands to read
* data from the flash.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashRead(XSpiPs *SpiPtr, u32 Address, u32 ByteCount, u8 Command)
{
/*
* Setup the read command with the specified address and data for the
* flash
*/
WriteBuffer[COMMAND_OFFSET] = Command;
WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);
WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);
WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);
XSpiPs_PolledTransfer(SpiPtr, WriteBuffer, ReadBuffer,
ByteCount + OVERHEAD_SIZE);
}
/******************************************************************************
*
* This function reads serial flash ID connected to the SPI interface.
*
* @param None.
*
* @return
* - XST_SUCCESS if successful
* - XST_FAILURE if not successful
*
* @note None.
*
******************************************************************************/
int FlashReadID(void)
{
u8 Index;
int Status;
u8 ByteCount = 4;
u8 SendBuffer[8];
u8 RecvBuffer[8];
SendBuffer[0] = READ_ID;
SendBuffer[1] = 0;
SendBuffer[2] = 0;
SendBuffer[3] = 0;
for(Index=0; Index < ByteCount; Index++) {
SendBuffer[4 + Index] = 0x00;
}
Status = XSpiPs_PolledTransfer(&SpiInstance, SendBuffer, RecvBuffer,
(4 + ByteCount));
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
for(Index=0; Index < ByteCount; Index++) {
xil_printf("ID : %0x\r\n", RecvBuffer[4 + Index]);
}
return XST_SUCCESS;
}
/******************************************************************************
*
*
* This function erases the sectors in the serial flash connected to the
* SPI interface.
*
* @param SpiPtr is a pointer to the SPI driver instance to use.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void FlashErase(XSpiPs *SpiPtr)
{
u8 WriteEnableCmd = { WRITE_ENABLE_CMD };
/* must send 2 bytes */
u8 ReadStatusCmd[] = { READ_STATUS_CMD, 0x0 };
/* must send 2 bytes */
u8 WriteStatusCmd[] = { WRITE_STATUS_CMD, 0x0 };
u8 FlashStatus[3];
/*
* Send the write enable command to the flash so that it can be
* written to, this needs to be sent as a separate transfer
* before the erase
*/
XSpiPs_PolledTransfer(SpiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
while (1) {
XSpiPs_PolledTransfer(SpiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write enabled, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x02) == 0x02) {
break;
}
}
/*
* Clear write protect bits using write status command to the flash
* so that it can be written to, this needs to be sent as a
* separate transfer before the erase
*/
XSpiPs_PolledTransfer(SpiPtr, WriteStatusCmd, NULL,
sizeof(WriteStatusCmd));
while (1) {
XSpiPs_PolledTransfer(SpiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the WP bits cleared, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x1C) == 0x0) {
break;
}
}
/*
* Send the write enable command to the flash so that it can be
* written to, this needs to be sent as a separate transfer
* before the erase
*/
XSpiPs_PolledTransfer(SpiPtr, &WriteEnableCmd, NULL,
sizeof(WriteEnableCmd));
while (1) {
XSpiPs_PolledTransfer(SpiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write enabled, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x02) == 0x02) {
break;
}
}
/*
* Performs chip erase.
*/
WriteBuffer[COMMAND_OFFSET] = CHIP_ERASE_CMD;
XSpiPs_PolledTransfer(SpiPtr, WriteBuffer, NULL, 1);
/*
* Wait for the erase command to the flash to be completed
*/
while (1) {
XSpiPs_PolledTransfer(SpiPtr, ReadStatusCmd, FlashStatus,
sizeof(ReadStatusCmd));
/*
* If the status indicates the write is done, then stop
* waiting; if a value of 0xFF in the status byte is
* read from the device and this loop never exits, the
* device slave select is possibly incorrect such that
* the device status is not being read
*/
if ((FlashStatus[1] & 0x01) == 0) {
break;
}
}
}

View file

@ -0,0 +1,156 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/******************************************************************************/
/**
* @file xspips_selftest_example.c
*
* This file contains an example for using the SPI Hardware, it does a simple
* hardware connection check.
*
* @note
*
* None
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- -----------------------------------------------
* 1.00 drg/jz 01/25/10 First release.
* </pre>
*
*******************************************************************************/
/***************************** Include Files **********************************/
#include "xparameters.h"
#include "xspips.h"
#include "xil_printf.h"
/************************** Constant Definitions ******************************/
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
/**************************** Type Definitions ********************************/
/***************** Macros (Inline Functions) Definitions **********************/
/************************** Function Prototypes *******************************/
int SpiPsSelfTestExample(u16 DeviceId);
/************************** Variable Definitions ******************************/
XSpiPs Spi; /* The instance of the SPI device */
/******************************************************************************/
/**
* Main function to call the Spi SelfTest example.
*
* @param None
*
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note None
*
*******************************************************************************/
#ifndef TESTAPP_GEN
int main(void)
{
int Status;
xil_printf("SPI Selftest Example \r\n");
/*
* Call the example , specify the device ID that is generated in
* xparameters.h
*/
Status = SpiPsSelfTestExample(SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("SPI Selftest Example Failed\r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran SPI Selftest Example\r\n");
return XST_SUCCESS;
}
#endif
/*****************************************************************************/
/**
*
* This function does a selftest on the SPI device and XSpiPs driver as an
* example. The purpose of this function is to illustrate the usage of the
* XSpiPs driver.
*
*
* @param DeviceId is the XPAR_<SPIPS_instance>_DEVICE_ID value from
* xparameters.h
*
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note None
*
****************************************************************************/
int SpiPsSelfTestExample(u16 DeviceId)
{
int Status;
XSpiPs_Config *SpiConfig;
/*
* Initialize the SPI device.
*/
SpiConfig = XSpiPs_LookupConfig(DeviceId);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize(&Spi, SpiConfig, SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build.
*/
Status = XSpiPs_SelfTest(&Spi);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}

View file

@ -0,0 +1,320 @@
/******************************************************************************
*
* Copyright (C) 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips_slave_polled_example.c
*
*
* This file contains a design example using the SPI controller in slave mode.
* This examples performs transfers in polled mode and has been tested with
* Aardvark Analyzer as Master. This example echoes data which it receives
* from the master. The slave controller expects MAX_DATA bytes of data from
* the master to transmit onto the SPI bus which the slave will receive into
* its Rx buffer. It will poll until the Rx FIFO is filled with the Threshold
* limit of data which is set to MAX_DATA. On sending data, the master will
* receive dummy bytes in response. Master has to send MAX_DATA dummy bytes
* to read back the echoed data.
*
*
* @note
*
* The slave mode test needs an external master to send data to the Spi device.
* This example has been tested with Aardvark Analyzer as Master.
* The Clock Polarity and Phase should match between master and the slave.
*
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 2.0 sb 08/22/14 First release
*
*</pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h" /* SDK generated parameters */
#include "xspips.h" /* SPI device driver */
#include "xil_printf.h"
/************************** Constant Definitions *****************************/
/*
* The following constant map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define SPI_DEVICE_ID XPAR_XSPIPS_0_DEVICE_ID
/*
* The following constant specify the max amount of data the slave is
* expecting to receive from the master.
*/
#define MAX_DATA 100
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
#define SpiPs_RecvByte(BaseAddress) \
(u8)XSpiPs_In32((BaseAddress) + XSPIPS_RXD_OFFSET)
#define SpiPs_SendByte(BaseAddress, Data) \
XSpiPs_Out32((BaseAddress) + XSPIPS_TXD_OFFSET, (Data))
/************************** Function Prototypes ******************************/
void SpiSlaveRead(int ByteCount);
void SpiSlaveWrite(u8 *Sendbuffer, int ByteCount);
int SpiPsSlavePolledExample(u16 SpiDeviceId);
/************************** Variable Definitions *****************************/
/*
* The instances to support the device drivers are global such that they
* are initialized to zero each time the program runs. They could be local
* but should at least be static so they are zeroed.
*/
static XSpiPs SpiInstance;
/*
* The ReadBuffer is used to read to the data which it received from the SPI
* Bus which master has sent.
*/
u8 ReadBuffer[MAX_DATA];
/*****************************************************************************/
/**
*
* Main function to call the SPI Slave Example.
*
* @param None
*
* @return
* - XST_SUCCESS if successful
* - XST_FAILURE if not successful
*
* @note None
*
******************************************************************************/
int main(void)
{
int Status;
xil_printf("Running SpiPS Slave Polled Example \r\n");
/*
* Run the SpiPs Slave Polled example.
*/
Status = SpiPsSlavePolledExample(SPI_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("SpiPs Slave Polled Example Failed \r\n");
return XST_FAILURE;
}
xil_printf("Successfully ran SpiPs Slave Polled Example \r\n");
return XST_SUCCESS;
}
/*****************************************************************************
*
* The purpose of this function is to illustrate how to use the XSpiPs
* device driver in Slave mode. This function reads data from a SPI Master
* and will echo it back to the Master.
*
* @param SpiDeviceId is the Instance Id of SPI in the system.
*
* @return
* - XST_SUCCESS if successful
* - XST_FAILURE if not successful
*
* @note None
*
*
*****************************************************************************/
int SpiPsSlavePolledExample(u16 SpiDeviceId)
{
int Status;
u8 *BufferPtr;
XSpiPs_Config *SpiConfig;
/*
* Initialize the SPI driver so that it's ready to use
*/
SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize((&SpiInstance), SpiConfig,
SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* The SPI device is a slave by default and the clock phase
* have to be set according to its master. In this example, CPOL is set
* to quiescent high and CPHA is set to 1.
*/
Status = XSpiPs_SetOptions((&SpiInstance), (XSPIPS_CR_CPHA_MASK) | \
(XSPIPS_CR_CPOL_MASK));
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
memset(ReadBuffer, 0x00, sizeof(ReadBuffer));
/*
* Set the Rx FIFO Threshold to the Max Data
*/
XSpiPs_SetRXWatermark((&SpiInstance),MAX_DATA);
/*
* Enable the device.
*/
XSpiPs_Enable((&SpiInstance));
/*
* Read the contents of the Receive buffer
* Master is expected to send MAX_DATA number of bytes
*/
SpiSlaveRead(MAX_DATA);
/*
* Setup a pointer to the start of the data that was read into the read
* buffer and the same back
*/
BufferPtr = ReadBuffer;
/*
* Send the data received back to Master
* Master is expected to send MAX_DATA number of dummy bytes for
* the slave to be able to echo previously received data.
*/
SpiSlaveWrite(BufferPtr, MAX_DATA);
/*
* Disable the device.
*/
XSpiPs_Disable((&SpiInstance));
return XST_SUCCESS;
}
/******************************************************************************
*
* This function reads from the Rx buffer
*
* @param ByteCount is the number of bytes to be read from Rx buffer.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiSlaveRead(int ByteCount)
{
int Count;
u32 StatusReg;
StatusReg = XSpiPs_ReadReg(SpiInstance.Config.BaseAddress,
XSPIPS_SR_OFFSET);
/*
* Polling the Rx Buffer for Data
*/
do{
StatusReg = XSpiPs_ReadReg(SpiInstance.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(
SpiInstance.Config.BaseAddress);
}
}
/******************************************************************************
*
* This function writes Data into the Tx buffer
*
* @param Sendbuffer is the buffer whose data is to be sent onto the
* Tx FIFO.
* @param ByteCount is the number of bytes to be read from Rx buffer.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void SpiSlaveWrite(u8 *Sendbuffer, int ByteCount)
{
u32 StatusReg;
int TransCount = 0;
StatusReg = XSpiPs_ReadReg(SpiInstance.Config.BaseAddress,
XSPIPS_SR_OFFSET);
/*
* Fill the TXFIFO with as many bytes as it will take (or as
* many as we have to send).
*/
while ((ByteCount > 0) &&
(TransCount < XSPIPS_FIFO_DEPTH)) {
SpiPs_SendByte(SpiInstance.Config.BaseAddress,
*Sendbuffer);
Sendbuffer++;
++TransCount;
ByteCount--;
}
/*
* Wait for the transfer to finish by polling Tx fifo status.
*/
do {
StatusReg = XSpiPs_ReadReg(
SpiInstance.Config.BaseAddress,
XSPIPS_SR_OFFSET);
} while ((StatusReg & XSPIPS_IXR_TXOW_MASK) == 0);
}

View file

@ -0,0 +1,40 @@
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
CC_FLAGS = $(COMPILER_FLAGS)
ECC_FLAGS = $(EXTRA_COMPILER_FLAGS)
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
OUTS = *.o
LIBSOURCES:=*.c
INCLUDEFILES:=*.h
OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c)))
libs: banner xspips_libs clean
%.o: %.c
${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $<
banner:
echo "Compiling spips"
xspips_libs: ${OBJECTS}
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS}
.PHONY: include
include: xspips_includes
xspips_includes:
${CP} ${INCLUDEFILES} ${INCLUDEDIR}
clean:
rm -rf ${OBJECTS}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,689 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips.h
*
* This file contains the implementation of the XSpiPs driver. It works for
* both the master and slave mode. User documentation for the driver functions
* is contained in this file in the form of comment blocks at the front of each
* function.
*
* An SPI device connects to an SPI bus through a 4-wire serial interface.
* The SPI bus is a full-duplex, synchronous bus that facilitates communication
* between one master and one slave. The device is always full-duplex,
* which means that for every byte sent, one is received, and vice-versa.
* The master controls the clock, so it can regulate when it wants to
* send or receive data. The slave is under control of the master, it must
* respond quickly since it has no control of the clock and must send/receive
* data as fast or as slow as the master does.
*
* <b>Initialization & Configuration</b>
*
* The XSpiPs_Config structure is used by the driver to configure itself. This
* configuration structure is typically created by the tool-chain based on HW
* build properties.
*
* To support multiple runtime loading and initialization strategies employed by
* various operating systems, the driver instance can be initialized in the
* following way:
* - XSpiPs_LookupConfig(DeviceId) - Use the devide identifier to find the
* static configuration structure defined in xspips_g.c. This is setup by
* the tools. For some operating systems the config structure will be
* initialized by the software and this call is not needed.
* - XSpiPs_CfgInitialize(InstancePtr, CfgPtr, EffectiveAddr) - Uses a
* configuration structure provided by the caller. If running in a system
* with address translation, the provided virtual memory base address
* replaces the physical address present in the configuration structure.
*
* <b>Multiple Masters</b>
*
* More than one master can exist, but arbitration is the responsibility of
* the higher layer software. The device driver does not perform any type of
* arbitration.
*
* <b>Multiple Slaves</b>
*
* Contention between multiple masters is detected by the hardware, in which
* case a mode fault occurs on the device. The device is disabled immediately
* by hardware, and the current word transfer is stopped. The Aborted word
* transfer due to the mode fault is resumed once the devie is enabled again.
*
* <b>Modes of Operation</b>
*
* There are four modes to perform a data transfer and the selection of a mode
* is based on Chip Select(CS) and Start. These two options individually, can
* be controlled either by software(Manual) or hardware(Auto).
* - Auto CS: Chip select is automatically asserted as soon as the first word
* is written into the TXFIFO and deasserted when the TXFIFO becomes
* empty
* - Manual CS: Software must assert and deassert CS.
* - Auto Start: Data transmission starts as soon as there is data in the
* TXFIFO and stalls when the TXFIFO is empty
* - Manual Start: Software must start data transmission at the beginning of
* the transaction or whenever the TXFIFO has become empty
*
* The preferred combination is Manual CS and Auto Start.
* In this combination, the software asserts CS before loading any data into
* TXFIFO. In Auto Start mode, whenever data is in TXFIFO, controller sends it
* out until TXFIFO becomes empty. The software reads the RXFIFO whenever the
* data is available. If no further data, software disables CS.
*
* Risks/challenges of other combinations:
* - Manual CS and Manual Start: Manual Start bit should be set after each
* TXFIFO write otherwise there could be a race condition where the TXFIFO
* becomes empty before the new word is written. In that case the
* transmission stops.
* - Auto CS with Manual or Auto Start: It is very difficult for software to
* keep the TXFIFO filled. Whenever the TXFIFO runs empty, CS is deasserted.
* This results in a single transaction to be split into multiple pieces each
* with its own chip select. This will result in garbage data to be sent.
*
* <b>Interrupts</b>
*
* The user must connect the interrupt handler of the driver,
* XSpiPs_InterruptHandler, to an interrupt system such that it will be
* called when an interrupt occurs. This function does not save and restore
* the processor context such that the user must provide this processing.
*
* The driver handles the following interrupts:
* - Data Transmit Register/FIFO Underflow
* - Data Receive Register/FIFO Full
* - Data Receive Register/FIFO Not Empty
* - Data Transmit Register/FIFO Full
* - Data Transmit Register/FIFO Overwater
* - Mode Fault Error
* - Data Receive Register/FIFO Overrun
*
* The Data Transmit Register/FIFO Overwater interrupt -- indicates that the
* SPI device has transmitted the data available to transmit, and now its data
* register and FIFO is ready to accept more data. The driver uses this
* interrupt to indicate progress while sending data. The driver may have
* more data to send, in which case the data transmit register and FIFO is
* filled for subsequent transmission. When this interrupt arrives and all
* the data has been sent, the driver invokes the status callback with a
* value of XST_SPI_TRANSFER_DONE to inform the upper layer software that
* all data has been sent.
*
* The Data Transmit Register/FIFO Underflow interrupt -- indicates that,
* as slave, the SPI device was required to transmit but there was no data
* available to transmit in the transmit register (or FIFO). This may not
* be an error if the master is not expecting data. But in the case where
* the master is expecting data, this serves as a notification of such a
* condition. The driver reports this condition to the upper layer
* software through the status handler.
*
* The Data Receive Register/FIFO Overrun interrupt -- indicates that the SPI
* device received data and subsequently dropped the data because the data
* receive register and FIFO was full. The interrupt applies to both master
* and slave operation. The driver reports this condition to the upper layer
* software through the status handler. This likely indicates a problem with
* the higher layer protocol, or a problem with the slave performance.
*
* The Mode Fault Error interrupt -- indicates that while configured as a
* master, the device was selected as a slave by another master. This can be
* used by the application for arbitration in a multimaster environment or to
* indicate a problem with arbitration. When this interrupt occurs, the
* driver invokes the status callback with a status value of
* XST_SPI_MODE_FAULT. It is up to the application to resolve the conflict.
* When configured as a slave, Mode Fault Error interrupt indicates that a slave
* device was selected as a slave by a master, but the slave device was
* disabled. When configured as a master, Mode Fault Error interrupt indicates
* that another SPI device is acting as a master on the bus.
*
*
* <b>Polled Operation</b>
*
* Transfer in polled mode is supported through a separate interface function
* XSpiPs_PolledTransfer(). Unlike the transfer function in the interrupt mode,
* this function blocks until all data has been sent/received.
*
* <b>Device Busy</b>
*
* Some operations are disallowed when the device is busy. The driver tracks
* whether a device is busy. The device is considered busy when a data transfer
* request is outstanding, and is considered not busy only when that transfer
* completes (or is aborted with a mode fault error). This applies to both
* master and slave devices.
*
* <b>Device Configuration</b>
*
* The device can be configured in various ways during the FPGA implementation
* process. Configuration parameters are stored in the xspips_g.c file or
* passed in via XSpiPs_CfgInitialize(). A table is defined where each entry
* contains configuration information for an SPI device, including the base
* address for the device.
*
* <b>RTOS Independence</b>
*
* This driver is intended to be RTOS and processor independent. It works with
* physical addresses only. Any needs for dynamic memory management, threads or
* thread mutual exclusion, virtual memory, or cache control must be satisfied
* by the layer above this driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- -----------------------------------------------
* 1.00 drg/jz 01/25/10 First release
* 1.00 sdm 10/25/11 Removed the Divide by 2 in the SPI Clock Prescaler
* options as this is not supported in the device.
* 1.01 sg 03/07/12 Updated the code to always clear the relevant bits
* before writing to config register.
* Always clear the slave select bits before write and
* clear the bits to no slave at the end of transfer
* Modified the Polled transfer transmit/receive logic.
* Tx should wait on TXOW Interrupt and Rx on RXNEMTY.
* 1.02 sg 05/31/12 Updated XSPIPS_FIFO_DEPTH to 128 from 32 to match HW
* for CR 658289
* 1.03 sg 09/21/12 Added memory barrier dmb in polled transfer and
* interrupt handler to overcome the clock domain
* crossing issue in the controller. For CR #679252.
* 1.04a sg 01/30/13 Created XSPIPS_MANUAL_START_OPTION. Created macros
* XSpiPs_IsMaster, XSpiPs_IsManualStart and
* XSpiPs_IsManualChipSelect. Changed SPI
* Enable/Disable macro argument from BaseAddress to
* Instance Pointer. Added DelayNss argument to SetDelays
* and GetDelays API's. Added macros to set/get the
* RX Watermark value.Created macros XSpiPs_IsMaster,
* XSpiPs_IsManualStart and XSpiPs_IsManualChipSelect.
* Changed SPI transfer logic for polled and interrupt
* modes to be based on filled tx fifo count and receive
* based on it. RXNEMPTY interrupt is not used.
* SetSlaveSelect API logic is modified to drive the bit
* position low based on the slave select value
* requested. GetSlaveSelect API will return the value
* based on bit position that is low.
* Created XSPIPS_CR_MODF_GEN_EN_MASK macro and added it
* to XSPIPS_CR_RESET_STATE. Created
* XSPIPS_IXR_WR_TO_CLR_MASK for interrupts which need
* write-to-clear. Added shift and mask macros for d_nss
* parameter. Added Rx Watermark mask.
* 1.05a hk 26/04/13 Added disable and enable in XSpiPs_SetOptions when
* CPOL/CPHA bits are set/reset. Fix for CR#707669.
* 1.06a hk 08/22/13 Changed GetSlaveSelect function. CR# 727866.
* Added masking ConfigReg before writing in SetSlaveSel
* Added extended slave select support - CR#722569.
* Added prototypes of reset API and related constant
* definitions.
* Added check for MODF in polled transfer function.
*
* </pre>
*
******************************************************************************/
#ifndef XSPIPS_H /* prevent circular inclusions */
#define XSPIPS_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xstatus.h"
#include "xspips_hw.h"
/************************** Constant Definitions *****************************/
/** @name Configuration options
*
* The following options are supported to enable/disable certain features of
* an SPI device. Each of the options is a bit mask, so more than one may be
* specified.
*
* <b>The Master option</b> configures the SPI device as a master.
* By default, the device is a slave.
*
* The <b>Active Low Clock option</b> configures the device's clock polarity.
* Setting this option means the clock is active low and the SCK signal idles
* high. By default, the clock is active high and SCK idles low.
*
* The <b>Clock Phase option</b> configures the SPI device for one of two
* transfer formats. A clock phase of 0, the default, means data is valid on
* the first SCK edge (rising or falling) after the slave select (SS) signal
* has been asserted. A clock phase of 1 means data is valid on the second SCK
* edge (rising or falling) after SS has been asserted.
*
* The <b>Slave Select Decode Enable option</b> selects how the SPI_SS_outN are
* controlled by the SPI Slave Select Decode bits.
* 0: Use this setting for the standard configuration of up to three slave
* select outputs. Only one of the three slave select outputs will be low.
* (Default)
* 1: Use this setting for the optional configuration of an additional decoder
* to support 8 slave select outputs. SPI_SS_outN reflects the value in the
* register.
*
* The <b>SPI Force Slave Select option</b> is used to enable manual control of
* the signals SPI_SS_outN.
* 0: The SPI_SS_outN signals are controlled by the SPI controller during
* transfers. (Default)
* 1: The SPI_SS_outN signal indicated by the Slave Select Control bit is
* forced active (driven low) regardless of any transfers in progress.
*
* NOTE: The driver will handle setting and clearing the Slave Select when
* the user sets the "FORCE_SSELECT_OPTION". Using this option will allow the
* SPI clock to be set to a faster speed. If the SPI clock is too fast, the
* processor cannot empty and refill the FIFOs before the TX FIFO is empty
* When the SPI hardware is controlling the Slave Select signals, this
* will cause slave to be de-selected and terminate the transfer.
*
* The <b>Manual Start option</b> is used to enable manual control of
* the Start command to perform data transfer.
* 0: The Start command is controlled by the SPI controller during
* transfers(Default). Data transmission starts as soon as there is data in
* the TXFIFO and stalls when the TXFIFO is empty
* 1: The Start command must be issued by software to perform data transfer.
* Bit 15 of Configuration register is used to issue Start command. This bit
* must be set whenever TXFIFO is filled with new data.
*
* NOTE: The driver will set the Manual Start Enable bit in Configuration
* Register, if Manual Start option is selected. Software will issue
* Manual Start command whenever TXFIFO is filled with data. When there is
* no further data, driver will clear the Manual Start Enable bit.
*
* @{
*/
#define XSPIPS_MASTER_OPTION 0x1 /**< Master mode option */
#define XSPIPS_CLK_ACTIVE_LOW_OPTION 0x2 /**< Active Low Clock option */
#define XSPIPS_CLK_PHASE_1_OPTION 0x4 /**< Clock Phase one option */
#define XSPIPS_DECODE_SSELECT_OPTION 0x8 /**< Select 16 slaves Option */
#define XSPIPS_FORCE_SSELECT_OPTION 0x10 /**< Force Slave Select */
#define XSPIPS_MANUAL_START_OPTION 0x20 /**< Manual Start mode option */
/*@}*/
/** @name SPI Clock Prescaler options
* The SPI Clock Prescaler Configuration bits are used to program master mode
* bit rate. The bit rate can be programmed in divide-by-two decrements from
* pclk/4 to pclk/256.
*
* @{
*/
#define XSPIPS_CLK_PRESCALE_4 0x01 /**< PCLK/4 Prescaler */
#define XSPIPS_CLK_PRESCALE_8 0x02 /**< PCLK/8 Prescaler */
#define XSPIPS_CLK_PRESCALE_16 0x03 /**< PCLK/16 Prescaler */
#define XSPIPS_CLK_PRESCALE_32 0x04 /**< PCLK/32 Prescaler */
#define XSPIPS_CLK_PRESCALE_64 0x05 /**< PCLK/64 Prescaler */
#define XSPIPS_CLK_PRESCALE_128 0x06 /**< PCLK/128 Prescaler */
#define XSPIPS_CLK_PRESCALE_256 0x07 /**< PCLK/256 Prescaler */
/*@}*/
/** @name Callback events
*
* These constants specify the handler events that are passed to
* a handler from the driver. These constants are not bit masks such that
* only one will be passed at a time to the handler.
*
* @{
*/
#define XSPIPS_EVENT_MODE_FAULT 1 /**< Mode fault error */
#define XSPIPS_EVENT_TRANSFER_DONE 2 /**< Transfer done */
#define XSPIPS_EVENT_TRANSMIT_UNDERRUN 3 /**< TX FIFO empty */
#define XSPIPS_EVENT_RECEIVE_OVERRUN 4 /**< Receive data loss because
RX FIFO full */
/*@}*/
/**************************** Type Definitions *******************************/
/**
* The handler data type allows the user to define a callback function to
* handle the asynchronous processing for the SPI device. The application
* using this driver is expected to define a handler of this type to support
* interrupt driven mode. The handler executes in an interrupt context, so
* only minimal processing should be performed.
*
* @param CallBackRef is the callback reference passed in by the upper
* layer when setting the callback functions, and passed back to
* the upper layer when the callback is invoked. Its type is
* not important to the driver, so it is a void pointer.
* @param StatusEvent holds one or more status events that have occurred.
* See the XSpiPs_SetStatusHandler() for details on the status
* events that can be passed in the callback.
* @param ByteCount indicates how many bytes of data were successfully
* transferred. This may be less than the number of bytes
* requested if the status event indicates an error.
*/
typedef void (*XSpiPs_StatusHandler) (void *CallBackRef, u32 StatusEvent,
unsigned ByteCount);
/**
* This typedef contains configuration information for the device.
*/
typedef struct {
u16 DeviceId; /**< Unique ID of device */
u32 BaseAddress; /**< Base address of the device */
u32 InputClockHz; /**< Input clock frequency */
} XSpiPs_Config;
/**
* The XSpiPs driver instance data. The user is required to allocate a
* variable of this type for every SPI device in the system. A pointer
* to a variable of this type is then passed to the driver API functions.
*/
typedef struct {
XSpiPs_Config Config; /**< Configuration structure */
u32 IsReady; /**< Device is initialized and ready */
u8 *SendBufferPtr; /**< Buffer to send (state) */
u8 *RecvBufferPtr; /**< Buffer to receive (state) */
unsigned RequestedBytes; /**< Number of bytes to transfer (state) */
unsigned RemainingBytes; /**< Number of bytes left to transfer(state) */
u32 IsBusy; /**< A transfer is in progress (state) */
u32 SlaveSelect; /**< The slave select value when
XSPIPS_FORCE_SSELECT_OPTION is set */
XSpiPs_StatusHandler StatusHandler;
void *StatusRef; /**< Callback reference for status handler */
} XSpiPs;
/***************** Macros (Inline Functions) Definitions *********************/
/****************************************************************************/
/*
*
* Check in OptionsTable if Manual Start Option is enabled or disabled.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return
* - TRUE if option is set
* - FALSE if option is not set
*
* @note C-Style signature:
* u8 XSpiPs_IsManualStart(XSpiPs *InstancePtr);
*
*****************************************************************************/
#define XSpiPs_IsManualStart(InstancePtr) \
((XSpiPs_GetOptions(InstancePtr) & \
XSPIPS_MANUAL_START_OPTION) ? TRUE : FALSE)
/****************************************************************************/
/*
*
* Check in OptionsTable if Manual Chip Select Option is enabled or disabled.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return
* - TRUE if option is set
* - FALSE if option is not set
*
* @note C-Style signature:
* u8 XSpiPs_IsManualChipSelect(XSpiPs *InstancePtr);
*
*****************************************************************************/
#define XSpiPs_IsManualChipSelect(InstancePtr) \
((XSpiPs_GetOptions(InstancePtr) & \
XSPIPS_FORCE_SSELECT_OPTION) ? TRUE : FALSE)
/****************************************************************************/
/*
*
* Check in OptionsTable if Decode Slave Select option is enabled or disabled.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return
* - TRUE if option is set
* - FALSE if option is not set
*
* @note C-Style signature:
* u8 XSpiPs_IsDecodeSSelect(XSpiPs *InstancePtr);
*
*****************************************************************************/
#define XSpiPs_IsDecodeSSelect(InstancePtr) \
((XSpiPs_GetOptions(InstancePtr) & \
XSPIPS_DECODE_SSELECT_OPTION) ? TRUE : FALSE)
/****************************************************************************/
/*
*
* Check in OptionsTable if Master Option is enabled or disabled.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return
* - TRUE if option is set
* - FALSE if option is not set
*
* @note C-Style signature:
* u8 XSpiPs_IsMaster(XSpiPs *InstancePtr);
*
*****************************************************************************/
#define XSpiPs_IsMaster(InstancePtr) \
((XSpiPs_GetOptions(InstancePtr) & \
XSPIPS_MASTER_OPTION) ? TRUE : FALSE)
/****************************************************************************/
/**
*
* Set the contents of the slave idle count register.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
* @param RegisterValue is the value to be writen, valid values are
* 0-255.
*
* @return None
*
* @note
* C-Style signature:
* void XSpiPs_SetSlaveIdle(XSpiPs *InstancePtr, u32 RegisterValue)
*
*****************************************************************************/
#define XSpiPs_SetSlaveIdle(InstancePtr, RegisterValue) \
XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + \
XSPIPS_SICR_OFFSET, (RegisterValue))
/****************************************************************************/
/**
*
* Get the contents of the slave idle count register. Use the XSPIPS_SICR_*
* constants defined in xspips_hw.h to interpret the bit-mask returned.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return 8-bit value representing the contents of the SIC register.
*
* @note C-Style signature:
* u32 XSpiPs_GetSlaveIdle(XSpiPs *InstancePtr)
*
*****************************************************************************/
#define XSpiPs_GetSlaveIdle(InstancePtr) \
XSpiPs_In32(((InstancePtr)->Config.BaseAddress) + \
XSPIPS_SICR_OFFSET)
/****************************************************************************/
/**
*
* Set the contents of the transmit FIFO watermark register.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
* @param RegisterValue is the value to be written, valid values
* are 1-128.
*
* @return None.
*
* @note
* C-Style signature:
* void XSpiPs_SetTXWatermark(XSpiPs *InstancePtr, u32 RegisterValue)
*
*****************************************************************************/
#define XSpiPs_SetTXWatermark(InstancePtr, RegisterValue) \
XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + \
XSPIPS_TXWR_OFFSET, (RegisterValue))
/****************************************************************************/
/**
*
* Get the contents of the transmit FIFO watermark register.
* Use the XSPIPS_TXWR_* constants defined xspips_hw.h to interpret
* the bit-mask returned.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return 8-bit value representing the contents of the TXWR register.
*
* @note C-Style signature:
* u32 XSpiPs_GetTXWatermark(u32 *InstancePtr)
*
*****************************************************************************/
#define XSpiPs_GetTXWatermark(InstancePtr) \
XSpiPs_In32((InstancePtr->Config.BaseAddress) + XSPIPS_TXWR_OFFSET)
/****************************************************************************/
/**
*
* Set the contents of the receive FIFO watermark register.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
* @param RegisterValue is the value to be written, valid values
* are 1-128.
*
* @return None.
*
* @note
* C-Style signature:
* void XSpiPs_SetRXWatermark(XSpiPs *InstancePtr, u32 RegisterValue)
*
*****************************************************************************/
#define XSpiPs_SetRXWatermark(InstancePtr, RegisterValue) \
XSpiPs_Out32(((InstancePtr)->Config.BaseAddress) + \
XSPIPS_RXWR_OFFSET, (RegisterValue))
/****************************************************************************/
/**
*
* Get the contents of the receive FIFO watermark register.
* Use the XSPIPS_RXWR_* constants defined xspips_hw.h to interpret
* the bit-mask returned.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return A 8-bit value representing the contents of the RXWR register.
*
* @note C-Style signature:
* u32 XSpiPs_GetRXWatermark(u32 *InstancePtr)
*
*****************************************************************************/
#define XSpiPs_GetRXWatermark(InstancePtr) \
XSpiPs_In32((InstancePtr->Config.BaseAddress) + XSPIPS_RXWR_OFFSET)
/****************************************************************************/
/**
*
* Enable the device and uninhibit master transactions.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return None.
*
* @note C-Style signature:
* void XSpiPs_Enable(u32 *InstancePtr)
*
*****************************************************************************/
#define XSpiPs_Enable(InstancePtr) \
XSpiPs_Out32((InstancePtr->Config.BaseAddress) + XSPIPS_ER_OFFSET, \
XSPIPS_ER_ENABLE_MASK)
/****************************************************************************/
/**
*
* Disable the device.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return None.
*
* @note C-Style signature:
* void XSpiPs_Disable(u32 *InstancePtr)
*
*****************************************************************************/
#define XSpiPs_Disable(InstancePtr) \
XSpiPs_Out32((InstancePtr->Config.BaseAddress) + XSPIPS_ER_OFFSET, 0)
/************************** Function Prototypes ******************************/
/*
* Initialization function, implemented in xspips_sinit.c
*/
XSpiPs_Config *XSpiPs_LookupConfig(u16 DeviceId);
/*
* Functions implemented in xspips.c
*/
int XSpiPs_CfgInitialize(XSpiPs *InstancePtr, XSpiPs_Config * Config,
u32 EffectiveAddr);
void XSpiPs_Reset(XSpiPs *InstancePtr);
int XSpiPs_Transfer(XSpiPs *InstancePtr, u8 *SendBufPtr, u8 *RecvBufPtr,
unsigned ByteCount);
int XSpiPs_PolledTransfer(XSpiPs *InstancePtr, u8 *SendBufPtr,
u8 *RecvBufPtr, unsigned ByteCount);
void XSpiPs_SetStatusHandler(XSpiPs *InstancePtr, void *CallBackRef,
XSpiPs_StatusHandler FuncPtr);
void XSpiPs_InterruptHandler(void *InstancePtr);
void XSpiPs_Abort(XSpiPs *InstancePtr);
int XSpiPs_SetSlaveSelect(XSpiPs *InstancePtr, u8 SelectValue);
u8 XSpiPs_GetSlaveSelect(XSpiPs *InstancePtr);
/*
* Functions for selftest, in xspips_selftest.c
*/
int XSpiPs_SelfTest(XSpiPs *InstancePtr);
/*
* Functions for options, in xspips_options.c
*/
int XSpiPs_SetOptions(XSpiPs *InstancePtr, u32 Options);
u32 XSpiPs_GetOptions(XSpiPs *InstancePtr);
int XSpiPs_SetClkPrescaler(XSpiPs *InstancePtr, u8 Prescaler);
u8 XSpiPs_GetClkPrescaler(XSpiPs *InstancePtr);
int XSpiPs_SetDelays(XSpiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn,
u8 DelayAfter, u8 DelayInit);
void XSpiPs_GetDelays(XSpiPs *InstancePtr, u8 *DelayNss, u8 *DelayBtwn,
u8 *DelayAfter, u8 *DelayInit);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,86 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips_g.c
*
* This file contains a configuration table that specifies the configuration of
* SPI devices in the system.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- -----------------------------------------------
* 1.00 drg/jz 01/25/10 First release
* 2.00 hk 22/01/14 Added check for picking second instance
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xspips.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Prototypes ******************************/
/**
* This table contains configuration information for each SPI device
* in the system.
*/
XSpiPs_Config XSpiPs_ConfigTable[XPAR_XSPIPS_NUM_INSTANCES] = {
{
XPAR_XSPIPS_0_DEVICE_ID, /* Device ID for instance */
XPAR_XSPIPS_0_BASEADDR, /* Device base address */
XPAR_XSPIPS_0_CLOCK_HZ
},
#ifdef XPAR_XSPIPS_1_DEVICE_ID
{
XPAR_XSPIPS_1_DEVICE_ID, /* Device ID for instance */
XPAR_XSPIPS_1_BASEADDR, /* Device base address */
XPAR_XSPIPS_1_CLOCK_HZ
}
#endif
};

View file

@ -0,0 +1,125 @@
/******************************************************************************
*
* Copyright (C) 2013 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips_hw.c
*
* Contains the reset and post boot rom state initialization.
* Function prototypes in xspips_hw.h
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- -----------------------------------------------
* 1.06a hk 08/22/13 First release.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xspips_hw.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
*
* Resets the spi module
*
* @param None
*
* @return None
*
* @note None.
*
******************************************************************************/
void XSpiPs_ResetHw(u32 BaseAddress)
{
/*
* Disable Interrupts
*/
XSpiPs_WriteReg(BaseAddress, XSPIPS_IDR_OFFSET,
XSPIPS_IXR_DISABLE_ALL_MASK);
/*
* Disable device
*/
XSpiPs_WriteReg(BaseAddress, XSPIPS_ER_OFFSET,
0);
/*
* Write default value to RX and TX threshold registers
* RX threshold should be set to 1 here as the corresponding
* status bit is used to clear the FIFO next
*/
XSpiPs_WriteReg(BaseAddress, XSPIPS_TXWR_OFFSET,
(XSPIPS_TXWR_RESET_VALUE & XSPIPS_TXWR_MASK));
XSpiPs_WriteReg(BaseAddress, XSPIPS_RXWR_OFFSET,
(XSPIPS_RXWR_RESET_VALUE & XSPIPS_RXWR_MASK));
/*
* Clear RXFIFO
*/
while ((XSpiPs_ReadReg(BaseAddress,XSPIPS_SR_OFFSET) &
XSPIPS_IXR_RXNEMPTY_MASK) != 0) {
XSpiPs_ReadReg(BaseAddress, XSPIPS_RXD_OFFSET);
}
/*
* Clear status register by writing 1 to the write to clear bits
*/
XSpiPs_WriteReg(BaseAddress, XSPIPS_SR_OFFSET,
XSPIPS_IXR_WR_TO_CLR_MASK);
/*
* Write default value to configuration register
* De-select all slaves
*/
XSpiPs_WriteReg(BaseAddress, XSPIPS_CR_OFFSET,
XSPIPS_CR_RESET_STATE |
XSPIPS_CR_SSCTRL_MASK);
}

View file

@ -0,0 +1,309 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips_hw.h
*
* This header file contains the identifiers and basic driver functions (or
* macros) that can be used to access the device. Other driver functions
* are defined in xspips.h.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- -----------------------------------------------
* 1.00 drg/jz 01/25/10 First release
* 1.02a sg 05/31/12 Updated XSPIPS_FIFO_DEPTH to 128 from 32 to match HW
* for CR 658289
* 1.04a sg 01/30/13 Created XSPIPS_CR_MODF_GEN_EN_MASK macro and added it
* to XSPIPS_CR_RESET_STATE. Created
* XSPIPS_IXR_WR_TO_CLR_MASK for interrupts which need
* write-to-clear. Added shift and mask macros for d_nss
* parameter. Added Rx Watermark mask.
* 1.06a hk 08/22/13 Added prototypes of reset API and related constant
* definitions.
*
* </pre>
*
******************************************************************************/
#ifndef XSPIPS_HW_H /* prevent circular inclusions */
#define XSPIPS_HW_H /* by using protection macros */
#ifdef __cplusplus
extern "C" {
#endif
/***************************** Include Files *********************************/
#include "xil_types.h"
#include "xil_assert.h"
#include "xil_io.h"
/************************** Constant Definitions *****************************/
/** @name Register Map
*
* Register offsets from the base address of an SPI device.
* @{
*/
#define XSPIPS_CR_OFFSET 0x00 /**< Configuration */
#define XSPIPS_SR_OFFSET 0x04 /**< Interrupt Status */
#define XSPIPS_IER_OFFSET 0x08 /**< Interrupt Enable */
#define XSPIPS_IDR_OFFSET 0x0c /**< Interrupt Disable */
#define XSPIPS_IMR_OFFSET 0x10 /**< Interrupt Enabled Mask */
#define XSPIPS_ER_OFFSET 0x14 /**< Enable/Disable Register */
#define XSPIPS_DR_OFFSET 0x18 /**< Delay Register */
#define XSPIPS_TXD_OFFSET 0x1C /**< Data Transmit Register */
#define XSPIPS_RXD_OFFSET 0x20 /**< Data Receive Register */
#define XSPIPS_SICR_OFFSET 0x24 /**< Slave Idle Count */
#define XSPIPS_TXWR_OFFSET 0x28 /**< Transmit FIFO Watermark */
#define XSPIPS_RXWR_OFFSET 0x2C /**< Receive FIFO Watermark */
/* @} */
/** @name Configuration Register
*
* This register contains various control bits that
* affects the operation of an SPI device. Read/Write.
* @{
*/
#define XSPIPS_CR_MODF_GEN_EN_MASK 0x00020000 /**< Modefail Generation
Enable */
#define XSPIPS_CR_MANSTRT_MASK 0x00010000 /**< Manual Transmission Start */
#define XSPIPS_CR_MANSTRTEN_MASK 0x00008000 /**< Manual Transmission Start
Enable */
#define XSPIPS_CR_SSFORCE_MASK 0x00004000 /**< Force Slave Select */
#define XSPIPS_CR_SSCTRL_MASK 0x00003C00 /**< Slave Select Decode */
#define XSPIPS_CR_SSCTRL_SHIFT 10 /**< Slave Select Decode shift */
#define XSPIPS_CR_SSCTRL_MAXIMUM 0xF /**< Slave Select maximum value */
#define XSPIPS_CR_SSDECEN_MASK 0x00000200 /**< Slave Select Decode Enable */
#define XSPIPS_CR_PRESC_MASK 0x00000038 /**< Prescaler Setting */
#define XSPIPS_CR_PRESC_SHIFT 3 /**< Prescaler shift */
#define XSPIPS_CR_PRESC_MAXIMUM 0x07 /**< Prescaler maximum value */
#define XSPIPS_CR_CPHA_MASK 0x00000004 /**< Phase Configuration */
#define XSPIPS_CR_CPOL_MASK 0x00000002 /**< Polarity Configuration */
#define XSPIPS_CR_MSTREN_MASK 0x00000001 /**< Master Mode Enable */
#define XSPIPS_CR_RESET_STATE 0x00020000 /**< Mode Fail Generation Enable */
/* @} */
/** @name SPI Interrupt Registers
*
* <b>SPI Status Register</b>
*
* This register holds the interrupt status flags for an SPI device. Some
* of the flags are level triggered, which means that they are set as long
* as the interrupt condition exists. Other flags are edge triggered,
* which means they are set once the interrupt condition occurs and remain
* set until they are cleared by software. The interrupts are cleared by
* writing a '1' to the interrupt bit position in the Status Register.
* Read/Write.
*
* <b>SPI Interrupt Enable Register</b>
*
* This register is used to enable chosen interrupts for an SPI device.
* Writing a '1' to a bit in this register sets the corresponding bit in the
* SPI Interrupt Mask register. Write only.
*
* <b>SPI Interrupt Disable Register </b>
*
* This register is used to disable chosen interrupts for an SPI device.
* Writing a '1' to a bit in this register clears the corresponding bit in the
* SPI Interrupt Mask register. Write only.
*
* <b>SPI Interrupt Mask Register</b>
*
* This register shows the enabled/disabled interrupts of an SPI device.
* Read only.
*
* All four registers have the same bit definitions. They are only defined once
* for each of the Interrupt Enable Register, Interrupt Disable Register,
* Interrupt Mask Register, and Channel Interrupt Status Register
* @{
*/
#define XSPIPS_IXR_TXUF_MASK 0x00000040 /**< Tx FIFO Underflow */
#define XSPIPS_IXR_RXFULL_MASK 0x00000020 /**< Rx FIFO Full */
#define XSPIPS_IXR_RXNEMPTY_MASK 0x00000010 /**< Rx FIFO Not Empty */
#define XSPIPS_IXR_TXFULL_MASK 0x00000008 /**< Tx FIFO Full */
#define XSPIPS_IXR_TXOW_MASK 0x00000004 /**< Tx FIFO Overwater */
#define XSPIPS_IXR_MODF_MASK 0x00000002 /**< Mode Fault */
#define XSPIPS_IXR_RXOVR_MASK 0x00000001 /**< Rx FIFO Overrun */
#define XSPIPS_IXR_DFLT_MASK 0x00000027 /**< Default interrupts
mask */
#define XSPIPS_IXR_WR_TO_CLR_MASK 0x00000043 /**< Interrupts which
need write to clear */
#define XSPIPS_ISR_RESET_STATE 0x04 /**< Default to tx/rx
* reg empty */
#define XSPIPS_IXR_DISABLE_ALL_MASK 0x00000043 /**< Disable all
* interrupts */
/* @} */
/** @name Enable Register
*
* This register is used to enable or disable an SPI device.
* Read/Write
* @{
*/
#define XSPIPS_ER_ENABLE_MASK 0x00000001 /**< SPI Enable Bit Mask */
/* @} */
/** @name Delay Register
*
* This register is used to program timing delays in
* slave mode. Read/Write
* @{
*/
#define XSPIPS_DR_NSS_MASK 0xFF000000 /**< Delay for slave select
* de-assertion between
* word transfers mask */
#define XSPIPS_DR_NSS_SHIFT 24 /**< Delay for slave select
* de-assertion between
* word transfers shift */
#define XSPIPS_DR_BTWN_MASK 0x00FF0000 /**< Delay Between Transfers mask */
#define XSPIPS_DR_BTWN_SHIFT 16 /**< Delay Between Transfers shift */
#define XSPIPS_DR_AFTER_MASK 0x0000FF00 /**< Delay After Transfers mask */
#define XSPIPS_DR_AFTER_SHIFT 8 /**< Delay After Transfers shift */
#define XSPIPS_DR_INIT_MASK 0x000000FF /**< Delay Initially mask */
/* @} */
/** @name Slave Idle Count Registers
*
* This register defines the number of pclk cycles the slave waits for a the
* SPI clock to become stable in quiescent state before it can detect the start
* of the next transfer in CPHA = 1 mode.
* Read/Write
*
* @{
*/
#define XSPIPS_SICR_MASK 0x000000FF /**< Slave Idle Count Mask */
/* @} */
/** @name Transmit FIFO Watermark Register
*
* This register defines the watermark setting for the Transmit FIFO. The
* transmit FIFO is 128 bytes deep, so the register is 7 bits. Valid values
* are 1 to 128.
*
* @{
*/
#define XSPIPS_TXWR_MASK 0x0000007F /**< Transmit Watermark Mask */
#define XSPIPS_TXWR_RESET_VALUE 0x00000001 /**< Transmit Watermark
* register reset value */
/* @} */
/** @name Receive FIFO Watermark Register
*
* This register defines the watermark setting for the Receive FIFO. The
* receive FIFO is 128 bytes deep, so the register is 7 bits. Valid values
* are 1 to 128.
*
* @{
*/
#define XSPIPS_RXWR_MASK 0x0000007F /**< Receive Watermark Mask */
#define XSPIPS_RXWR_RESET_VALUE 0x00000001 /**< Receive Watermark
* register reset value */
/* @} */
/** @name FIFO Depth
*
* This macro provides the depth of transmit FIFO and receive FIFO.
*
* @{
*/
#define XSPIPS_FIFO_DEPTH 128 /**< FIFO depth of Tx and Rx */
/* @} */
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
#define XSpiPs_In32 Xil_In32
#define XSpiPs_Out32 Xil_Out32
/****************************************************************************/
/**
* Read a register.
*
* @param BaseAddress contains the base address of the device.
* @param RegOffset contains the offset from the 1st register of the
* device to the target register.
*
* @return The value read from the register.
*
* @note C-Style signature:
* u32 XSpiPs_ReadReg(u32 BaseAddress. int RegOffset)
*
******************************************************************************/
#define XSpiPs_ReadReg(BaseAddress, RegOffset) \
XSpiPs_In32((BaseAddress) + (RegOffset))
/***************************************************************************/
/**
* Write to a register.
*
* @param BaseAddress contains the base address of the device.
* @param RegOffset contains the offset from the 1st register of the
* device to target register.
* @param RegisterValue is the value to be written to the register.
*
* @return None.
*
* @note C-Style signature:
* void XSpiPs_WriteReg(u32 BaseAddress, int RegOffset,
* u32 RegisterValue)
*
******************************************************************************/
#define XSpiPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \
XSpiPs_Out32((BaseAddress) + (RegOffset), (RegisterValue))
/************************** Function Prototypes ******************************/
void XSpiPs_ResetHw(u32 BaseAddress);
/************************** Variable Definitions *****************************/
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */

View file

@ -0,0 +1,420 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips_options.c
*
* Contains functions for the configuration of the XSpiPs driver.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- -----------------------------------------------
* 1.00 drg/jz 01/25/10 First release
* 1.00 sdm 10/25/11 Removed the Divide by 2 in the SPI Clock Prescaler
* options as this is not supported in the device
* 1.04a sg 01/30/13 Added XSPIPS_MANUAL_START_OPTION. SetDelays and
* GetDelays API's include DelayNss parameter.
* 1.05a hk 26/04/13 Added disable and enable in XSpiPs_SetOptions when
* CPOL/CPHA bits are set/reset. Fix for CR#707669.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xspips.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*
* Create the table of options which are processed to get/set the device
* options. These options are table driven to allow easy maintenance and
* expansion of the options.
*/
typedef struct {
u32 Option;
u32 Mask;
} OptionsMap;
static OptionsMap OptionsTable[] = {
{XSPIPS_MASTER_OPTION, XSPIPS_CR_MSTREN_MASK},
{XSPIPS_CLK_ACTIVE_LOW_OPTION, XSPIPS_CR_CPOL_MASK},
{XSPIPS_CLK_PHASE_1_OPTION, XSPIPS_CR_CPHA_MASK},
{XSPIPS_DECODE_SSELECT_OPTION, XSPIPS_CR_SSDECEN_MASK},
{XSPIPS_FORCE_SSELECT_OPTION, XSPIPS_CR_SSFORCE_MASK},
{XSPIPS_MANUAL_START_OPTION, XSPIPS_CR_MANSTRTEN_MASK}
};
#define XSPIPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap))
/*****************************************************************************/
/**
*
* This function sets the options for the SPI device driver. The options control
* how the device behaves relative to the SPI bus. The device must be idle
* rather than busy transferring data before setting these device options.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
* @param Options contains the specified options to be set. This is a bit
* mask where a 1 means to turn the option on, and a 0 means to
* turn the option off. One or more bit values may be contained in
* the mask. See the bit definitions named XSPIPS_*_OPTIONS in the
* file xspips.h.
*
* @return
* - XST_SUCCESS if options are successfully set.
* - XST_DEVICE_BUSY if the device is currently transferring data.
* The transfer must complete or be aborted before setting options.
*
* @note
* This function is not thread-safe.
*
******************************************************************************/
int XSpiPs_SetOptions(XSpiPs *InstancePtr, u32 Options)
{
u32 ConfigReg;
unsigned int Index;
u32 CurrentConfigReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Do not allow the slave select to change while a transfer is in
* progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return XST_DEVICE_BUSY;
}
ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
CurrentConfigReg = ConfigReg;
/*
* Loop through the options table, turning the option on or off
* depending on whether the bit is set in the incoming options flag.
*/
for (Index = 0; Index < XSPIPS_NUM_OPTIONS; Index++) {
if (Options & OptionsTable[Index].Option) {
/* Turn it on */
ConfigReg |= OptionsTable[Index].Mask;
}
else {
/* Turn it off */
ConfigReg &= ~(OptionsTable[Index].Mask);
}
}
/*
* If CPOL-CPHA bits are toggled from previous state,
* disable before writing the configuration register and then enable.
*/
if( ((CurrentConfigReg & XSPIPS_CR_CPOL_MASK) !=
(ConfigReg & XSPIPS_CR_CPOL_MASK)) ||
((CurrentConfigReg & XSPIPS_CR_CPHA_MASK) !=
(ConfigReg & XSPIPS_CR_CPHA_MASK)) ) {
XSpiPs_Disable(InstancePtr);
}
/*
* Now write the Config register. Leave it to the upper layers
* to restart the device.
*/
XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET, ConfigReg);
/*
* Enable
*/
if( ((CurrentConfigReg & XSPIPS_CR_CPOL_MASK) !=
(ConfigReg & XSPIPS_CR_CPOL_MASK)) ||
((CurrentConfigReg & XSPIPS_CR_CPHA_MASK) !=
(ConfigReg & XSPIPS_CR_CPHA_MASK)) ) {
XSpiPs_Enable(InstancePtr);
}
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function gets the options for the SPI device. The options control how
* the device behaves relative to the SPI bus.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return
*
* Options contains the specified options currently set. This is a bit value
* where a 1 means the option is on, and a 0 means the option is off.
* See the bit definitions named XSPIPS_*_OPTIONS in file xspips.h.
*
* @note None.
*
******************************************************************************/
u32 XSpiPs_GetOptions(XSpiPs *InstancePtr)
{
u32 OptionsFlag = 0;
u32 ConfigReg;
unsigned int Index;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Get the current options
*/
ConfigReg =
XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
/*
* Loop through the options table to grab options
*/
for (Index = 0; Index < XSPIPS_NUM_OPTIONS; Index++) {
if (ConfigReg & OptionsTable[Index].Mask) {
OptionsFlag |= OptionsTable[Index].Option;
}
}
return OptionsFlag;
}
/*****************************************************************************/
/**
*
* This function sets the clock prescaler for an SPI device. The device
* must be idle rather than busy transferring data before setting these device
* options.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
* @param Prescaler is the value that determine how much the clock should
* be divided by. Use the XSPIPS_CLK_PRESCALE_* constants defined
* in xspips.h for this setting.
*
* @return
* - XST_SUCCESS if options are successfully set.
* - XST_DEVICE_BUSY if the device is currently transferring data.
* The transfer must complete or be aborted before setting options.
*
* @note
* This function is not thread-safe.
*
******************************************************************************/
int XSpiPs_SetClkPrescaler(XSpiPs *InstancePtr, u8 Prescaler)
{
u32 ConfigReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
Xil_AssertNonvoid((Prescaler > 0) && (Prescaler <= XSPIPS_CR_PRESC_MAXIMUM));
/*
* Do not allow the prescaler to be changed while a transfer is in
* progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return XST_DEVICE_BUSY;
}
/*
* Read the Config register, mask out the interesting bits, and set
* them with the shifted value passed into the function. Write the
* results back to the Config register.
*/
ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
ConfigReg &= ~XSPIPS_CR_PRESC_MASK;
ConfigReg |= (u32) (Prescaler & XSPIPS_CR_PRESC_MAXIMUM) <<
XSPIPS_CR_PRESC_SHIFT;
XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET,
ConfigReg);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function gets the clock prescaler of an SPI device.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return The prescaler value.
*
* @note None.
*
*
******************************************************************************/
u8 XSpiPs_GetClkPrescaler(XSpiPs *InstancePtr)
{
u32 ConfigReg;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
ConfigReg &= XSPIPS_CR_PRESC_MASK;
return (u8)(ConfigReg >> XSPIPS_CR_PRESC_SHIFT);
}
/*****************************************************************************/
/**
*
* This function sets the delay register for the SPI device driver.
* The delay register controls the Delay Between Transfers, Delay After
* Transfers, and the Delay Initially. The default value is 0x0. The range of
* each delay value is 0-255.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
* @param DelayNss is the delay for which the chip select outputs will
* be de-asserted between words when CPHA=0.
* @param DelayBtwn is the delay between one Slave Select being
* de-activated and the activation of another slave. The delay is
* the number of master clock periods given by DelayBtwn + 2.
* @param DelayAfter define the delay between the last bit of the current
* byte transfer and the first bit of the next byte transfer.
* The delay in number of master clock periods is given as:
* CPHA=0:DelayInit+DelayAfter+3
* CPHA=1:DelayAfter+1
* @param DelayInit is the delay between asserting the slave select signal
* and the first bit transfer. The delay int number of master clock
* periods is DelayInit+1.
*
* @return
* - XST_SUCCESS if delays are successfully set.
* - XST_DEVICE_BUSY if the device is currently transferring data.
* The transfer must complete or be aborted before setting options.
*
* @note None.
*
******************************************************************************/
int XSpiPs_SetDelays(XSpiPs *InstancePtr, u8 DelayNss, u8 DelayBtwn,
u8 DelayAfter, u8 DelayInit)
{
u32 DelayRegister;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Do not allow the delays to change while a transfer is in
* progress. Not thread-safe.
*/
if (InstancePtr->IsBusy) {
return XST_DEVICE_BUSY;
}
/* Shift, Mask and OR the values to build the register settings */
DelayRegister = (u32) DelayNss << XSPIPS_DR_NSS_SHIFT;
DelayRegister |= (u32) DelayBtwn << XSPIPS_DR_BTWN_SHIFT;
DelayRegister |= (u32) DelayAfter << XSPIPS_DR_AFTER_SHIFT;
DelayRegister |= (u32) DelayInit;
XSpiPs_WriteReg(InstancePtr->Config.BaseAddress,
XSPIPS_DR_OFFSET, DelayRegister);
return XST_SUCCESS;
}
/*****************************************************************************/
/**
*
* This function gets the delay settings for an SPI device.
* The delay register controls the Delay Between Transfers, Delay After
* Transfers, and the Delay Initially. The default value is 0x0.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
* @param DelayNss is a pointer to the delay for which the chip select
* outputs will be de-asserted between words when CPHA=0.
* @param DelayBtwn is a pointer to the Delay Between transfers value.
* This is a return parameter.
* @param DelayAfter is a pointer to the Delay After transfer value.
* This is a return parameter.
* @param DelayInit is a pointer to the Delay Initially value. This is
* a return parameter.
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XSpiPs_GetDelays(XSpiPs *InstancePtr,u8 *DelayNss, u8 *DelayBtwn,
u8 *DelayAfter, u8 *DelayInit)
{
u32 DelayRegister;
Xil_AssertVoid(InstancePtr != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
DelayRegister = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_DR_OFFSET);
*DelayInit = (u8)(DelayRegister & XSPIPS_DR_INIT_MASK);
*DelayAfter = (u8)((DelayRegister & XSPIPS_DR_AFTER_MASK) >>
XSPIPS_DR_AFTER_SHIFT);
*DelayBtwn = (u8)((DelayRegister & XSPIPS_DR_BTWN_MASK) >>
XSPIPS_DR_BTWN_SHIFT);
*DelayNss = (u8)((DelayRegister & XSPIPS_DR_NSS_MASK) >>
XSPIPS_DR_NSS_SHIFT);
}

View file

@ -0,0 +1,155 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips_selftest.c
*
* This component contains the implementation of selftest functions for an SPI
* device.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- ----------------------------------------------
* 1.00 drg/jz 01/25/10 First release
* 1.04a sg 01/30/13 SetDelays test includes DelayTestNss parameter.
*
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xspips.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
/*****************************************************************************/
/**
*
* Runs a self-test on the driver/device. The self-test is destructive in that
* a reset of the device is performed in order to check the reset values of
* the registers and to get the device into a known state.
*
* Upon successful return from the self-test, the device is reset.
*
* @param InstancePtr is a pointer to the XSpiPs instance.
*
* @return
* - XST_SUCCESS if successful
* - XST_REGISTER_ERROR indicates a register did not read or write
* correctly.
*
* @note None.
*
******************************************************************************/
int XSpiPs_SelfTest(XSpiPs *InstancePtr)
{
int Status;
u32 Register;
u8 DelayTestNss;
u8 DelayTestBtwn;
u8 DelayTestAfter;
u8 DelayTestInit;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
/*
* Reset the SPI device to leave it in a known good state
*/
XSpiPs_Reset(InstancePtr);
/*
* All the SPI registers should be in their default state right now.
*/
Register = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_CR_OFFSET);
if (Register != XSPIPS_CR_RESET_STATE) {
return XST_REGISTER_ERROR;
}
Register = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress,
XSPIPS_SR_OFFSET);
if (Register != XSPIPS_ISR_RESET_STATE) {
return XST_REGISTER_ERROR;
}
DelayTestNss = 0x5A;
DelayTestBtwn = 0xA5;
DelayTestAfter = 0xAA;
DelayTestInit = 0x55;
/*
* Write and read the delay register, just to be sure there is some
* hardware out there.
*/
Status = XSpiPs_SetDelays(InstancePtr, DelayTestNss, DelayTestBtwn,
DelayTestAfter, DelayTestInit);
if (Status != XST_SUCCESS) {
return Status;
}
XSpiPs_GetDelays(InstancePtr, &DelayTestNss, &DelayTestBtwn,
&DelayTestAfter, &DelayTestInit);
if ((0x5A != DelayTestNss) || (0xA5 != DelayTestBtwn) ||
(0xAA != DelayTestAfter) || (0x55 != DelayTestInit)) {
return XST_REGISTER_ERROR;
}
Status = XSpiPs_SetDelays(InstancePtr, 0, 0, 0, 0);
if (Status != XST_SUCCESS) {
return Status;
}
/*
* Reset the SPI device to leave it in a known good state
*/
XSpiPs_Reset(InstancePtr);
return XST_SUCCESS;
}

View file

@ -0,0 +1,96 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xspips_sinit.c
*
* The implementation of the XSpiPs driver's static initialization
* functionality.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- -----------------------------------------------
* 1.00 drg/jz 01/25/10 First release
* </pre>
*
******************************************************************************/
/***************************** Include Files *********************************/
#include "xstatus.h"
#include "xspips.h"
#include "xparameters.h"
/************************** Constant Definitions *****************************/
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/************************** Variable Definitions *****************************/
extern XSpiPs_Config XSpiPs_ConfigTable[];
/*****************************************************************************/
/**
*
* Looks up the device configuration based on the unique device ID. A table
* contains the configuration info for each device in the system.
*
* @param DeviceId contains the ID of the device to look up the
* configuration for.
*
* @return
*
* A pointer to the configuration found or NULL if the specified device ID was
* not found. See xspips.h for the definition of XSpiPs_Config.
*
* @note None.
*
******************************************************************************/
XSpiPs_Config *XSpiPs_LookupConfig(u16 DeviceId)
{
XSpiPs_Config *CfgPtr = NULL;
int Index;
for (Index = 0; Index < XPAR_XSPIPS_NUM_INSTANCES; Index++) {
if (XSpiPs_ConfigTable[Index].DeviceId == DeviceId) {
CfgPtr = &XSpiPs_ConfigTable[Index];
break;
}
}
return CfgPtr;
}