diff --git a/XilinxProcessorIPLib/drivers/iicps/data/iicps.mdd b/XilinxProcessorIPLib/drivers/iicps/data/iicps.mdd new file mode 100755 index 00000000..23d5a021 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/data/iicps.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 iicps + + OPTION supported_peripherals = (ps7_i2c ps8_i2c pss_i2c); + OPTION driver_state = ACTIVE; + OPTION copyfiles = all; + OPTION VERSION = 3.0; + OPTION NAME = iicps; + +END driver diff --git a/XilinxProcessorIPLib/drivers/iicps/data/iicps.tcl b/XilinxProcessorIPLib/drivers/iicps/data/iicps.tcl new file mode 100755 index 00000000..3c0c11c0 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/data/iicps.tcl @@ -0,0 +1,52 @@ +############################################################################### +# +# 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 +# 2.0 adk 12/10/13 Updated as per the New Tcl API's +# +############################################################################## + +#uses "xillib.tcl" + +proc generate {drv_handle} { + xdefine_zynq_include_file $drv_handle "xparameters.h" "XIicPs" "NUM_INSTANCES" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_I2C_CLK_FREQ_HZ" + + xdefine_zynq_config_file $drv_handle "xiicps_g.c" "XIicPs" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_I2C_CLK_FREQ_HZ" + + xdefine_zynq_canonical_xpars $drv_handle "xparameters.h" "XIicPs" "DEVICE_ID" "C_S_AXI_BASEADDR" "C_S_AXI_HIGHADDR" "C_I2C_CLK_FREQ_HZ" + +} diff --git a/XilinxProcessorIPLib/drivers/iicps/data/iicps_header.h b/XilinxProcessorIPLib/drivers/iicps/data/iicps_header.h new file mode 100644 index 00000000..64015c94 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/data/iicps_header.h @@ -0,0 +1,41 @@ +/****************************************************************************** +* +* 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 IICPS_HEADER_H /* prevent circular inclusions */ +#define IICPS_HEADER_H /* by using protection macros */ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" + +int IicPsSelfTestExample(u16 DeviceId); + +#endif diff --git a/XilinxProcessorIPLib/drivers/iicps/data/iicps_tapp.tcl b/XilinxProcessorIPLib/drivers/iicps/data/iicps_tapp.tcl new file mode 100755 index 00000000..64efea87 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/data/iicps_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 {xiicps.h iicps_header.h} + } + return $inc_file_lines +} + +proc gen_src_files {swproj mhsinst} { + if {$swproj == 0} { + return "" + } + if {$swproj == 1} { + + set inc_file_lines {examples/xiicps_selftest_example.c data/iicps_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 [common::get_property NAME $mhsinst] + set deviceid [::hsi::utils::get_ip_param_name $mhsinst "DEVICE_ID"] + set stdout [common::get_property CONFIG.STDOUT [hsi::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 = IicPsSelfTestExample(${deviceid}); + + }" + + + } else { + + append testfunc_call " + + { + int Status; + + print(\"\\r\\n Running IicPsSelfTestExample() for ${ipname}...\\r\\n\"); + + Status = IicPsSelfTestExample(${deviceid}); + + if (Status == 0) { + print(\"IicPsSelfTestExample PASSED\\r\\n\"); + } + else { + print(\"IicPsSelfTestExample FAILED\\r\\n\"); + } + }" + + } + + return $testfunc_call +} diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/index.html b/XilinxProcessorIPLib/drivers/iicps/examples/index.html new file mode 100755 index 00000000..aa3177ff --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/index.html @@ -0,0 +1,25 @@ + + + + + +Driver example applications + + + +

Example Applications for the driver iicps_v2_4

+
+ +

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

+ + \ No newline at end of file diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_eeprom_intr_example.c b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_eeprom_intr_example.c new file mode 100644 index 00000000..18e0eb4a --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_eeprom_intr_example.c @@ -0,0 +1,597 @@ +/****************************************************************************** +* +* 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 xiicps_eeprom_intr_example.c +* +* This file consists of a interrutp mode design example which uses the Xilinx +* PS IIC device and XIicPs driver to exercise the EEPROM. +* +* The XIicPs_MasterSend() API is used to transmit the data and the +* XIicPs_MasterRecv() API is used to receive the data. +* +* The example is tested with a 2Kb/8Kb serial IIC EEPROM (ST M24C02/M24C08). +* The WP pin of this EEPROM is hardwired to ground on the HW in which this +* was tested. +* +* The AddressType should be u8 as the address pointer in the on-board +* EEPROM is 1 bytes. +* +* This code assumes that no Operating System is being used. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a sdm  03/15/10 First release
+* 1.01a sg   04/13/12 Added MuxInit function for initializing the IIC Mux
+*		      on the ZC702 board and to configure it for accessing
+*		      the IIC EEPROM.
+*                     Updated to use usleep instead of delay loop
+* 1.04a hk   09/03/13 Removed GPIO code to pull MUX out of reset - CR#722425.
+* 2.3 	sk	 10/07/14 Removed multiple initializations for read buffer.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "sleep.h" +#include "xiicps.h" +#include "xscugic.h" +#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 IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define IIC_INTR_ID XPAR_XIICPS_0_INTR + +/* + * The following constant defines the address of the IIC Slave device on the + * IIC bus. Note that since the address is only 7 bits, this constant is the + * address divided by 2. + */ +#define IIC_SLAVE_ADDR 0x54 +#define IIC_SCLK_RATE 100000 +#define IIC_MUX_ADDRESS 0x74 +/* + * The page size determines how much data should be written at a time. + * The write function should be called with this as a maximum byte count. + */ +#define PAGE_SIZE 16 + +/* + * The Starting address in the IIC EEPROM on which this test is performed. + */ +#define EEPROM_START_ADDRESS 0 + +/**************************** Type Definitions *******************************/ + +/* + * The AddressType should be u8 as the address pointer in the on-board + * EEPROM is 1 byte. + */ +typedef u8 AddressType; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +int IicPsEepromIntrExample(void); +int EepromWriteData(u16 ByteCount); +int MuxInit(void); +int EepromReadData(u8 *BufferPtr, u16 ByteCount); + +static int SetupInterruptSystem(XIicPs * IicInstPtr); + +static void Handler(void *CallBackRef, u32 Event); + +/************************** Variable Definitions *****************************/ + +XIicPs IicInstance; /* The instance of the IIC device. */ +XScuGic InterruptController; /* The instance of the Interrupt Controller. */ + +/* + * Write buffer for writing a page. + */ +u8 WriteBuffer[sizeof(AddressType) + PAGE_SIZE]; + +u8 ReadBuffer[PAGE_SIZE]; /* Read buffer for reading a page. */ + +volatile u8 TransmitComplete; /* Flag to check completion of Transmission */ +volatile u8 ReceiveComplete; /* Flag to check completion of Reception */ +volatile u32 TotalErrorCount; + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* Main function to call the Iic EEPROM interrupt example. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("IIC EEPROM Interrupt Example Test \r\n"); + + /* + * Run the Iic EEPROM interrupt mode example. + */ + Status = IicPsEepromIntrExample(); + if (Status != XST_SUCCESS) { + xil_printf("IIC EEPROM Interrupt Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran IIC EEPROM Interrupt Example Test\r\n"); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function writes, reads, and verifies the data to the IIC EEPROM. It +* does the write as a single page write, performs a buffered read. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int IicPsEepromIntrExample(void) +{ + u32 Index; + int Status; + XIicPs_Config *ConfigPtr; /* Pointer to configuration data */ + AddressType Address = EEPROM_START_ADDRESS; + + /* + * Initialize the IIC driver so that it is ready to use. + */ + ConfigPtr = XIicPs_LookupConfig(IIC_DEVICE_ID); + if (ConfigPtr == NULL) { + return XST_FAILURE; + } + + Status = XIicPs_CfgInitialize(&IicInstance, ConfigPtr, + ConfigPtr->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the Interrupt System. + */ + Status = SetupInterruptSystem(&IicInstance); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handlers for the IIC that will be called from the + * interrupt context when data has been sent and received, specify a + * pointer to the IIC driver instance as the callback reference so + * the handlers are able to access the instance data. + */ + XIicPs_SetStatusHandler(&IicInstance, (void *) &IicInstance, Handler); + + /* + * Set the IIC serial clock rate. + */ + XIicPs_SetSClk(&IicInstance, IIC_SCLK_RATE); + + /* + * Set the channel value in IIC Mux. + */ + Status = MuxInit(); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Initialize the data to write and the read buffer. + */ + if (sizeof(Address) == 1) { + WriteBuffer[0] = (u8) (Address); + } else { + WriteBuffer[0] = (u8) (Address >> 8); + WriteBuffer[1] = (u8) (Address); + } + + for (Index = 0; Index < PAGE_SIZE; Index++) { + WriteBuffer[sizeof(Address) + Index] = 0xFF; + ReadBuffer[Index] = 0; + } + + /* + * Write to the EEPROM. + */ + Status = EepromWriteData(sizeof(Address) + PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the EEPROM. + */ + Status = EepromReadData(ReadBuffer, PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Verify the data read against the data written. + */ + for (Index = 0; Index < PAGE_SIZE; Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index + sizeof(Address)]) { + return XST_FAILURE; + } + } + + /* + * Initialize the data to write and the read buffer. + */ + if (sizeof(Address) == 1) { + WriteBuffer[0] = (u8) (Address); + } else { + WriteBuffer[0] = (u8) (Address >> 8); + WriteBuffer[1] = (u8) (Address); + } + + for (Index = 0; Index < PAGE_SIZE; Index++) { + WriteBuffer[sizeof(Address) + Index] = Index + 10; + ReadBuffer[Index] = 0; + } + + /* + * Write to the EEPROM. + */ + Status = EepromWriteData(sizeof(Address) + PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the EEPROM. + */ + Status = EepromReadData(ReadBuffer, PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Verify the data read against the data written. + */ + for (Index = 0; Index < PAGE_SIZE; Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index + sizeof(Address)]) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function writes a buffer of data to the IIC serial EEPROM. +* +* @param ByteCount contains the number of bytes in the buffer to be +* written. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note The Byte count should not exceed the page size of the EEPROM as +* noted by the constant PAGE_SIZE. +* +******************************************************************************/ +int EepromWriteData(u16 ByteCount) +{ + + TransmitComplete = FALSE; + + /* + * Send the Data. + */ + XIicPs_MasterSend(&IicInstance, WriteBuffer, + ByteCount, IIC_SLAVE_ADDR); + + /* + * Wait for the entire buffer to be sent, letting the interrupt + * processing work in the background, this function may get + * locked up in this loop if the interrupts are not working + * correctly. + */ + while (TransmitComplete == FALSE) { + if (0 != TotalErrorCount) { + return XST_FAILURE; + } + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + /* + * Wait for a bit of time to allow the programming to complete + */ + usleep(250000); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function reads data from the IIC serial EEPROM into a specified buffer. +* +* @param BufferPtr contains the address of the data buffer to be filled. +* @param ByteCount contains the number of bytes in the buffer to be read. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int EepromReadData(u8 *BufferPtr, u16 ByteCount) +{ + int Status; + AddressType Address = EEPROM_START_ADDRESS; + + /* + * Position the Pointer in EEPROM. + */ + if (sizeof(Address) == 1) { + WriteBuffer[0] = (u8) (Address); + } + else { + WriteBuffer[0] = (u8) (Address >> 8); + WriteBuffer[1] = (u8) (Address); + } + + Status = EepromWriteData(sizeof(Address)); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + ReceiveComplete = FALSE; + + /* + * Receive the Data. + */ + XIicPs_MasterRecv(&IicInstance, BufferPtr, + ByteCount, IIC_SLAVE_ADDR); + + while (ReceiveComplete == FALSE) { + if (0 != TotalErrorCount) { + return XST_FAILURE; + } + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + return XST_SUCCESS; +} + +/******************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the IIC. +* +* @param IicPsPtr contains a pointer to the instance of the Iic +* which is going to be connected to the interrupt controller. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +*******************************************************************************/ +static int SetupInterruptSystem(XIicPs *IicPsPtr) +{ + 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(&InterruptController, 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_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + &InterruptController); + + /* + * 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(&InterruptController, IIC_INTR_ID, + (Xil_InterruptHandler)XIicPs_MasterInterruptHandler, + (void *)IicPsPtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Enable the interrupt for the Iic device. + */ + XScuGic_Enable(&InterruptController, IIC_INTR_ID); + + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing to handle data events +* from the IIC. It is called from an interrupt context such that the amount +* of processing performed should be minimized. +* +* This handler provides an example of how to handle data for the IIC and +* is application specific. +* +* @param CallBackRef contains a callback reference from the driver, in +* this case it is the instance pointer for the IIC driver. +* @param Event contains the specific kind of event that has occurred. +* @param EventData contains the number of bytes sent or received for sent +* and receive events. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void Handler(void *CallBackRef, u32 Event) +{ + /* + * All of the data transfer has been finished. + */ + if (0 != (Event & XIICPS_EVENT_COMPLETE_RECV)){ + ReceiveComplete = TRUE; + } else if (0 != (Event & XIICPS_EVENT_COMPLETE_SEND)) { + TransmitComplete = TRUE; + } else if (0 == (Event & XIICPS_EVENT_SLAVE_RDY)){ + /* + * If it is other interrupt but not slave ready interrupt, it is + * an error. + * Data was received with an error. + */ + TotalErrorCount++; + } +} + +/*****************************************************************************/ +/** +* This function initializes the IIC MUX to select EEPROM. +* +* @param None. +* +* @return XST_SUCCESS if pass, otherwise XST_FAILURE. +* +* @note None. +* +****************************************************************************/ +int MuxInit(void) +{ + u8 WriteBuffer; + u8 MuxIicAddr = IIC_MUX_ADDRESS; + u8 Buffer = 0; + + /* + * Channel select value for EEPROM. + */ + WriteBuffer = 0x04; + + TransmitComplete = FALSE; + + /* + * Send the Data. + */ + XIicPs_MasterSend(&IicInstance, &WriteBuffer,1, MuxIicAddr); + while (TransmitComplete == FALSE) { + if (0 != TotalErrorCount) { + return XST_FAILURE; + } + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + ReceiveComplete = FALSE; + + /* + * Receive the Data. + */ + XIicPs_MasterRecv(&IicInstance, &Buffer,1, MuxIicAddr); + while (ReceiveComplete == FALSE) { + if (0 != TotalErrorCount) { + return XST_FAILURE; + } + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_eeprom_polled_example.c b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_eeprom_polled_example.c new file mode 100644 index 00000000..0e38b9ae --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_eeprom_polled_example.c @@ -0,0 +1,436 @@ +/****************************************************************************** +* +* 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 xiicps_eeprom_polled_example.c +* +* This file consists of a polled mode design example which uses the Xilinx PS +* IIC device and XIicPs driver to exercise the EEPROM. +* +* The XIicPs_MasterSendPolled() API is used to transmit the data and +* XIicPs_MasterRecvPolled() API is used to receive the data. +* +* The example is tested with a 2Kb/8Kb serial IIC EEPROM (ST M24C02/M24C08). +* The WP pin of this EEPROM is hardwired to ground in the HW in which this +* was tested. +* +* The AddressType should be u8 as the address pointer in the on-board +* EEPROM is 1 bytes. +* +* This code assumes that no Operating System is being used. +* +* @note +* +* None. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 1.00a sdm  03/15/10 First release
+* 1.01a sg   04/13/12 Added MuxInit function for initializing the IIC Mux
+*		      on the ZC702 board and to configure it for accessing
+*		      the IIC EEPROM.
+*                     Updated to use usleep instead of delay loop
+* 1.04a hk   09/03/13 Removed GPIO code to pull MUX out of reset - CR#722425.
+* 2.3 	sk	 10/07/14 Removed multiple initializations for read buffer.
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "sleep.h" +#include "xiicps.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 IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID + +/* + * The following constant defines the address of the IIC Slave device on the + * IIC bus. Note that since the address is only 7 bits, this constant is the + * address divided by 2. + */ +#define IIC_SLAVE_ADDR 0x54 +#define IIC_SCLK_RATE 100000 +#define IIC_MUX_ADDRESS 0x74 + +/* + * The page size determines how much data should be written at a time. + * The write function should be called with this as a maximum byte count. + */ +#define PAGE_SIZE 16 + +/* + * The Starting address in the IIC EEPROM on which this test is performed. + */ +#define EEPROM_START_ADDRESS 128 + +/**************************** Type Definitions *******************************/ + +/* + * The AddressType should be u8 as the address pointer in the on-board + * EEPROM is 1 bytes. + */ +typedef u8 AddressType; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +int IicPsEepromPolledExample(void); +int EepromWriteData(u16 ByteCount); +int MuxInit(void); +int EepromReadData(u8 *BufferPtr, u16 ByteCount); + +/************************** Variable Definitions *****************************/ + +XIicPs IicInstance; /* The instance of the IIC device. */ + +/* + * Write buffer for writing a page. + */ +u8 WriteBuffer[sizeof(AddressType) + PAGE_SIZE]; + +u8 ReadBuffer[PAGE_SIZE]; /* Read buffer for reading a page. */ + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* Main function to call the Iic EEPROM polled example. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("IIC EEPROM Polled Mode Example Test \r\n"); + + /* + * Run the Iic EEPROM Polled Mode example. + */ + Status = IicPsEepromPolledExample(); + if (Status != XST_SUCCESS) { + xil_printf("IIC EEPROM Polled Mode Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran IIC EEPROM Polled Mode Example Test\r\n"); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function writes, reads, and verifies the data to the IIC EEPROM. It +* does the write as a single page write, performs a buffered read. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int IicPsEepromPolledExample(void) +{ + u32 Index; + int Status; + XIicPs_Config *ConfigPtr; /* Pointer to configuration data */ + AddressType Address = EEPROM_START_ADDRESS; + + /* + * Initialize the IIC driver so that it is ready to use. + */ + ConfigPtr = XIicPs_LookupConfig(IIC_DEVICE_ID); + if (ConfigPtr == NULL) { + return XST_FAILURE; + } + + Status = XIicPs_CfgInitialize(&IicInstance, ConfigPtr, + ConfigPtr->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the IIC serial clock rate. + */ + XIicPs_SetSClk(&IicInstance, IIC_SCLK_RATE); + + /* + * Set the channel value in IIC Mux. + */ + Status = MuxInit(); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Initialize the data to write and the read buffer. + */ + if (sizeof(Address) == 1) { + WriteBuffer[0] = (u8) (Address); + } else { + WriteBuffer[0] = (u8) (Address >> 8); + WriteBuffer[1] = (u8) (Address); + } + + for (Index = 0; Index < PAGE_SIZE; Index++) { + WriteBuffer[sizeof(Address) + Index] = 0xFF; + ReadBuffer[Index] = 0; + } + + /* + * Write to the EEPROM. + */ + Status = EepromWriteData(sizeof(Address) + PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the EEPROM. + */ + Status = EepromReadData(ReadBuffer, PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Verify the data read against the data written. + */ + for (Index = 0; Index < PAGE_SIZE; Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index + sizeof(Address)]) { + return XST_FAILURE; + } + } + + /* + * Initialize the data to write and the read buffer. + */ + if (sizeof(Address) == 1) { + WriteBuffer[0] = (u8) (Address); + } else { + WriteBuffer[0] = (u8) (Address >> 8); + WriteBuffer[1] = (u8) (Address); + } + + for (Index = 0; Index < PAGE_SIZE; Index++) { + WriteBuffer[sizeof(Address) + Index] = Index + 10; + ReadBuffer[Index] = 0; + } + + /* + * Write to the EEPROM. + */ + Status = EepromWriteData(sizeof(Address) + PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Read from the EEPROM. + */ + Status = EepromReadData(ReadBuffer, PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Verify the data read against the data written. + */ + for (Index = 0; Index < PAGE_SIZE; Index++) { + if (ReadBuffer[Index] != WriteBuffer[Index + sizeof(Address)]) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function writes a buffer of data to the IIC serial EEPROM. +* +* @param ByteCount contains the number of bytes in the buffer to be +* written. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note The Byte count should not exceed the page size of the EEPROM as +* noted by the constant PAGE_SIZE. +* +******************************************************************************/ +int EepromWriteData(u16 ByteCount) +{ + int Status; + + /* + * Send the Data. + */ + Status = XIicPs_MasterSendPolled(&IicInstance, WriteBuffer, + ByteCount, IIC_SLAVE_ADDR); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + /* + * Wait for a bit of time to allow the programming to complete + */ + usleep(250000); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function reads data from the IIC serial EEPROM into a specified buffer. +* +* @param BufferPtr contains the address of the data buffer to be filled. +* @param ByteCount contains the number of bytes in the buffer to be read. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int EepromReadData(u8 *BufferPtr, u16 ByteCount) +{ + int Status; + AddressType Address = EEPROM_START_ADDRESS; + + /* + * Position the Pointer in EEPROM. + */ + if (sizeof(Address) == 1) { + WriteBuffer[0] = (u8) (Address); + } + else { + WriteBuffer[0] = (u8) (Address >> 8); + WriteBuffer[1] = (u8) (Address); + } + + Status = EepromWriteData(sizeof(Address)); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Receive the Data. + */ + Status = XIicPs_MasterRecvPolled(&IicInstance, BufferPtr, + ByteCount, IIC_SLAVE_ADDR); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function initializes the IIC MUX to select EEPROM. +* +* @param None. +* +* @return XST_SUCCESS if pass, otherwise XST_FAILURE. +* +* @note None. +* +****************************************************************************/ +int MuxInit(void) +{ + u8 WriteBuffer; + u8 MuxIicAddr = IIC_MUX_ADDRESS; + u8 Buffer = 0; + int Status = 0; + + /* + * Channel select value for EEPROM. + */ + WriteBuffer = 0x04; + + /* + * Send the Data. + */ + Status = XIicPs_MasterSendPolled(&IicInstance, &WriteBuffer,1, + MuxIicAddr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + /* + * Receive the Data. + */ + Status = XIicPs_MasterRecvPolled(&IicInstance, &Buffer,1, MuxIicAddr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_intr_master_example.c b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_intr_master_example.c new file mode 100644 index 00000000..cef6e336 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_intr_master_example.c @@ -0,0 +1,403 @@ +/****************************************************************************** +* +* 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 xiicps_intr_master_example.c + * + * Design example to use the IIC device as master in interrupt-driven mode. + * + * It continuously sends 18 buffers to slave. + * + *
 MODIFICATION HISTORY:
