diff --git a/XilinxProcessorIPLib/drivers/iicps_v2_4/examples/xiicps_repeated_start_example.c b/XilinxProcessorIPLib/drivers/iicps_v2_4/examples/xiicps_repeated_start_example.c new file mode 100755 index 00000000..da784821 --- /dev/null +++ b/XilinxProcessorIPLib/drivers/iicps_v2_4/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; +}