iicps_v3_0: Added new version for iicps.

This patch add new version for iicps driver which supports
both zynq and Alto.

Signed-off-by: P L Sai Krishna <lakshmis@xilinx.com>
This commit is contained in:
P L Sai Krishna 2015-01-31 19:56:18 +05:30 committed by Suneel Garapati
parent 4b2b01d3e5
commit 3f029f1c87
27 changed files with 7158 additions and 1 deletions

View file

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

View file

@ -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"
}

View file

@ -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

View file

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

View file

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

View file

@ -0,0 +1,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.
*
* <pre>
* 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.
*
* </pre>
*
******************************************************************************/
/***************************** 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;
}

View file

@ -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.
*
* <pre>
* 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.
* </pre>
*
******************************************************************************/
/***************************** 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;
}

View file

@ -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.
*
* <pre> MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a jz 01/30/10 First release
*
* </pre>
*
****************************************************************************/
/***************************** 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_<IICPS_instance>_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;
}

View file

@ -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.
*
* <pre> MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a jz 01/30/10 First release
*
* </pre>
*
******************************************************************************/
/***************************** 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_<IICPS_instance>_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;
}

View file

@ -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.
*
* <pre> MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a jz 01/30/10 First release
*
* </pre>
*
****************************************************************************/
/***************************** 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_<IICPS_instance>_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;
}

View file

@ -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.
*
* <pre> MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a jz 01/30/10 First release
*
* </pre>
*
****************************************************************************/
/***************************** 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_<IICPS_instance>_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;
}

View file

@ -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.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ---- -------- ---------------------------------------------------------
* 2.1 hk 03/15/10 First release
*
* </pre>
*
******************************************************************************/
/***************************** 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;
}

View file

@ -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.
*
*
* <pre> MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a sdm 05/30/11 First release
*
* </pre>
*
****************************************************************************/
/***************************** 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_<IICPS_instance>_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;
}

View file

@ -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.
*
* <pre> MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- --- -------- -----------------------------------------------
* 1.00a jz 01/30/10 First release
*
* </pre>
*
****************************************************************************/
/***************************** 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_<IICPS_instance>_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;
}

View file

@ -0,0 +1,40 @@
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
CC_FLAGS = $(COMPILER_FLAGS)
ECC_FLAGS = $(EXTRA_COMPILER_FLAGS)
RELEASEDIR=../../../lib
INCLUDEDIR=../../../include
INCLUDES=-I./. -I${INCLUDEDIR}
OUTS = *.o
LIBSOURCES:=*.c
INCLUDEFILES:=*.h
OBJECTS = $(addsuffix .o, $(basename $(wildcard *.c)))
libs: banner 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}

View file

@ -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.
*
* <pre> 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.
*
* </pre>
*
******************************************************************************/
/***************************** 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;
}

View file

@ -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.
*
* <b>Initialization & Configuration</b>
*
* 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.
*
* <b>Multiple Masters</b>
*
* More than one master can exist, bus arbitration is defined in the IIC
* standard. Lost of arbitration causes arbitration loss interrupt on the device.
*
* <b>Multiple Slaves</b>
*
* 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.
*
* <b>Addressing</b>
*
* 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.
*
* <b>FIFO Size </b>
* 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.
*
* <b>Data Rates</b>
*
* 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.
*
* <b>Polled Mode Operation</b>
*
* This driver supports polled mode transfers.
*
* <b>Interrupts</b>
*
* 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
*
* <b>Bus Busy</b>
*
* Bus busy is checked before the setup of a master mode device, to avoid
* unnecessary arbitration loss interrupt.
*
* <b>RTOS Independence</b>
*
* This driver is intended to be RTOS and processor independent. It works with
* physical addresses only. Any needs for dynamic memory management, threads or
* thread mutual exclusion, virtual memory, or cache control must be satisfied by
* the layer above this driver.
*
*<b>Repeated Start</b>
*
* 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.
*
* <pre> 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.
*
* </pre>
*
******************************************************************************/
#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 */

View file

@ -0,0 +1,86 @@
/******************************************************************************
*
* Copyright (C) 2010 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiicps_g.c
*
* This file contains a configuration table that specifies the configuration of
* IIC devices in the system.
*
* <pre>
* 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
* </pre>
*
******************************************************************************/
/***************************** 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
};

View file

@ -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
*
* <pre> 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
*
* </pre>
*
******************************************************************************/
/***************************** 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);
}

View file

@ -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.
*
* <pre>
* 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
* </pre>
*
******************************************************************************/
#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
*
* <b>IIC Interrupt Status Register</b>
*
* 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.
*
* <b>IIC Interrupt Enable Register</b>
*
* 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.
*
* <b>IIC Interrupt Disable Register </b>
*
* 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.
*
* <b>IIC Interrupt Mask Register</b>
*
* 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 */

View file

@ -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.
*
* <pre> MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- -----------------------------------------------
* 1.00a drg/jz 01/30/10 First release
*
* </pre>
*
******************************************************************************/
/***************************** 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;
}

View file

@ -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.
*
* <pre> 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.
*
* </pre>
*
******************************************************************************/
/***************************** 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.
*
* <pre>
* 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.
*
* </pre>
*
* @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;
}

View file

@ -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.
*
* <pre>
* 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.
*
* </pre>
*
******************************************************************************/
/***************************** 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;
}

View file

@ -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.
*
* <pre>
* 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
* </pre>
*
******************************************************************************/
/***************************** 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;
}

View file

@ -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.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver Who Date Changes
* ----- ------ -------- --------------------------------------------
* 1.00a drg/jz 01/30/10 First release
* </pre>
*
******************************************************************************/
/***************************** 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;
}

View file

@ -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
*
* <pre> 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
*
* </pre>
*
******************************************************************************/
/***************************** 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.
*
* <pre>
*
* 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.
*
* </pre>
*
* @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;
}

View file

@ -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;