+ *
+ * Ver   Who Date     Changes
+ * ----- --- -------- -----------------------------------------------
+ * 1.00a jz  01/30/10 First release
+ *
+ * 
+ * + ****************************************************************************/ + +/***************************** Include Files **********************************/ +#include "xparameters.h" +#include "xiicps.h" +#include "xscugic.h" +#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 IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define IIC_INT_VEC_ID XPAR_XIICPS_0_INTR + +/* + * The slave address to send to and receive from. + */ +#define IIC_SLAVE_ADDR 0x55 +#define IIC_SCLK_RATE 100000 + + +/* + * The following constant controls the length of the buffers to be sent + * and received with the IIC. + */ +#define TEST_BUFFER_SIZE 250 +#define NUMBER_OF_SIZES 18 + +/**************************** Type Definitions ********************************/ + +/************************** Function Prototypes *******************************/ + +int IicPsMasterIntrExample(u16 DeviceId); +static int SetupInterruptSystem(XIicPs *IicPsPtr); + +void Handler(void *CallBackRef, u32 Event); + +/************************** Variable Definitions ******************************/ + +XIicPs Iic; /* Instance of the IIC Device */ +XScuGic InterruptController; /* Instance of the Interrupt Controller */ + +/* + * The following buffers are used in this example to send and receive data + * with the IIC. They are defined as global so that they are not on the stack. + */ +u8 SendBuffer[TEST_BUFFER_SIZE]; /* Buffer for Transmitting Data */ +u8 RecvBuffer[TEST_BUFFER_SIZE]; /* Buffer for Receiving Data */ + +/* + * The following counters are used to determine when the entire buffer has + * been sent and received. + */ +volatile u32 SendComplete; +volatile u32 RecvComplete; +volatile u32 TotalErrorCount; + +/******************************************************************************/ +/** +* +* Main function to call the example. +* +* @param None. +* +* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful. +* +* @note None. +* +*******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("IIC Master Interrupt Example Test \r\n"); + + /* + * Run the Iic Master Interrupt example , specify the Device ID that is + * generated in xparameters.h + */ + Status = IicPsMasterIntrExample(IIC_DEVICE_ID); + if (Status != XST_SUCCESS) { + xil_printf("IIC Master Interrupt Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran IIC Master Interrupt Example Test\r\n"); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function does a minimal test on the Iic device and driver as a +* design example. The purpose of this function is to illustrate +* how to use the XIicPs driver. +* +* This function sends data and expects to receive the same data through the IIC +* using the Aardvark test hardware. +* +* This function uses interrupt driver mode of the IIC. +* +* @param DeviceId is the Device ID of the IicPs Device and is the +* XPAR__DEVICE_ID value from xparameters.h +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note +* +* This function contains an infinite loop such that if interrupts are not +* working it may never return. +* +*******************************************************************************/ +int IicPsMasterIntrExample(u16 DeviceId) +{ + int Status; + XIicPs_Config *Config; + int Index; + int tmp; + int BufferSizes[NUMBER_OF_SIZES] = {1, 2, 19, 31, 32, 33, 62, 63, 64, + 65, 66, 94, 95, 96, 97, 98, 99, 250}; + + /* + * Initialize the IIC driver so that it's ready to use + * Look up the configuration in the config table, then initialize it. + */ + Config = XIicPs_LookupConfig(DeviceId); + if (NULL == Config) { + return XST_FAILURE; + } + + Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test to ensure that the hardware was built correctly. + */ + Status = XIicPs_SelfTest(&Iic); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the IIC to the interrupt subsystem such that interrupts can + * occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Iic); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handlers for the IIC that will be called from the + * interrupt context when data has been sent and received, specify a + * pointer to the IIC driver instance as the callback reference so + * the handlers are able to access the instance data. + */ + XIicPs_SetStatusHandler(&Iic, (void *) &Iic, Handler); + + /* + * Set the IIC serial clock rate. + */ + XIicPs_SetSClk(&Iic, IIC_SCLK_RATE); + + /* + * Initialize the send buffer bytes with a pattern to send and the + * the receive buffer bytes to zero to allow the receive data to be + * verified. + */ + for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { + SendBuffer[Index] = (Index % TEST_BUFFER_SIZE); + RecvBuffer[Index] = 0; + } + + for(Index = 0; Index < NUMBER_OF_SIZES; Index++) { + + /* Wait for bus to become idle + */ + while (XIicPs_BusIsBusy(&Iic)) { + /* NOP */ + } + + SendComplete = FALSE; + + /* + * Send the buffer, errors are reported by TotalErrorCount. + */ + XIicPs_MasterSend(&Iic, SendBuffer, BufferSizes[Index], + IIC_SLAVE_ADDR); + + /* + * Wait for the entire buffer to be sent, letting the interrupt + * processing work in the background, this function may get + * locked up in this loop if the interrupts are not working + * correctly. + */ + while (!SendComplete) { + if (0 != TotalErrorCount) { + return XST_FAILURE; + } + } + + /* + * Wait bus activities to finish. + */ + while (XIicPs_BusIsBusy(&Iic)) { + /* NOP */ + } + + /* + * Receive data from slave, errors are reported through + * TotalErrorCount. + */ + RecvComplete = FALSE; + XIicPs_MasterRecv(&Iic, RecvBuffer, BufferSizes[Index], + IIC_SLAVE_ADDR); + + while (!RecvComplete) { + if (0 != TotalErrorCount) { + return XST_FAILURE; + } + } + + /* Check for received data. + */ + for(tmp = 0; tmp < BufferSizes[Index]; tmp ++) { + + /* + * Aardvark as slave can only set up to 64 bytes for + * output. + */ + if (RecvBuffer[tmp] != tmp % 64) { + return XST_FAILURE; + } + } + } + return XST_SUCCESS; +} +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing to handle data events +* from the IIC. It is called from an interrupt context such that the amount +* of processing performed should be minimized. +* +* This handler provides an example of how to handle data for the IIC and +* is application specific. +* +* @param CallBackRef contains a callback reference from the driver, in +* this case it is the instance pointer for the IIC driver. +* @param Event contains the specific kind of event that has occurred. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void Handler(void *CallBackRef, u32 Event) +{ + /* + * All of the data transfer has been finished. + */ + if (0 != (Event & XIICPS_EVENT_COMPLETE_RECV)){ + RecvComplete = TRUE; + } else if (0 != (Event & XIICPS_EVENT_COMPLETE_SEND)) { + SendComplete = TRUE; + } else if (0 == (Event & XIICPS_EVENT_SLAVE_RDY)){ + /* + * If it is other interrupt but not slave ready interrupt, it is + * an error. + * Data was received with an error. + */ + TotalErrorCount++; + } +} + +/******************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the IIC. This function is application specific since the actual +* system may or may not have an interrupt controller. The IIC could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param IicPsPtr contains a pointer to the instance of the Iic +* which is going to be connected to the interrupt controller. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +*******************************************************************************/ +static int SetupInterruptSystem(XIicPs *IicPsPtr) +{ + 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(&InterruptController, 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_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + &InterruptController); + + /* + * 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(&InterruptController, IIC_INT_VEC_ID, + (Xil_InterruptHandler)XIicPs_MasterInterruptHandler, + (void *)IicPsPtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Enable the interrupt for the Iic device. + */ + XScuGic_Enable(&InterruptController, IIC_INT_VEC_ID); + + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_intr_slave_example.c b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_intr_slave_example.c new file mode 100644 index 00000000..8e0bca11 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_intr_slave_example.c @@ -0,0 +1,397 @@ +/****************************************************************************** +* +* 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 xiicps_intr_slave_example.c +* +* A design example of using the IIC device as slave for interrupt-driven +* transfers using the external Aardvark IIC analyzer as the master. +* +* This example uses buffer size of 250. Set the send buffer of the +* Aardvark device as continuous data from 0x00 to 0xF9. +* +* @note None. +* +*
 MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --- -------- -----------------------------------------------
+* 1.00a jz  01/30/10 First release
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files **********************************/ +#include "xparameters.h" +#include "xiicps.h" +#include "xscugic.h" +#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 IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define IIC_INT_VEC_ID XPAR_XIICPS_0_INTR + +/* + * The slave address to send to and receive from. + */ +#define IIC_SLAVE_ADDR 0x45 +#define IIC_SCLK_RATE 400000 + +/* + * The following constant controls the length of the buffers to be sent + * and received with the IIC. + */ +#define TEST_BUFFER_SIZE 250 + +/**************************** Type Definitions ********************************/ + + +/************************** Function Prototypes *******************************/ + +int IicPsSlaveIntrExample(u16 DeviceId); +static int SetupInterruptSystem(XIicPs *IicPsPtr); + +void Handler(void *CallBackRef, u32 Event); + +/************************** Variable Definitions ******************************/ + +XIicPs Iic; /* Instance of the IIC Device */ +XScuGic InterruptController; /* Instance of the Interrupt Controller */ + +/* + * The following buffers are used in this example to send and receive data + * with the IIC. The buffers are defined as global so that they are not on the + * stack. + */ +u8 SendBuffer[TEST_BUFFER_SIZE]; /* Buffer for Transmitting Data */ +u8 RecvBuffer[TEST_BUFFER_SIZE]; /* Buffer for Receiving Data */ + +/* + * The following counters are used to determine when the entire buffer has + * been sent and received. + */ +volatile u32 SendComplete; +volatile u32 RecvComplete; +volatile u32 TotalErrorCount; + +/******************************************************************************/ +/** +* +* Main function to call the interrupt example in the slave mode. +* +* @param None +* +* @return +* - XST_SUCCESS if successful. +* - XST_FAILURE if unsuccessful. +* +* @note None +* +*******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("IIC Slave Interrupt Example Test \r\n"); + + /* + * Run the Iic Slave Interrupt example , specify the Device ID that is + * generated in xparameters.h. + */ + Status = IicPsSlaveIntrExample(IIC_DEVICE_ID); + if (Status != XST_SUCCESS) { + xil_printf("IIC Slave Interrupt Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran IIC Slave Interrupt Example Test\r\n"); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function does a minimal test on the Iic device and driver as a +* design example. The purpose of this function is to illustrate +* how to use the XIicPs component. +* +* This function sends data and expects to receive the same data through the IIC +* using the Aardvark test hardware. +* +* This function uses interrupt driver mode of the IIC. +* +* @param DeviceId is the Device ID of the IicPs Device and is the +* XPAR__DEVICE_ID value from xparameters.h +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note +* +* This function contains an infinite loop such that if interrupts are not +* working it may never return. +* +*******************************************************************************/ +int IicPsSlaveIntrExample(u16 DeviceId) +{ + int Status; + XIicPs_Config *Config; + int Index; + + /* + * Initialize the IIC driver so that it's ready to use + * Look up the configuration in the config table, + * then initialize it. + */ + Config = XIicPs_LookupConfig(DeviceId); + if (NULL == Config) { + return XST_FAILURE; + } + + Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test to ensure that the hardware was built correctly. + */ + Status = XIicPs_SelfTest(&Iic); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the IIC to the interrupt subsystem such that interrupts can + * occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Iic); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handlers for the IIC that will be called from the + * interrupt context when data has been sent and received, specify a + * pointer to the IIC driver instance as the callback reference so + * the handlers are able to access the instance data. + */ + XIicPs_SetStatusHandler(&Iic, (void *) &Iic, Handler); + XIicPs_SetupSlave(&Iic, IIC_SLAVE_ADDR); + + /* + * Set the IIC serial clock rate. + */ + XIicPs_SetSClk(&Iic, IIC_SCLK_RATE); + + /* + * Initialize the send buffer bytes with a pattern to send and the + * the receive buffer bytes to zero to allow the receive data to be + * verified. + */ + for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { + SendBuffer[Index] = (Index % TEST_BUFFER_SIZE); + RecvBuffer[Index] = 0; + } + + TotalErrorCount = 0; + SendComplete = FALSE; + + /* + * Send the buffer using the IIC and ignore the number of bytes sent. + * In case of error, the interrupt handler will inform us through event + * flag. + */ + XIicPs_SlaveSend(&Iic, SendBuffer, TEST_BUFFER_SIZE); + + /* + * Wait for the entire buffer to be sent, let the interrupt + * processing work in the background, this function may get locked + * up in this loop if the interrupts are not working correctly. + */ + while (!SendComplete) { + if (0 != TotalErrorCount) { + return XST_FAILURE; + } + } + + /* + * Wait until the bus transfer finishes. + */ + while (XIicPs_BusIsBusy(&Iic)) { + /* NOP */ + } + + /* + * Receive data from master. + * Receive errors will be singalled through event flag. + */ + RecvComplete = FALSE; + XIicPs_SlaveRecv(&Iic, RecvBuffer, TEST_BUFFER_SIZE); + + while (!RecvComplete) { + if (0 != TotalErrorCount) { + return XST_FAILURE; + } + } + + /* + * Verify received data. + */ + for(Index = 0; Index < TEST_BUFFER_SIZE; Index ++) { + if (RecvBuffer[Index] != Index) { + return XST_FAILURE; + } + } + return XST_SUCCESS; +} +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing to handle data events +* from the IIC. It is called from an interrupt context such that the amount +* of processing performed should be minimized. +* +* This handler provides an example of how to handle data for the IIC and +* is application specific. +* +* @param CallBackRef contains a callback reference from the driver, +* in this case it is the instance pointer for the IIC driver. +* @param Event contains the specific kind of event that has occurred. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void Handler(void *CallBackRef, u32 Event) +{ + /* + * Data transfer finishes. + */ + if (0 != (Event & XIICPS_EVENT_COMPLETE_RECV)){ + RecvComplete = TRUE; + } + else if (0 != (Event & XIICPS_EVENT_COMPLETE_SEND)) { + SendComplete = TRUE; + } else { + + /* + * Data was received with an error. + */ + TotalErrorCount++; + } +} + +/******************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the IIC. This function is application specific since the actual +* system may or may not have an interrupt controller. The IIC could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param IicPsPtr contains a pointer to the instance of the Iic +* component which is going to be connected to the interrupt +* controller. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None +* +*******************************************************************************/ +static int SetupInterruptSystem(XIicPs *IicPsPtr) +{ + 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(&InterruptController, 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_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + &InterruptController); + + /* + * 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(&InterruptController, IIC_INT_VEC_ID, + (Xil_InterruptHandler)XIicPs_SlaveInterruptHandler, + (void *)IicPsPtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Enable the interrupt for the Iic device. + */ + XScuGic_Enable(&InterruptController, IIC_INT_VEC_ID); + + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_polled_master_example.c b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_polled_master_example.c new file mode 100644 index 00000000..d3daefc9 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_polled_master_example.c @@ -0,0 +1,222 @@ +/****************************************************************************** +* +* 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 xiicps_polled_master_example.c +* +* A design example of using the device in polled mode as master. +* +* The example uses buffer size 132. Please set the send buffer of the +* Aardvark device to be continuous 64 bytes from 0x00 to 0x3F. + * + *
 MODIFICATION HISTORY:
