diff --git a/XilinxProcessorIPLib/drivers/spips/data/spips.mdd b/XilinxProcessorIPLib/drivers/spips/data/spips.mdd new file mode 100755 index 00000000..e5c794e4 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/data/spips.mdd @@ -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 diff --git a/XilinxProcessorIPLib/drivers/spips/data/spips.tcl b/XilinxProcessorIPLib/drivers/spips/data/spips.tcl new file mode 100755 index 00000000..ad9289c4 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/data/spips.tcl @@ -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" + +} diff --git a/XilinxProcessorIPLib/drivers/spips/data/spips_header.h b/XilinxProcessorIPLib/drivers/spips/data/spips_header.h new file mode 100755 index 00000000..d06e4b82 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/data/spips_header.h @@ -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 diff --git a/XilinxProcessorIPLib/drivers/spips/data/spips_tapp.tcl b/XilinxProcessorIPLib/drivers/spips/data/spips_tapp.tcl new file mode 100755 index 00000000..ed89fb9d --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/data/spips_tapp.tcl @@ -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 +} diff --git a/XilinxProcessorIPLib/drivers/spips/examples/index.html b/XilinxProcessorIPLib/drivers/spips/examples/index.html new file mode 100755 index 00000000..40ebe765 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/examples/index.html @@ -0,0 +1,21 @@ + + + + + +Driver example applications + + + +

Example Applications for the driver spips_v2_0

+
+ +

Copyright � 1995-2014 Xilinx, Inc. All rights reserved.