+ *
+ * Ver   Who Date     Changes
+ * ----- --- -------- -----------------------------------------------
+ * 1.00a jz  01/30/10 First release
+ *
+ * 
+ * + ****************************************************************************/ + +/***************************** Include Files **********************************/ +#include "xparameters.h" +#include "xiicps.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 IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID + +/* + * The slave address to send to and receive from. + */ +#define IIC_SLAVE_ADDR 0x55 +#define IIC_SCLK_RATE 100000 + +/* + * The following constant controls the length of the buffers to be sent + * and received with the IIC. + */ +#define TEST_BUFFER_SIZE 132 + +/**************************** Type Definitions ********************************/ + + +/************************** Function Prototypes *******************************/ + +int IicPsMasterPolledExample(u16 DeviceId); +/************************** Variable Definitions ******************************/ + +XIicPs Iic; /**< Instance of the IIC Device */ + +/* + * The following buffers are used in this example to send and receive data + * with the IIC. + */ +u8 SendBuffer[TEST_BUFFER_SIZE]; /**< Buffer for Transmitting Data */ +u8 RecvBuffer[TEST_BUFFER_SIZE]; /**< Buffer for Receiving Data */ + + +/******************************************************************************/ +/** +* +* Main function to call the polled master example. +* +* @param None. +* +* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful. +* +* @note None. +* +*******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("IIC Master Polled Example Test \r\n"); + + /* + * Run the Iic polled example in master mode, specify the Device + * ID that is specified in xparameters.h. + */ + Status = IicPsMasterPolledExample(IIC_DEVICE_ID); + if (Status != XST_SUCCESS) { + xil_printf("IIC Master Polled Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran IIC Master Polled Example Test\r\n"); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function sends data and expects to receive data from slave as modular +* of 64. +* +* This function uses interrupt-driven mode of the device. +* +* @param DeviceId is the Device ID of the IicPs Device and is the +* XPAR__DEVICE_ID value from xparameters.h +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +*******************************************************************************/ +int IicPsMasterPolledExample(u16 DeviceId) +{ + int Status; + XIicPs_Config *Config; + int Index; + + /* + * Initialize the IIC driver so that it's ready to use + * Look up the configuration in the config table, + * then initialize it. + */ + Config = XIicPs_LookupConfig(DeviceId); + if (NULL == Config) { + return XST_FAILURE; + } + + Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test to ensure that the hardware was built correctly. + */ + Status = XIicPs_SelfTest(&Iic); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the IIC serial clock rate. + */ + XIicPs_SetSClk(&Iic, IIC_SCLK_RATE); + + /* + * Initialize the send buffer bytes with a pattern to send and the + * the receive buffer bytes to zero to allow the receive data to be + * verified. + */ + for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { + SendBuffer[Index] = (Index % TEST_BUFFER_SIZE); + RecvBuffer[Index] = 0; + } + + /* + * Send the buffer using the IIC and ignore the number of bytes sent + * as the return value since we are using it in interrupt mode. + */ + Status = XIicPs_MasterSendPolled(&Iic, SendBuffer, + TEST_BUFFER_SIZE, IIC_SLAVE_ADDR); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&Iic)) { + /* NOP */ + } + + Status = XIicPs_MasterRecvPolled(&Iic, RecvBuffer, + TEST_BUFFER_SIZE, IIC_SLAVE_ADDR); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Verify received data is correct. + */ + for(Index = 0; Index < TEST_BUFFER_SIZE; Index ++) { + + /* Aardvark as slave can only set 64 bytes for output */ + if (RecvBuffer[Index] != Index % 64) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_polled_slave_example.c b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_polled_slave_example.c new file mode 100644 index 00000000..c8788d75 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_polled_slave_example.c @@ -0,0 +1,215 @@ +/****************************************************************************** +* +* 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 xiicps_polled_slave_example.c + * + * A design example of using the device as slave in polled mode. + * + * This example uses buffer of size 250. Please set the send buffer of the + * Aardvark device to be continuous data from 0x00 to 0xF9. + * + *
 MODIFICATION HISTORY:
+ *
+ * Ver   Who Date     Changes
+ * ----- --- -------- -----------------------------------------------
+ * 1.00a jz  01/30/10 First release
+ *
+ * 
+ * + ****************************************************************************/ + +/***************************** Include Files **********************************/ +#include "xparameters.h" +#include "xiicps.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 IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID + +/* The slave address to send to and receive from. + */ +#define IIC_SLAVE_ADDR 0x45 +#define IIC_SCLK_RATE 400000 + +/* + * The following constant controls the length of the buffers to be sent + * and received with the IIC + */ +#define TEST_BUFFER_SIZE 250 + +/**************************** Type Definitions ********************************/ + +/************************** Function Prototypes *******************************/ + +int IicPsSlavePolledExample(u16 DeviceId); +/************************** Variable Definitions ******************************/ + +XIicPs Iic; /* Instance of the IIC Device */ + +/* + * The following buffers are used in this example to send and receive data + * with the IIC. These buffers are defined as global so that they are not + * defined on the stack. + */ +u8 SendBuffer[TEST_BUFFER_SIZE]; /* Buffer for Transmitting Data */ +u8 RecvBuffer[TEST_BUFFER_SIZE]; /* Buffer for Receiving Data */ + +/******************************************************************************/ +/** +* +* Main function to call the polled slave example. +* +* @param None. +* +* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful. +* +* @note None. +* +*******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("IIC Slave Polled Example Test \r\n"); + + /* + * Run the Iic polled slave example , specify the Device ID that is + * generated in xparameters.h. + */ + Status = IicPsSlavePolledExample(IIC_DEVICE_ID); + if (Status != XST_SUCCESS) { + xil_printf("IIC Slave Polled Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran IIC Slave Polled Example Test\r\n"); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function does polled mode transfer in slave mode. It first sends to +* master then receives. +* +* @param DeviceId is the Device ID of the IicPs Device and is the +* XPAR__DEVICE_ID value from xparameters.h +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +*******************************************************************************/ +int IicPsSlavePolledExample(u16 DeviceId) +{ + int Status; + XIicPs_Config *Config; + int Index; + + /* + * Initialize the IIC driver so that it's ready to use + * Look up the configuration in the config table, + * then initialize it. + */ + Config = XIicPs_LookupConfig(DeviceId); + if (NULL == Config) { + return XST_FAILURE; + } + + Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test to ensure that the hardware was built correctly. + */ + Status = XIicPs_SelfTest(&Iic); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + XIicPs_SetupSlave(&Iic, IIC_SLAVE_ADDR); + + /* + * Set the IIC serial clock rate. + */ + XIicPs_SetSClk(&Iic, IIC_SCLK_RATE); + + /* + * Initialize the send buffer bytes with a pattern to send and the + * the receive buffer bytes to zero to allow the receive data to be + * verified. + */ + for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) { + SendBuffer[Index] = (Index % TEST_BUFFER_SIZE); + RecvBuffer[Index] = 0; + } + + /* + * Send the buffer using the IIC and ignore the number of bytes sent + * as the return value since we are using it in interrupt mode. + */ + Status = XIicPs_SlaveSendPolled(&Iic, SendBuffer, + TEST_BUFFER_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + while (XIicPs_BusIsBusy(&Iic)) { + /* NOP */ + } + + Status = XIicPs_SlaveRecvPolled(&Iic, RecvBuffer, + TEST_BUFFER_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Verify received data is correct. + */ + for(Index = 0; Index < TEST_BUFFER_SIZE; Index ++) { + if (RecvBuffer[Index] != Index % TEST_BUFFER_SIZE) { + return XST_FAILURE; + } + } + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_repeated_start_example.c b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_repeated_start_example.c new file mode 100644 index 00000000..da784821 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_repeated_start_example.c @@ -0,0 +1,468 @@ +/****************************************************************************** +* +* 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 xiicps_repeated_start_example.c +* +* This file consists of a repeated start example using xiicps driver +* in polled mode. The slave used is an EEPROM. +* +* The example is tested with a 2Kb/8Kb serial IIC EEPROM (ST M24C02/M24C08). +* The WP pin of this EEPROM is hardwired to ground in the HW in which this +* was tested. +* This example can be used directly to read upto 16 pages +* from start address in this EEPROM (Since single address byte). +* +* The AddressType should be u8 as the address pointer in the on-board +* EEPROM is 1 bytes. +* +* This code assumes that no Operating System is being used. +* +* @note +* +* The I2C controller does not indicate completion of a receive transfer if HOLD +* bit is set. Due to this errata, repeated start cannot be used if a receive +* transfer is followed by any other transfer. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---- -------- ---------------------------------------------------------
+* 2.1   hk   03/15/10 First release
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xparameters.h" +#include "sleep.h" +#include "xiicps.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 IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID + +/* + * The following constant defines the address of the IIC Slave device on the + * IIC bus. Note that since the address is only 7 bits, this constant is the + * address divided by 2. + */ +#define IIC_SLAVE_ADDR 0x54 +#define IIC_SCLK_RATE 100000 +#define IIC_MUX_ADDRESS 0x74 + +/* + * The page size determines how much data should be written at a time. + * The write function should be called with this as a maximum byte count. + */ +#define PAGE_SIZE 16 + +/* + * The Starting address in the IIC EEPROM on which this test is performed. + */ +#define EEPROM_START_ADDRESS 0 + +/**************************** Type Definitions *******************************/ + +/* + * The AddressType should be u8 as the address pointer in the on-board + * EEPROM is 1 bytes. + */ +typedef u8 AddressType; + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +int IicPsRepeatedStartExample(void); +int EepromWriteData(u16 ByteCount); +int MuxInit(void); +int EepromReadDataRepStart(u8 *BufferPtr, u16 ByteCount); + +/************************** Variable Definitions *****************************/ + +XIicPs IicInstance; /* The instance of the IIC device. */ + +/* + * Write buffer for writing a page. + */ +u8 WriteBuffer[sizeof(AddressType) + PAGE_SIZE]; + +u8 ReadBuffer[PAGE_SIZE*20]; /* Read buffer for reading a page. */ + +/************************** Function Definitions *****************************/ + +/*****************************************************************************/ +/** +* Main function to call the Iic repeated start example. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("IIC Repeated Start Example Test \r\n"); + + /* + * Run the Iic repeated start example. + * Refer to note in the header - repeated start cannot be used + * if read transfer is followed by any other transfer. + */ + Status = IicPsRepeatedStartExample(); + if (Status != XST_SUCCESS) { + xil_printf("IIC Repeated Start Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran IIC Repeated Start Example Test\r\n"); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function writes, reads, and verifies the data to the IIC EEPROM. +* Page write is used. Buffered read with repeated start option is done. +* +* @param None. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int IicPsRepeatedStartExample(void) +{ + u32 Index; + int Status; + XIicPs_Config *ConfigPtr; /* Pointer to configuration data */ + AddressType Address = EEPROM_START_ADDRESS; + AddressType AddressTemp; + int PageCnt; + int NumPages = 16; + + /* + * Initialize the IIC driver so that it is ready to use. + */ + ConfigPtr = XIicPs_LookupConfig(IIC_DEVICE_ID); + if (ConfigPtr == NULL) { + return XST_FAILURE; + } + + Status = XIicPs_CfgInitialize(&IicInstance, ConfigPtr, + ConfigPtr->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Set the IIC serial clock rate. + */ + XIicPs_SetSClk(&IicInstance, IIC_SCLK_RATE); + + /* + * Set the channel value in IIC Mux. + */ + Status = MuxInit(); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + AddressTemp = Address; + for(PageCnt = 0; PageCnt < NumPages; PageCnt++) { + /* + * Initialize the data to write and the read buffer. + */ + if (sizeof(AddressTemp) == 1) { + WriteBuffer[0] = (u8) (AddressTemp); + } else { + WriteBuffer[0] = (u8) (AddressTemp >> 8); + WriteBuffer[1] = (u8) (AddressTemp); + } + + for (Index = 0; Index < PAGE_SIZE; Index++) { + WriteBuffer[sizeof(AddressTemp) + Index] = 0xFF; + ReadBuffer[Index] = 0; + } + + /* + * Write to the EEPROM. + */ + Status = EepromWriteData(sizeof(AddressTemp) + PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + AddressTemp += PAGE_SIZE; + } + + /* + * Read from the EEPROM. + */ + Status = EepromReadDataRepStart(ReadBuffer, PAGE_SIZE*NumPages); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Verify the data read against the data written. + */ + for (Index = 0; Index < PAGE_SIZE*NumPages; Index++) { + if (ReadBuffer[Index] != + WriteBuffer[Index%PAGE_SIZE + sizeof(Address)]) { + return XST_FAILURE; + } + + ReadBuffer[Index] = 0; + } + + AddressTemp = Address; + for(PageCnt = 0; PageCnt < NumPages; PageCnt++) { + /* + * Initialize the data to write and the read buffer. + */ + if (sizeof(AddressTemp) == 1) { + WriteBuffer[0] = (u8) (AddressTemp); + } else { + WriteBuffer[0] = (u8) (AddressTemp >> 8); + WriteBuffer[1] = (u8) (AddressTemp); + } + + for (Index = 0; Index < PAGE_SIZE; Index++) { + WriteBuffer[sizeof(AddressTemp) + Index] = Index + 10; + ReadBuffer[Index] = 0; + } + + /* + * Write to the EEPROM. + */ + Status = EepromWriteData(sizeof(AddressTemp) + PAGE_SIZE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + AddressTemp += PAGE_SIZE; + } + + /* + * Read from the EEPROM. + */ + Status = EepromReadDataRepStart(ReadBuffer, PAGE_SIZE*NumPages); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Verify the data read against the data written. + */ + for (Index = 0; Index < PAGE_SIZE*NumPages; Index++) { + if (ReadBuffer[Index] != + WriteBuffer[Index%PAGE_SIZE + sizeof(Address)]) { + return XST_FAILURE; + } + + ReadBuffer[Index] = 0; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function writes a buffer of data to the IIC serial EEPROM. +* +* @param ByteCount contains the number of bytes in the buffer to be +* written. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note The Byte count should not exceed the page size of the EEPROM as +* noted by the constant PAGE_SIZE. +* +******************************************************************************/ +int EepromWriteData(u16 ByteCount) +{ + int Status; + + /* + * Send the Data. + */ + Status = XIicPs_MasterSendPolled(&IicInstance, WriteBuffer, + ByteCount, IIC_SLAVE_ADDR); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait until bus is idle to start another transfer. + */ + if (!(IicInstance.IsRepeatedStart)) { + while (XIicPs_BusIsBusy(&IicInstance)); + } + + /* + * Wait for a bit of time to allow the programming to complete + */ + usleep(250000); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function reads data from the IIC serial EEPROM into a specified buffer. +* +* @param BufferPtr contains the address of the data buffer to be filled. +* @param ByteCount contains the number of bytes in the buffer to be read. +* +* @return XST_SUCCESS if successful else XST_FAILURE. +* +* @note None. +* +******************************************************************************/ +int EepromReadDataRepStart(u8 *BufferPtr, u16 ByteCount) +{ + int Status; + AddressType Address = EEPROM_START_ADDRESS; + + /* + * Enable repeated start option. + * This call will give an indication to the driver. + * The hold bit is actually set before beginning the following transfer + */ + XIicPs_SetOptions(&IicInstance, XIICPS_REP_START_OPTION); + + /* + * Position the Pointer in EEPROM. + */ + if (sizeof(Address) == 1) { + WriteBuffer[0] = (u8) (Address); + } + else { + WriteBuffer[0] = (u8) (Address >> 8); + WriteBuffer[1] = (u8) (Address); + } + + Status = EepromWriteData(sizeof(Address)); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Disbale repeated start option. + * This call will give an indication to the driver. + * The hold bit is actually reset when the following transfer ends. + */ + XIicPs_ClearOptions(&IicInstance, XIICPS_REP_START_OPTION); + + /* + * Receive the Data. + */ + Status = XIicPs_MasterRecvPolled(&IicInstance, BufferPtr, + ByteCount, IIC_SLAVE_ADDR); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function initializes the IIC MUX to select EEPROM. +* +* @param None. +* +* @return XST_SUCCESS if pass, otherwise XST_FAILURE. +* +* @note None. +* +****************************************************************************/ +int MuxInit(void) +{ + u8 WriteBuffer; + u8 MuxIicAddr = IIC_MUX_ADDRESS; + u8 Buffer = 0; + int Status = 0; + + /* + * Channel select value for EEPROM. + */ + WriteBuffer = 0x04; + + /* + * Send the Data. + */ + Status = XIicPs_MasterSendPolled(&IicInstance, &WriteBuffer,1, + MuxIicAddr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + /* + * Receive the Data. + */ + Status = XIicPs_MasterRecvPolled(&IicInstance, &Buffer,1, MuxIicAddr); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait until bus is idle to start another transfer. + */ + while (XIicPs_BusIsBusy(&IicInstance)); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_selftest_example.c b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_selftest_example.c new file mode 100644 index 00000000..e3c9d1d5 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_selftest_example.c @@ -0,0 +1,154 @@ +/****************************************************************************** +* +* 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 xiicps_selftest_example.c + * + * This file contains a example for using the IIC hardware device and + * XIicPs driver. + * + * + *
 MODIFICATION HISTORY:
+ *
+ * Ver	 Who Date    	Changes
+ * ----- --- -------- 	-----------------------------------------------
+ * 1.00a sdm 05/30/11 	First release
+ *
+ * 
+ * + ****************************************************************************/ + +/***************************** Include Files **********************************/ +#include "xparameters.h" +#include "xiicps.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 IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID + + +/**************************** Type Definitions ********************************/ + +/************************** Function Prototypes *******************************/ + +int IicPsSelfTestExample(u16 DeviceId); + +/************************** Variable Definitions ******************************/ + +XIicPs Iic; /* Instance of the IIC Device */ + +/******************************************************************************/ +/** +* +* Main function to call the Self Test example. +* +* @param None. +* +* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful. +* +* @note None. +* +*******************************************************************************/ +#ifndef TESTAPP_GEN +int main(void) +{ + int Status; + + xil_printf("IIC Self Test Example \r\n"); + + /* + * Run the Iic Self Test example, specify the Device ID that is + * generated in xparameters.h + */ + Status = IicPsSelfTestExample(IIC_DEVICE_ID); + if (Status != XST_SUCCESS) { + xil_printf("IIC Self Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran IIC Self Test Example Test\r\n"); + return XST_SUCCESS; +} +#endif + +/*****************************************************************************/ +/** +* +* This function does a minimal test on the Iic device and driver as a +* design example. The purpose of this function is to illustrate +* how to use the XIicPs component. +* +* +* @param DeviceId is the Device ID of the IicPs Device and is the +* XPAR__DEVICE_ID value from xparameters.h +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +* +*******************************************************************************/ +int IicPsSelfTestExample(u16 DeviceId) +{ + int Status; + XIicPs_Config *Config; + + /* + * Initialize the IIC driver so that it's ready to use + * Look up the configuration in the config table, then initialize it. + */ + Config = XIicPs_LookupConfig(DeviceId); + if (NULL == Config) { + return XST_FAILURE; + } + + Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test. + */ + Status = XIicPs_SelfTest(&Iic); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_slave_monitor_example.c b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_slave_monitor_example.c new file mode 100644 index 00000000..02a1c505 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/examples/xiicps_slave_monitor_example.c @@ -0,0 +1,354 @@ +/****************************************************************************** +* +* 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 xiicps_slave_monitor_example.c + * + * A design example of using the device as master to check slave's + * availability. + * + * @note + * Please set the slave address to 0x3FB, which tests the device's ability + * to handle 10-bit address. + * + *
 MODIFICATION HISTORY:
+ *
+ * Ver   Who Date     Changes
+ * ----- --- -------- -----------------------------------------------
+ * 1.00a jz  01/30/10 First release
+ *
+ * 
+ * + ****************************************************************************/ + +/***************************** Include Files **********************************/ +#include "xparameters.h" +#include "xiicps.h" +#include "xscugic.h" +#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 IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID +#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID +#define IIC_INT_VEC_ID XPAR_XIICPS_0_INTR + +/* + * The slave address to send to and receive from. + */ +#define IIC_SLAVE_ADDR 0x3FB +#define IIC_SCLK_RATE 100000 + +/* + * This timeout interval is used in polling mode transfers. + * Please increase the timeout limit on faster systems to avoid + * unintended timeout failure. + */ +#define POLL_TIME_OUT 2000000 /**< Time out count for polled transfer*/ + +/**************************** Type Definitions ********************************/ + +/************************** Function Prototypes *******************************/ + +int IicPsSlaveMonitorExample(u16 DeviceId); + +static int SetupInterruptSystem(XIicPs *IicPsPtr); + +void Handler(void *CallBackRef, u32 Event); + +/************************** Variable Definitions ******************************/ + +XIicPs Iic; /* Instance of the IIC Device */ +XScuGic InterruptController; /* Instance of the Interrupt Controller */ + +/* + * The following counters are used to determine when the entire buffer has + * been sent and received. + */ +volatile int SlaveReady; +volatile int TotalError; + +/******************************************************************************/ +/** +* +* Main function to call the Slave Monitor example. +* +* @param None. +* +* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful. +* +* @note None. +* +*******************************************************************************/ +int main(void) +{ + int Status; + + xil_printf("IIC Slave Monitor Example Test \r\n"); + + /* + * Run the Iic Slave Monitor example, specify the Device ID that is + * generated in xparameters.h. + */ + Status = IicPsSlaveMonitorExample(IIC_DEVICE_ID); + if (Status != XST_SUCCESS) { + xil_printf("IIC Slave Monitor Example Test Failed\r\n"); + return XST_FAILURE; + } + + xil_printf("Successfully ran IIC Slave Monitor Example Test\r\n"); + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function checks the availability of a slave using slave monitor mode. +* +* @param DeviceId is the Device ID of the IicPs Device and is the +* XPAR__DEVICE_ID value from xparameters.h +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +*******************************************************************************/ +int IicPsSlaveMonitorExample(u16 DeviceId) +{ + int Status; + int Timeout; + XIicPs_Config *Config; + + /* + * Initialize the IIC driver so that it's ready to use + * Look up the configuration in the config table, + * then initialize it. + */ + Config = XIicPs_LookupConfig(DeviceId); + if (NULL == Config) { + return XST_FAILURE; + } + + Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Perform a self-test to ensure that the hardware was built correctly. + */ + Status = XIicPs_SelfTest(&Iic); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Connect the IIC to the interrupt subsystem such that interrupts can + * occur. This function is application specific. + */ + Status = SetupInterruptSystem(&Iic); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Setup the handlers for the IIC that will be called from the + * interrupt context when slave response to the address transfer. + */ + XIicPs_SetStatusHandler(&Iic, (void *) &Iic, Handler); + + /* + * Set 10-bit address mode. + */ + XIicPs_SetOptions(&Iic, XIICPS_10_BIT_ADDR_OPTION); + + /* + * Set the IIC serial clock rate. + */ + Status = XIicPs_SetSClk(&Iic, IIC_SCLK_RATE); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * Wait for the bus to be idle. + */ + while (XIicPs_BusIsBusy(&Iic)) { + /* NOP */ + } + + XIicPs_EnableSlaveMonitor(&Iic, IIC_SLAVE_ADDR); + + TotalError= 0; + SlaveReady = FALSE; + + Timeout = POLL_TIME_OUT; + + /* + * Wait for the Slave Monitor Interrupt, the interrupt processing + * works in the background, this function may get locked up in this + * loop if the interrupts are not working correctly or the slave + * never responds. + */ + while ((!SlaveReady) && (Timeout > 0)) { + Timeout --; + /* + * Ignore any errors. The hardware generates NACK interrupts + * if the slave is not present. + */ + if (0 != TotalError) { + return XST_FAILURE; + } + + } + + if (Timeout == 0) { + return XST_FAILURE; + } + + XIicPs_DisableSlaveMonitor(&Iic); + + /* + * Clear 10-bit address mode. + */ + XIicPs_ClearOptions(&Iic, XIICPS_10_BIT_ADDR_OPTION); + + return XST_SUCCESS; +} +/*****************************************************************************/ +/** +* +* This function is the handler which performs processing to handle data events +* from the IIC. It is called from an interrupt context such that the amount +* of processing performed should be minimized. +* +* This handler provides an example of how to handle data for the IIC and +* is application specific. +* +* @param CallBackRef contains a callback reference from the driver, +* in this case it is the instance pointer for the IIC driver. +* @param Event contains the specific kind of event that has occurred. +* +* @return None. +* +* @note None. +* +*******************************************************************************/ +void Handler(void *CallBackRef, u32 Event) +{ + if (0 != (Event & XIICPS_EVENT_SLAVE_RDY)){ + SlaveReady = TRUE; + return; + } + TotalError += 1; + + return; +} + +/******************************************************************************/ +/** +* +* This function setups the interrupt system such that interrupts can occur +* for the IIC. This function is application specific since the actual +* system may or may not have an interrupt controller. The IIC could be +* directly connected to a processor without an interrupt controller. The +* user should modify this function to fit the application. +* +* @param IicPsPtr contains a pointer to the instance of the Iic +* which is going to be connected to the interrupt controller. +* +* @return XST_SUCCESS if successful, otherwise XST_FAILURE. +* +* @note None. +* +*******************************************************************************/ +static int SetupInterruptSystem(XIicPs *IicPsPtr) +{ + int Status; + XScuGic_Config *IntcConfig; + + 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(&InterruptController, 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_IRQ_INT, + (Xil_ExceptionHandler)XScuGic_InterruptHandler, + &InterruptController); + + /* + * 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(&InterruptController, IIC_INT_VEC_ID, + (Xil_InterruptHandler)XIicPs_MasterInterruptHandler, + (void *)IicPsPtr); + if (Status != XST_SUCCESS) { + return Status; + } + + /* + * Enable the interrupt for the Iic device. + */ + XScuGic_Enable(&InterruptController, IIC_INT_VEC_ID); + + + /* + * Enable interrupts in the Processor. + */ + Xil_ExceptionEnable(); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/src/Makefile b/XilinxProcessorIPLib/drivers/iicps/src/Makefile new file mode 100644 index 00000000..8c16c35a --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/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 xiicps_libs clean + +%.o: %.c + ${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) -o $@ $< + +banner: + echo "Compiling iicps" + +xiicps_libs: ${OBJECTS} + $(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OBJECTS} + +.PHONY: include +include: xiicps_includes + +xiicps_includes: + ${CP} ${INCLUDEFILES} ${INCLUDEDIR} + +clean: + rm -rf ${OBJECTS} diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps.c b/XilinxProcessorIPLib/drivers/iicps/src/xiicps.c new file mode 100644 index 00000000..a1876bec --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps.c @@ -0,0 +1,326 @@ +/****************************************************************************** +* +* 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 xiicps.c +* +* Contains implementation of required functions for the XIicPs driver. +* See xiicps.h for detailed description of the device and driver. +* +*
 MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------  -------- --------------------------------------------