+ + diff --git a/XilinxProcessorIPLib/drivers/spips/examples/xspips_eeprom_intr_example.c b/XilinxProcessorIPLib/drivers/spips/examples/xspips_eeprom_intr_example.c new file mode 100755 index 00000000..aa95801e --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/examples/xspips_eeprom_intr_example.c @@ -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. +* +*
+* 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
+*
+*
+* +******************************************************************************/ + +/***************************** 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); +} diff --git a/XilinxProcessorIPLib/drivers/spips/examples/xspips_eeprom_polled_example.c b/XilinxProcessorIPLib/drivers/spips/examples/xspips_eeprom_polled_example.c new file mode 100755 index 00000000..13026291 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/examples/xspips_eeprom_polled_example.c @@ -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. +* +*
+* 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
+*
+*
+* +******************************************************************************/ + +/***************************** 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; + } + } +} diff --git a/XilinxProcessorIPLib/drivers/spips/examples/xspips_flash_intr_example.c b/XilinxProcessorIPLib/drivers/spips/examples/xspips_flash_intr_example.c new file mode 100755 index 00000000..e92fe1ac --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/examples/xspips_flash_intr_example.c @@ -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. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sg  1/30/13  First release
+*
+*
+* +******************************************************************************/ + +/***************************** 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); +} diff --git a/XilinxProcessorIPLib/drivers/spips/examples/xspips_flash_polled_example.c b/XilinxProcessorIPLib/drivers/spips/examples/xspips_flash_polled_example.c new file mode 100755 index 00000000..15699f02 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/examples/xspips_flash_polled_example.c @@ -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. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00  sg  1/30/13  First release
+*
+*
+* +******************************************************************************/ + +/***************************** 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; + } + } +} diff --git a/XilinxProcessorIPLib/drivers/spips/examples/xspips_selftest_example.c b/XilinxProcessorIPLib/drivers/spips/examples/xspips_selftest_example.c new file mode 100755 index 00000000..de2f7f64 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/examples/xspips_selftest_example.c @@ -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 +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/25/10 First release.
+* 
+* +*******************************************************************************/ + +/***************************** 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__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; +} diff --git a/XilinxProcessorIPLib/drivers/spips/examples/xspips_slave_polled_example.c b/XilinxProcessorIPLib/drivers/spips/examples/xspips_slave_polled_example.c new file mode 100755 index 00000000..fcbb3795 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/examples/xspips_slave_polled_example.c @@ -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. +* +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 2.0   sb  08/22/14  First release
+*
+*
+* +******************************************************************************/ + +/***************************** 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); + +} diff --git a/XilinxProcessorIPLib/drivers/spips/src/Makefile b/XilinxProcessorIPLib/drivers/spips/src/Makefile new file mode 100755 index 00000000..10d24d73 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/src/Makefile @@ -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} diff --git a/XilinxProcessorIPLib/drivers/spips/src/xspips.c b/XilinxProcessorIPLib/drivers/spips/src/xspips.c new file mode 100755 index 00000000..66c191c8 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/src/xspips.c @@ -0,0 +1,1106 @@ +/****************************************************************************** +* +* 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.c +* +* Contains implements the interface functions of the XSpiPs driver. +* See xspips.h for a detailed description of the device and driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/25/10 First release
+* 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.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 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.
+* 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 check for MODF in polled transfer function.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xspips.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + +/****************************************************************************/ +/* +* +* Send one byte to the currently selected slave. A byte of data is written to +* transmit FIFO/register. +* +* @param BaseAddress is the base address of the device +* +* @return None. +* +* @note C-Style signature: +* void XSpiPs_SendByte(u32 BaseAddress, u8 Data); +* +*****************************************************************************/ +#define XSpiPs_SendByte(BaseAddress, Data) \ + XSpiPs_Out32((BaseAddress) + XSPIPS_TXD_OFFSET, (Data)) + +/****************************************************************************/ +/* +* +* Receive one byte from the device's receive FIFO/register. It is assumed +* that the byte is already available. +* +* @param BaseAddress is the base address of the device +* +* @return The byte retrieved from the receive FIFO/register. +* +* @note C-Style signature: +* u8 XSpiPs_RecvByte(u32 BaseAddress); +* +*****************************************************************************/ +#define XSpiPs_RecvByte(BaseAddress) \ + (u8)XSpiPs_In32((BaseAddress) + XSPIPS_RXD_OFFSET) + +/************************** Function Prototypes ******************************/ + +static void StubStatusHandler(void *CallBackRef, u32 StatusEvent, + unsigned ByteCount); + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Initializes a specific XSpiPs instance such that the driver is ready to use. +* +* The state of the device after initialization is: +* - Device is disabled +* - Slave mode +* - Active high clock polarity +* - Clock phase 0 +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param ConfigPtr is a reference to a structure containing information +* about a specific SPI device. This function initializes an +* InstancePtr object for a specific device specified by the +* contents of Config. This function can initialize multiple +* instance objects with the use of multiple calls giving different +* Config information on each call. +* @param EffectiveAddr is the device base address in the virtual memory +* address space. The caller is responsible for keeping the address +* mapping from EffectiveAddr to the device physical base address +* unchanged once this function is invoked. Unexpected errors may +* occur if the address mapping changes after this function is +* called. If address translation is not used, use +* ConfigPtr->Config.BaseAddress for this device. +* +* @return +* - XST_SUCCESS if successful. +* - XST_DEVICE_IS_STARTED if the device is already started. +* It must be stopped to re-initialize. +* +* @note None. +* +******************************************************************************/ +int XSpiPs_CfgInitialize(XSpiPs *InstancePtr, XSpiPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * If the device is busy, disallow the initialize and return a status + * indicating it is already started. This allows the user to stop the + * device and re-initialize, but prevents a user from inadvertently + * initializing. This assumes the busy flag is cleared at startup. + */ + if (InstancePtr->IsBusy == TRUE) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Set some default values. + */ + InstancePtr->IsBusy = FALSE; + + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->StatusHandler = StubStatusHandler; + + InstancePtr->SendBufferPtr = NULL; + InstancePtr->RecvBufferPtr = NULL; + InstancePtr->RequestedBytes = 0; + InstancePtr->RemainingBytes = 0; + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* + * Reset the SPI device to get it into its initial state. It is + * expected that device configuration will take place after this + * initialization is done, but before the device is started. + */ + XSpiPs_Reset(InstancePtr); + + return XST_SUCCESS; +} + + +/*****************************************************************************/ +/** +* +* Resets the SPI device. Reset must only be called after the driver has been +* initialized. The configuration of the device after reset is the same as its +* configuration after initialization. Any data transfer that is in progress +* is aborted. +* +* The upper layer software is responsible for re-configuring (if necessary) +* and restarting the SPI device after the reset. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XSpiPs_Reset(XSpiPs *InstancePtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Abort any transfer that is in progress + */ + XSpiPs_Abort(InstancePtr); + + /* + * Reset any values that are not reset by the hardware reset such that + * the software state matches the hardware device + */ + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, XSPIPS_CR_OFFSET, + XSPIPS_CR_RESET_STATE); + +} + +/*****************************************************************************/ +/** +* +* Transfers specified data on the SPI bus. If the SPI device is configured as +* a master, this function initiates bus communication and sends/receives the +* data to/from the selected SPI slave. If the SPI device is configured as a +* slave, this function prepares the buffers to be sent/received when selected +* by a master. For every byte sent, a byte is received. This function should +* be used to perform interrupt based transfers. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XSpiPs_Transfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XSpiPs_Transfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XSpiPs_Transfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XSpiPs_Transfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+* 
+* Although this function takes entire buffers as arguments, the driver can only +* transfer a limited number of bytes at a time, limited by the size of the +* FIFO. A call to this function only starts the transfer, then subsequent +* transfers of the data is performed by the interrupt service routine until +* the entire buffer has been transferred. The status callback function is +* called when the entire buffer has been sent/received. +* +* This function is non-blocking. As a master, the SetSlaveSelect function must +* be called prior to this function. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param SendBufPtr is a pointer to a buffer of data for sending. +* This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. +* +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the SPI bus at the same time. +* +******************************************************************************/ +int XSpiPs_Transfer(XSpiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, unsigned ByteCount) +{ + u32 ConfigReg; + u8 TransCount = 0; + + /* + * The RecvBufPtr argument can be null + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Set the busy flag, which will be cleared in the ISR when the + * transfer is entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * If manual chip select mode, initialize the slave select value. + */ + if (XSpiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + /* + * Set the slave select value. + */ + ConfigReg &= ~XSPIPS_CR_SSCTRL_MASK; + ConfigReg |= InstancePtr->SlaveSelect; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Enable the device. + */ + XSpiPs_Enable(InstancePtr); + + /* + * Clear all the interrrupts. + */ + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, XSPIPS_SR_OFFSET, + XSPIPS_IXR_WR_TO_CLR_MASK); + + /* + * Fill the TXFIFO with as many bytes as it will take (or as many as + * we have to send). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XSPIPS_FIFO_DEPTH)) { + XSpiPs_SendByte(InstancePtr->Config.BaseAddress, + *InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr++; + InstancePtr->RemainingBytes--; + TransCount++; + } + + /* + * Enable interrupts (connecting to the interrupt controller and + * enabling interrupts should have been done by the caller). + */ + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_IER_OFFSET, XSPIPS_IXR_DFLT_MASK); + + /* + * If master mode and manual start mode, issue manual start command + * to start the transfer. + */ + if (XSpiPs_IsManualStart(InstancePtr) + && XSpiPs_IsMaster(InstancePtr)) { + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_MANSTRT_MASK; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Transfers specified data on the SPI bus in polled mode. +* +* The caller has the option of providing two different buffers for send and +* receive, or one buffer for both send and receive, or no buffer for receive. +* The receive buffer must be at least as big as the send buffer to prevent +* unwanted memory writes. This implies that the byte count passed in as an +* argument must be the smaller of the two buffers if they differ in size. +* Here are some sample usages: +*
+*   XSpiPs_PolledTransfer(InstancePtr, SendBuf, RecvBuf, ByteCount)
+*	The caller wishes to send and receive, and provides two different
+*	buffers for send and receive.
+*
+*   XSpiPs_PolledTransfer(InstancePtr, SendBuf, NULL, ByteCount)
+*	The caller wishes only to send and does not care about the received
+*	data. The driver ignores the received data in this case.
+*
+*   XSpiPs_PolledTransfer(InstancePtr, SendBuf, SendBuf, ByteCount)
+*	The caller wishes to send and receive, but provides the same buffer
+*	for doing both. The driver sends the data and overwrites the send
+*	buffer with received data as it transfers the data.
+*
+*   XSpiPs_PolledTransfer(InstancePtr, RecvBuf, RecvBuf, ByteCount)
+*	The caller wishes to only receive and does not care about sending
+*	data.  In this case, the caller must still provide a send buffer, but
+*	it can be the same as the receive buffer if the caller does not care
+*	what it sends.  The device must send N bytes of data if it wishes to
+*	receive N bytes of data.
+*
+* 
+* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param SendBufPtr is a pointer to a buffer of data for sending. +* This buffer must not be NULL. +* @param RecvBufPtr is a pointer to a buffer for received data. +* This argument can be NULL if do not care about receiving. +* @param ByteCount contains the number of bytes to send/receive. +* The number of bytes received always equals the number of bytes +* sent. + +* @return +* - XST_SUCCESS if the buffers are successfully handed off to the +* device for transfer. +* - XST_DEVICE_BUSY indicates that a data transfer is already in +* progress. This is determined by the driver. +* +* @note +* +* This function is not thread-safe. The higher layer software must ensure that +* no two threads are transferring data on the SPI bus at the same time. +* +******************************************************************************/ +int XSpiPs_PolledTransfer(XSpiPs *InstancePtr, u8 *SendBufPtr, + u8 *RecvBufPtr, unsigned ByteCount) +{ + u32 StatusReg; + u32 ConfigReg; + u32 TransCount; + + /* + * The RecvBufPtr argument can be NULL. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(SendBufPtr != NULL); + Xil_AssertNonvoid(ByteCount > 0); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Check whether there is another transfer in progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + + /* + * Set the busy flag, which will be cleared when the transfer is + * entirely done. + */ + InstancePtr->IsBusy = TRUE; + + /* + * Set up buffer pointers. + */ + InstancePtr->SendBufferPtr = SendBufPtr; + InstancePtr->RecvBufferPtr = RecvBufPtr; + + InstancePtr->RequestedBytes = ByteCount; + InstancePtr->RemainingBytes = ByteCount; + + /* + * If manual chip select mode, initialize the slave select value. + */ + if (XSpiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + /* + * Set the slave select value. + */ + ConfigReg &= ~XSPIPS_CR_SSCTRL_MASK; + ConfigReg |= InstancePtr->SlaveSelect; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Enable the device. + */ + XSpiPs_Enable(InstancePtr); + + while((InstancePtr->RemainingBytes > 0) || + (InstancePtr->RequestedBytes > 0)) { + TransCount = 0; + /* + * Fill the TXFIFO with as many bytes as it will take (or as + * many as we have to send). + */ + while ((InstancePtr->RemainingBytes > 0) && + (TransCount < XSPIPS_FIFO_DEPTH)) { + XSpiPs_SendByte(InstancePtr->Config.BaseAddress, + *InstancePtr->SendBufferPtr); + InstancePtr->SendBufferPtr++; + InstancePtr->RemainingBytes--; + ++TransCount; + } + + /* + * If master mode and manual start mode, issue manual start + * command to start the transfer. + */ + if (XSpiPs_IsManualStart(InstancePtr) + && XSpiPs_IsMaster(InstancePtr)) { + ConfigReg = XSpiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_MANSTRT_MASK; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Wait for the transfer to finish by polling Tx fifo status. + */ + do { + StatusReg = XSpiPs_ReadReg( + InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET); + if ( StatusReg & XSPIPS_IXR_MODF_MASK ) + { + /* + * Clear the mode fail bit + */ + XSpiPs_WriteReg( + InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET, + XSPIPS_IXR_MODF_MASK); + return XST_SEND_ERROR; + } + } while ((StatusReg & XSPIPS_IXR_TXOW_MASK) == 0); + + /* + * A transmit has just completed. Process received data and + * check for more data to transmit. + * First get the data received as a result of the transmit + * that just completed. Receive data based on the + * count obtained while filling tx fifo. Always get the + * received data, but only fill the receive buffer if it + * points to something (the upper layer software may not + * care to receive data). + */ + while (TransCount) { + u8 TempData; + TempData = XSpiPs_RecvByte( + InstancePtr->Config.BaseAddress); + if (InstancePtr->RecvBufferPtr != NULL) { + *InstancePtr->RecvBufferPtr++ = (u8) TempData; + } + InstancePtr->RequestedBytes--; + --TransCount; + } + } + + /* + * Clear the slave selects now, before terminating the transfer. + */ + if (XSpiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_SSCTRL_MASK; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Clear the busy flag. + */ + InstancePtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XSpiPs_Disable(InstancePtr); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Selects or deselect the slave with which the master communicates. This setting +* affects the SPI_ss_outN signals. The behavior depends on the setting of the +* CR_SSDECEN bit. If CR_SSDECEN is 0, the SPI_ss_outN bits will be output with a +* single signal low. If CR_SSDECEN is 1, the SPI_ss_outN bits will reflect the +* value set. +* +* The user is not allowed to deselect the slave while a transfer is in progress. +* If no transfer is in progress, the user can select a new slave, which +* implicitly deselects the current slave. In order to explicitly deselect the +* current slave, a value of all 1's, 0x0F can be passed in as the argument to +* the function. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* @param SlaveSel is the slave number to be selected. +* Normally, 3 slaves can be selected with values 0-2. +* In case, 3-8 decode option is set, then upto 8 slaves +* can be selected. Only one slave can be selected at a time. +* +* @return +* - XST_SUCCESS if the slave is selected or deselected +* successfully. +* - XST_DEVICE_BUSY if a transfer is in progress, slave cannot be +* changed. +* +* @note +* +* This function only sets the slave which will be selected when a transfer +* occurs. The slave is not selected when the SPI is idle. The slave select +* has no affect when the device is configured as a slave. +* +******************************************************************************/ +int XSpiPs_SetSlaveSelect(XSpiPs *InstancePtr, u8 SlaveSel) +{ + u32 ConfigReg; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(SlaveSel <= XSPIPS_CR_SSCTRL_MAXIMUM); + + /* + * Do not allow the slave select to change while a transfer is in + * progress. Not thread-safe. + */ + if (InstancePtr->IsBusy) { + return XST_DEVICE_BUSY; + } + /* + * If decode slave select option is set, + * then set slave select value directly. + * Update the Instance structure member. + */ + if ( XSpiPs_IsDecodeSSelect( InstancePtr ) ) { + InstancePtr->SlaveSelect = SlaveSel << XSPIPS_CR_SSCTRL_SHIFT; + } + else { + /* + * Set the bit position to low using SlaveSel. Update the Instance + * structure member. + */ + InstancePtr->SlaveSelect = ((~(1 << SlaveSel)) & \ + XSPIPS_CR_SSCTRL_MAXIMUM) << XSPIPS_CR_SSCTRL_SHIFT; + } + + /* + * Read the config register, update the slave select value and write + * back to config register. + */ + ConfigReg = XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg &= (~XSPIPS_CR_SSCTRL_MASK); + ConfigReg |= InstancePtr->SlaveSelect; + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, XSPIPS_CR_OFFSET, + ConfigReg); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* Gets the current slave select setting for the SPI device. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return The slave number selected (starting from 0). +* +* @note None. +* +******************************************************************************/ +u8 XSpiPs_GetSlaveSelect(XSpiPs *InstancePtr) +{ + u32 ConfigReg; + u8 SlaveSel; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ConfigReg = InstancePtr->SlaveSelect; + ConfigReg &= XSPIPS_CR_SSCTRL_MASK; + ConfigReg >>= XSPIPS_CR_SSCTRL_SHIFT; + ConfigReg &= XSPIPS_CR_SSCTRL_MAXIMUM; + + /* + * If decode slave select option is set, then read value directly. + */ + if ( XSpiPs_IsDecodeSSelect( InstancePtr ) ) { + SlaveSel = ConfigReg; + } + else { + + /* + * Get the slave select value + */ + if(ConfigReg == 0x0F) { + /* + * No slave selected + */ + SlaveSel = 0xF; + }else { + /* + * Get selected slave number (0,1 or 2) + */ + SlaveSel = ((~ConfigReg) & XSPIPS_CR_SSCTRL_MAXIMUM)/2; + } + } + return SlaveSel; +} + +/*****************************************************************************/ +/** +* +* Sets the status callback function, the status handler, which the driver +* calls when it encounters conditions that should be reported to upper +* layer software. The handler executes in an interrupt context, so it must +* minimize the amount of processing performed. One of the following status +* events is passed to the status handler. +* +*
+* XST_SPI_MODE_FAULT		A mode fault error occurred, meaning the device
+*				is selected as slave while being a master.
+*
+* XST_SPI_TRANSFER_DONE		The requested data transfer is done
+*
+* XST_SPI_TRANSMIT_UNDERRUN	As a slave device, the master clocked data
+*				but there were none available in the transmit
+*				register/FIFO. This typically means the slave
+*				application did not issue a transfer request
+*				fast enough, or the processor/driver could not
+*				fill the transmit register/FIFO fast enough.
+*
+* XST_SPI_RECEIVE_OVERRUN	The SPI device lost data. Data was received
+*				but the receive data register/FIFO was full.
+*
+* XST_SPI_SLAVE_MODE_FAULT	A slave SPI device was selected as a slave
+*				while it was disabled. This indicates the
+*				master is already transferring data (which is
+*				being dropped until the slave application
+*				issues a transfer).
+* 
+* @param InstancePtr is a pointer to the XSpiPs instance. +* @param CallBackRef is the upper layer callback reference passed back +* when the callback function is invoked. +* @param FuncPtr is the pointer to the callback function. +* +* @return None. +* +* @note +* +* The handler is called within interrupt context, so it should do its work +* quickly and queue potentially time-consuming work to a task-level thread. +* +******************************************************************************/ +void XSpiPs_SetStatusHandler(XSpiPs *InstancePtr, void *CallBackRef, + XSpiPs_StatusHandler FuncPtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = FuncPtr; + InstancePtr->StatusRef = CallBackRef; +} + +/*****************************************************************************/ +/** +* +* This is a stub for the status callback. The stub is here in case the upper +* layers forget to set the handler. +* +* @param CallBackRef is a pointer to the upper layer callback reference +* @param StatusEvent is the event that just occurred. +* @param ByteCount is the number of bytes transferred up until the event +* occurred. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +static void StubStatusHandler(void *CallBackRef, u32 StatusEvent, + unsigned ByteCount) +{ + (void) CallBackRef; + (void) StatusEvent; + (void) ByteCount; + + Xil_AssertVoidAlways(); +} + +/*****************************************************************************/ +/** +* +* The interrupt handler for SPI interrupts. This function must be connected +* by the user to an interrupt controller. +* +* The interrupts that are handled are: +* +* - Mode Fault Error. This interrupt is generated if this device is selected +* as a slave when it is configured as a master. The driver aborts any data +* transfer that is in progress by resetting FIFOs (if present) and resetting +* its buffer pointers. The upper layer software is informed of the error. +* +* - Data Transmit Register (FIFO) Empty. This interrupt is generated when the +* transmit register or FIFO is empty. The driver uses this interrupt during a +* transmission to continually send/receive data until the transfer is done. +* +* - Data Transmit Register (FIFO) Underflow. This interrupt is generated when +* the SPI device, when configured as a slave, attempts to read an empty +* DTR/FIFO. An empty DTR/FIFO usually means that software is not giving the +* device data in a timely manner. No action is taken by the driver other than +* to inform the upper layer software of the error. +* +* - Data Receive Register (FIFO) Overflow. This interrupt is generated when the +* SPI device attempts to write a received byte to an already full DRR/FIFO. +* A full DRR/FIFO usually means software is not emptying the data in a timely +* manner. No action is taken by the driver other than to inform the upper +* layer software of the error. +* +* - Slave Mode Fault Error. This interrupt is generated if a slave device is +* selected as a slave while it is disabled. No action is taken by the driver +* other than to inform the upper layer software of the error. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note +* +* The slave select register is being set to deselect the slave when a transfer +* is complete. This is being done regardless of whether it is a slave or a +* master since the hardware does not drive the slave select as a slave. +* +******************************************************************************/ +void XSpiPs_InterruptHandler(void *InstancePtr) +{ + XSpiPs *SpiPtr = (XSpiPs *)InstancePtr; + u32 IntrStatus; + u32 ConfigReg; + unsigned BytesDone; /* Number of bytes done so far. */ + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(SpiPtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Immediately clear the interrupts in case the ISR causes another + * interrupt to be generated. If we clear at the end of the ISR, + * we may miss newly generated interrupts. + * Disable the TXOW interrupt because we transmit from within the ISR, + * which could potentially cause another TX_OW interrupt. + */ + IntrStatus = + XSpiPs_ReadReg(SpiPtr->Config.BaseAddress, XSPIPS_SR_OFFSET); + XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, XSPIPS_SR_OFFSET, + (IntrStatus & XSPIPS_IXR_WR_TO_CLR_MASK)); + XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, XSPIPS_IDR_OFFSET, + XSPIPS_IXR_TXOW_MASK); + + /* + * Check for mode fault error. We want to check for this error first, + * before checking for progress of a transfer, since this error needs + * to abort any operation in progress. + */ + if (XSPIPS_IXR_MODF_MASK == (IntrStatus & XSPIPS_IXR_MODF_MASK)) { + BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes; + + /* + * Abort any operation currently in progress. This includes + * clearing the mode fault condition by reading the status + * register. Note that the status register should be read after + * the abort, since reading the status register clears the mode + * fault condition and would cause the device to restart any + * transfer that may be in progress. + */ + XSpiPs_Abort(SpiPtr); + + SpiPtr->StatusHandler(SpiPtr->StatusRef, XST_SPI_MODE_FAULT, + BytesDone); + + return; /* Do not continue servicing other interrupts. */ + } + + + if (IntrStatus & XSPIPS_IXR_TXOW_MASK) { + u8 TempData; + u32 TransCount; + /* + * A transmit has just completed. Process received data and + * check for more data to transmit. + * First get the data received as a result of the transmit that + * just completed. Always get the received data, but only fill + * the receive buffer if it is not null (it can be null when + * the device does not care to receive data). + * Initialize the TransCount based on the requested bytes. + * Loop on receive FIFO based on TransCount. + */ + TransCount = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes; + + while (TransCount) { + TempData = XSpiPs_RecvByte(SpiPtr->Config.BaseAddress); + if (SpiPtr->RecvBufferPtr != NULL) { + *SpiPtr->RecvBufferPtr++ = (u8) TempData; + } + SpiPtr->RequestedBytes--; + --TransCount; + } + + /* + * Fill the TXFIFO until data exists, otherwise fill upto + * FIFO depth. + */ + while ((SpiPtr->RemainingBytes > 0) && + (TransCount < XSPIPS_FIFO_DEPTH)) { + XSpiPs_SendByte(SpiPtr->Config.BaseAddress, + *SpiPtr->SendBufferPtr); + SpiPtr->SendBufferPtr++; + SpiPtr->RemainingBytes--; + ++TransCount; + } + + if ((SpiPtr->RemainingBytes == 0) && + (SpiPtr->RequestedBytes == 0)) { + /* + * No more data to send. Disable the interrupt and + * inform the upper layer software that the transfer + * is done. The interrupt will be re-enabled when + * another transfer is initiated. + */ + XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, + XSPIPS_IDR_OFFSET, XSPIPS_IXR_DFLT_MASK); + + /* + * Disable slave select lines as the transfer + * is complete. + */ + if (XSpiPs_IsManualChipSelect(InstancePtr)) { + ConfigReg = XSpiPs_ReadReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_SSCTRL_MASK; + XSpiPs_WriteReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + /* + * Clear the busy flag. + */ + SpiPtr->IsBusy = FALSE; + + /* + * Disable the device. + */ + XSpiPs_Disable(SpiPtr); + + /* + * Inform the Transfer done to upper layers. + */ + SpiPtr->StatusHandler(SpiPtr->StatusRef, + XST_SPI_TRANSFER_DONE, + SpiPtr->RequestedBytes); + } else { + /* + * Enable the TXOW interrupt. + */ + XSpiPs_WriteReg(SpiPtr->Config.BaseAddress, + XSPIPS_IER_OFFSET, XSPIPS_IXR_TXOW_MASK); + /* + * Start the transfer by not inhibiting the transmitter + * any longer. + */ + if (XSpiPs_IsManualStart(SpiPtr) + && XSpiPs_IsMaster(SpiPtr)) { + ConfigReg = XSpiPs_ReadReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_MANSTRT_MASK; + XSpiPs_WriteReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + } + } + + /* + * Check for overflow and underflow errors. + */ + if (IntrStatus & XSPIPS_IXR_RXOVR_MASK) { + BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes; + SpiPtr->IsBusy = FALSE; + + /* + * The Slave select lines are being manually controlled. + * Disable them because the transfer is complete. + */ + if (XSpiPs_IsManualChipSelect(SpiPtr)) { + ConfigReg = XSpiPs_ReadReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_SSCTRL_MASK; + XSpiPs_WriteReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + SpiPtr->StatusHandler(SpiPtr->StatusRef, + XST_SPI_RECEIVE_OVERRUN, BytesDone); + } + + if (IntrStatus & XSPIPS_IXR_TXUF_MASK) { + BytesDone = SpiPtr->RequestedBytes - SpiPtr->RemainingBytes; + + SpiPtr->IsBusy = FALSE; + /* + * The Slave select lines are being manually controlled. + * Disable them because the transfer is complete. + */ + if (XSpiPs_IsManualChipSelect(SpiPtr)) { + ConfigReg = XSpiPs_ReadReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET); + ConfigReg |= XSPIPS_CR_SSCTRL_MASK; + XSpiPs_WriteReg( + SpiPtr->Config.BaseAddress, + XSPIPS_CR_OFFSET, ConfigReg); + } + + SpiPtr->StatusHandler(SpiPtr->StatusRef, + XST_SPI_TRANSMIT_UNDERRUN, BytesDone); + } + +} + +/*****************************************************************************/ +/** +* +* Aborts a transfer in progress by disabling the device and resetting the FIFOs +* if present. The byte counts are cleared, the busy flag is cleared, and mode +* fault is cleared. +* +* @param InstancePtr is a pointer to the XSpiPs instance. +* +* @return None. +* +* @note +* +* This function does a read/modify/write of the Config register. The user of +* this function needs to take care of critical sections. +* +******************************************************************************/ +void XSpiPs_Abort(XSpiPs *InstancePtr) +{ + + XSpiPs_Disable(InstancePtr); + + /* + * Clear the RX FIFO and drop any data. + */ + while ((XSpiPs_ReadReg(InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET) & XSPIPS_IXR_RXNEMPTY_MASK) == + XSPIPS_IXR_RXNEMPTY_MASK) { + (void) XSpiPs_RecvByte(InstancePtr->Config.BaseAddress); + } + + /* + * Clear mode fault condition. + */ + XSpiPs_WriteReg(InstancePtr->Config.BaseAddress, + XSPIPS_SR_OFFSET, + XSPIPS_IXR_MODF_MASK); + + InstancePtr->RemainingBytes = 0; + InstancePtr->RequestedBytes = 0; + InstancePtr->IsBusy = FALSE; +} diff --git a/XilinxProcessorIPLib/drivers/spips/src/xspips.h b/XilinxProcessorIPLib/drivers/spips/src/xspips.h new file mode 100755 index 00000000..37a16702 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/src/xspips.h @@ -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. +* +* Initialization & Configuration +* +* 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. +* +* Multiple Masters +* +* 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. +* +* Multiple Slaves +* +* 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. +* +* Modes of Operation +* +* 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. +* +* Interrupts +* +* 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. +* +* +* Polled Operation +* +* 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. +* +* Device Busy +* +* 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. +* +* Device Configuration +* +* 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. +* +* RTOS Independence +* +* 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. +* +*
+* 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.
+*
+* 
+* +******************************************************************************/ +#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. + * + * The Master option configures the SPI device as a master. + * By default, the device is a slave. + * + * The Active Low Clock option 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 Clock Phase option 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 Slave Select Decode Enable option 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 SPI Force Slave Select option 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 Manual Start option 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 */ diff --git a/XilinxProcessorIPLib/drivers/spips/src/xspips_g.c b/XilinxProcessorIPLib/drivers/spips/src/xspips_g.c new file mode 100755 index 00000000..4a44e973 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/src/xspips_g.c @@ -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. +* +*
+* 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
+* 
+* +******************************************************************************/ + +/***************************** 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 +}; diff --git a/XilinxProcessorIPLib/drivers/spips/src/xspips_hw.c b/XilinxProcessorIPLib/drivers/spips/src/xspips_hw.c new file mode 100755 index 00000000..4503f161 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/src/xspips_hw.c @@ -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 +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.06a hk     08/22/13 First release.
+*
+* 
+* +******************************************************************************/ + +/***************************** 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); + +} diff --git a/XilinxProcessorIPLib/drivers/spips/src/xspips_hw.h b/XilinxProcessorIPLib/drivers/spips/src/xspips_hw.h new file mode 100755 index 00000000..d2dbbd27 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/src/xspips_hw.h @@ -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. +* +*
+* 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.
+*
+* 
+* +******************************************************************************/ + +#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 + * + * SPI Status Register + * + * 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. + * + * SPI Interrupt Enable Register + * + * 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. + * + * SPI Interrupt Disable Register + * + * 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. + * + * SPI Interrupt Mask Register + * + * 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 */ diff --git a/XilinxProcessorIPLib/drivers/spips/src/xspips_options.c b/XilinxProcessorIPLib/drivers/spips/src/xspips_options.c new file mode 100755 index 00000000..0c13a047 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/src/xspips_options.c @@ -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. +* +*
+* 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.
+*
+* 
+* +******************************************************************************/ + +/***************************** 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); + +} diff --git a/XilinxProcessorIPLib/drivers/spips/src/xspips_selftest.c b/XilinxProcessorIPLib/drivers/spips/src/xspips_selftest.c new file mode 100755 index 00000000..dbd9a042 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/src/xspips_selftest.c @@ -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. +* +*
+* 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.
+*
+* 
+* +******************************************************************************/ + +/***************************** 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; +} diff --git a/XilinxProcessorIPLib/drivers/spips/src/xspips_sinit.c b/XilinxProcessorIPLib/drivers/spips/src/xspips_sinit.c new file mode 100755 index 00000000..94d35b62 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/spips/src/xspips_sinit.c @@ -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. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- -----------------------------------------------
+* 1.00  drg/jz 01/25/10 First release
+* 
+* +******************************************************************************/ + +/***************************** 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; +}