+* 1.00a drg/jz  01/30/10 First release
+* 1.00a sdm     09/21/11 Updated the InstancePtr->Options in the
+*			 XIicPs_CfgInitialize by calling XIicPs_GetOptions.
+* 2.1   hk      04/25/14 Explicitly reset CR and clear FIFO in Abort function
+*                        and state the same in the comments. CR# 784254.
+*                        Fix for CR# 761060 - provision for repeated start.
+* 2.3	sk		10/07/14 Repeated start feature removed.
+* 2.4	sk		11/03/14 Modified TimeOut Register value to 0xFF
+* 						 in XIicPs_Reset.
+*				12/06/14 Implemented Repeated start feature.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xiicps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +static void StubHandler(void *CallBackRef, u32 StatusEvent); + +/************************** Variable Definitions *****************************/ + + +/*****************************************************************************/ +/** +* +* Initializes a specific XIicPs instance such that the driver is ready to use. +* +* The state of the device after initialization is: +* - Device is disabled +* - Slave mode +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param ConfigPtr is a reference to a structure containing information +* about a specific IIC device. This function initializes an +* InstancePtr object for a specific device specified by the +* contents of Config. +* @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->BaseAddress for this parameter, passing the physical +* address instead. +* +* @return The return value is XST_SUCCESS if successful. +* +* @note None. +* +******************************************************************************/ +int XIicPs_CfgInitialize(XIicPs *InstancePtr, XIicPs_Config *ConfigPtr, + u32 EffectiveAddr) +{ + /* + * Assert validates the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(ConfigPtr != NULL); + + /* + * Set some default values. + */ + InstancePtr->Config.DeviceId = ConfigPtr->DeviceId; + InstancePtr->Config.BaseAddress = EffectiveAddr; + InstancePtr->Config.InputClockHz = ConfigPtr->InputClockHz; + InstancePtr->StatusHandler = StubHandler; + InstancePtr->CallBackRef = NULL; + + InstancePtr->IsReady = XIL_COMPONENT_IS_READY; + + /* + * Reset the IIC 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. + */ + XIicPs_Reset(InstancePtr); + + /* + * Keep a copy of what options this instance has. + */ + InstancePtr->Options = XIicPs_GetOptions(InstancePtr); + + /* Initialize repeated start flag to 0 */ + InstancePtr->IsRepeatedStart = 0; + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* Check whether the I2C bus is busy +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return +* - TRUE if the bus is busy. +* - FALSE if the bus is not busy. +* +* @note None. +* +******************************************************************************/ +int XIicPs_BusIsBusy(XIicPs *InstancePtr) +{ + u32 StatusReg; + + StatusReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_SR_OFFSET); + if (StatusReg & XIICPS_SR_BA_MASK) { + return TRUE; + }else { + return FALSE; + } +} + +/*****************************************************************************/ +/** +* +* 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 StubHandler(void *CallBackRef, u32 StatusEvent) +{ + (void) CallBackRef; + (void) StatusEvent; + Xil_AssertVoidAlways(); +} + + +/*****************************************************************************/ +/** +* +* Aborts a transfer in progress by resetting the FIFOs. The byte counts are +* cleared. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIicPs_Abort(XIicPs *InstancePtr) +{ + u32 IntrMaskReg; + u32 IntrStatusReg; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Enter a critical section, so disable the interrupts while we clear + * the FIFO and the status register. + */ + IntrMaskReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_IMR_OFFSET); + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, + XIICPS_IDR_OFFSET, XIICPS_IXR_ALL_INTR_MASK); + + /* + * Reset the settings in config register and clear the FIFOs. + */ + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET, + XIICPS_CR_RESET_VALUE | XIICPS_CR_CLR_FIFO_MASK); + + /* + * Read, then write the interrupt status to make sure there are no + * pending interrupts. + */ + IntrStatusReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_ISR_OFFSET); + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, + XIICPS_ISR_OFFSET, IntrStatusReg); + + /* + * Restore the interrupt state. + */ + IntrMaskReg = XIICPS_IXR_ALL_INTR_MASK & (~IntrMaskReg); + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, + XIICPS_IER_OFFSET, IntrMaskReg); + +} + +/*****************************************************************************/ +/** +* +* Resets the IIC 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 reenabling interrupts for the IIC device after the reset. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return None. +* +* @note None. +* +******************************************************************************/ +void XIicPs_Reset(XIicPs *InstancePtr) +{ + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Abort any transfer that is in progress. + */ + XIicPs_Abort(InstancePtr); + + /* + * Reset any values so the software state matches the hardware device. + */ + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET, + XIICPS_CR_RESET_VALUE); + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, + XIICPS_TIME_OUT_OFFSET, XIICPS_TO_RESET_VALUE); + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_IDR_OFFSET, + XIICPS_IXR_ALL_INTR_MASK); + +} +/*****************************************************************************/ +/** +* Put more data into the transmit FIFO, number of bytes is ether expected +* number of bytes for this transfer or available space in FIFO, which ever +* is less. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return Number of bytes left for this instance. +* +* @note This is function is shared by master and slave. +* +******************************************************************************/ +int TransmitFifoFill(XIicPs *InstancePtr) +{ + u8 AvailBytes; + int LoopCnt; + int NumBytesToSend; + + /* + * Determine number of bytes to write to FIFO. + */ + AvailBytes = XIICPS_FIFO_DEPTH - + XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_TRANS_SIZE_OFFSET); + + if (InstancePtr->SendByteCount > AvailBytes) { + NumBytesToSend = AvailBytes; + } else { + NumBytesToSend = InstancePtr->SendByteCount; + } + + /* + * Fill FIFO with amount determined above. + */ + for (LoopCnt = 0; LoopCnt < NumBytesToSend; LoopCnt++) { + XIicPs_SendByte(InstancePtr); + } + + return InstancePtr->SendByteCount; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps.h b/XilinxProcessorIPLib/drivers/iicps/src/xiicps.h new file mode 100644 index 00000000..3c7420e9 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps.h @@ -0,0 +1,405 @@ +/****************************************************************************** +* +* 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 xiicps.h +* +* This is an implementation of IIC driver in the PS block. The device can +* be either a master or a slave on the IIC bus. This implementation supports +* both interrupt mode transfer and polled mode transfer. Only 7-bit address +* is used in the driver, although the hardware also supports 10-bit address. +* +* IIC is a 2-wire serial interface. 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. +* +* The higher level software must implement a higher layer protocol to inform +* the slave what to send to the master. +* +* Initialization & Configuration +* +* The XIicPs_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: +* +* - XIicPs_LookupConfig(DeviceId) - Use the device identifier to find +* the static configuration structure defined in xiicps_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. +* +* - XIicPs_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 in the configuration +* structure. +* +* Multiple Masters +* +* More than one master can exist, bus arbitration is defined in the IIC +* standard. Lost of arbitration causes arbitration loss interrupt on the device. +* +* Multiple Slaves +* +* Multiple slaves are supported by selecting them with unique addresses. It is +* up to the system designer to be sure all devices on the IIC bus have +* unique addresses. +* +* Addressing +* +* The IIC hardware can use 7 or 10 bit addresses. The driver provides the +* ability to control which address size is sent in messages as a master to a +* slave device. +* +* FIFO Size +* The hardware FIFO is 32 bytes deep. The user must know the limitations of +* other IIC devices on the bus. Some are only able to receive a limited number +* of bytes in a single transfer. +* +* Data Rates +* +* The data rate is set by values in the control register. The formula for +* determining the correct register values is: +* Fscl = Fpclk/(22 x (divisor_a+1) x (divisor_b+1)) +* +* When the device is configured as a slave, the slck setting controls the +* sample rate and so must be set to be at least as fast as the fastest scl +* expected to be seen in the system. +* +* Polled Mode Operation +* +* This driver supports polled mode transfers. +* +* Interrupts +* +* The user must connect the interrupt handler of the driver, +* XIicPs_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: +* - Transfer complete +* - More Data +* - Transfer not Acknowledged +* - Transfer Time out +* - Monitored slave ready - master mode only +* - Receive Overflow +* - Transmit FIFO overflow +* - Receive FIFO underflow +* - Arbitration lost +* +* Bus Busy +* +* Bus busy is checked before the setup of a master mode device, to avoid +* unnecessary arbitration loss interrupt. +* +* 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. +* +*Repeated Start +* +* The I2C controller does not indicate completion of a receive transfer if HOLD +* bit is set. Due to this errata, repeated start cannot be used if a receive +* transfer is followed by any other transfer. +* +*
 MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------  -------- -----------------------------------------------
+* 1.00a drg/jz  01/30/08 First release
+* 1.00a sdm     09/21/11 Fixed an issue in the XIicPs_SetOptions and
+*			 XIicPs_ClearOptions where the InstancePtr->Options
+*			 was not updated correctly.
+* 			 Updated the InstancePtr->Options in the
+*			 XIicPs_CfgInitialize by calling XIicPs_GetOptions.
+*			 Updated the XIicPs_SetupMaster to not check for
+*			 Bus Busy condition when the Hold Bit is set.
+*			 Removed some unused variables.
+* 1.01a sg      03/30/12 Fixed an issue in XIicPs_MasterSendPolled where a
+*			 check for transfer completion is added, which indicates
+*			 the completion of current transfer.
+* 1.02a sg	08/29/12 Updated the logic to arrive at the best divisors
+*			 to achieve I2C clock with minimum error for
+*			 CR #674195
+* 1.03a hk  05/04/13 Initialized BestDivA and BestDivB to 0.
+*			 This is fix for CR#704398 to remove warning.
+* 2.0   hk  03/07/14 Added check for error status in the while loop that
+*                    checks for completion.
+*                    (XIicPs_MasterSendPolled function). CR# 762244, 764875.
+*                    Limited frequency set when 100KHz or 400KHz is
+*                    selected. This is a hardware limitation. CR#779290.
+* 2.1   hk  04/24/14 Fix for CR# 789821 to handle >14 byte transfers.
+*                    Explicitly reset CR and clear FIFO in Abort function
+*                    and state the same in the comments. CR# 784254.
+*                    Fix for CR# 761060 - provision for repeated start.
+* 2.2   hk  08/23/14 Slave monitor mode changes - clear FIFO, enable
+*                    read mode and clear transfer size register.
+*                    Disable NACK to avoid interrupts on each retry.
+* 2.3	sk	10/07/14 Repeated start feature deleted.
+* 2.4	sk	11/03/14 Modified TimeOut Register value to 0xFF
+* 					 in XIicPs_Reset.
+* 			12/06/14 Implemented Repeated start feature.
+*
+* 
+* +******************************************************************************/ + +#ifndef XIICPS_H /* prevent circular inclusions */ +#define XIICPS_H /* by using protection macros */ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************** Include Files *********************************/ + +#include "xil_types.h" +#include "xil_assert.h" +#include "xstatus.h" +#include "xiicps_hw.h" + +/************************** Constant Definitions *****************************/ + +/** @name Configuration options + * + * The following options may be specified or retrieved for the device and + * enable/disable additional features of the IIC. Each of the options + * are bit fields, so more than one may be specified. + * + * @{ + */ +#define XIICPS_7_BIT_ADDR_OPTION 0x01 /**< 7-bit address mode */ +#define XIICPS_10_BIT_ADDR_OPTION 0x02 /**< 10-bit address mode */ +#define XIICPS_SLAVE_MON_OPTION 0x04 /**< Slave monitor mode */ +#define XIICPS_REP_START_OPTION 0x08 /**< Repeated Start */ +/*@}*/ + +/** @name Callback events + * + * These constants specify the handler events that are passed to an application + * event handler from the driver. These constants are bit masks such that + * more than one event can be passed to the handler. + * + * @{ + */ +#define XIICPS_EVENT_COMPLETE_SEND 0x0001 /**< Transmit Complete Event*/ +#define XIICPS_EVENT_COMPLETE_RECV 0x0002 /**< Receive Complete Event*/ +#define XIICPS_EVENT_TIME_OUT 0x0004 /**< Transfer timed out */ +#define XIICPS_EVENT_ERROR 0x0008 /**< Receive error */ +#define XIICPS_EVENT_ARB_LOST 0x0010 /**< Arbitration lost */ +#define XIICPS_EVENT_NACK 0x0020 /**< NACK Received */ +#define XIICPS_EVENT_SLAVE_RDY 0x0040 /**< Slave ready */ +#define XIICPS_EVENT_RX_OVR 0x0080 /**< RX overflow */ +#define XIICPS_EVENT_TX_OVR 0x0100 /**< TX overflow */ +#define XIICPS_EVENT_RX_UNF 0x0200 /**< RX underflow */ +/*@}*/ + +/** @name Role constants + * + * These constants are used to pass into the device setup routines to + * set up the device according to transfer direction. + */ +#define SENDING_ROLE 1 /**< Transfer direction is sending */ +#define RECVING_ROLE 0 /**< Transfer direction is receiving */ + +/* Maximum transfer size */ +#define XIICPS_MAX_TRANSFER_SIZE (255 - 3) + +/**************************** Type Definitions *******************************/ + +/** +* The handler data type allows the user to define a callback function to +* respond to interrupt events in the system. This function is executed +* in interrupt context, so amount of processing should be minimized. +* +* @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 indicates one or more status events that occurred. +*/ +typedef void (*XIicPs_IntrHandler) (void *CallBackRef, u32 StatusEvent); + +/** + * 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 */ +} XIicPs_Config; + +/** + * The XIicPs driver instance data. The user is required to allocate a + * variable of this type for each IIC device in the system. A pointer + * to a variable of this type is then passed to the driver API functions. + */ +typedef struct { + XIicPs_Config Config; /* Configuration structure */ + u32 IsReady; /* Device is initialized and ready */ + u32 Options; /* Options set in the device */ + + u8 *SendBufferPtr; /* Pointer to send buffer */ + u8 *RecvBufferPtr; /* Pointer to recv buffer */ + int SendByteCount; /* Number of bytes still expected to send */ + int RecvByteCount; /* Number of bytes still expected to receive */ + int CurrByteCount; /* No. of bytes expected in current transfer */ + + int UpdateTxSize; /* If tx size register has to be updated */ + int IsSend; /* Whether master is sending or receiving */ + int IsRepeatedStart; /* Indicates if user set repeated start */ + + XIicPs_IntrHandler StatusHandler; /* Event handler function */ + void *CallBackRef; /* Callback reference for event handler */ +} XIicPs; + +/***************** Macros (Inline Functions) Definitions *********************/ +/****************************************************************************/ +/* +* +* Place one byte into the transmit FIFO. +* +* @param InstancePtr is the instance of IIC +* +* @return None. +* +* @note C-Style signature: +* void XIicPs_SendByte(XIicPs *InstancePtr) +* +*****************************************************************************/ +#define XIicPs_SendByte(InstancePtr) \ +{ \ + XIicPs_Out32((InstancePtr)->Config.BaseAddress \ + + XIICPS_DATA_OFFSET, \ + *(InstancePtr)->SendBufferPtr ++); \ + (InstancePtr)->SendByteCount --; \ +} + +/****************************************************************************/ +/* +* +* Receive one byte from FIFO. +* +* @param InstancePtr is the instance of IIC +* +* @return None. +* +* @note C-Style signature: +* u8 XIicPs_RecvByte(XIicPs *InstancePtr) +* +*****************************************************************************/ +#define XIicPs_RecvByte(InstancePtr) \ +{ \ + *(InstancePtr)->RecvBufferPtr ++ = \ + (u8)XIicPs_In32((InstancePtr)->Config.BaseAddress \ + + XIICPS_DATA_OFFSET); \ + (InstancePtr)->RecvByteCount --; \ +} + +/************************** Function Prototypes ******************************/ + +/* + * Function for configuration lookup, in xiicps_sinit.c + */ +XIicPs_Config *XIicPs_LookupConfig(u16 DeviceId); + +/* + * Functions for general setup, in xiicps.c + */ +int XIicPs_CfgInitialize(XIicPs *InstancePtr, XIicPs_Config * Config, + u32 EffectiveAddr); + +void XIicPs_Abort(XIicPs *InstancePtr); +void XIicPs_Reset(XIicPs *InstancePtr); + +int XIicPs_BusIsBusy(XIicPs *InstancePtr); + +/* + * Functions for interrupts, in xiicps_intr.c + */ +void XIicPs_SetStatusHandler(XIicPs *InstancePtr, void *CallBackRef, + XIicPs_IntrHandler FuncPtr); + +/* + * Functions for device as master, in xiicps_master.c + */ +void XIicPs_MasterSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, + u16 SlaveAddr); +void XIicPs_MasterRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, + u16 SlaveAddr); +int XIicPs_MasterSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, + u16 SlaveAddr); +int XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, + u16 SlaveAddr); +void XIicPs_EnableSlaveMonitor(XIicPs *InstancePtr, u16 SlaveAddr); +void XIicPs_DisableSlaveMonitor(XIicPs *InstancePtr); +void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr); + +/* + * Functions for device as slave, in xiicps_slave.c + */ +void XIicPs_SetupSlave(XIicPs *InstancePtr, u16 SlaveAddr); +void XIicPs_SlaveSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount); +void XIicPs_SlaveRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount); +int XIicPs_SlaveSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount); +int XIicPs_SlaveRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount); +void XIicPs_SlaveInterruptHandler(XIicPs *InstancePtr); + +/* + * Functions for selftest, in xiicps_selftest.c + */ +int XIicPs_SelfTest(XIicPs *InstancePtr); + +/* + * Functions for setting and getting data rate, in xiicps_options.c + */ +int XIicPs_SetOptions(XIicPs *InstancePtr, u32 Options); +int XIicPs_ClearOptions(XIicPs *InstancePtr, u32 Options); +u32 XIicPs_GetOptions(XIicPs *InstancePtr); + +int XIicPs_SetSClk(XIicPs *InstancePtr, u32 FsclHz); +u32 XIicPs_GetSClk(XIicPs *InstancePtr); + +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps_g.c b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_g.c new file mode 100644 index 00000000..05db9eea --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_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 xiicps_g.c +* +* This file contains a configuration table that specifies the configuration of +* IIC devices in the system. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------  -------- --------------------------------------------
+* 1.00a drg/jz  01/30/10 First release
+* 2.00  hk   22/01/14 Added check for picking second instance
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xparameters.h" +#include "xiicps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + + +/************************** Variable Prototypes ******************************/ + +/** + * This table contains configuration information for each IIC device + * in the system. + */ +XIicPs_Config XIicPs_ConfigTable[XPAR_XIICPS_NUM_INSTANCES] = { + { + XPAR_XIICPS_0_DEVICE_ID, /* Device ID for instance */ + XPAR_XIICPS_0_BASEADDR, /* Device base address */ + XPAR_XIICPS_0_I2C_CLK_FREQ_HZ /* Device input clock frequency */ + }, +#ifdef XPAR_XIICPS_1_DEVICE_ID + { + XPAR_XIICPS_1_DEVICE_ID, /* Device ID for instance */ + XPAR_XIICPS_1_BASEADDR, /* Device base address */ + XPAR_XIICPS_1_CLOCK_HZ /* Device input clock frequency */ + } +#endif +}; diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps_hw.c b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_hw.c new file mode 100644 index 00000000..66b221d3 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_hw.c @@ -0,0 +1,107 @@ +/****************************************************************************** +* +* 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 xiicps_hw.c +* +* Contains implementation of required functions for providing the reset sequence +* to the i2c interface +* +*
 MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------  -------- --------------------------------------------
+* 1.04a kpc     11/07/13 First release
+* 2.4	sk		11/03/14 Modified TimeOut Register value to 0xFF
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xiicps_hw.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +/*****************************************************************************/ +/** +* This function perform the reset sequence to the given I2c interface by +* configuring the appropriate control bits in the I2c specifc registers +* the i2cps reset squence involves the following steps +* Disable all the interuupts +* Clear the status +* Clear FIFO's and disable hold bit +* Clear the line status +* Update relevant config registers with reset values +* +* @param BaseAddress of the interface +* +* @return N/A +* +* @note +* This function will not modify the slcr registers that are relavant for +* I2c controller +******************************************************************************/ +void XIicPs_ResetHw(u32 BaseAddress) +{ + u32 RegVal; + + /* Disable all the interrupts */ + XIicPs_WriteReg(BaseAddress, XIICPS_IDR_OFFSET, XIICPS_IXR_ALL_INTR_MASK); + /* Clear the interrupt status */ + RegVal = XIicPs_ReadReg(BaseAddress,XIICPS_ISR_OFFSET); + XIicPs_WriteReg(BaseAddress, XIICPS_ISR_OFFSET, RegVal); + /* Clear the hold bit,master enable bit and ack bit */ + RegVal = XIicPs_ReadReg(BaseAddress,XIICPS_CR_OFFSET); + RegVal &= ~(XIICPS_CR_HOLD_MASK|XIICPS_CR_MS_MASK|XIICPS_CR_ACKEN_MASK); + /* Clear the fifos */ + RegVal |= XIICPS_CR_CLR_FIFO_MASK; + XIicPs_WriteReg(BaseAddress, XIICPS_CR_OFFSET, RegVal); + /* Clear the timeout register */ + XIicPs_WriteReg(BaseAddress, XIICPS_TIME_OUT_OFFSET, XIICPS_TO_RESET_VALUE); + /* Clear the transfer size register */ + XIicPs_WriteReg(BaseAddress, XIICPS_TRANS_SIZE_OFFSET, 0x0); + /* Clear the status register */ + RegVal = XIicPs_ReadReg(BaseAddress,XIICPS_SR_OFFSET); + XIicPs_WriteReg(BaseAddress, XIICPS_SR_OFFSET, RegVal); + /* Update the configuraqtion register with reset value */ + XIicPs_WriteReg(BaseAddress, XIICPS_CR_OFFSET, 0x0); +} diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps_hw.h b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_hw.h new file mode 100644 index 00000000..ca6e980b --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_hw.h @@ -0,0 +1,379 @@ +/****************************************************************************** +* +* 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 xiicps_hw.h +* +* This header file contains the hardware definition for an IIC device. +* It includes register definitions and interface functions to read/write +* the registers. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who 	Date     Changes
+* ----- ------  -------- -----------------------------------------------
+* 1.00a drg/jz  01/30/10 First release
+* 1.04a kpc		11/07/13 Added function prototype.
+* 2.4	sk		11/03/14 Modified the TimeOut Register value to 0xFF
+* 
+* +******************************************************************************/ +#ifndef XIICPS_HW_H /* prevent circular inclusions */ +#define XIICPS_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 for the IIC. + * @{ + */ +#define XIICPS_CR_OFFSET 0x00 /**< 32-bit Control */ +#define XIICPS_SR_OFFSET 0x04 /**< Status */ +#define XIICPS_ADDR_OFFSET 0x08 /**< IIC Address */ +#define XIICPS_DATA_OFFSET 0x0C /**< IIC FIFO Data */ +#define XIICPS_ISR_OFFSET 0x10 /**< Interrupt Status */ +#define XIICPS_TRANS_SIZE_OFFSET 0x14 /**< Transfer Size */ +#define XIICPS_SLV_PAUSE_OFFSET 0x18 /**< Slave monitor pause */ +#define XIICPS_TIME_OUT_OFFSET 0x1C /**< Time Out */ +#define XIICPS_IMR_OFFSET 0x20 /**< Interrupt Enabled Mask */ +#define XIICPS_IER_OFFSET 0x24 /**< Interrupt Enable */ +#define XIICPS_IDR_OFFSET 0x28 /**< Interrupt Disable */ +/* @} */ + +/** @name Control Register + * + * This register contains various control bits that + * affects the operation of the IIC controller. Read/Write. + * @{ + */ + +#define XIICPS_CR_DIV_A_MASK 0x0000C000 /**< Clock Divisor A */ +#define XIICPS_CR_DIV_A_SHIFT 14 /**< Clock Divisor A shift */ +#define XIICPS_DIV_A_MAX 4 /**< Maximum value of Divisor A */ +#define XIICPS_CR_DIV_B_MASK 0x00003F00 /**< Clock Divisor B */ +#define XIICPS_CR_DIV_B_SHIFT 8 /**< Clock Divisor B shift */ +#define XIICPS_CR_CLR_FIFO_MASK 0x00000040 /**< Clear FIFO, auto clears*/ +#define XIICPS_CR_SLVMON_MASK 0x00000020 /**< Slave monitor mode */ +#define XIICPS_CR_HOLD_MASK 0x00000010 /**< Hold bus 1=Hold scl, + 0=terminate transfer */ +#define XIICPS_CR_ACKEN_MASK 0x00000008 /**< Enable TX of ACK when + Master receiver*/ +#define XIICPS_CR_NEA_MASK 0x00000004 /**< Addressing Mode 1=7 bit, + 0=10 bit */ +#define XIICPS_CR_MS_MASK 0x00000002 /**< Master mode bit 1=Master, + 0=Slave */ +#define XIICPS_CR_RD_WR_MASK 0x00000001 /**< Read or Write Master + transfer 0=Transmitter, + 1=Receiver*/ +#define XIICPS_CR_RESET_VALUE 0 /**< Reset value of the Control + register */ +/* @} */ + +/** @name IIC Status Register + * + * This register is used to indicate status of the IIC controller. Read only + * @{ + */ +#define XIICPS_SR_BA_MASK 0x00000100 /**< Bus Active Mask */ +#define XIICPS_SR_RXOVF_MASK 0x00000080 /**< Receiver Overflow Mask */ +#define XIICPS_SR_TXDV_MASK 0x00000040 /**< Transmit Data Valid Mask */ +#define XIICPS_SR_RXDV_MASK 0x00000020 /**< Receiver Data Valid Mask */ +#define XIICPS_SR_RXRW_MASK 0x00000008 /**< Receive read/write Mask */ +/* @} */ + +/** @name IIC Address Register + * + * Normal addressing mode uses add[6:0]. Extended addressing mode uses add[9:0]. + * A write access to this register always initiates a transfer if the IIC is in + * master mode. Read/Write + * @{ + */ +#define XIICPS_ADDR_MASK 0x000003FF /**< IIC Address Mask */ +/* @} */ + +/** @name IIC Data Register + * + * When written to, the data register sets data to transmit. When read from, the + * data register reads the last received byte of data. Read/Write + * @{ + */ +#define XIICPS_DATA_MASK 0x000000FF /**< IIC Data Mask */ +/* @} */ + +/** @name IIC Interrupt Registers + * + * IIC Interrupt Status Register + * + * This register holds the interrupt status flags for the IIC controller. Some + * of the flags are level triggered + * - i.e. are set as long as the interrupt condition exists. Other flags are + * edge triggered, which means they are set one the interrupt condition occurs + * then remain set until they are cleared by software. + * The interrupts are cleared by writing a one to the interrupt bit position + * in the Interrupt Status Register. Read/Write. + * + * IIC Interrupt Enable Register + * + * This register is used to enable interrupt sources for the IIC controller. + * Writing a '1' to a bit in this register clears the corresponding bit in the + * IIC Interrupt Mask register. Write only. + * + * IIC Interrupt Disable Register + * + * This register is used to disable interrupt sources for the IIC controller. + * Writing a '1' to a bit in this register sets the corresponding bit in the + * IIC Interrupt Mask register. Write only. + * + * IIC Interrupt Mask Register + * + * This register shows the enabled/disabled status of each IIC controller + * interrupt source. A bit set to 1 will ignore the corresponding interrupt in + * the status register. A bit set to 0 means the interrupt is enabled. + * All mask bits are set and all interrupts are disabled after reset. 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 Interrupt Status Register + * @{ + */ + +#define XIICPS_IXR_ARB_LOST_MASK 0x00000200 /**< Arbitration Lost Interrupt + mask */ +#define XIICPS_IXR_RX_UNF_MASK 0x00000080 /**< FIFO Recieve Underflow + Interrupt mask */ +#define XIICPS_IXR_TX_OVR_MASK 0x00000040 /**< Transmit Overflow + Interrupt mask */ +#define XIICPS_IXR_RX_OVR_MASK 0x00000020 /**< Receive Overflow Interrupt + mask */ +#define XIICPS_IXR_SLV_RDY_MASK 0x00000010 /**< Monitored Slave Ready + Interrupt mask */ +#define XIICPS_IXR_TO_MASK 0x00000008 /**< Transfer Time Out + Interrupt mask */ +#define XIICPS_IXR_NACK_MASK 0x00000004 /**< NACK Interrupt mask */ +#define XIICPS_IXR_DATA_MASK 0x00000002 /**< Data Interrupt mask */ +#define XIICPS_IXR_COMP_MASK 0x00000001 /**< Transfer Complete + Interrupt mask */ +#define XIICPS_IXR_DEFAULT_MASK 0x000002FF /**< Default ISR Mask */ +#define XIICPS_IXR_ALL_INTR_MASK 0x000002FF /**< All ISR Mask */ +/* @} */ + + +/** @name IIC Transfer Size Register +* +* The register's meaning varies according to the operating mode as follows: +* - Master transmitter mode: number of data bytes still not transmitted minus +* one +* - Master receiver mode: number of data bytes that are still expected to be +* received +* - Slave transmitter mode: number of bytes remaining in the FIFO after the +* master terminates the transfer +* - Slave receiver mode: number of valid data bytes in the FIFO +* +* This register is cleared if CLR_FIFO bit in the control register is set. +* Read/Write +* @{ +*/ +#define XIICPS_TRANS_SIZE_MASK 0x0000003F /**< IIC Transfer Size Mask */ +#define XIICPS_FIFO_DEPTH 16 /**< Number of bytes in the FIFO */ +#define XIICPS_DATA_INTR_DEPTH 14 /**< Number of bytes at DATA intr */ +/* @} */ + + +/** @name IIC Slave Monitor Pause Register +* +* This register is associated with the slave monitor mode of the I2C interface. +* It is meaningful only when the module is in master mode and bit SLVMON in the +* control register is set. +* +* This register defines the pause interval between consecutive attempts to +* address the slave once a write to an I2C address register is done by the +* host. It represents the number of sclk cycles minus one between two attempts. +* +* The reset value of the register is 0, which results in the master repeatedly +* trying to access the slave immediately after unsuccessful attempt. +* Read/Write +* @{ +*/ +#define XIICPS_SLV_PAUSE_MASK 0x0000000F /**< Slave monitor pause mask */ +/* @} */ + + +/** @name IIC Time Out Register +* +* The value of time out register represents the time out interval in number of +* sclk cycles minus one. +* +* When the accessed slave holds the sclk line low for longer than the time out +* period, thus prohibiting the I2C interface in master mode to complete the +* current transfer, an interrupt is generated and TO interrupt flag is set. +* +* The reset value of the register is 0x1f. +* Read/Write +* @{ + */ +#define XIICPS_TIME_OUT_MASK 0x000000FF /**< IIC Time Out mask */ +#define XIICPS_TO_RESET_VALUE 0x000000FF /**< IIC Time Out reset value */ +/* @} */ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +#define XIicPs_In32 Xil_In32 +#define XIicPs_Out32 Xil_Out32 + +/****************************************************************************/ +/** +* Read an IIC register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to select the specific register. +* +* @return The value read from the register. +* +* @note C-Style signature: +* u32 XIicPs_ReadReg(u32 BaseAddress. int RegOffset) +* +******************************************************************************/ +#define XIicPs_ReadReg(BaseAddress, RegOffset) \ + XIicPs_In32((BaseAddress) + (RegOffset)) + +/***************************************************************************/ +/** +* Write an IIC register. +* +* @param BaseAddress contains the base address of the device. +* @param RegOffset contains the offset from the 1st register of the +* device to select the specific register. +* @param RegisterValue is the value to be written to the register. +* +* @return None. +* +* @note C-Style signature: +* void XIicPs_WriteReg(u32 BaseAddress, int RegOffset, u32 RegisterValue) +* +******************************************************************************/ +#define XIicPs_WriteReg(BaseAddress, RegOffset, RegisterValue) \ + XIicPs_Out32((BaseAddress) + (RegOffset), (RegisterValue)) + +/***************************************************************************/ +/** +* Read the interrupt enable register. +* +* @param BaseAddress contains the base address of the device. +* +* @return Current bit mask that represents currently enabled interrupts. +* +* @note C-Style signature: +* u32 XIicPs_ReadIER(u32 BaseAddress) +* +******************************************************************************/ +#define XIicPs_ReadIER(BaseAddress) \ + XIicPs_ReadReg((BaseAddress), XIICPS_IER_OFFSET) + +/***************************************************************************/ +/** +* Write to the interrupt enable register. +* +* @param BaseAddress contains the base address of the device. +* +* @param IntrMask is the interrupts to be enabled. +* +* @return None. +* +* @note C-Style signature: +* void XIicPs_EnabledInterrupts(u32 BaseAddress, u32 IntrMask) +* +******************************************************************************/ +#define XIicPs_EnableInterrupts(BaseAddress, IntrMask) \ + XIicPs_WriteReg((BaseAddress), XIICPS_IER_OFFSET, (IntrMask)) + +/***************************************************************************/ +/** +* Disable all interrupts. +* +* @param BaseAddress contains the base address of the device. +* +* @return None. +* +* @note C-Style signature: +* void XIicPs_DisableAllInterrupts(u32 BaseAddress) +* +******************************************************************************/ +#define XIicPs_DisableAllInterrupts(BaseAddress) \ + XIicPs_WriteReg((BaseAddress), XIICPS_IDR_OFFSET, \ + XIICPS_IXR_ALL_INTR_MASK) + +/***************************************************************************/ +/** +* Disable selected interrupts. +* +* @param BaseAddress contains the base address of the device. +* +* @param IntrMask is the interrupts to be disabled. +* +* @return None. +* +* @note C-Style signature: +* void XIicPs_DisableInterrupts(u32 BaseAddress, u32 IntrMask) +* +******************************************************************************/ +#define XIicPs_DisableInterrupts(BaseAddress, IntrMask) \ + XIicPs_WriteReg((BaseAddress), XIICPS_IDR_OFFSET, \ + (IntrMask)) + +/************************** Variable Definitions *****************************/ + +/************************** Function Prototypes ******************************/ +/* + * Perform reset operation to the I2c interface + */ +void XIicPs_ResetHw(u32 BaseAddr); +#ifdef __cplusplus +} +#endif + +#endif /* end of protection macro */ diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps_intr.c b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_intr.c new file mode 100644 index 00000000..9db11490 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_intr.c @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* 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 xiicps_intr.c +* +* Contains functions of the XIicPs driver for interrupt-driven transfers. +* See xiicps.h for a detailed description of the device and driver. +* +*
 MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------  -------- -----------------------------------------------
+* 1.00a drg/jz  01/30/10 First release
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xiicps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ + +/************************* Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* +* This function sets the status callback function, the status handler, which the +* driver calls when it encounters conditions that should be reported to the +* higher layer software. The handler executes in an interrupt context, so +* the amount of processing should be minimized +* +* Refer to the xiicps.h file for a list of the Callback events. The events are +* defined to start with XIICPS_EVENT_*. +* +* @param InstancePtr is a pointer to the XIicPs 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 finish its +* work quickly. +* +******************************************************************************/ +void XIicPs_SetStatusHandler(XIicPs *InstancePtr, void *CallBackRef, + XIicPs_IntrHandler FuncPtr) +{ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(FuncPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + InstancePtr->StatusHandler = FuncPtr; + InstancePtr->CallBackRef = CallBackRef; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps_master.c b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_master.c new file mode 100644 index 00000000..636c37c2 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_master.c @@ -0,0 +1,885 @@ +/****************************************************************************** +* +* 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 xiicps_master.c +* +* Handles master mode transfers. +* +*
 MODIFICATION HISTORY:
+*
+* Ver   Who  Date     Changes
+* ----- ---  -------- ---------------------------------------------
+* 1.00a jz   01/30/10 First release
+* 1.00a sdm  09/21/11 Updated the XIicPs_SetupMaster to not check for
+*		      Bus Busy condition when the Hold Bit is set.
+* 1.01a sg   03/30/12 Fixed an issue in XIicPs_MasterSendPolled where a
+*		      check for transfer completion is added, which indicates
+*			 the completion of current transfer.
+* 2.0   hk   03/07/14 Added check for error status in the while loop that
+*                     checks for completion. CR# 762244, 764875.
+* 2.1   hk   04/24/14 Fix for CR# 789821 to handle >14 byte transfers.
+*                     Fix for CR# 761060 - provision for repeated start.
+* 2.2   hk   08/23/14 Slave monitor mode changes - clear FIFO, enable
+*                     read mode and clear transfer size register.
+*                     Disable NACK to avoid interrupts on each retry.
+* 2.3	sk	 10/06/14 Fill transmit fifo before address register when sending.
+* 					  Replaced XIICPS_DATA_INTR_DEPTH with XIICPS_FIFO_DEPTH.
+* 					  Repeated start feature removed.
+*			 12/06/14 Implemented Repeated start feature.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xiicps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +int TransmitFifoFill(XIicPs *InstancePtr); + +static int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role); +static void MasterSendData(XIicPs *InstancePtr); + +/************************* Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function initiates an interrupt-driven send in master mode. +* +* It tries to send the first FIFO-full of data, then lets the interrupt +* handler to handle the rest of the data if there is any. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param MsgPtr is the pointer to the send buffer. +* @param ByteCount is the number of bytes to be sent. +* @param SlaveAddr is the address of the slave we are sending to. +* +* @return None. +* +* @note This send routine is for interrupt-driven transfer only. +* + ****************************************************************************/ +void XIicPs_MasterSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, + u16 SlaveAddr) +{ + u32 BaseAddr; + + /* + * Assert validates the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(MsgPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr); + + + BaseAddr = InstancePtr->Config.BaseAddress; + InstancePtr->SendBufferPtr = MsgPtr; + InstancePtr->SendByteCount = ByteCount; + InstancePtr->RecvBufferPtr = NULL; + InstancePtr->IsSend = 1; + + /* + * Set repeated start if sending more than FIFO of data. + */ + if ((InstancePtr->IsRepeatedStart) || + (ByteCount > XIICPS_FIFO_DEPTH)) { + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) | + XIICPS_CR_HOLD_MASK); + } + + /* + * Setup as a master sending role. + */ + XIicPs_SetupMaster(InstancePtr, SENDING_ROLE); + + TransmitFifoFill(InstancePtr); + + /* + * Do the address transfer to notify the slave. + */ + XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); + + XIicPs_EnableInterrupts(BaseAddr, + XIICPS_IXR_NACK_MASK | XIICPS_IXR_COMP_MASK | + XIICPS_IXR_ARB_LOST_MASK); +} + +/*****************************************************************************/ +/** +* This function initiates an interrupt-driven receive in master mode. +* +* It sets the transfer size register so the slave can send data to us. +* The rest of the work is managed by interrupt handler. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param MsgPtr is the pointer to the receive buffer. +* @param ByteCount is the number of bytes to be received. +* @param SlaveAddr is the address of the slave we are receiving from. +* +* @return None. +* +* @note This receive routine is for interrupt-driven transfer only. +* +****************************************************************************/ +void XIicPs_MasterRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount, + u16 SlaveAddr) +{ + u32 BaseAddr; + + /* + * Assert validates the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(MsgPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr); + + BaseAddr = InstancePtr->Config.BaseAddress; + InstancePtr->RecvBufferPtr = MsgPtr; + InstancePtr->RecvByteCount = ByteCount; + InstancePtr->CurrByteCount = ByteCount; + InstancePtr->SendBufferPtr = NULL; + InstancePtr->IsSend = 0; + InstancePtr->UpdateTxSize = 0; + + if ((ByteCount > XIICPS_FIFO_DEPTH) || + (InstancePtr->IsRepeatedStart)) + { + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) | + XIICPS_CR_HOLD_MASK); + } + + /* + * Initialize for a master receiving role. + */ + XIicPs_SetupMaster(InstancePtr, RECVING_ROLE); + + /* + * Do the address transfer to signal the slave. + */ + XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); + + /* + * Setup the transfer size register so the slave knows how much + * to send to us. + */ + if (ByteCount > XIICPS_MAX_TRANSFER_SIZE) { + XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, + XIICPS_MAX_TRANSFER_SIZE); + InstancePtr->CurrByteCount = XIICPS_MAX_TRANSFER_SIZE; + InstancePtr->UpdateTxSize = 1; + }else { + XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, + ByteCount); + } + + XIicPs_EnableInterrupts(BaseAddr, + XIICPS_IXR_NACK_MASK | XIICPS_IXR_DATA_MASK | + XIICPS_IXR_RX_OVR_MASK | XIICPS_IXR_COMP_MASK | + XIICPS_IXR_ARB_LOST_MASK); +} + +/*****************************************************************************/ +/** +* This function initiates a polled mode send in master mode. +* +* It sends data to the FIFO and waits for the slave to pick them up. +* If slave fails to remove data from FIFO, the send fails with +* time out. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param MsgPtr is the pointer to the send buffer. +* @param ByteCount is the number of bytes to be sent. +* @param SlaveAddr is the address of the slave we are sending to. +* +* @return +* - XST_SUCCESS if everything went well. +* - XST_FAILURE if timed out. +* +* @note This send routine is for polled mode transfer only. +* +****************************************************************************/ +int XIicPs_MasterSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, + int ByteCount, u16 SlaveAddr) +{ + u32 IntrStatusReg; + u32 StatusReg; + u32 BaseAddr; + u32 Intrs; + + /* + * Assert validates the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(MsgPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr); + + BaseAddr = InstancePtr->Config.BaseAddress; + InstancePtr->SendBufferPtr = MsgPtr; + InstancePtr->SendByteCount = ByteCount; + + if ((InstancePtr->IsRepeatedStart) || + (ByteCount > XIICPS_FIFO_DEPTH)) { + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) | + XIICPS_CR_HOLD_MASK); + } + + XIicPs_SetupMaster(InstancePtr, SENDING_ROLE); + + /* + * Intrs keeps all the error-related interrupts. + */ + Intrs = XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_TX_OVR_MASK | + XIICPS_IXR_NACK_MASK; + + /* + * Clear the interrupt status register before use it to monitor. + */ + IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); + XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); + + /* + * Transmit first FIFO full of data. + */ + TransmitFifoFill(InstancePtr); + + XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); + + IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); + + /* + * Continue sending as long as there is more data and + * there are no errors. + */ + while ((InstancePtr->SendByteCount > 0) && + ((IntrStatusReg & Intrs) == 0)) { + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + + /* + * Wait until transmit FIFO is empty. + */ + if ((StatusReg & XIICPS_SR_TXDV_MASK) != 0) { + IntrStatusReg = XIicPs_ReadReg(BaseAddr, + XIICPS_ISR_OFFSET); + continue; + } + + /* + * Send more data out through transmit FIFO. + */ + TransmitFifoFill(InstancePtr); + } + + /* + * Check for completion of transfer. + */ + while ((IntrStatusReg & XIICPS_IXR_COMP_MASK) != XIICPS_IXR_COMP_MASK){ + + IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); + /* + * If there is an error, tell the caller. + */ + if ((IntrStatusReg & Intrs) != 0) { + return XST_FAILURE; + } + } + + if (!(InstancePtr->IsRepeatedStart)) { + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) & + (~XIICPS_CR_HOLD_MASK)); + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function initiates a polled mode receive in master mode. +* +* It repeatedly sets the transfer size register so the slave can +* send data to us. It polls the data register for data to come in. +* If slave fails to send us data, it fails with time out. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param MsgPtr is the pointer to the receive buffer. +* @param ByteCount is the number of bytes to be received. +* @param SlaveAddr is the address of the slave we are receiving from. +* +* @return +* - XST_SUCCESS if everything went well. +* - XST_FAILURE if timed out. +* +* @note This receive routine is for polled mode transfer only. +* +****************************************************************************/ +int XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, + int ByteCount, u16 SlaveAddr) +{ + u32 IntrStatusReg; + u32 Intrs; + u32 StatusReg; + u32 BaseAddr; + int IsHold = 0; + int UpdateTxSize = 0; + + /* + * Assert validates the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(MsgPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr); + + BaseAddr = InstancePtr->Config.BaseAddress; + InstancePtr->RecvBufferPtr = MsgPtr; + InstancePtr->RecvByteCount = ByteCount; + + if((ByteCount > XIICPS_FIFO_DEPTH) || + (InstancePtr->IsRepeatedStart)) + { + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) | + XIICPS_CR_HOLD_MASK); + IsHold = 1; + } + + XIicPs_SetupMaster(InstancePtr, RECVING_ROLE); + + /* + * Clear the interrupt status register before use it to monitor. + */ + IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); + XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); + + XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); + + /* + * Set up the transfer size register so the slave knows how much + * to send to us. + */ + if (ByteCount > XIICPS_MAX_TRANSFER_SIZE) { + XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, + XIICPS_MAX_TRANSFER_SIZE); + ByteCount = XIICPS_MAX_TRANSFER_SIZE; + UpdateTxSize = 1; + }else { + XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, + ByteCount); + } + + /* + * Intrs keeps all the error-related interrupts. + */ + Intrs = XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_RX_OVR_MASK | + XIICPS_IXR_RX_UNF_MASK | XIICPS_IXR_NACK_MASK; + + /* + * Poll the interrupt status register to find the errors. + */ + IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); + while ((InstancePtr->RecvByteCount > 0) && + ((IntrStatusReg & Intrs) == 0)) { + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + + while (StatusReg & XIICPS_SR_RXDV_MASK) { + if ((InstancePtr->RecvByteCount < + XIICPS_DATA_INTR_DEPTH) && IsHold && + (!(InstancePtr->IsRepeatedStart))) { + IsHold = 0; + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, + XIICPS_CR_OFFSET) & + (~XIICPS_CR_HOLD_MASK)); + } + XIicPs_RecvByte(InstancePtr); + ByteCount --; + + if (UpdateTxSize && + (ByteCount == XIICPS_FIFO_DEPTH + 1)) + break; + + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + } + + if (UpdateTxSize && (ByteCount == XIICPS_FIFO_DEPTH + 1)) { + /* + * wait while fifo is full + */ + while(XIicPs_ReadReg(BaseAddr, + XIICPS_TRANS_SIZE_OFFSET) != + (ByteCount - XIICPS_FIFO_DEPTH)); + + if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) > + XIICPS_MAX_TRANSFER_SIZE) { + + XIicPs_WriteReg(BaseAddr, + XIICPS_TRANS_SIZE_OFFSET, + XIICPS_MAX_TRANSFER_SIZE); + ByteCount = XIICPS_MAX_TRANSFER_SIZE + + XIICPS_FIFO_DEPTH; + }else { + XIicPs_WriteReg(BaseAddr, + XIICPS_TRANS_SIZE_OFFSET, + InstancePtr->RecvByteCount - + XIICPS_FIFO_DEPTH); + UpdateTxSize = 0; + ByteCount = InstancePtr->RecvByteCount; + } + } + + IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); + } + + if (!(InstancePtr->IsRepeatedStart)) { + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) & + (~XIICPS_CR_HOLD_MASK)); + } + + if (IntrStatusReg & Intrs) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* This function enables the slave monitor mode. +* +* It enables slave monitor in the control register and enables +* slave ready interrupt. It then does an address transfer to slave. +* Interrupt handler will signal the caller if slave responds to +* the address transfer. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param SlaveAddr is the address of the slave we want to contact. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIicPs_EnableSlaveMonitor(XIicPs *InstancePtr, u16 SlaveAddr) +{ + u32 BaseAddr; + u32 ConfigReg; + + Xil_AssertVoid(InstancePtr != NULL); + + BaseAddr = InstancePtr->Config.BaseAddress; + + /* Clear transfer size register */ + XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET, 0x0); + + /* + * Enable slave monitor mode in control register. + */ + ConfigReg = XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET); + ConfigReg |= XIICPS_CR_MS_MASK | XIICPS_CR_NEA_MASK | + XIICPS_CR_CLR_FIFO_MASK | XIICPS_CR_SLVMON_MASK; + ConfigReg &= ~XIICPS_CR_RD_WR_MASK; + + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, ConfigReg); + + /* + * Set up interrupt flag for slave monitor interrupt. + * Dont enable NACK. + */ + XIicPs_EnableInterrupts(BaseAddr, XIICPS_IXR_SLV_RDY_MASK); + + /* + * Initialize the slave monitor register. + */ + XIicPs_WriteReg(BaseAddr, XIICPS_SLV_PAUSE_OFFSET, 0xF); + + /* + * Set the slave address to start the slave address transmission. + */ + XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr); + + return; +} + +/*****************************************************************************/ +/** +* This function disables slave monitor mode. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIicPs_DisableSlaveMonitor(XIicPs *InstancePtr) +{ + u32 BaseAddr; + + Xil_AssertVoid(InstancePtr != NULL); + + BaseAddr = InstancePtr->Config.BaseAddress; + + /* + * Clear slave monitor control bit. + */ + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) + & (~XIICPS_CR_SLVMON_MASK)); + + /* + * Clear interrupt flag for slave monitor interrupt. + */ + XIicPs_DisableInterrupts(BaseAddr, XIICPS_IXR_SLV_RDY_MASK); + + return; +} + +/*****************************************************************************/ +/** +* The interrupt handler for the master mode. It does the protocol handling for +* the interrupt-driven transfers. +* +* Completion events and errors are signaled to upper layer for proper handling. +* +*
+* The interrupts that are handled are:
+* - DATA
+*	This case is handled only for master receive data.
+*	The master has to request for more data (if there is more data to
+*	receive) and read the data from the FIFO .
+*
+* - COMP
+*	If the Master is transmitting data and there is more data to be
+*	sent then the data is written to the FIFO. If there is no more data to
+*	be transmitted then a completion event is signalled to the upper layer
+*	by calling the callback handler.
+*
+*	If the Master is receiving data then the data is read from the FIFO and
+*	the Master has to request for more data (if there is more data to
+*	receive). If all the data has been received then a completion event
+*	is signalled to the upper layer by calling the callback handler.
+*	It is an error if the amount of received data is more than expected.
+*
+* - NAK and SLAVE_RDY
+*	This is signalled to the upper layer by calling the callback handler.
+*
+* - All Other interrupts
+*	These interrupts are marked as error. This is signalled to the upper
+*	layer by calling the callback handler.
+*
+* 
+* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr) +{ + u32 IntrStatusReg; + u32 StatusEvent = 0; + u32 BaseAddr; + int ByteCnt; + int IsHold; + + /* + * Assert validates the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + BaseAddr = InstancePtr->Config.BaseAddress; + + /* + * Read the Interrupt status register. + */ + IntrStatusReg = XIicPs_ReadReg(BaseAddr, + XIICPS_ISR_OFFSET); + + /* + * Write the status back to clear the interrupts so no events are + * missed while processing this interrupt. + */ + XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); + + /* + * Use the Mask register AND with the Interrupt Status register so + * disabled interrupts are not processed. + */ + IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET)); + + ByteCnt = InstancePtr->CurrByteCount; + + IsHold = 0; + if (XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) & XIICPS_CR_HOLD_MASK) { + IsHold = 1; + } + + /* + * Send + */ + if ((InstancePtr->IsSend) && + (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK))) { + if (InstancePtr->SendByteCount > 0) { + MasterSendData(InstancePtr); + } else { + StatusEvent |= XIICPS_EVENT_COMPLETE_SEND; + } + } + + + /* + * Receive + */ + if ((!(InstancePtr->IsSend)) && + ((0 != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) || + (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK)))){ + + while (XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET) & + XIICPS_SR_RXDV_MASK) { + if ((InstancePtr->RecvByteCount < + XIICPS_DATA_INTR_DEPTH) && IsHold && + (!(InstancePtr->IsRepeatedStart))) { + IsHold = 0; + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, + XIICPS_CR_OFFSET) & + (~XIICPS_CR_HOLD_MASK)); + } + XIicPs_RecvByte(InstancePtr); + ByteCnt--; + + if (InstancePtr->UpdateTxSize && + (ByteCnt == XIICPS_FIFO_DEPTH + 1)) + break; + } + + if (InstancePtr->UpdateTxSize && + (ByteCnt == XIICPS_FIFO_DEPTH + 1)) { + /* + * wait while fifo is full + */ + while(XIicPs_ReadReg(BaseAddr, + XIICPS_TRANS_SIZE_OFFSET) != + (ByteCnt - XIICPS_FIFO_DEPTH)); + + if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) > + XIICPS_MAX_TRANSFER_SIZE) { + + XIicPs_WriteReg(BaseAddr, + XIICPS_TRANS_SIZE_OFFSET, + XIICPS_MAX_TRANSFER_SIZE); + ByteCnt = XIICPS_MAX_TRANSFER_SIZE + + XIICPS_FIFO_DEPTH; + }else { + XIicPs_WriteReg(BaseAddr, + XIICPS_TRANS_SIZE_OFFSET, + InstancePtr->RecvByteCount - + XIICPS_FIFO_DEPTH); + InstancePtr->UpdateTxSize = 0; + ByteCnt = InstancePtr->RecvByteCount; + } + } + InstancePtr->CurrByteCount = ByteCnt; + } + + if ((!(InstancePtr->IsSend)) && + (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK))) { + /* + * If all done, tell the application. + */ + if (InstancePtr->RecvByteCount == 0){ + if (!(InstancePtr->IsRepeatedStart)) { + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, + XIICPS_CR_OFFSET) & + (~XIICPS_CR_HOLD_MASK)); + } + StatusEvent |= XIICPS_EVENT_COMPLETE_RECV; + } + } + + + /* + * Slave ready interrupt, it is only meaningful for master mode. + */ + if (0 != (IntrStatusReg & XIICPS_IXR_SLV_RDY_MASK)) { + StatusEvent |= XIICPS_EVENT_SLAVE_RDY; + } + + if (0 != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) { + if (!(InstancePtr->IsRepeatedStart)) { + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, + XIICPS_CR_OFFSET) & + (~XIICPS_CR_HOLD_MASK)); + } + StatusEvent |= XIICPS_EVENT_NACK; + } + + /* + * All other interrupts are treated as error. + */ + if (0 != (IntrStatusReg & (XIICPS_IXR_NACK_MASK | + XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_RX_UNF_MASK | + XIICPS_IXR_TX_OVR_MASK | XIICPS_IXR_RX_OVR_MASK))) { + if (!(InstancePtr->IsRepeatedStart)) { + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + XIicPs_ReadReg(BaseAddr, + XIICPS_CR_OFFSET) & + (~XIICPS_CR_HOLD_MASK)); + } + StatusEvent |= XIICPS_EVENT_ERROR; + } + + /* + * Signal application if there are any events. + */ + if (0 != StatusEvent) { + InstancePtr->StatusHandler(InstancePtr->CallBackRef, + StatusEvent); + } + +} + +/*****************************************************************************/ +/* +* This function prepares a device to transfers as a master. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @param Role specifies whether the device is sending or receiving. +* +* @return +* - XST_SUCCESS if everything went well. +* - XST_FAILURE if bus is busy. +* +* @note Interrupts are always disabled, device which needs to use +* interrupts needs to setup interrupts after this call. +* +****************************************************************************/ +static int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role) +{ + u32 ControlReg; + u32 BaseAddr; + u32 EnabledIntr = 0x0; + + Xil_AssertNonvoid(InstancePtr != NULL); + + BaseAddr = InstancePtr->Config.BaseAddress; + ControlReg = XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET); + + + /* + * Only check if bus is busy when repeated start option is not set. + */ + if ((ControlReg & XIICPS_CR_HOLD_MASK) == 0) { + if (XIicPs_BusIsBusy(InstancePtr)) { + return XST_FAILURE; + } + } + + /* + * Set up master, AckEn, nea and also clear fifo. + */ + ControlReg |= XIICPS_CR_ACKEN_MASK | XIICPS_CR_CLR_FIFO_MASK | + XIICPS_CR_NEA_MASK | XIICPS_CR_MS_MASK; + + if (Role == RECVING_ROLE) { + ControlReg |= XIICPS_CR_RD_WR_MASK; + EnabledIntr = XIICPS_IXR_DATA_MASK |XIICPS_IXR_RX_OVR_MASK; + }else { + ControlReg &= ~XIICPS_CR_RD_WR_MASK; + } + EnabledIntr |= XIICPS_IXR_COMP_MASK | XIICPS_IXR_ARB_LOST_MASK; + + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, ControlReg); + + XIicPs_DisableAllInterrupts(BaseAddr); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/* +* This function handles continuation of sending data. It is invoked +* from interrupt handler. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +static void MasterSendData(XIicPs *InstancePtr) +{ + TransmitFifoFill(InstancePtr); + + /* + * Clear hold bit if done, so stop can be sent out. + */ + if (InstancePtr->SendByteCount == 0) { + + /* + * If user has enabled repeated start as an option, + * do not disable it. + */ + if (!(InstancePtr->IsRepeatedStart)) { + + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, + XIICPS_CR_OFFSET, + XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_CR_OFFSET) & ~ XIICPS_CR_HOLD_MASK); + } + } + + return; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps_options.c b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_options.c new file mode 100644 index 00000000..959a9635 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_options.c @@ -0,0 +1,487 @@ +/****************************************************************************** +* +* 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 xiicps_options.c +* +* Contains functions for the configuration of the XIccPs driver. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who     Date     Changes
+* ----- ------  -------- -----------------------------------------------
+* 1.00a drg/jz  01/30/10 First release
+* 1.02a sg	08/29/12 Updated the logic to arrive at the best divisors
+*			 to achieve I2C clock with minimum error.
+*			 This is a fix for CR #674195
+* 1.03a hk  05/04/13 Initialized BestDivA and BestDivB to 0.
+*			 This is fix for CR#704398 to remove warning.
+* 2.0   hk  03/07/14 Limited frequency set when 100KHz or 400KHz is
+*                    selected. This is a hardware limitation. CR#779290.
+* 2.1   hk  04/24/14 Fix for CR# 761060 - provision for repeated start.
+* 2.3	sk	10/07/14 Repeated start feature removed.
+* 2.4	sk	12/06/14 Implemented Repeated start feature.
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xiicps.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[] = { + {XIICPS_7_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK}, + {XIICPS_10_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK}, + {XIICPS_SLAVE_MON_OPTION, XIICPS_CR_SLVMON_MASK}, + {XIICPS_REP_START_OPTION, XIICPS_CR_HOLD_MASK}, +}; + +#define XIICPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap)) + +/*****************************************************************************/ +/** +* +* This function sets the options for the IIC device driver. The options control +* how the device behaves relative to the IIC bus. The device must be idle +* rather than busy transferring data before setting these device options. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param Options contains the specified options to be set. This is a bit +* mask where a 1 means to turn the option on. One or more bit +* values may be contained in the mask. See the bit definitions +* named XIICPS_*_OPTION in xiicps.h. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_IS_STARTED if the device is currently transferring +* data. The transfer must complete or be aborted before setting +* options. +* +* @note None. +* +******************************************************************************/ +int XIicPs_SetOptions(XIicPs *InstancePtr, u32 Options) +{ + u32 ControlReg; + unsigned int Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_CR_OFFSET); + + /* + * If repeated start option is requested, set the flag. + * The hold bit in CR will be written by driver when the next transfer + * is initiated. + */ + if (Options & XIICPS_REP_START_OPTION) { + InstancePtr->IsRepeatedStart = 1; + Options = Options & (~XIICPS_REP_START_OPTION); + } + + /* + * Loop through the options table, turning the option on. + */ + for (Index = 0; Index < XIICPS_NUM_OPTIONS; Index++) { + if (Options & OptionsTable[Index].Option) { + /* + * 10-bit option is specially treated, because it is + * using the 7-bit option, so turning it on means + * turning 7-bit option off. + */ + if (OptionsTable[Index].Option & + XIICPS_10_BIT_ADDR_OPTION) { + /* Turn 7-bit off */ + ControlReg &= ~OptionsTable[Index].Mask; + } else { + /* Turn 7-bit on */ + ControlReg |= OptionsTable[Index].Mask; + } + } + } + + /* + * Now write to the control register. Leave it to the upper layers + * to restart the device. + */ + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET, + ControlReg); + + /* + * Keep a copy of what options this instance has. + */ + InstancePtr->Options = XIicPs_GetOptions(InstancePtr); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function clears the options for the IIC device driver. The options +* control how the device behaves relative to the IIC bus. The device must be +* idle rather than busy transferring data before setting these device options. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param Options contains the specified options to be cleared. This is a +* bit mask where a 1 means to turn the option off. One or more bit +* values may be contained in the mask. See the bit definitions +* named XIICPS_*_OPTION in xiicps.h. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_IS_STARTED if the device is currently transferring +* data. The transfer must complete or be aborted before setting +* options. +* +* @note None +* +******************************************************************************/ +int XIicPs_ClearOptions(XIicPs *InstancePtr, u32 Options) +{ + u32 ControlReg; + unsigned int Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_CR_OFFSET); + + /* + * If repeated start option is cleared, set the flag. + * The hold bit in CR will be cleared by driver when the + * following transfer ends. + */ + if (Options & XIICPS_REP_START_OPTION) { + InstancePtr->IsRepeatedStart = 0; + Options = Options & (~XIICPS_REP_START_OPTION); + } + + /* + * Loop through the options table and clear the specified options. + */ + for (Index = 0; Index < XIICPS_NUM_OPTIONS; Index++) { + if (Options & OptionsTable[Index].Option) { + + /* + * 10-bit option is specially treated, because it is + * using the 7-bit option, so clearing it means turning + * 7-bit option on. + */ + if (OptionsTable[Index].Option & + XIICPS_10_BIT_ADDR_OPTION) { + + /* Turn 7-bit on */ + ControlReg |= OptionsTable[Index].Mask; + } else { + + /* Turn 7-bit off */ + ControlReg &= ~OptionsTable[Index].Mask; + } + } + } + + + /* + * Now write the control register. Leave it to the upper layers + * to restart the device. + */ + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET, + ControlReg); + + /* + * Keep a copy of what options this instance has. + */ + InstancePtr->Options = XIicPs_GetOptions(InstancePtr); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the options for the IIC device. The options control how +* the device behaves relative to the IIC bus. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return 32 bit mask of the options, where a 1 means the option is on, +* and a 0 means to the option is off. One or more bit values may +* be contained in the mask. See the bit definitions named +* XIICPS_*_OPTION in the file xiicps.h. +* +* @note None. +* +******************************************************************************/ +u32 XIicPs_GetOptions(XIicPs *InstancePtr) +{ + u32 OptionsFlag = 0; + u32 ControlReg; + unsigned int Index; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * Read control register to find which options are currently set. + */ + ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_CR_OFFSET); + + /* + * Loop through the options table to determine which options are set. + */ + for (Index = 0; Index < XIICPS_NUM_OPTIONS; Index++) { + if (ControlReg & OptionsTable[Index].Mask) { + OptionsFlag |= OptionsTable[Index].Option; + } + if ((ControlReg & XIICPS_CR_NEA_MASK) == 0) { + OptionsFlag |= XIICPS_10_BIT_ADDR_OPTION; + } + } + + if (InstancePtr->IsRepeatedStart) { + OptionsFlag |= XIICPS_REP_START_OPTION; + } + return OptionsFlag; +} + +/*****************************************************************************/ +/** +* +* This function sets the serial clock rate for the IIC device. The device +* must be idle rather than busy transferring data before setting these device +* options. +* +* The data rate is set by values in the control register. The formula for +* determining the correct register values is: +* Fscl = Fpclk/(22 x (divisor_a+1) x (divisor_b+1)) +* See the hardware data sheet for a full explanation of setting the serial +* clock rate. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param FsclHz is the clock frequency in Hz. The two most common clock +* rates are 100KHz and 400KHz. +* +* @return +* - XST_SUCCESS if options are successfully set. +* - XST_DEVICE_IS_STARTED if the device is currently transferring +* data. The transfer must complete or be aborted before setting +* options. +* - XST_FAILURE if the Fscl frequency can not be set. +* +* @note The clock can not be faster than the input clock divide by 22. +* +******************************************************************************/ +int XIicPs_SetSClk(XIicPs *InstancePtr, u32 FsclHz) +{ + u32 Div_a; + u32 Div_b; + u32 ActualFscl; + u32 Temp; + u32 TempLimit; + u32 LastError; + u32 BestError; + u32 CurrentError; + u32 ControlReg; + u32 CalcDivA; + u32 CalcDivB; + u32 BestDivA = 0; + u32 BestDivB = 0; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertNonvoid(FsclHz > 0); + + if (0 != XIicPs_In32((InstancePtr->Config.BaseAddress) + + XIICPS_TRANS_SIZE_OFFSET)) { + return XST_DEVICE_IS_STARTED; + } + + /* + * Assume Div_a is 0 and calculate (divisor_a+1) x (divisor_b+1). + */ + Temp = (InstancePtr->Config.InputClockHz) / (22 * FsclHz); + + /* + * If the answer is negative or 0, the Fscl input is out of range. + */ + if (0 == Temp) { + return XST_FAILURE; + } + + /* + * If frequency 400KHz is selected, 384.6KHz should be set. + * If frequency 100KHz is selected, 90KHz should be set. + * This is due to a hardware limitation. + */ + if(FsclHz > 384600) { + FsclHz = 384600; + } + + if((FsclHz <= 100000) && (FsclHz > 90000)) { + FsclHz = 90000; + } + + /* + * TempLimit helps in iterating over the consecutive value of Temp to + * find the closest clock rate achievable with divisors. + * Iterate over the next value only if fractional part is involved. + */ + TempLimit = ((InstancePtr->Config.InputClockHz) % (22 * FsclHz)) ? + Temp + 1 : Temp; + BestError = FsclHz; + + for ( ; Temp <= TempLimit ; Temp++) + { + LastError = FsclHz; + CalcDivA = 0; + CalcDivB = 0; + CurrentError = 0; + + for (Div_b = 0; Div_b < 64; Div_b++) { + + Div_a = Temp / (Div_b + 1); + + if (Div_a != 0) + Div_a = Div_a - 1; + + if (Div_a > 3) + continue; + + ActualFscl = (InstancePtr->Config.InputClockHz) / + (22 * (Div_a + 1) * (Div_b + 1)); + + if (ActualFscl > FsclHz) + CurrentError = (ActualFscl - FsclHz); + else + CurrentError = (FsclHz - ActualFscl); + + if (LastError > CurrentError) { + CalcDivA = Div_a; + CalcDivB = Div_b; + LastError = CurrentError; + } + } + + /* + * Used to capture the best divisors. + */ + if (LastError < BestError) { + BestError = LastError; + BestDivA = CalcDivA; + BestDivB = CalcDivB; + } + } + + + /* + * Read the control register and mask the Divisors. + */ + ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_CR_OFFSET); + ControlReg &= ~(XIICPS_CR_DIV_A_MASK | XIICPS_CR_DIV_B_MASK); + ControlReg |= (BestDivA << XIICPS_CR_DIV_A_SHIFT) | + (BestDivB << XIICPS_CR_DIV_B_SHIFT); + + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, XIICPS_CR_OFFSET, + ControlReg); + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* +* This function gets the serial clock rate for the IIC device. The device +* must be idle rather than busy transferring data before setting these device +* options. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return The value of the IIC clock to the nearest Hz based on the +* control register settings. The actual value may not be exact to +* to integer math rounding errors. +* +* @note None. +* +******************************************************************************/ +u32 XIicPs_GetSClk(XIicPs *InstancePtr) +{ + u32 ControlReg; + u32 ActualFscl; + u32 Div_a; + u32 Div_b; + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_CR_OFFSET); + + Div_a = (ControlReg & XIICPS_CR_DIV_A_MASK) >> XIICPS_CR_DIV_A_SHIFT; + Div_b = (ControlReg & XIICPS_CR_DIV_B_MASK) >> XIICPS_CR_DIV_B_SHIFT; + + ActualFscl = (InstancePtr->Config.InputClockHz) / + (22 * (Div_a + 1) * (Div_b + 1)); + + return ActualFscl; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps_selftest.c b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_selftest.c new file mode 100644 index 00000000..c8daf239 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_selftest.c @@ -0,0 +1,128 @@ +/****************************************************************************** +* +* 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 xiicps_selftest.c +* +* This component contains the implementation of selftest functions for the +* XIicPs driver component. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- ---------------------------------------------
+* 1.00a drg/jz 01/30/10 First release
+* 1.00a sdm    09/22/11 Removed unused code
+* 2.4	sk	   11/03/14 Removed TimeOut Register value check
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xiicps.h" + +/************************** Constant Definitions *****************************/ + +#define REG_TEST_VALUE 0x00000005 + +/**************************** 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 XIicPs instance. +* +* @return +* - XST_SUCCESS if successful. +* - XST_REGISTER_ERROR indicates a register did not read or write +* correctly +* +* @note None. +* +******************************************************************************/ +int XIicPs_SelfTest(XIicPs *InstancePtr) +{ + + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + /* + * All the IIC registers should be in their default state right now. + */ + if ((XIICPS_CR_RESET_VALUE != + XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_CR_OFFSET)) || + (XIICPS_IXR_ALL_INTR_MASK != + XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_IMR_OFFSET))) { + return XST_FAILURE; + } + + XIicPs_Reset(InstancePtr); + + /* + * Write, Read then write a register + */ + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, + XIICPS_SLV_PAUSE_OFFSET, REG_TEST_VALUE); + + if (REG_TEST_VALUE != XIicPs_ReadReg(InstancePtr->Config.BaseAddress, + XIICPS_SLV_PAUSE_OFFSET)) { + return XST_FAILURE; + } + + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, + XIICPS_SLV_PAUSE_OFFSET, 0); + + XIicPs_Reset(InstancePtr); + + return XST_SUCCESS; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps_sinit.c b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_sinit.c new file mode 100644 index 00000000..8e2c82db --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_sinit.c @@ -0,0 +1,98 @@ +/****************************************************************************** +* +* 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 xiicps_sinit.c +* +* The implementation of the XIicPs component's static initialization +* functionality. +* +*
+* MODIFICATION HISTORY:
+*
+* Ver   Who    Date     Changes
+* ----- ------ -------- --------------------------------------------
+* 1.00a drg/jz 01/30/10 First release
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ + +#include "xstatus.h" +#include "xparameters.h" +#include "xiicps.h" + +/************************** Constant Definitions *****************************/ + + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + + +/************************** Function Prototypes ******************************/ + +/************************** Variable Definitions *****************************/ +extern XIicPs_Config XIicPs_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 xiicps.h for the definition of +* XIicPs_Config. +* +* @note None. +* +******************************************************************************/ +XIicPs_Config *XIicPs_LookupConfig(u16 DeviceId) +{ + XIicPs_Config *CfgPtr = NULL; + int Index; + + for (Index = 0; Index < XPAR_XIICPS_NUM_INSTANCES; Index++) { + if (XIicPs_ConfigTable[Index].DeviceId == DeviceId) { + CfgPtr = &XIicPs_ConfigTable[Index]; + break; + } + } + + return CfgPtr; +} diff --git a/XilinxProcessorIPLib/drivers/iicps/src/xiicps_slave.c b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_slave.c new file mode 100644 index 00000000..1da9ccbb --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps/src/xiicps_slave.c @@ -0,0 +1,575 @@ +/****************************************************************************** +* +* 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 xiicps_slave.c +* +* Handles slave transfers +* +*
 MODIFICATION HISTORY:
+*
+* Ver   Who Date     Changes
+* ----- --  -------- ---------------------------------------------
+* 1.00a jz  01/30/10 First release
+* 1.04a kpc 08/30/13 Avoid buffer overwrite in SlaveRecvData function
+*
+* 
+* +******************************************************************************/ + +/***************************** Include Files *********************************/ +#include "xiicps.h" + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +extern int TransmitFifoFill(XIicPs *InstancePtr); + +static int SlaveRecvData(XIicPs *InstancePtr); + +/************************* Variable Definitions *****************************/ + +/*****************************************************************************/ +/** +* This function sets up the device to be a slave. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param SlaveAddr is the address of the slave we are receiving from. +* +* @return None. +* +* @note +* Interrupt is always enabled no matter the tranfer is interrupt- +* driven or polled mode. Whether device will be interrupted or not +* depends on whether the device is connected to an interrupt +* controller and interrupt for the device is enabled. +* +****************************************************************************/ +void XIicPs_SetupSlave(XIicPs *InstancePtr, u16 SlaveAddr) +{ + volatile u32 ControlReg; + u32 BaseAddr; + + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr); + + BaseAddr = InstancePtr->Config.BaseAddress; + + ControlReg = XIicPs_In32(BaseAddr + XIICPS_CR_OFFSET); + + /* + * Set up master, AckEn, nea and also clear fifo. + */ + ControlReg |= XIICPS_CR_ACKEN_MASK | XIICPS_CR_CLR_FIFO_MASK; + ControlReg |= XIICPS_CR_NEA_MASK; + ControlReg &= ~XIICPS_CR_MS_MASK; + + XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, + ControlReg); + + XIicPs_DisableAllInterrupts(BaseAddr); + + XIicPs_WriteReg(InstancePtr->Config.BaseAddress, + XIICPS_ADDR_OFFSET, SlaveAddr); + + return; +} + +/*****************************************************************************/ +/** +* This function setup a slave interrupt-driven send. It set the repeated +* start for the device is the tranfer size is larger than FIFO depth. +* Data processing for the send is initiated by the interrupt handler. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param MsgPtr is the pointer to the send buffer. +* @param ByteCount is the number of bytes to be sent. +* +* @return None. +* +* @note This send routine is for interrupt-driven transfer only. +* +****************************************************************************/ +void XIicPs_SlaveSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount) +{ + u32 BaseAddr; + + /* + * Assert validates the input arguments + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(MsgPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + BaseAddr = InstancePtr->Config.BaseAddress; + InstancePtr->SendBufferPtr = MsgPtr; + InstancePtr->SendByteCount = ByteCount; + InstancePtr->RecvBufferPtr = NULL; + + XIicPs_EnableInterrupts(BaseAddr, + XIICPS_IXR_DATA_MASK | XIICPS_IXR_COMP_MASK | + XIICPS_IXR_TO_MASK | XIICPS_IXR_NACK_MASK | + XIICPS_IXR_TX_OVR_MASK); +} + +/*****************************************************************************/ +/** +* This function setup a slave interrupt-driven receive. +* Data processing for the receive is handled by the interrupt handler. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param MsgPtr is the pointer to the receive buffer. +* @param ByteCount is the number of bytes to be received. +* +* @return None. +* +* @note This routine is for interrupt-driven transfer only. +* +****************************************************************************/ +void XIicPs_SlaveRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount) +{ + /* + * Assert validates the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(MsgPtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + + InstancePtr->RecvBufferPtr = MsgPtr; + InstancePtr->RecvByteCount = ByteCount; + InstancePtr->SendBufferPtr = NULL; + + XIicPs_EnableInterrupts(InstancePtr->Config.BaseAddress, + XIICPS_IXR_DATA_MASK | XIICPS_IXR_COMP_MASK | + XIICPS_IXR_NACK_MASK | XIICPS_IXR_TO_MASK | + XIICPS_IXR_RX_OVR_MASK | XIICPS_IXR_RX_UNF_MASK); + +} + +/*****************************************************************************/ +/** +* This function sends a buffer in polled mode as a slave. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param MsgPtr is the pointer to the send buffer. +* @param ByteCount is the number of bytes to be sent. +* +* @return +* - XST_SUCCESS if everything went well. +* - XST_FAILURE if master sends us data or master terminates the +* transfer before all data has sent out. +* +* @note This send routine is for polled mode transfer only. +* +****************************************************************************/ +int XIicPs_SlaveSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount) +{ + volatile u32 IntrStatusReg; + volatile u32 StatusReg; + u32 BaseAddr; + int Tmp; + int BytesToSend; + int Error = 0; + + /* + * Assert validates the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(MsgPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + BaseAddr = InstancePtr->Config.BaseAddress; + InstancePtr->SendBufferPtr = MsgPtr; + InstancePtr->SendByteCount = ByteCount; + + /* + * Use RXRW bit in status register to wait master to start a read. + */ + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + while (((StatusReg & XIICPS_SR_RXRW_MASK) == 0) && (!Error)) { + + /* + * If master tries to send us data, it is an error. + */ + if (StatusReg & XIICPS_SR_RXDV_MASK) { + Error = 1; + } + + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + } + + if (Error) { + return XST_FAILURE; + } + + /* + * Clear the interrupt status register. + */ + IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); + XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); + + /* + * Send data as long as there is more data to send and + * there are no errors. + */ + while ((InstancePtr->SendByteCount > 0) && (!Error)){ + + /* + * Find out how many can be sent. + */ + BytesToSend = InstancePtr->SendByteCount; + if (BytesToSend > XIICPS_FIFO_DEPTH) { + BytesToSend = XIICPS_FIFO_DEPTH; + } + + for(Tmp = 0; Tmp < BytesToSend; Tmp ++) { + XIicPs_SendByte(InstancePtr); + } + + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + + /* + * Wait for master to read the data out of fifo. + */ + while (((StatusReg & XIICPS_SR_TXDV_MASK) != 0) && (!Error)) { + + /* + * If master terminates the transfer before all data is + * sent, it is an error. + */ + IntrStatusReg = XIicPs_ReadReg(BaseAddr, + XIICPS_ISR_OFFSET); + if (IntrStatusReg & XIICPS_IXR_NACK_MASK) { + Error = 1; + } + + /* Clear ISR. + */ + XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, + IntrStatusReg); + + StatusReg = XIicPs_ReadReg(BaseAddr, + XIICPS_SR_OFFSET); + } + } + + if (Error) { + return XST_FAILURE; + } + + return XST_SUCCESS; +} +/*****************************************************************************/ +/** +* This function receives a buffer in polled mode as a slave. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* @param MsgPtr is the pointer to the receive buffer. +* @param ByteCount is the number of bytes to be received. +* +* @return +* - XST_SUCCESS if everything went well. +* - XST_FAILURE if timed out. +* +* @note This receive routine is for polled mode transfer only. +* +****************************************************************************/ +int XIicPs_SlaveRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount) +{ + volatile u32 IntrStatusReg; + volatile u32 StatusReg; + u32 BaseAddr; + + /* + * Assert validates the input arguments. + */ + Xil_AssertNonvoid(InstancePtr != NULL); + Xil_AssertNonvoid(MsgPtr != NULL); + Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + BaseAddr = InstancePtr->Config.BaseAddress; + InstancePtr->RecvBufferPtr = MsgPtr; + InstancePtr->RecvByteCount = ByteCount; + + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + + /* + * Clear the interrupt status register. + */ + IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); + XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); + + /* + * Clear the status register. + */ + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + XIicPs_WriteReg(BaseAddr, XIICPS_SR_OFFSET, StatusReg); + + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + while (InstancePtr->RecvByteCount > 0) { + + /* Wait for master to put data */ + while ((StatusReg & XIICPS_SR_RXDV_MASK) == 0) { + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + + /* + * If master terminates the transfer before we get all + * the data or the master tries to read from us, + * it is an error. + */ + IntrStatusReg = XIicPs_ReadReg(BaseAddr, + XIICPS_ISR_OFFSET); + if ((IntrStatusReg & (XIICPS_IXR_DATA_MASK | + XIICPS_IXR_COMP_MASK)) && + ((StatusReg & XIICPS_SR_RXDV_MASK) == 0) && + (InstancePtr->RecvByteCount > 0)) { + + return XST_FAILURE; + } + + /* + * Clear the interrupt status register. + */ + XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, + IntrStatusReg); + } + + /* + * Read all data from FIFO. + */ + while ((StatusReg & XIICPS_SR_RXDV_MASK) && + (InstancePtr->RecvByteCount > 0)){ + + XIicPs_RecvByte(InstancePtr); + + StatusReg = XIicPs_ReadReg(BaseAddr, + XIICPS_SR_OFFSET); + } + } + + return XST_SUCCESS; +} + +/*****************************************************************************/ +/** +* The interrupt handler for slave mode. It does the protocol handling for +* the interrupt-driven transfers. +* +* Completion events and errors are signaled to upper layer for proper +* handling. +* +*
+*
+* The interrupts that are handled are:
+* - DATA
+*	If the instance is sending, it means that the master wants to read more
+*	data from us. Send more data, and check whether we are done with this
+*	send.
+*
+*	If the instance is receiving, it means that the master has writen
+* 	more data to us. Receive more data, and check whether we are done with
+*	with this receive.
+*
+* - COMP
+*	This marks that stop sequence has been sent from the master, transfer
+*	is about to terminate. However, for receiving, the master may have
+*	written us some data, so receive that first.
+*
+*	It is an error if the amount of transfered data is less than expected.
+*
+* - NAK
+*	This marks that master does not want our data. It is for send only.
+*
+* - Other interrupts
+*	These interrupts are marked as error.
+*
+* 
+* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return None. +* +* @note None. +* +****************************************************************************/ +void XIicPs_SlaveInterruptHandler(XIicPs *InstancePtr) +{ + volatile u32 IntrStatusReg; + u32 IsSend = 0; + u32 StatusEvent = 0; + int LeftOver; + u32 BaseAddr; + + /* + * Assert validates the input arguments. + */ + Xil_AssertVoid(InstancePtr != NULL); + Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); + + BaseAddr = InstancePtr->Config.BaseAddress; + + /* + * Read the Interrupt status register. + */ + IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET); + + /* + * Write the status back to clear the interrupts so no events are missed + * while processing this interrupt. + */ + XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg); + + /* + * Use the Mask register AND with the Interrupt Status register so + * disabled interrupts are not processed. + */ + IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET)); + + /* + * Determine whether the device is sending. + */ + if (InstancePtr->RecvBufferPtr == NULL) { + IsSend = 1; + } + + /* Data interrupt + * + * This means master wants to do more data transfers. + * Also check for completion of transfer, signal upper layer if done. + */ + if (0 != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) { + if (IsSend) { + LeftOver = TransmitFifoFill(InstancePtr); + /* + * We may finish send here + */ + if (LeftOver == 0) { + StatusEvent |= + XIICPS_EVENT_COMPLETE_SEND; + } + } else { + LeftOver = SlaveRecvData(InstancePtr); + + /* We may finish the receive here */ + if (LeftOver == 0) { + StatusEvent |= XIICPS_EVENT_COMPLETE_RECV; + } + } + } + + /* + * Complete interrupt. + * + * In slave mode, it means the master has done with this transfer, so + * we signal the application using completion event. + */ + if (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK)) { + if (IsSend) { + if (InstancePtr->SendByteCount > 0) { + StatusEvent |= XIICPS_EVENT_ERROR; + }else { + StatusEvent |= XIICPS_EVENT_COMPLETE_SEND; + } + } else { + LeftOver = SlaveRecvData(InstancePtr); + if (LeftOver > 0) { + StatusEvent |= XIICPS_EVENT_ERROR; + } else { + StatusEvent |= XIICPS_EVENT_COMPLETE_RECV; + } + } + } + + /* + * Nack interrupt, pass this information to application. + */ + if (0 != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) { + StatusEvent |= XIICPS_EVENT_NACK; + } + + /* + * All other interrupts are treated as error. + */ + if (0 != (IntrStatusReg & (XIICPS_IXR_TO_MASK | + XIICPS_IXR_RX_UNF_MASK | + XIICPS_IXR_TX_OVR_MASK | + XIICPS_IXR_RX_OVR_MASK))){ + + StatusEvent |= XIICPS_EVENT_ERROR; + } + + /* + * Signal application if there are any events. + */ + if (0 != StatusEvent) { + InstancePtr->StatusHandler(InstancePtr->CallBackRef, + StatusEvent); + } +} + +/*****************************************************************************/ +/* +* +* This function handles continuation of receiving data. It is invoked +* from interrupt handler. +* +* @param InstancePtr is a pointer to the XIicPs instance. +* +* @return Number of bytes still expected by the instance. +* +* @note None. +* +****************************************************************************/ +static int SlaveRecvData(XIicPs *InstancePtr) +{ + volatile u32 StatusReg; + u32 BaseAddr; + + BaseAddr = InstancePtr->Config.BaseAddress; + + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + + while ((StatusReg & XIICPS_SR_RXDV_MASK) && + (InstancePtr->RecvByteCount > 0)) { + XIicPs_RecvByte(InstancePtr); + StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET); + } + + return InstancePtr->RecvByteCount; +} diff --git a/XilinxProcessorIPLib/drivers/iicps_v2_4/data/iicps.mdd b/XilinxProcessorIPLib/drivers/iicps_v2_4/data/iicps.mdd index d28f820c..786a1b3b 100755 --- a/XilinxProcessorIPLib/drivers/iicps_v2_4/data/iicps.mdd +++ b/XilinxProcessorIPLib/drivers/iicps_v2_4/data/iicps.mdd @@ -34,7 +34,7 @@ OPTION psf_version = 2.1; BEGIN driver iicps OPTION supported_peripherals = (ps7_i2c); - OPTION driver_state = ACTIVE; + OPTION driver_state = DEPRECATED; OPTION copyfiles = all; OPTION VERSION = 2.4; OPTION NAME = iicps;