iic: Add iic_v3_1 and deprecate iic_v3_0
This patch adds newer version of the iic driver and deprecates the older version. Signed-off-by: Kedareswara rao Appana <appanad@xilinx.com>
This commit is contained in:
parent
6973baf6a7
commit
6d2fff8bb9
32 changed files with 12226 additions and 0 deletions
68
XilinxProcessorIPLib/drivers/iic/data/iic.mdd
Executable file
68
XilinxProcessorIPLib/drivers/iic/data/iic.mdd
Executable file
|
@ -0,0 +1,68 @@
|
|||
##############################################################################
|
||||
#
|
||||
# (c) Copyright 2005-2014 Xilinx, Inc. All rights reserved.
|
||||
#
|
||||
# This file contains confidential and proprietary information of Xilinx, Inc.
|
||||
# and is protected under U.S. and international copyright and other
|
||||
# intellectual property laws.
|
||||
#
|
||||
# DISCLAIMER
|
||||
# This disclaimer is not a license and does not grant any rights to the
|
||||
# materials distributed herewith. Except as otherwise provided in a valid
|
||||
# license issued to you by Xilinx, and to the maximum extent permitted by
|
||||
# applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL
|
||||
# FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,
|
||||
# IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
|
||||
# MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;
|
||||
# and (2) Xilinx shall not be liable (whether in contract or tort, including
|
||||
# negligence, or under any other theory of liability) for any loss or damage
|
||||
# of any kind or nature related to, arising under or in connection with these
|
||||
# materials, including for any direct, or any indirect, special, incidental,
|
||||
# or consequential loss or damage (including loss of data, profits, goodwill,
|
||||
# or any type of loss or damage suffered as a result of any action brought by
|
||||
# a third party) even if such damage or loss was reasonably foreseeable or
|
||||
# Xilinx had been advised of the possibility of the same.
|
||||
#
|
||||
# CRITICAL APPLICATIONS
|
||||
# Xilinx products are not designed or intended to be fail-safe, or for use in
|
||||
# any application requiring fail-safe performance, such as life-support or
|
||||
# safety devices or systems, Class III medical devices, nuclear facilities,
|
||||
# applications related to the deployment of airbags, or any other applications
|
||||
# that could lead to death, personal injury, or severe property or
|
||||
# environmental damage (individually and collectively, "Critical
|
||||
# Applications"). Customer assumes the sole risk and liability of any use of
|
||||
# Xilinx products in Critical Applications, subject only to applicable laws
|
||||
# and regulations governing limitations on product liability.
|
||||
#
|
||||
# THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
|
||||
# AT ALL TIMES.
|
||||
#
|
||||
# MODIFICATION HISTORY:
|
||||
#
|
||||
# Ver Who Date Changes
|
||||
# -------- ------ -------- --------------------------------------------------
|
||||
# 3.0 adk 10/12/13 Removed support for xps_iic
|
||||
##############################################################################
|
||||
## @BEGIN_CHANGELOG EDK_M
|
||||
##
|
||||
## - Removed support for opb_iic
|
||||
##
|
||||
## @END_CHANGELOG
|
||||
|
||||
## @BEGIN_CHANGELOG EDK_MS3
|
||||
##
|
||||
## 06/16/10 sv Added support for axi_iic
|
||||
##
|
||||
## @END_CHANGELOG
|
||||
|
||||
OPTION psf_version = 2.1;
|
||||
|
||||
BEGIN driver iic
|
||||
|
||||
OPTION supported_peripherals = (axi_iic);
|
||||
OPTION driver_state = ACTIVE;
|
||||
OPTION copyfiles = all;
|
||||
OPTION VERSION = 3.1;
|
||||
OPTION NAME = iic;
|
||||
|
||||
END driver
|
56
XilinxProcessorIPLib/drivers/iic/data/iic.tcl
Executable file
56
XilinxProcessorIPLib/drivers/iic/data/iic.tcl
Executable file
|
@ -0,0 +1,56 @@
|
|||
###############################################################################
|
||||
#
|
||||
# Copyright (C) 2004 - 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
|
||||
# -------- ------ -------- ------------------------------------
|
||||
# 3.0 adk 12/10/13 Updated as per the New Tcl API's
|
||||
##############################################################################
|
||||
## @BEGIN_CHANGELOG EDK_M
|
||||
## Removed the local xdefine_canonical_xpars API as there is
|
||||
## a common API in the tcl of the tools
|
||||
##
|
||||
## @END_CHANGELOG
|
||||
|
||||
## @BEGIN_CHANGELOG EDK_LS3
|
||||
## Updated to handle the corner cases described in CR #518193 while
|
||||
## generating canonical definitions
|
||||
##
|
||||
## @END_CHANGELOG
|
||||
|
||||
#uses "xillib.tcl"
|
||||
|
||||
proc generate {drv_handle} {
|
||||
xdefine_include_file $drv_handle "xparameters.h" "XIic" "NUM_INSTANCES" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_TEN_BIT_ADR" "C_GPO_WIDTH"
|
||||
xdefine_config_file $drv_handle "xiic_g.c" "XIic" "DEVICE_ID" "C_BASEADDR" "C_TEN_BIT_ADR" "C_GPO_WIDTH"
|
||||
|
||||
xdefine_canonical_xpars $drv_handle "xparameters.h" "Iic" "DEVICE_ID" "C_BASEADDR" "C_HIGHADDR" "C_TEN_BIT_ADR" "C_GPO_WIDTH"
|
||||
}
|
41
XilinxProcessorIPLib/drivers/iic/data/iic_header.h
Normal file
41
XilinxProcessorIPLib/drivers/iic/data/iic_header.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 - 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 IIC_HEADER_H /* prevent circular inclusions */
|
||||
#define IIC_HEADER_H /* by using protection macros */
|
||||
|
||||
#include "xil_types.h"
|
||||
#include "xil_assert.h"
|
||||
#include "xstatus.h"
|
||||
|
||||
int IicSelfTestExample(u16 DeviceId);
|
||||
|
||||
#endif
|
140
XilinxProcessorIPLib/drivers/iic/data/iic_tapp.tcl
Executable file
140
XilinxProcessorIPLib/drivers/iic/data/iic_tapp.tcl
Executable file
|
@ -0,0 +1,140 @@
|
|||
###############################################################################
|
||||
#
|
||||
# Copyright (C) 2005 - 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
|
||||
# -------- ------ -------- ------------------------------------
|
||||
# 3.0 adk 12/10/13 Updated as per the New Tcl API's
|
||||
##############################################################################
|
||||
|
||||
## @BEGIN_CHANGELOG EDK_I
|
||||
##
|
||||
## - include header files
|
||||
##
|
||||
## @END_CHANGELOG
|
||||
|
||||
## @BEGIN_CHANGELOG EDK_H
|
||||
##
|
||||
## - Added support for generation of multiple applications.
|
||||
## All TCL procedures are now required to have a software
|
||||
## project type as its first argument
|
||||
##
|
||||
## @END_CHANGELOG
|
||||
|
||||
# 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 {iic_header.h}
|
||||
return $inc_file_lines
|
||||
}
|
||||
}
|
||||
|
||||
proc gen_src_files {swproj mhsinst} {
|
||||
if {$swproj == 0} {
|
||||
return ""
|
||||
}
|
||||
if {$swproj == 1} {
|
||||
set inc_file_lines {examples/xiic_selftest_example.c data/iic_header.h}
|
||||
return $inc_file_lines
|
||||
}
|
||||
}
|
||||
|
||||
proc gen_testfunc_def {swproj mhsinst} {
|
||||
return ""
|
||||
}
|
||||
|
||||
proc gen_init_code {swproj mhsinst} {
|
||||
return ""
|
||||
}
|
||||
|
||||
proc gen_testfunc_call {swproj mhsinst} {
|
||||
|
||||
if {$swproj == 0} {
|
||||
return ""
|
||||
}
|
||||
|
||||
set ipname [get_property NAME $mhsinst]
|
||||
set deviceid [::hsi::utils::get_ip_param_name $mhsinst "DEVICE_ID"]
|
||||
set stdout [get_property CONFIG.STDOUT [get_os]]
|
||||
if { $stdout == "" || $stdout == "none" } {
|
||||
set hasStdout 0
|
||||
} else {
|
||||
set hasStdout 1
|
||||
}
|
||||
|
||||
set testfunc_call ""
|
||||
|
||||
if {${hasStdout} == 0} {
|
||||
|
||||
append testfunc_call "
|
||||
|
||||
{
|
||||
int status;
|
||||
|
||||
status = IicSelfTestExample(${deviceid});
|
||||
|
||||
}"
|
||||
} else {
|
||||
|
||||
append testfunc_call "
|
||||
|
||||
{
|
||||
int status;
|
||||
|
||||
|
||||
print(\"\\r\\n Running IicSelfTestExample() for ${ipname}...\\r\\n\");
|
||||
|
||||
status = IicSelfTestExample(${deviceid});
|
||||
|
||||
if (status == 0) {
|
||||
print(\"IicSelfTestExample PASSED\\r\\n\");
|
||||
}
|
||||
else {
|
||||
print(\"IicSelfTestExample FAILED\\r\\n\");
|
||||
}
|
||||
}"
|
||||
}
|
||||
|
||||
return $testfunc_call
|
||||
}
|
27
XilinxProcessorIPLib/drivers/iic/examples/index.html
Executable file
27
XilinxProcessorIPLib/drivers/iic/examples/index.html
Executable file
|
@ -0,0 +1,27 @@
|
|||
<!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 iic_v3_0 </h1>
|
||||
<HR>
|
||||
<ul>
|
||||
<li>xiic_dynamic_eeprom_example.c <a href="xiic_dynamic_eeprom_example.c">(source)</a> </li>
|
||||
<li>xiic_low_level_eeprom_example.c <a href="xiic_low_level_eeprom_example.c">(source)</a> </li>
|
||||
<li>xiic_multi_master_example.c <a href="xiic_multi_master_example.c">(source)</a> </li>
|
||||
<li>xiic_eeprom_example.c <a href="xiic_eeprom_example.c">(source)</a> </li>
|
||||
<li>xiic_low_level_dynamic_eeprom_example.c <a href="xiic_low_level_dynamic_eeprom_example.c">(source)</a> </li>
|
||||
<li>xiic_low_level_tempsensor_example.c <a href="xiic_low_level_tempsensor_example.c">(source)</a> </li>
|
||||
<li>xiic_repeated_start_example.c <a href="xiic_repeated_start_example.c">(source)</a> </li>
|
||||
<li>xiic_selftest_example.c <a href="xiic_selftest_example.c">(source)</a> </li>
|
||||
<li>xiic_slave_example.c <a href="xiic_slave_example.c">(source)</a> </li>
|
||||
<li>xiic_tempsensor_example.c <a href="xiic_tempsensor_example.c">(source)</a> </li>
|
||||
<li>xiic_tenbitaddr_example.c <a href="xiic_tenbitaddr_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>
|
|
@ -0,0 +1,666 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_dynamic_eeprom_example.c
|
||||
*
|
||||
* This file consists of a Interrupt mode design example which uses the Xilinx
|
||||
* IIC device and XIic driver to exercise the EEPROM in Dynamic controller mode.
|
||||
* The XIic driver uses the complete FIFO functionality to transmit/receive data.
|
||||
*
|
||||
* This example writes/reads from the lower 256 bytes of the IIC EEPROMS. Please
|
||||
* refer to the datasheets of the IIC EEPROM's for details about the internal
|
||||
* addressing and page size of these devices.
|
||||
*
|
||||
* The XIic_DynMasterSend() API is used to transmit the data and
|
||||
* XIic_DynMasterRecv() API is used to receive the data.
|
||||
*
|
||||
* This example is tested on ML300/ML310/ML403/ML501/ML507/ML510/ML605/SP601 and
|
||||
* SP605 Xilinx boards.
|
||||
*
|
||||
* The ML310/ML410/ML510 boards have a on-board 64 Kb serial IIC EEPROM
|
||||
* (Microchip 24LC64A). The WP pin of the IIC EEPROM is hardwired to ground on
|
||||
* this board.
|
||||
*
|
||||
* The ML300 board has an on-board 32 Kb serial IIC EEPROM(Microchip 24LC32A).
|
||||
* The WP pin of the IIC EEPROM has to be connected to ground for this example.
|
||||
* The WP is connected to pin Y3 of the FPGA.
|
||||
*
|
||||
* The ML403 board has an on-board 4 Kb serial IIC EEPROM(Microchip 24LC04A).
|
||||
* The WP pin of the IIC EEPROM is hardwired to ground on this board.
|
||||
*
|
||||
* The ML501/ML505/ML507/ML605/SP601/SP605 boards have an on-board 8 Kb serial
|
||||
* IIC EEPROM(STM M24C08). The WP pin of the IIC EEPROM is hardwired to ground
|
||||
* on these boards.
|
||||
*
|
||||
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
|
||||
* address pointer in the on board EEPROM is 2 bytes.
|
||||
*
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
|
||||
* be u8 as the address pointer for the on board EEPROM is 1 byte.
|
||||
*
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML410/
|
||||
* ML501/ML505/ML507/ML510 boards is 0x50.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML605/SP601/SP605 boards
|
||||
* is 0x54.
|
||||
* Refer to the User Guide's of the respective boards for further information
|
||||
* about the IIC slave address of IIC EEPROM's.
|
||||
*
|
||||
* The define EEPROM_ADDRESS in this file needs to be changed depending on
|
||||
* the board on which this example is to be run.
|
||||
*
|
||||
* This code assumes that no Operating System is being used.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- ---------------------------------------------------------
|
||||
* 1.00a mta 04/13/06 Created.
|
||||
* 2.00a ktn 11/17/09 Updated to use the HAL APIs.
|
||||
* 2.01a ktn 03/17/10 Updated the information about the EEPROM's used on
|
||||
* ML605/SP601/SP605 boards. Updated the example so that it
|
||||
* can be used to access the entire IIC EEPROM for devices
|
||||
* like M24C04/M24C08 that use LSB bits of the IIC device
|
||||
* select code (IIC slave address) to specify the higher
|
||||
* address bits of the EEPROM internal address.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.h"
|
||||
#include "xintc.h"
|
||||
#include "xil_exception.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_IIC_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
|
||||
#define IIC_INTR_ID XPAR_INTC_0_IIC_0_VEC_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.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML510/
|
||||
* ML501/ML505/ML507/ML510 boards is 0x50. The 7 bit IIC Slave address of the
|
||||
* IIC EEPROM on the ML605/SP601/SP605 boards is 0x54.
|
||||
* Please refer the User Guide's of the respective boards for further
|
||||
* information about the IIC slave address of IIC EEPROM's.
|
||||
*/
|
||||
#define EEPROM_ADDRESS 0x50 /* 0xA0 as an 8 bit number. */
|
||||
|
||||
/*
|
||||
* The page size determines how much data should be written at a time.
|
||||
* The ML310/ML300 board supports a page size of 32 and 16.
|
||||
* 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_TEST_START_ADDRESS 128
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/*
|
||||
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
|
||||
* address pointer in the on board EEPROM is 2 bytes.
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards 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 IicDynEepromExample();
|
||||
|
||||
int DynEepromWriteData(u16 ByteCount);
|
||||
|
||||
int DynEepromReadData(u8 *BufferPtr, u16 ByteCount);
|
||||
|
||||
static int SetupInterruptSystem(XIic *IicInstPtr);
|
||||
|
||||
static void SendHandler(XIic *InstancePtr);
|
||||
|
||||
static void ReceiveHandler(XIic *InstancePtr);
|
||||
|
||||
static void StatusHandler(XIic *InstancePtr, int Event);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
XIic IicInstance; /* The instance of the IIC device. */
|
||||
XIntc 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 */
|
||||
|
||||
u8 EepromIicAddr; /* Variable for storing Eeprom IIC address */
|
||||
|
||||
/************************** Function Definitions *****************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to call the Dynamic EEPROM example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Run the Dynamic EEPROM example.
|
||||
*/
|
||||
Status = IicDynEepromExample();
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes, reads, and verifies the data to the IIC EEPROM in
|
||||
* Dynamic controller mode. 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 IicDynEepromExample()
|
||||
{
|
||||
u8 Index;
|
||||
int Status;
|
||||
XIic_Config *ConfigPtr; /* Pointer to configuration data */
|
||||
AddressType Address = EEPROM_TEST_START_ADDRESS;
|
||||
EepromIicAddr = EEPROM_ADDRESS;
|
||||
|
||||
/*
|
||||
* Initialize the IIC driver so that it is ready to use.
|
||||
*/
|
||||
ConfigPtr = XIic_LookupConfig(IIC_DEVICE_ID);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIic_CfgInitialize(&IicInstance, ConfigPtr,
|
||||
ConfigPtr->BaseAddress);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
/*
|
||||
* Initialize the Dynamic IIC core.
|
||||
*/
|
||||
Status = XIic_DynamicInitialize(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup the Interrupt System.
|
||||
*/
|
||||
Status = SetupInterruptSystem(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Handlers for transmit and reception.
|
||||
*/
|
||||
XIic_SetSendHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) SendHandler);
|
||||
XIic_SetRecvHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) ReceiveHandler);
|
||||
XIic_SetStatusHandler(&IicInstance, &IicInstance,
|
||||
(XIic_StatusHandler) StatusHandler);
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the data to write and the read buffer.
|
||||
*/
|
||||
if (sizeof(Address) == 1) {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
EepromIicAddr |= (EEPROM_TEST_START_ADDRESS >> 8) & 0x7;
|
||||
} else {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS >> 8);
|
||||
WriteBuffer[1] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < PAGE_SIZE; Index++) {
|
||||
WriteBuffer[sizeof(Address) + Index] = 0xFF;
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Slave address.
|
||||
*/
|
||||
Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE,
|
||||
EepromIicAddr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to the EEPROM.
|
||||
*/
|
||||
Status = DynEepromWriteData(sizeof(Address) + PAGE_SIZE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the EEPROM.
|
||||
*/
|
||||
Status = DynEepromReadData(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;
|
||||
}
|
||||
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the data to write and the read buffer.
|
||||
*/
|
||||
if (sizeof(Address) == 1) {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
} else {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS >> 8);
|
||||
WriteBuffer[1] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < PAGE_SIZE; Index++) {
|
||||
WriteBuffer[sizeof(Address) + Index] = Index;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to the EEPROM.
|
||||
*/
|
||||
Status = DynEepromWriteData(sizeof(Address) + PAGE_SIZE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the EEPROM.
|
||||
*/
|
||||
Status = DynEepromReadData(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;
|
||||
}
|
||||
|
||||
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 DynEepromWriteData(u16 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Set the defaults.
|
||||
*/
|
||||
TransmitComplete = 1;
|
||||
IicInstance.Stats.TxErrors = 0;
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the Data.
|
||||
*/
|
||||
Status = XIic_DynMasterSend(&IicInstance, WriteBuffer, ByteCount);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the transmission is completed.
|
||||
*/
|
||||
while ((TransmitComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
/*
|
||||
* This condition is required to be checked in the case where we
|
||||
* are writing two consecutive buffers of data to the EEPROM.
|
||||
* The EEPROM takes about 2 milliseconds time to update the data
|
||||
* internally after a STOP has been sent on the bus.
|
||||
* A NACK will be generated in the case of a second write before
|
||||
* the EEPROM updates the data internally resulting in a
|
||||
* Transmission Error.
|
||||
*/
|
||||
if (IicInstance.Stats.TxErrors != 0) {
|
||||
|
||||
|
||||
/*
|
||||
* Enable the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if (!XIic_IsIicBusy(&IicInstance)) {
|
||||
/*
|
||||
* Send the Data.
|
||||
*/
|
||||
Status = XIic_MasterSend(&IicInstance,
|
||||
WriteBuffer,
|
||||
ByteCount);
|
||||
if (Status == XST_SUCCESS) {
|
||||
IicInstance.Stats.TxErrors = 0;
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
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 DynEepromReadData(u8 *BufferPtr, u16 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
AddressType Address = EEPROM_TEST_START_ADDRESS;
|
||||
/*
|
||||
* Set the Defaults.
|
||||
*/
|
||||
ReceiveComplete = 1;
|
||||
|
||||
/*
|
||||
* Position the Pointer in EEPROM.
|
||||
*/
|
||||
Status = DynEepromWriteData(sizeof(Address));
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive the Data.
|
||||
*/
|
||||
Status = XIic_DynMasterRecv(&IicInstance, BufferPtr, ByteCount);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till all the data is received.
|
||||
*/
|
||||
while ((ReceiveComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function setups the interrupt system so interrupts can occur for the
|
||||
* IIC device. The function is application-specific since the actual system may
|
||||
* or may not have an interrupt controller. The IIC device could be directly
|
||||
* connected to a processor without an interrupt controller. The user should
|
||||
* modify this function to fit the application.
|
||||
*
|
||||
* @param IicInstPtr contains a pointer to the instance of the IIC device
|
||||
* which is going to be connected to the interrupt controller.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SetupInterruptSystem(XIic *IicInstPtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
if (InterruptController.IsStarted == XIL_COMPONENT_IS_STARTED) {
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the interrupt controller driver so that it's ready to use.
|
||||
*/
|
||||
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = XIntc_Connect(&InterruptController, IIC_INTR_ID,
|
||||
(XInterruptHandler) XIic_InterruptHandler,
|
||||
IicInstPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the interrupt controller so interrupts are enabled for all
|
||||
* devices that cause interrupts.
|
||||
*/
|
||||
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupts for the IIC device.
|
||||
*/
|
||||
XIntc_Enable(&InterruptController, IIC_INTR_ID);
|
||||
|
||||
/*
|
||||
* Initialize the exception table.
|
||||
*/
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/*
|
||||
* Register the interrupt controller handler with the exception table.
|
||||
*/
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler) XIntc_InterruptHandler,
|
||||
&InterruptController);
|
||||
|
||||
/*
|
||||
* Enable non-critical exceptions.
|
||||
*/
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This Send handler is called asynchronously from an interrupt
|
||||
* context and indicates that data in the specified buffer has been sent.
|
||||
*
|
||||
* @param InstancePtr is not used, but contains a pointer to the IIC
|
||||
* device driver instance which the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void SendHandler(XIic *InstancePtr)
|
||||
{
|
||||
TransmitComplete = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This Receive handler is called asynchronously from an interrupt
|
||||
* context and indicates that data in the specified buffer has been Received.
|
||||
*
|
||||
* @param InstancePtr is not used, but contains a pointer to the IIC
|
||||
* device driver instance which the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void ReceiveHandler(XIic *InstancePtr)
|
||||
{
|
||||
ReceiveComplete = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This Status handler is called asynchronously from an interrupt
|
||||
* context and indicates the events that have occurred.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
* @param Event indicates the condition that has occurred.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void StatusHandler(XIic *InstancePtr, int Event)
|
||||
{
|
||||
|
||||
}
|
818
XilinxProcessorIPLib/drivers/iic/examples/xiic_eeprom_example.c
Normal file
818
XilinxProcessorIPLib/drivers/iic/examples/xiic_eeprom_example.c
Normal file
|
@ -0,0 +1,818 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_eeprom_example.c
|
||||
*
|
||||
* This file consists of a Interrupt mode design example which uses the Xilinx
|
||||
* IIC device and XIic driver to exercise the EEPROM. The XIic driver uses the
|
||||
* complete FIFO functionality to transmit/receive data.
|
||||
*
|
||||
* This example writes/reads from the lower 256 bytes of the IIC EEPROMS. Please
|
||||
* refer to the datasheets of the IIC EEPROM's for details about the internal
|
||||
* addressing and page size of these devices.
|
||||
*
|
||||
* The XIic_MasterSend() API is used to transmit the data and
|
||||
* XIic_MasterRecv() API is used to receive the data.
|
||||
*
|
||||
* This example is tested on ML300/ML310/ML410/ML403/ML501/ML507/ML510/ML605/
|
||||
* SP601, SP605, KC705 , ZC702 and ZC706 Xilinx boards.
|
||||
*
|
||||
* The ML310/ML510/ML410 boards have a on-board 64 Kb serial IIC EEPROM
|
||||
* (Microchip 24LC64A). The WP pin of the IIC EEPROM is hardwired to ground on
|
||||
* this board.
|
||||
*
|
||||
* The ML300 board has an on-board 32 Kb serial IIC EEPROM(Microchip 24LC32A).
|
||||
* The WP pin of the IIC EEPROM has to be connected to ground for this example.
|
||||
* The WP is connected to pin Y3 of the FPGA.
|
||||
*
|
||||
* The ML403 board has an on-board 4 Kb serial IIC EEPROM(Microchip 24LC04A).
|
||||
* The WP pin of the IIC EEPROM is hardwired to ground on this board.
|
||||
*
|
||||
* The ML501/ML505/ML507/ML605/SP601/SP605/KC705/ZC702/ZC706 boards have an
|
||||
* on-board 8 Kb serial IIC EEPROM(STM M24C08). The WP pin of the IIC EEPROM is
|
||||
* hardwired to ground on these boards.
|
||||
*
|
||||
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
|
||||
* address pointer in the on board EEPROM is 2 bytes.
|
||||
*
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605/KC705/ZC702/
|
||||
* ZC706 boards should be u8 as the address pointer for the on board EEPROM
|
||||
* is 1 byte.
|
||||
*
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML410/
|
||||
* ML501/ML505/ML507/ML510 boards is 0x50.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML605/SP601/SP605/KC705
|
||||
* /ZC702/ZC706 boards is 0x54.
|
||||
* Refer to the User Guide's of the respective boards for further information
|
||||
* about the IIC slave address of IIC EEPROM's.
|
||||
*
|
||||
* The define EEPROM_ADDRESS in this file needs to be changed depending on
|
||||
* the board on which this example is to be run. This is the IIC address of the
|
||||
* EEPROM.
|
||||
*
|
||||
* The define IIC_MUX_ADDRESS in this file needs to be changed depending on
|
||||
* the board on which this example is to be run. This is the IIC address of the
|
||||
* the MUX.
|
||||
*
|
||||
* The define IIC_MUX_ENABLE should be defined so that the IIC Mux initialization
|
||||
* is done for the boards on the which the EEPROM is connected to an IIC Mux.
|
||||
* The boards with a MUX are a KC705/ZC702/ZC706.
|
||||
*
|
||||
* The define IIC_EEPROM_CHANNEL needs to be changed depending on the Channel
|
||||
* number of EEPROM for IIC Mux. On KC705 it is 0x08 and ZC702 is 0x04. Please
|
||||
* refer the User Guide's of the respective boards for further information
|
||||
* about the Channel number to use EEPROM.
|
||||
*
|
||||
* This code assumes that no Operating System is being used.
|
||||
*
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- ---------------------------------------------------------
|
||||
* 1.00a mta 02/24/06 Created.
|
||||
* 1.00a mta 04/05/07 Added support for microblaze.
|
||||
* 2.00a ktn 11/17/09 Updated to use the HAL APIs and replaced call to
|
||||
* XIic_Initialize API with XIic_LookupConfig and
|
||||
* XIic_CfgInitialize.
|
||||
* 2.01a ktn 03/17/10 Updated the information about the EEPROM's used on
|
||||
* ML605/SP601/SP605 boards. Updated the example so that it
|
||||
* can be used to access the entire IIC EEPROM for devices
|
||||
* like M24C04/M24C08 that use LSB bits of the IIC device
|
||||
* select code (IIC slave address) to specify the higher
|
||||
* address bits of the EEPROM internal address.
|
||||
* 2.02a bss 01/30/13 Updated for using the GIC in case of Zynq
|
||||
* 2.06a bss 02/14/13 Added MuxInit API to support Zynq and KC705 boards and
|
||||
* modified to use ScuGic in case of Zynq CR# 683509
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.h"
|
||||
#include "xil_exception.h"
|
||||
|
||||
#ifdef XPAR_INTC_0_DEVICE_ID
|
||||
#include "xintc.h"
|
||||
#else
|
||||
#include "xscugic.h"
|
||||
#endif
|
||||
|
||||
/************************** 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_IIC_0_DEVICE_ID
|
||||
|
||||
|
||||
|
||||
#ifdef XPAR_INTC_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
|
||||
#define IIC_INTR_ID XPAR_INTC_0_IIC_0_VEC_ID
|
||||
#define INTC XIntc
|
||||
#define INTC_HANDLER XIntc_InterruptHandler
|
||||
#else
|
||||
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
|
||||
#define IIC_INTR_ID XPAR_FABRIC_IIC_0_VEC_ID
|
||||
#define INTC XScuGic
|
||||
#define INTC_HANDLER XScuGic_InterruptHandler
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML410/
|
||||
* ML501/ML505/ML507/ML510 boards is 0x50. The 7 bit IIC Slave address of the
|
||||
* IIC EEPROM on the ML605/SP601/SP605/KC705/ZC702/ZC706 boards is 0x54.
|
||||
* Please refer the User Guide's of the respective boards for further
|
||||
* information about the IIC slave address of IIC EEPROM's.
|
||||
*/
|
||||
#define EEPROM_ADDRESS 0x54 /* 0xA0 as an 8 bit number. */
|
||||
|
||||
|
||||
/*
|
||||
* The IIC_MUX_ADDRESS defines the address of the IIC MUX device on the
|
||||
* IIC bus. Note that since the address is only 7 bits, this constant is the
|
||||
* address divided by 2.
|
||||
* The IIC Slaves on the KC705/ZC702/ZC706 boards are connected to an
|
||||
* IIC MUX.
|
||||
* IIC_EEPROM_CHANNEL is the Channel number of EEPROM for IIC Mux. On KC705 it
|
||||
* is 0x08 and ZC702 is 0x04.Please refer the User Guide's of the respective
|
||||
* boards for further information about the Channel number to use EEPROM.
|
||||
*/
|
||||
#define IIC_MUX_ADDRESS 0x74
|
||||
#define IIC_EEPROM_CHANNEL 0x08
|
||||
|
||||
/*
|
||||
* This define should be uncommented if there is IIC MUX on the board to which
|
||||
* this EEPROM is connected. The boards that have IIC MUX are KC705/ZC702/ZC706.
|
||||
*/
|
||||
/* #define IIC_MUX_ENABLE */
|
||||
|
||||
/*
|
||||
* The page size determines how much data should be written at a time.
|
||||
* The ML310/ML300 board supports a page size of 32 and 16.
|
||||
* 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_TEST_START_ADDRESS 128
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/*
|
||||
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the address
|
||||
* pointer in the on board EEPROM is 2 bytes.
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605/KC705/ZC702
|
||||
* /ZC706 boards 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 IicEepromExample();
|
||||
|
||||
int EepromWriteData(u16 ByteCount);
|
||||
|
||||
int EepromReadData(u8 *BufferPtr, u16 ByteCount);
|
||||
|
||||
static int SetupInterruptSystem(XIic *IicInstPtr);
|
||||
|
||||
static void SendHandler(XIic *InstancePtr);
|
||||
|
||||
static void ReceiveHandler(XIic *InstancePtr);
|
||||
|
||||
static void StatusHandler(XIic *InstancePtr, int Event);
|
||||
|
||||
#ifdef IIC_MUX_ENABLE
|
||||
static int MuxInit(void);
|
||||
#endif
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
XIic IicInstance; /* The instance of the IIC device. */
|
||||
INTC Intc; /* The instance of the Interrupt Controller Driver */
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
|
||||
u8 EepromIicAddr; /* Variable for storing Eeprom IIC address */
|
||||
|
||||
/************************** Function Definitions *****************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Main function to call the High level EEPROM example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Run the EEPROM example.
|
||||
*/
|
||||
Status = IicEepromExample();
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
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 IicEepromExample()
|
||||
{
|
||||
u32 Index;
|
||||
int Status;
|
||||
XIic_Config *ConfigPtr; /* Pointer to configuration data */
|
||||
AddressType Address = EEPROM_TEST_START_ADDRESS;
|
||||
EepromIicAddr = EEPROM_ADDRESS;
|
||||
|
||||
/*
|
||||
* Initialize the IIC driver so that it is ready to use.
|
||||
*/
|
||||
ConfigPtr = XIic_LookupConfig(IIC_DEVICE_ID);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIic_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Handlers for transmit and reception.
|
||||
*/
|
||||
XIic_SetSendHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) SendHandler);
|
||||
XIic_SetRecvHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) ReceiveHandler);
|
||||
XIic_SetStatusHandler(&IicInstance, &IicInstance,
|
||||
(XIic_StatusHandler) StatusHandler);
|
||||
|
||||
|
||||
#ifdef IIC_MUX_ENABLE
|
||||
/*
|
||||
* Initialize the IIC MUX on the boards on which the EEPROM
|
||||
* are connected through the MUX.
|
||||
*/
|
||||
Status = MuxInit();
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize the data to write and the read buffer.
|
||||
*/
|
||||
if (sizeof(Address) == 1) {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
EepromIicAddr |= (EEPROM_TEST_START_ADDRESS >> 8) & 0x7;
|
||||
} else {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS >> 8);
|
||||
WriteBuffer[1] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < PAGE_SIZE; Index++) {
|
||||
WriteBuffer[sizeof(Address) + Index] = 0xFF;
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Slave address.
|
||||
*/
|
||||
Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE,
|
||||
EepromIicAddr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the data to write and the read buffer.
|
||||
*/
|
||||
if (sizeof(Address) == 1) {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
} else {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS >> 8);
|
||||
WriteBuffer[1] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < PAGE_SIZE; Index++) {
|
||||
WriteBuffer[sizeof(Address) + Index] = Index;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* Set the defaults.
|
||||
*/
|
||||
TransmitComplete = 1;
|
||||
IicInstance.Stats.TxErrors = 0;
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the Data.
|
||||
*/
|
||||
Status = XIic_MasterSend(&IicInstance, WriteBuffer, ByteCount);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till the transmission is completed.
|
||||
*/
|
||||
while ((TransmitComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
/*
|
||||
* This condition is required to be checked in the case where we
|
||||
* are writing two consecutive buffers of data to the EEPROM.
|
||||
* The EEPROM takes about 2 milliseconds time to update the data
|
||||
* internally after a STOP has been sent on the bus.
|
||||
* A NACK will be generated in the case of a second write before
|
||||
* the EEPROM updates the data internally resulting in a
|
||||
* Transmission Error.
|
||||
*/
|
||||
if (IicInstance.Stats.TxErrors != 0) {
|
||||
|
||||
|
||||
/*
|
||||
* Enable the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if (!XIic_IsIicBusy(&IicInstance)) {
|
||||
/*
|
||||
* Send the Data.
|
||||
*/
|
||||
Status = XIic_MasterSend(&IicInstance,
|
||||
WriteBuffer,
|
||||
ByteCount);
|
||||
if (Status == XST_SUCCESS) {
|
||||
IicInstance.Stats.TxErrors = 0;
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
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_TEST_START_ADDRESS;
|
||||
|
||||
/*
|
||||
* Set the Defaults.
|
||||
*/
|
||||
ReceiveComplete = 1;
|
||||
|
||||
/*
|
||||
* Position the Pointer in EEPROM.
|
||||
*/
|
||||
if (sizeof(Address) == 1) {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
}
|
||||
else {
|
||||
WriteBuffer[0] = (u8) (EEPROM_TEST_START_ADDRESS >> 8);
|
||||
WriteBuffer[1] = (u8) (EEPROM_TEST_START_ADDRESS);
|
||||
}
|
||||
|
||||
Status = EepromWriteData(sizeof(Address));
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive the Data.
|
||||
*/
|
||||
Status = XIic_MasterRecv(&IicInstance, BufferPtr, ByteCount);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till all the data is received.
|
||||
*/
|
||||
while ((ReceiveComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function setups the interrupt system so interrupts can occur for the
|
||||
* IIC device. The function is application-specific since the actual system may
|
||||
* or may not have an interrupt controller. The IIC device could be directly
|
||||
* connected to a processor without an interrupt controller. The user should
|
||||
* modify this function to fit the application.
|
||||
*
|
||||
* @param IicInstPtr contains a pointer to the instance of the IIC device
|
||||
* which is going to be connected to the interrupt controller.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SetupInterruptSystem(XIic *IicInstPtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
#ifdef XPAR_INTC_0_DEVICE_ID
|
||||
|
||||
/*
|
||||
* Initialize the interrupt controller driver so that it's ready to use.
|
||||
*/
|
||||
Status = XIntc_Initialize(&Intc, INTC_DEVICE_ID);
|
||||
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = XIntc_Connect(&Intc, IIC_INTR_ID,
|
||||
(XInterruptHandler) XIic_InterruptHandler,
|
||||
IicInstPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the interrupt controller so interrupts are enabled for all
|
||||
* devices that cause interrupts.
|
||||
*/
|
||||
Status = XIntc_Start(&Intc, XIN_REAL_MODE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupts for the IIC device.
|
||||
*/
|
||||
XIntc_Enable(&Intc, IIC_INTR_ID);
|
||||
|
||||
#else
|
||||
|
||||
XScuGic_Config *IntcConfig;
|
||||
|
||||
/*
|
||||
* 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(&Intc, IntcConfig,
|
||||
IntcConfig->CpuBaseAddress);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
XScuGic_SetPriorityTriggerType(&Intc, IIC_INTR_ID,
|
||||
0xA0, 0x3);
|
||||
|
||||
/*
|
||||
* Connect the interrupt handler that will be called when an
|
||||
* interrupt occurs for the device.
|
||||
*/
|
||||
Status = XScuGic_Connect(&Intc, IIC_INTR_ID,
|
||||
(Xil_InterruptHandler)XIic_InterruptHandler,
|
||||
IicInstPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupt for the IIC device.
|
||||
*/
|
||||
XScuGic_Enable(&Intc, IIC_INTR_ID);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize the exception table and register the interrupt
|
||||
* controller handler with the exception table
|
||||
*/
|
||||
Xil_ExceptionInit();
|
||||
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler)INTC_HANDLER, &Intc);
|
||||
|
||||
/* Enable non-critical exceptions */
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This Send handler is called asynchronously from an interrupt
|
||||
* context and indicates that data in the specified buffer has been sent.
|
||||
*
|
||||
* @param InstancePtr is not used, but contains a pointer to the IIC
|
||||
* device driver instance which the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void SendHandler(XIic *InstancePtr)
|
||||
{
|
||||
TransmitComplete = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This Receive handler is called asynchronously from an interrupt
|
||||
* context and indicates that data in the specified buffer has been Received.
|
||||
*
|
||||
* @param InstancePtr is not used, but contains a pointer to the IIC
|
||||
* device driver instance which the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void ReceiveHandler(XIic *InstancePtr)
|
||||
{
|
||||
ReceiveComplete = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This Status handler is called asynchronously from an interrupt
|
||||
* context and indicates the events that have occurred.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
* @param Event indicates the condition that has occurred.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void StatusHandler(XIic *InstancePtr, int Event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#ifdef IIC_MUX_ENABLE
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function initializes the IIC MUX to select EEPROM.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if pass, otherwise XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int MuxInit(void)
|
||||
{
|
||||
|
||||
int Status;
|
||||
/*
|
||||
* Set the Slave address to the IIC MUC - PCA9543A.
|
||||
*/
|
||||
Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE,
|
||||
IIC_MUX_ADDRESS);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Enabling all the channels
|
||||
*/
|
||||
WriteBuffer[0] = IIC_EEPROM_CHANNEL;
|
||||
|
||||
Status = EepromWriteData(1);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,381 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_low_level_dynamic_eeprom_example.c
|
||||
*
|
||||
* This file consists of a polled mode design example which uses the Xilinx
|
||||
* IIC device in dynamic mode and low-level driver to exercise the EEPROM.
|
||||
*
|
||||
* The XIic_DynSend() API is used to transmit the data and XIic_DynRecv() API
|
||||
* is used to receive the data.
|
||||
*
|
||||
* The example is tested on ML300/ML310/ML403/ML501/ML507/ML510 Xilinx boards.
|
||||
*
|
||||
* The ML310/ML410/ML510 boards have a on-board 64 Kb serial IIC EEPROM
|
||||
* (Microchip 24LC64A). The WP pin of the IIC EEPROM is hardwired to ground on
|
||||
* this board.
|
||||
*
|
||||
* The ML300 board has an on-board 32 Kb serial IIC EEPROM(Microchip 24LC32A).
|
||||
* The WP pin of the IIC EEPROM has to be connected to ground for this example.
|
||||
* The WP is connected to pin Y3 of the FPGA.
|
||||
*
|
||||
* The ML403 board has an on-board 4 Kb serial IIC EEPROM(Microchip 24LC04A).
|
||||
* The WP pin of the IIC EEPROM is hardwired to ground on this board.
|
||||
*
|
||||
* The ML501/ML505/ML507/ML605/SP601/SP605 boards have an on-board 8 Kb serial
|
||||
* IIC EEPROM(STM M24C08). The WP pin of the IIC EEPROM is hardwired to
|
||||
* ground on these boards.
|
||||
*
|
||||
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
|
||||
* address pointer in the on board EEPROM is 2 bytes.
|
||||
*
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
|
||||
* be u8 as the address pointer for the on board EEPROM is 1 byte.
|
||||
*
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML410/ML403/
|
||||
* ML501/ML505/ML507/ML510 boards is 0x50.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML605/SP601/SP605 boards
|
||||
* is 0x54.
|
||||
* Refer to the User Guide's of the respective boards for further information
|
||||
* about the IIC slave address of IIC EEPROM's.
|
||||
*
|
||||
* The define EEPROM_ADDRESS in this file needs to be changed depending on
|
||||
* the board on which this example is to be run.
|
||||
*
|
||||
* This code assumes that no Operating System is being used.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- ---------------------------------------------------------
|
||||
* 1.00a mta 03/20/06 Created.
|
||||
* 2.00a sdm 09/22/09 Converted all register accesses to 32 bit access.
|
||||
* 2.01a ktn 03/17/10 Updated the information about the EEPROM's used on
|
||||
* ML605/SP601/SP605 boards. Updated the example so that it
|
||||
* can be used to access the entire IIC EEPROM for devices
|
||||
* like M24C04/M24C08 that use LSB bits of the IIC device
|
||||
* select code (IIC slave address) to specify the higher
|
||||
* address bits of the EEPROM internal address.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.h"
|
||||
#include "xil_io.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_BASE_ADDRESS XPAR_IIC_0_BASEADDR
|
||||
|
||||
/*
|
||||
* The Starting address in the IIC EEPROM on which this test is performed.
|
||||
*/
|
||||
#define EEPROM_TEST_START_ADDRESS 0x80
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML410/
|
||||
* ML501/ML505/ML507/ML510 boards is 0x50. The 7 bit IIC Slave address of the IIC
|
||||
* EEPROM on the ML605/SP601/SP605 boards is 0x54.
|
||||
* Please refer the User Guide's of the respective boards for further
|
||||
* information about the IIC slave address of IIC EEPROM's.
|
||||
*/
|
||||
#define EEPROM_ADDRESS 0x50
|
||||
|
||||
/*
|
||||
* The page size determines how much data should be written at a time.
|
||||
* The ML310/ML300 board supports a page size of 32 and 16.
|
||||
* The write function should be called with this as a maximum byte count.
|
||||
*/
|
||||
#define PAGE_SIZE 16
|
||||
|
||||
#define IIC_SLAVE_ADDRESS 1
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/*
|
||||
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the address
|
||||
* pointer in the on board EEPROM is 2 bytes.
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
|
||||
* be u8 as the address pointer in the on board EEPROM is 1 bytes.
|
||||
*/
|
||||
typedef u8 AddressType;
|
||||
|
||||
u8 EepromIicAddr; /* Variable for storing Eeprom IIC address */
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
int IicLowLevelDynEeprom();
|
||||
|
||||
u8 EepromReadByte(u8 *BufferPtr, u8 ByteCount);
|
||||
u8 EepromWriteByte(u8 *BufferPtr, u8 ByteCount);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
u8 WriteBuffer[PAGE_SIZE]; /* Write buffer for writing a page. */
|
||||
|
||||
u8 ReadBuffer[PAGE_SIZE]; /* Read buffer for reading a page. */
|
||||
|
||||
/************************** Function Definitions *****************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Main function to call the low level Dynamic EEPROM example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Perform the Read and Write operation.
|
||||
*/
|
||||
Status = IicLowLevelDynEeprom();
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* The function uses the low level driver of IIC to read from the IIC EEPROM on
|
||||
* the ML300/ML310 board. The addresses tested starts from 128.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IicLowLevelDynEeprom()
|
||||
{
|
||||
u8 BytesRead;
|
||||
u8 BytesWritten;
|
||||
u32 StatusReg;
|
||||
u8 Index;
|
||||
int Status;
|
||||
EepromIicAddr = EEPROM_ADDRESS;
|
||||
|
||||
/*
|
||||
* Initialize the IIC Core.
|
||||
*/
|
||||
Status = XIic_DynInit(IIC_BASE_ADDRESS);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure all the Fifo's are cleared and Bus is Not busy.
|
||||
*/
|
||||
while (((StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS,
|
||||
XIIC_SR_REG_OFFSET)) &
|
||||
(XIIC_SR_RX_FIFO_EMPTY_MASK |
|
||||
XIIC_SR_TX_FIFO_EMPTY_MASK |
|
||||
XIIC_SR_BUS_BUSY_MASK)) !=
|
||||
(XIIC_SR_RX_FIFO_EMPTY_MASK |
|
||||
XIIC_SR_TX_FIFO_EMPTY_MASK)) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the data to written and the read buffer.
|
||||
*/
|
||||
for (Index = 0; Index < PAGE_SIZE; Index++) {
|
||||
WriteBuffer[Index] = Index;
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to the EEPROM.
|
||||
*/
|
||||
BytesWritten = EepromWriteByte(WriteBuffer, PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Read from the EEPROM.
|
||||
*/
|
||||
BytesRead = EepromReadByte(ReadBuffer, PAGE_SIZE);
|
||||
if (BytesRead != PAGE_SIZE) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the data read against the data written.
|
||||
*/
|
||||
for (Index = 0; Index < PAGE_SIZE; Index++) {
|
||||
if (ReadBuffer[Index] != WriteBuffer[Index]) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes a buffer of bytes to the IIC serial EEPROM.
|
||||
*
|
||||
* @param BufferPtr contains the address of the data to write.
|
||||
* @param ByteCount contains the number of bytes in the buffer to be
|
||||
* written. Note that this should not exceed the page size of the
|
||||
* EEPROM as noted by the constant PAGE_SIZE.
|
||||
*
|
||||
* @return The number of bytes written, a value less than that which was
|
||||
* specified as an input indicates an error.
|
||||
*
|
||||
* @note one.
|
||||
*
|
||||
******************************************************************************/
|
||||
u8 EepromWriteByte(u8 *BufferPtr, u8 ByteCount)
|
||||
{
|
||||
u8 SentByteCount;
|
||||
AddressType Address = EEPROM_TEST_START_ADDRESS;
|
||||
u8 WriteBuffer[sizeof(Address) + PAGE_SIZE];
|
||||
u8 Index;
|
||||
|
||||
/*
|
||||
* A temporary write buffer must be used which contains both the address
|
||||
* and the data to be written, put the address in first based upon the
|
||||
* size of the address for the EEPROM
|
||||
*/
|
||||
if (sizeof(AddressType) == 2) {
|
||||
WriteBuffer[0] = (u8) (Address >> 8);
|
||||
WriteBuffer[1] = (u8) (Address);
|
||||
} else if (sizeof(AddressType) == 1) {
|
||||
WriteBuffer[0] = (u8) (Address);
|
||||
EepromIicAddr |= (EEPROM_TEST_START_ADDRESS >> 8) & 0x7;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the data in the write buffer following the address.
|
||||
*/
|
||||
for (Index = 0; Index < ByteCount; Index++) {
|
||||
WriteBuffer[sizeof(Address) + Index] = BufferPtr[Index];
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a page of data at the specified address to the EEPROM.
|
||||
*/
|
||||
SentByteCount = XIic_DynSend(IIC_BASE_ADDRESS, EepromIicAddr,
|
||||
WriteBuffer, sizeof(Address) + PAGE_SIZE,
|
||||
XIIC_STOP);
|
||||
|
||||
/*
|
||||
* Return the number of bytes written to the EEPROM.
|
||||
*/
|
||||
return SentByteCount - sizeof(Address);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function reads a number of bytes 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.
|
||||
* This value is constrained by the page size of the device such
|
||||
* that up to 64K may be read in one call.
|
||||
*
|
||||
* @return The number of bytes read. A value less than the specified input
|
||||
* value indicates an error.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
u8 EepromReadByte(u8 *BufferPtr, u8 ByteCount)
|
||||
{
|
||||
u8 ReceivedByteCount;
|
||||
u8 SentByteCount;
|
||||
u16 StatusReg;
|
||||
AddressType Address = EEPROM_TEST_START_ADDRESS;
|
||||
|
||||
/*
|
||||
* Position the Read pointer to specific location in the EEPROM.
|
||||
*/
|
||||
do {
|
||||
StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS, XIIC_SR_REG_OFFSET);
|
||||
if (!(StatusReg & XIIC_SR_BUS_BUSY_MASK)) {
|
||||
SentByteCount = XIic_DynSend(IIC_BASE_ADDRESS,
|
||||
EepromIicAddr,
|
||||
(u8 *) &Address,
|
||||
sizeof(Address),
|
||||
XIIC_STOP);
|
||||
}
|
||||
|
||||
} while (SentByteCount != sizeof(Address));
|
||||
|
||||
StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS, XIIC_SR_REG_OFFSET);
|
||||
|
||||
while ((StatusReg & XIIC_SR_BUS_BUSY_MASK)) {
|
||||
StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS, XIIC_SR_REG_OFFSET);
|
||||
}
|
||||
|
||||
do {
|
||||
/*
|
||||
* Receive the data.
|
||||
*/
|
||||
ReceivedByteCount = XIic_DynRecv(IIC_BASE_ADDRESS,
|
||||
EepromIicAddr, BufferPtr,
|
||||
ByteCount);
|
||||
} while (ReceivedByteCount != ByteCount);
|
||||
|
||||
/*
|
||||
* Return the number of bytes received from the EEPROM.
|
||||
*/
|
||||
return ReceivedByteCount;
|
||||
}
|
|
@ -0,0 +1,515 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_low_level_eeprom_example.c
|
||||
*
|
||||
* This file consists of a polled mode design example which uses the Xilinx
|
||||
* IIC device and low-level driver to exercise the EEPROM.
|
||||
*
|
||||
* This example writes/reads from the lower 256 bytes of the IIC EEPROMS. Please
|
||||
* refer to the datasheets of the IIC EEPROM's for details about the internal
|
||||
* addressing and page size of these devices.
|
||||
*
|
||||
* The XIic_Send() API is used to transmit the data and XIic_Recv() API is used
|
||||
* to receive the data.
|
||||
*
|
||||
* This example is tested on ML300/ML310/ML403/ML501/ML507/ML510/ML605/SP601 and
|
||||
* SP605 Xilinx boards.
|
||||
*
|
||||
* The ML310/ML410/ML510 boards have a on-board 64 Kb serial IIC EEPROM
|
||||
* (Microchip 24LC64A). The WP pin of the IIC EEPROM is hardwired to ground on
|
||||
* this board.
|
||||
*
|
||||
* The ML300 board has an on-board 32 Kb serial IIC EEPROM(Microchip 24LC32A).
|
||||
* The WP pin of the IIC EEPROM has to be connected to ground for this example.
|
||||
* The WP is connected to pin Y3 of the FPGA.
|
||||
*
|
||||
* The ML403 board has an on-board 4 Kb serial IIC EEPROM(Microchip 24LC04A).
|
||||
* The WP pin of the IIC EEPROM is hardwired to ground on this board.
|
||||
*
|
||||
* The ML501/ML505/ML507/ML605/SP601/SP605 boards have an on-board 8 Kb serial
|
||||
* IIC EEPROM(STM M24C08). The WP pin of the IIC EEPROM is hardwired to
|
||||
* ground on these boards.
|
||||
*
|
||||
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
|
||||
* address pointer in the on board EEPROM is 2 bytes.
|
||||
*
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
|
||||
* be u8 as the address pointer for the on board EEPROM is 1 byte.
|
||||
*
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML410/
|
||||
* ML501/ML505/ML507/ML510 boards is 0x50.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML605/SP601/SP605 boards
|
||||
* is 0x54.
|
||||
* Refer to the User Guide's of the respective boards for further information
|
||||
* about the IIC slave address of IIC EEPROM's.
|
||||
*
|
||||
* The define EEPROM_ADDRESS in this file needs to be changed depending on
|
||||
* the board on which this example is to be run.
|
||||
*
|
||||
* This code assumes that no Operating System is being used.
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a jhl 09/10/03 Created
|
||||
* 1.00a sv 05/09/05 Minor changes to comply to Doxygen and coding guidelines
|
||||
* 1.00a mta 03/09/06 Minor updates due to changes in the low level driver for
|
||||
* supporting repeated start functionality.
|
||||
* 2.00a sdm 09/22/09 Converted all register accesses to 32 bit access and minor
|
||||
* modifications as per coding guidelines.
|
||||
* 2.01a ktn 03/17/10 Updated the information about the EEPROM's used on
|
||||
* ML605/SP601/SP605 boards. Updated the example so that it
|
||||
* can be used to access the entire IIC EEPROM for devices
|
||||
* like M24C04/M24C08 that use LSB bits of the IIC device
|
||||
* select code (IIC slave address) to specify the higher
|
||||
* address bits of the EEPROM internal address.
|
||||
* 2.01a sdm 06/13/11 Updated the example to flush the Tx FIFO when waiting for
|
||||
* the previous command to be completed for CR612546.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.h"
|
||||
#include "xil_io.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_BASE_ADDRESS XPAR_IIC_0_BASEADDR
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML410/
|
||||
* ML501/ML505/ML507/ML510 boards is 0x50. The 7 bit IIC Slave address of the
|
||||
* IIC EEPROM on the ML605/SP601/SP605 boards is 0x54.
|
||||
* Please refer the User Guide's of the respective boards for further
|
||||
* information about the IIC slave address of IIC EEPROM's.
|
||||
*/
|
||||
#define EEPROM_ADDRESS 0x54 /* 0xA0 as an 8 bit number */
|
||||
|
||||
/*
|
||||
* The page size determines how much data should be written at a time.
|
||||
* The ML300 board supports a page size of 32 and 16
|
||||
* 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_TEST_START_ADDRESS 128
|
||||
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/*
|
||||
* The AddressType for ML300/ML310/ML510 boards should be u16 as the address
|
||||
* pointer in the on board EEPROM is 2 bytes.
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards 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 IicLowLevelEeprom();
|
||||
|
||||
int ReadWriteVerify(AddressType Address);
|
||||
|
||||
unsigned EepromWriteByte(AddressType Address, u8 *BufferPtr, u16 ByteCount);
|
||||
|
||||
unsigned EepromReadByte(AddressType Address, u8 *BufferPtr, u16 ByteCount);
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
int ErrorCount; /* The Error Count */
|
||||
|
||||
u8 WriteBuffer[PAGE_SIZE]; /* Write buffer for writing a page */
|
||||
u8 ReadBuffer[PAGE_SIZE]; /* Read buffer for reading a page */
|
||||
u8 ReadBufferAll[PAGE_SIZE * 4]; /* Buffer used for reading all the data */
|
||||
|
||||
u8 EepromIicAddr; /* Variable for storing Eeprom IIC address */
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Main function to call the low level EEPROM example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Run the Low Level EEPROM example.
|
||||
*/
|
||||
Status = IicLowLevelEeprom();
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* The function uses the low level driver of IIC to read and write to the
|
||||
* IIC EEPROM board. The addresses tested are from 128 to 192.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int IicLowLevelEeprom()
|
||||
{
|
||||
int Status;
|
||||
unsigned BytesRead;
|
||||
EepromIicAddr = EEPROM_ADDRESS;
|
||||
|
||||
/*
|
||||
* Read, write and verify a page of data at the specified address.
|
||||
*/
|
||||
Status = ReadWriteVerify(EEPROM_TEST_START_ADDRESS);
|
||||
if (Status != XST_SUCCESS) {
|
||||
ErrorCount++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read, write and verify a page of data at the
|
||||
* specified address + PAGE_SIZE.
|
||||
*/
|
||||
Status = ReadWriteVerify(EEPROM_TEST_START_ADDRESS + PAGE_SIZE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
ErrorCount++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read, write and verify a page of data at the
|
||||
* specified address + (PAGE_SIZE * 3).
|
||||
*/
|
||||
Status = ReadWriteVerify(EEPROM_TEST_START_ADDRESS + (PAGE_SIZE * 3));
|
||||
if (Status != XST_SUCCESS) {
|
||||
ErrorCount++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read, write and verify a page of data at the
|
||||
* specified address + (PAGE_SIZE * 2).
|
||||
*/
|
||||
Status = ReadWriteVerify(EEPROM_TEST_START_ADDRESS + (PAGE_SIZE * 2));
|
||||
if (Status != XST_SUCCESS) {
|
||||
ErrorCount++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read all the locations that were written in a single read,
|
||||
* this data is not verified, only read to show that a larger
|
||||
* amount of data can be read.
|
||||
*/
|
||||
BytesRead = EepromReadByte(EEPROM_TEST_START_ADDRESS,
|
||||
ReadBufferAll,
|
||||
PAGE_SIZE * 4);
|
||||
if (BytesRead != PAGE_SIZE * 4) {
|
||||
ErrorCount++;
|
||||
}
|
||||
|
||||
if (ErrorCount != 0x0) {
|
||||
Status = XST_FAILURE;
|
||||
} else {
|
||||
Status = XST_SUCCESS;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes, reads, and verifies the read to the IIC EEPROM. It
|
||||
* does the write as a single page write, performs a buffered read, and also
|
||||
* performs byte reads.
|
||||
*
|
||||
* @param Address is the starting address of the page in the EEPROM device
|
||||
* to which the data is to be written.
|
||||
*
|
||||
* @return XST_FAILURE if the test fails, XST_SUCCESS if the test passes.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int ReadWriteVerify(AddressType Address)
|
||||
{
|
||||
unsigned BytesWritten;
|
||||
unsigned BytesRead;
|
||||
int Index;
|
||||
|
||||
/*
|
||||
* Initialize the data to written and the read buffer.
|
||||
*/
|
||||
for (Index = 0; Index < PAGE_SIZE; Index++) {
|
||||
WriteBuffer[Index] = Index;
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to the EEPROM.
|
||||
*/
|
||||
BytesWritten = EepromWriteByte(Address, WriteBuffer, PAGE_SIZE);
|
||||
if (BytesWritten != PAGE_SIZE) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the EEPROM.
|
||||
*/
|
||||
BytesRead = EepromReadByte(Address, ReadBuffer, PAGE_SIZE);
|
||||
if (BytesRead != PAGE_SIZE) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the data read against the data written.
|
||||
*/
|
||||
for (Index = 0; Index < PAGE_SIZE; Index++)
|
||||
{
|
||||
if (ReadBuffer[Index] != WriteBuffer[Index]) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read each byte one at a time and verify.
|
||||
*/
|
||||
for (Index = 0; Index < PAGE_SIZE; Index++)
|
||||
{
|
||||
BytesRead = EepromReadByte(Address + Index,
|
||||
&ReadBuffer[Index], 1);
|
||||
if (BytesRead != 1) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
if (ReadBuffer[Index] != WriteBuffer[Index]) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes a buffer of bytes to the IIC serial EEPROM.
|
||||
*
|
||||
* @param Address contains the address in the EEPROM to write to.
|
||||
* @param BufferPtr contains the address of the data to write.
|
||||
* @param ByteCount contains the number of bytes in the buffer to be written.
|
||||
* Note that this should not exceed the page size of the EEPROM as
|
||||
* noted by the constant PAGE_SIZE.
|
||||
*
|
||||
* @return The number of bytes written, a value less than that which was
|
||||
* specified as an input indicates an error.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
unsigned EepromWriteByte(AddressType Address, u8 *BufferPtr, u16 ByteCount)
|
||||
{
|
||||
volatile unsigned SentByteCount;
|
||||
volatile unsigned AckByteCount;
|
||||
u8 WriteBuffer[sizeof(Address) + PAGE_SIZE];
|
||||
int Index;
|
||||
|
||||
|
||||
/*
|
||||
* A temporary write buffer must be used which contains both the address
|
||||
* and the data to be written, put the address in first based upon the
|
||||
* size of the address for the EEPROM.
|
||||
*/
|
||||
if (sizeof(AddressType) == 2) {
|
||||
WriteBuffer[0] = (u8)(Address >> 8);
|
||||
WriteBuffer[1] = (u8)(Address);
|
||||
} else if (sizeof(AddressType) == 1) {
|
||||
WriteBuffer[0] = (u8)(Address);
|
||||
EepromIicAddr |= (EEPROM_TEST_START_ADDRESS >> 8) & 0x7;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the data in the write buffer following the address.
|
||||
*/
|
||||
for (Index = 0; Index < ByteCount; Index++) {
|
||||
WriteBuffer[sizeof(Address) + Index] = BufferPtr[Index];
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the address register to the specified address by writing
|
||||
* the address to the device, this must be tried until it succeeds
|
||||
* because a previous write to the device could be pending and it
|
||||
* will not ack until that write is complete.
|
||||
*/
|
||||
do {
|
||||
SentByteCount = XIic_Send(IIC_BASE_ADDRESS,
|
||||
EepromIicAddr,
|
||||
(u8 *)&Address, sizeof(Address),
|
||||
XIIC_STOP);
|
||||
if (SentByteCount != sizeof(Address)) {
|
||||
|
||||
/* Send is aborted so reset Tx FIFO */
|
||||
XIic_WriteReg(IIC_BASE_ADDRESS, XIIC_CR_REG_OFFSET,
|
||||
XIIC_CR_TX_FIFO_RESET_MASK);
|
||||
XIic_WriteReg(IIC_BASE_ADDRESS, XIIC_CR_REG_OFFSET,
|
||||
XIIC_CR_ENABLE_DEVICE_MASK);
|
||||
}
|
||||
|
||||
} while (SentByteCount != sizeof(Address));
|
||||
|
||||
/*
|
||||
* Write a page of data at the specified address to the EEPROM.
|
||||
*/
|
||||
SentByteCount = XIic_Send(IIC_BASE_ADDRESS, EepromIicAddr,
|
||||
WriteBuffer, sizeof(Address) + PAGE_SIZE,
|
||||
XIIC_STOP);
|
||||
|
||||
/*
|
||||
* Wait for the write to be complete by trying to do a write and
|
||||
* the device will not ack if the write is still active.
|
||||
*/
|
||||
do {
|
||||
AckByteCount = XIic_Send(IIC_BASE_ADDRESS, EepromIicAddr,
|
||||
(u8 *)&Address, sizeof(Address),
|
||||
XIIC_STOP);
|
||||
if (AckByteCount != sizeof(Address)) {
|
||||
|
||||
/* Send is aborted so reset Tx FIFO */
|
||||
XIic_WriteReg(IIC_BASE_ADDRESS, XIIC_CR_REG_OFFSET,
|
||||
XIIC_CR_TX_FIFO_RESET_MASK);
|
||||
XIic_WriteReg(IIC_BASE_ADDRESS, XIIC_CR_REG_OFFSET,
|
||||
XIIC_CR_ENABLE_DEVICE_MASK);
|
||||
}
|
||||
|
||||
} while (AckByteCount != sizeof(Address));
|
||||
|
||||
|
||||
/*
|
||||
* Return the number of bytes written to the EEPROM
|
||||
*/
|
||||
return SentByteCount - sizeof(Address);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function reads a number of bytes from the IIC serial EEPROM into a
|
||||
* specified buffer.
|
||||
*
|
||||
* @param Address contains the address in the EEPROM to read from.
|
||||
* @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.
|
||||
* This value is not constrained by the page size of the device
|
||||
* such that up to 64K may be read in one call.
|
||||
*
|
||||
* @return The number of bytes read. A value less than the specified input
|
||||
* value indicates an error.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
unsigned EepromReadByte(AddressType Address, u8 *BufferPtr, u16 ByteCount)
|
||||
{
|
||||
volatile unsigned ReceivedByteCount;
|
||||
u16 StatusReg;
|
||||
|
||||
/*
|
||||
* Set the address register to the specified address by writing
|
||||
* the address to the device, this must be tried until it succeeds
|
||||
* because a previous write to the device could be pending and it
|
||||
* will not ack until that write is complete.
|
||||
*/
|
||||
do {
|
||||
StatusReg = XIic_ReadReg(IIC_BASE_ADDRESS, XIIC_SR_REG_OFFSET);
|
||||
if(!(StatusReg & XIIC_SR_BUS_BUSY_MASK)) {
|
||||
ReceivedByteCount = XIic_Send(IIC_BASE_ADDRESS,
|
||||
EepromIicAddr,
|
||||
(u8 *)&Address,
|
||||
sizeof(Address),
|
||||
XIIC_STOP);
|
||||
|
||||
if (ReceivedByteCount != sizeof(Address)) {
|
||||
|
||||
/* Send is aborted so reset Tx FIFO */
|
||||
XIic_WriteReg(IIC_BASE_ADDRESS,
|
||||
XIIC_CR_REG_OFFSET,
|
||||
XIIC_CR_TX_FIFO_RESET_MASK);
|
||||
XIic_WriteReg(IIC_BASE_ADDRESS,
|
||||
XIIC_CR_REG_OFFSET,
|
||||
XIIC_CR_ENABLE_DEVICE_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
} while (ReceivedByteCount != sizeof(Address));
|
||||
|
||||
/*
|
||||
* Read the number of bytes at the specified address from the EEPROM.
|
||||
*/
|
||||
ReceivedByteCount = XIic_Recv(IIC_BASE_ADDRESS, EepromIicAddr,
|
||||
BufferPtr, ByteCount, XIIC_STOP);
|
||||
|
||||
/*
|
||||
* Return the number of bytes read from the EEPROM.
|
||||
*/
|
||||
return ReceivedByteCount;
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_low_level_tempsensor_example.c
|
||||
*
|
||||
* This file contains a polled mode design example which uses the Xilinx IIC
|
||||
* device and low-level driver to execise the temperature sensor on the ML300
|
||||
* board. This example only performs read operations (receive) from the IIC
|
||||
* temperature sensor of the platform.
|
||||
*
|
||||
* The XIic_Recv() API is used to receive the data.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* 7-bit addressing is used to access the tempsensor.
|
||||
*
|
||||
* None
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a jhl 10/09/03 Initial Release
|
||||
* 1.00a sv 05/09/05 Minor changes to comply to Doxygen and coding guidelines
|
||||
* 1.00a mta 03/09/06 Minor updates due to changes in the low level driver for
|
||||
* supporting repeated start functionality.
|
||||
* 2.00a sdm 09/22/09 Minor modifications as per coding guidelines.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic_l.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_BASE_ADDRESS XPAR_IIC_0_BASEADDR
|
||||
|
||||
|
||||
/*
|
||||
* The following constant defines the address of the IIC
|
||||
* temperature sensor device on the IIC bus. Note that since
|
||||
* the address is only 7 bits, this constant is the address divided by 2.
|
||||
*/
|
||||
#define TEMP_SENSOR_ONCHIP_ADDRESS 0x18 /* The actual address is 0x30 */
|
||||
#define TEMP_SENSOR_AMBIENT_ADDRESS 0x4B /* The actual address is 0x96 */
|
||||
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
int LowLevelTempSensorExample(u32 IicBaseAddress,
|
||||
u8 TempSensorAddress,
|
||||
u8 *TemperaturePtr);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* The purpose of this function is to illustrate how to use the IIC level 0
|
||||
* driver to read the temperature.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return Always 0
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* The main function is returning an integer to prevent compiler warnings.
|
||||
*
|
||||
****************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
u8 TemperaturePtr;
|
||||
|
||||
/*
|
||||
* Run the example, specify the Base Address that is generated in
|
||||
* xparameters.h
|
||||
*/
|
||||
LowLevelTempSensorExample(IIC_BASE_ADDRESS,
|
||||
TEMP_SENSOR_ONCHIP_ADDRESS,
|
||||
&TemperaturePtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* The function reads the temperature of the IIC temperature sensor on the
|
||||
* IIC bus using the low-level driver.
|
||||
*
|
||||
* @param IicBaseAddress is the base address of the device.
|
||||
* @param TempSensorAddress is the address of the Temperature Sensor device
|
||||
* on the IIC bus.
|
||||
* @param TemperaturePtr is the databyte read from the temperature sensor.
|
||||
*
|
||||
* @return The number of bytes read from the temperature sensor, normally one
|
||||
* byte if successful.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int LowLevelTempSensorExample(u32 IicBaseAddress,
|
||||
u8 TempSensorAddress,
|
||||
u8 *TemperaturePtr)
|
||||
{
|
||||
int ByteCount;
|
||||
|
||||
ByteCount = XIic_Recv(IicBaseAddress, TempSensorAddress,
|
||||
TemperaturePtr, 1, XIIC_STOP);
|
||||
|
||||
|
||||
|
||||
return ByteCount;
|
||||
}
|
|
@ -0,0 +1,504 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_multi_master_example.c
|
||||
*
|
||||
* This file consists of a Interrupt mode design example which uses the Xilinx
|
||||
* IIC device and XIic driver to exercise the EEPROM on the Xilinx boards in a
|
||||
* Multi master mode. This example has been tested with an off-board external
|
||||
* IIC Master connected on the IIC bus.
|
||||
*
|
||||
* This example writes/reads from the lower 256 bytes of the IIC EEPROMS. Please
|
||||
* refer to the datasheets of the IIC EEPROM's for details about the internal
|
||||
* addressing and page size of these devices.
|
||||
*
|
||||
* The XIic_MasterSend() API is used to transmit the data and XIic_MasterRecv()
|
||||
* API is used to receive the data.
|
||||
*
|
||||
* The example is tested on ML300/ML310/ML403/ML501 Xilinx boards.
|
||||
*
|
||||
* The ML310/ML410/ML510 boards have a on-board 64 Kb serial IIC EEPROM
|
||||
* (Microchip 24LC64A). The WP pin of the IIC EEPROM is hardwired to ground on
|
||||
* this board.
|
||||
*
|
||||
* The ML300 board has an on-board 32 Kb serial IIC EEPROM(Microchip 24LC32A).
|
||||
* The WP pin of the IIC EEPROM has to be connected to ground for this example.
|
||||
* The WP is connected to pin Y3 of the FPGA.
|
||||
*
|
||||
* The ML403 board has an on-board 4 Kb serial IIC EEPROM(Microchip 24LC04A).
|
||||
* The WP pin of the IIC EEPROM is hardwired to ground on this board.
|
||||
*
|
||||
* The ML501/ML505/ML507/ML605/SP601/SP605 boards have an on-board 8 Kb serial
|
||||
* IIC EEPROM(STM M24C08). The WP pin of the IIC EEPROM is hardwired to
|
||||
* ground on these boards.
|
||||
*
|
||||
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
|
||||
* address pointer in the on board EEPROM is 2 bytes.
|
||||
*
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards should
|
||||
* be u8 as the address pointer for the on board EEPROM is 1 byte.
|
||||
*
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML410/
|
||||
* ML501/ML505/ML507/ML510 boards is 0x50.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML605/SP601/SP605 boards
|
||||
* is 0x54.
|
||||
* Refer to the User Guide's of the respective boards for further information
|
||||
* about the IIC slave address of IIC EEPROM's.
|
||||
*
|
||||
* The define EEPROM_ADDRESS in this file needs to be changed depending on
|
||||
* the board on which this example is to be run.
|
||||
* This code assumes that no Operating System is being used.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a mta 03/01/06 Created.
|
||||
* 2.00a sdm 09/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs, replaced call to
|
||||
* XIic_Initialize API with XIic_LookupConfig and
|
||||
* XIic_CfgInitialize.
|
||||
* 2.01a ktn 03/17/10 Updated the information about the EEPROM's used on
|
||||
* ML605/SP601/SP605 boards.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.h"
|
||||
#include "xintc.h"
|
||||
#include "xil_exception.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_IIC_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
|
||||
#define IIC_INTR_ID XPAR_INTC_0_IIC_0_VEC_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.
|
||||
* The 7 bit IIC Slave address of the IIC EEPROM on the ML300/ML310/ML403/ML501/
|
||||
* ML410/ML505/ML507/ML510 boards is 0x50. The 7 bit IIC Slave address of the
|
||||
* IIC EEPROM on the ML605/SP601/SP605 boards is 0x54.
|
||||
* Please refer the User Guide's of the respective boards for further
|
||||
* information about the IIC slave address of IIC EEPROM's.
|
||||
*/
|
||||
#define EEPROM_ADDRESS 0x50 /* 0xA0 as an 8 bit number. */
|
||||
|
||||
/*
|
||||
* The page size determines how much data should be written at a time.
|
||||
* The ML300 board supports a page size of 32 and 16.
|
||||
* 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_TEST_START_ADDRESS 128
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/*
|
||||
* The AddressType for ML300/ML310/ML410/ML510 boards should be u16 as the
|
||||
* address pointer in the on board EEPROM is 2 bytes.
|
||||
* The AddressType for ML403/ML501/ML505/ML507/ML605/SP601/SP605 boards 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 IicMultiMasterExample();
|
||||
|
||||
static int SetupInterruptSystem(XIic *IicInstPtr);
|
||||
|
||||
static void SendHandler(XIic *InstancePtr);
|
||||
static void StatusHandler(XIic *InstancePtr, int Event);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
XIic IicInstance; /* The instance of the IIC device. */
|
||||
XIntc InterruptController; /* The instance of the Interrupt Controller. */
|
||||
|
||||
/*
|
||||
* Write buffer for writing a page.
|
||||
*/
|
||||
u8 WriteBuffer[sizeof(AddressType) + PAGE_SIZE];
|
||||
|
||||
volatile u8 TransmitComplete;
|
||||
volatile u8 ReceiveComplete;
|
||||
volatile u8 BusNotBusy;
|
||||
|
||||
/************************** Function Definitions *****************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Main function to call the Multi Master example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Run the Multi master example.
|
||||
*/
|
||||
Status = IicMultiMasterExample();
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes the data to the IIC EEPROM.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int IicMultiMasterExample()
|
||||
{
|
||||
u8 Index;
|
||||
int Status;
|
||||
XIic_Config *ConfigPtr; /* Pointer to configuration data */
|
||||
AddressType Address = EEPROM_TEST_START_ADDRESS;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Include the multi master functionality.
|
||||
*/
|
||||
XIic_MultiMasterInclude();
|
||||
|
||||
/*
|
||||
* Initialize the IIC driver so that it is ready to use.
|
||||
*/
|
||||
ConfigPtr = XIic_LookupConfig(XPAR_IIC_0_DEVICE_ID);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIic_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Transmit and status handlers.
|
||||
*/
|
||||
XIic_SetSendHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) SendHandler);
|
||||
XIic_SetStatusHandler(&IicInstance, &IicInstance,
|
||||
(XIic_StatusHandler) StatusHandler);
|
||||
|
||||
/*
|
||||
* Set the address of the slave.
|
||||
*/
|
||||
Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE,
|
||||
EEPROM_ADDRESS);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
IicInstance.Stats.TxErrors = 0;
|
||||
/*
|
||||
* Set the defaults.
|
||||
*/
|
||||
TransmitComplete = 1;
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to the EEPROM.
|
||||
*/
|
||||
XIic_MasterSend(&IicInstance, WriteBuffer, PAGE_SIZE);
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* If arbitration is lost and some time later Bus if bus
|
||||
* becomes free transmit the data.
|
||||
*/
|
||||
if (BusNotBusy) {
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the data.
|
||||
*/
|
||||
XIic_MasterSend(&IicInstance, WriteBuffer, PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Clear the Flag.
|
||||
*/
|
||||
BusNotBusy = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This condition is required to be checked in the case where we
|
||||
* are writing two consecutive buffers of data to the EEPROM.
|
||||
* The EEPROM takes about 2 milliseconds time to update the data
|
||||
* internally after a STOP has been sent on the bus.
|
||||
* A NACK will be generated in the case of a second write before
|
||||
* the EEPROM updates the data internally resulting in a
|
||||
* Transmission Error.
|
||||
*/
|
||||
if (IicInstance.Stats.TxErrors != 0) {
|
||||
/*
|
||||
* If the Slave didn't acknowledge then we should keep
|
||||
* making attempts to transmit the data.
|
||||
*/
|
||||
IicInstance.Stats.TxErrors = 0;
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the data.
|
||||
*/
|
||||
XIic_MasterSend(&IicInstance, WriteBuffer, PAGE_SIZE);
|
||||
}
|
||||
|
||||
if ((!TransmitComplete) &&
|
||||
(XIic_IsIicBusy(&IicInstance) == FALSE))
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This function setups the interrupt system so interrupts can occur for the
|
||||
* IIC. The function is application-specific since the actual system may or
|
||||
* may not have an interrupt controller. The IIC device could be directly
|
||||
* connected to a processor without an interrupt controller. The user should
|
||||
* modify this function to fit the application.
|
||||
*
|
||||
* @param IicInstPtr contains a pointer to the instance of the IIC which
|
||||
* is going to be connected to the interrupt controller.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static int SetupInterruptSystem(XIic *IicInstPtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
if (InterruptController.IsStarted == XIL_COMPONENT_IS_STARTED) {
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the interrupt controller driver so that it's ready to use.
|
||||
*/
|
||||
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = XIntc_Connect(&InterruptController, IIC_INTR_ID,
|
||||
(XInterruptHandler) XIic_InterruptHandler,
|
||||
IicInstPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the interrupt controller so interrupts are enabled for all
|
||||
* devices that cause interrupts.
|
||||
*/
|
||||
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupts for the IIC device.
|
||||
*/
|
||||
XIntc_Enable(&InterruptController, IIC_INTR_ID);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the exception table.
|
||||
*/
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/*
|
||||
* Register the interrupt controller handler with the exception table.
|
||||
*/
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler) XIntc_InterruptHandler,
|
||||
&InterruptController);
|
||||
|
||||
/*
|
||||
* Enable non-critical exceptions.
|
||||
*/
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* The Send handler is called asynchronously from an interrupt context and
|
||||
* indicates that data in the specified buffer has been sent.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void SendHandler(XIic *InstancePtr)
|
||||
{
|
||||
TransmitComplete = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* The Status handler is called asynchronously from an interrupt context and
|
||||
* indicates the events that have occured.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
* @param Event indicates the condition that has occurred.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void StatusHandler(XIic *InstancePtr, int Event)
|
||||
{
|
||||
if (Event == XII_ARB_LOST_EVENT) {
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
XIIC_CR_ENABLE_DEVICE_MASK);
|
||||
XIic_WriteIisr(InstancePtr->BaseAddress, XIIC_INTR_BNB_MASK);
|
||||
XIic_WriteIier(InstancePtr->BaseAddress, XIIC_INTR_BNB_MASK);
|
||||
InstancePtr->BNBOnly = TRUE;
|
||||
}
|
||||
else if (Event == XII_BUS_NOT_BUSY_EVENT) {
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
0x0);
|
||||
BusNotBusy = 1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,535 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_repeated_start_example.c
|
||||
*
|
||||
* This file consists of a interrupt mode design example to demonstrate the use
|
||||
* of repeated start using the XIic driver.
|
||||
*
|
||||
* The XIic_MasterSend() API is used to transmit the data and XIic_MasterRecv()
|
||||
* API is used to receive the data.
|
||||
*
|
||||
* The IIC devices that are present on the Xilinx boards donot support the
|
||||
* repeated start option. These examples have been tested with an IIC
|
||||
* device external to the boards.
|
||||
*
|
||||
* This code assumes that no Operating System is being used.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a mta 02/20/06 Created.
|
||||
* 2.00a sdm 09/22/09 Updated to use the HAL APIs, replaced call to
|
||||
* XIic_Initialize API with XIic_LookupConfig and
|
||||
* XIic_CfgInitialize. Updated the example with a
|
||||
* fix for CR539763 where XIic_Start was being called
|
||||
* instead of XIic_Stop. Added code for setting up the
|
||||
* StatusHandler callback.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.h"
|
||||
#include "xintc.h"
|
||||
#include "xil_exception.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_IIC_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
|
||||
#define IIC_INTR_ID XPAR_INTC_0_IIC_0_VEC_ID
|
||||
|
||||
/*
|
||||
* The following constant defines the address of the IIC
|
||||
* device on the IIC bus. Note that since the address is only 7 bits, this
|
||||
* constant is the address divided by 2.
|
||||
*/
|
||||
#define SLAVE_ADDRESS 0x70 /* 0xE0 as an 8 bit number. */
|
||||
|
||||
#define SEND_COUNT 16
|
||||
#define RECEIVE_COUNT 16
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
int IicRepeatedStartExample();
|
||||
static int WriteData(u16 ByteCount);
|
||||
static int ReadData(u8 *BufferPtr, u16 ByteCount);
|
||||
static int SetupInterruptSystem(XIic *IicInstPtr);
|
||||
static void SendHandler(XIic *InstancePtr);
|
||||
static void ReceiveHandler(XIic *InstancePtr);
|
||||
static void StatusHandler(XIic *InstancePtr, int Event);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
XIic IicInstance;
|
||||
XIntc InterruptController;
|
||||
|
||||
u8 WriteBuffer[SEND_COUNT]; /* Write buffer for writing a page. */
|
||||
u8 ReadBuffer[RECEIVE_COUNT]; /* Read buffer for reading a page. */
|
||||
|
||||
volatile u8 TransmitComplete;
|
||||
volatile u8 ReceiveComplete;
|
||||
|
||||
/************************** Function Definitions *****************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Main function to call the Repeated Start example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Run the Repeated Start example.
|
||||
*/
|
||||
Status = IicRepeatedStartExample();
|
||||
if (Status != XST_SUCCESS) {
|
||||
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes and reads the data to the IIC Slave.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IicRepeatedStartExample(void)
|
||||
{
|
||||
u8 Index;
|
||||
int Status;
|
||||
XIic_Config *ConfigPtr; /* Pointer to configuration data */
|
||||
|
||||
/*
|
||||
* Initialize the data to write and the read buffer.
|
||||
*/
|
||||
for (Index = 0; Index < SEND_COUNT; Index++) {
|
||||
WriteBuffer[Index] = Index;
|
||||
ReadBuffer[Index] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the IIC driver so that it is ready to use.
|
||||
*/
|
||||
ConfigPtr = XIic_LookupConfig(XPAR_IIC_0_DEVICE_ID);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIic_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Transmit, Receive and Status handlers.
|
||||
*/
|
||||
XIic_SetSendHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) SendHandler);
|
||||
XIic_SetRecvHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) ReceiveHandler);
|
||||
XIic_SetStatusHandler(&IicInstance, &IicInstance,
|
||||
(XIic_StatusHandler) StatusHandler);
|
||||
|
||||
/*
|
||||
* Set the Address of the Slave.
|
||||
*/
|
||||
Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE,
|
||||
SLAVE_ADDRESS);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to the IIC Slave.
|
||||
*/
|
||||
Status = WriteData(SEND_COUNT);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the IIC Slave.
|
||||
*/
|
||||
Status = ReadData(ReadBuffer, RECEIVE_COUNT);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes a buffer of data to IIC Slave.
|
||||
*
|
||||
* @param ByteCount contains the number of bytes in the buffer to be
|
||||
* written.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int WriteData(u16 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
int BusBusy;
|
||||
|
||||
/*
|
||||
* Set the defaults.
|
||||
*/
|
||||
TransmitComplete = 1;
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Repeated Start option.
|
||||
*/
|
||||
IicInstance.Options = XII_REPEATED_START_OPTION;
|
||||
|
||||
/*
|
||||
* Send the data.
|
||||
*/
|
||||
Status = XIic_MasterSend(&IicInstance, WriteBuffer, ByteCount);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till data is transmitted.
|
||||
*/
|
||||
while (TransmitComplete) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This is for verification that Bus is not released and still Busy.
|
||||
*/
|
||||
BusBusy = XIic_IsIicBusy(&IicInstance);
|
||||
|
||||
TransmitComplete = 1;
|
||||
IicInstance.Options = 0x0;
|
||||
|
||||
/*
|
||||
* Send the Data.
|
||||
*/
|
||||
Status = XIic_MasterSend(&IicInstance, WriteBuffer, ByteCount);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till data is transmitted.
|
||||
*/
|
||||
while ((TransmitComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function reads a data from the IIC Slave into a specified buffer.
|
||||
*
|
||||
* @param BufferPtr contains the address of the data buffer to be filled.
|
||||
* @param ByteCount contains the number of bytes to be read.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int ReadData(u8 *BufferPtr, u16 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
int BusBusy;
|
||||
|
||||
/*
|
||||
* Set the defaults.
|
||||
*/
|
||||
ReceiveComplete = 1;
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Repeated Start option.
|
||||
*/
|
||||
IicInstance.Options = XII_REPEATED_START_OPTION;
|
||||
|
||||
/*
|
||||
* Receive the data.
|
||||
*/
|
||||
Status = XIic_MasterRecv(&IicInstance, BufferPtr, ByteCount);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till all the data is received.
|
||||
*/
|
||||
while (ReceiveComplete) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This is for verification that Bus is not released and still Busy.
|
||||
*/
|
||||
BusBusy = XIic_IsIicBusy(&IicInstance);
|
||||
|
||||
ReceiveComplete = 1;
|
||||
IicInstance.Options = 0x0;
|
||||
|
||||
/*
|
||||
* Receive the Data.
|
||||
*/
|
||||
Status = XIic_MasterRecv(&IicInstance, BufferPtr, ByteCount);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait till all the data is received.
|
||||
*/
|
||||
while ((ReceiveComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function setups the interrupt system so interrupts can occur for the
|
||||
* IIC. The function is application-specific since the actual system may or
|
||||
* may not have an interrupt controller. The IIC device could be directly
|
||||
* connected to a processor without an interrupt controller. The user should
|
||||
* modify this function to fit the application.
|
||||
*
|
||||
* @param IicInstPtr contains a pointer to the instance of the IIC which
|
||||
* is going to be connected to the interrupt controller.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int SetupInterruptSystem(XIic *IicInstPtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
if (InterruptController.IsStarted == XIL_COMPONENT_IS_STARTED) {
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the interrupt controller driver so that it's ready to use.
|
||||
*/
|
||||
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = XIntc_Connect(&InterruptController, IIC_INTR_ID,
|
||||
(XInterruptHandler) XIic_InterruptHandler,
|
||||
IicInstPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the interrupt controller so interrupts are enabled for all
|
||||
* devices that cause interrupts.
|
||||
*/
|
||||
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupts for the IIC device.
|
||||
*/
|
||||
XIntc_Enable(&InterruptController, IIC_INTR_ID);
|
||||
|
||||
/*
|
||||
* Initialize the exception table.
|
||||
*/
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/*
|
||||
* Register the interrupt controller handler with the exception table.
|
||||
*/
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler) XIntc_InterruptHandler,
|
||||
&InterruptController);
|
||||
|
||||
/*
|
||||
* Enable non-critical exceptions.
|
||||
*/
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This Send handler is called asynchronously from an interrupt context and
|
||||
* indicates that data in the specified buffer has been sent.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void SendHandler(XIic *InstancePtr)
|
||||
{
|
||||
TransmitComplete = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This Receive handler is called asynchronously from an interrupt context and
|
||||
* indicates that data in the specified buffer has been Received.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void ReceiveHandler(XIic *InstancePtr)
|
||||
{
|
||||
ReceiveComplete = 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This Status handler is called asynchronously from an interrupt
|
||||
* context and indicates the events that have occurred.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
* @param Event indicates the condition that has occurred.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void StatusHandler(XIic *InstancePtr, int Event)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_selftest_example.c
|
||||
*
|
||||
* This file contains a example for using the IIC hardware device and
|
||||
* XIic driver.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a sv 05/09/05 Initial release for TestApp integration.
|
||||
* 2.00a sdm 09/22/09 Updated to use the HAL APIs, replaced call to
|
||||
* XIic_Initialize API with XIic_LookupConfig and
|
||||
* XIic_CfgInitialize. Minor changes made as per
|
||||
* coding guidelines.
|
||||
* </pre>
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.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.
|
||||
*/
|
||||
#ifndef TESTAPP_GEN
|
||||
#define IIC_DEVICE_ID XPAR_IIC_0_DEVICE_ID
|
||||
#endif
|
||||
|
||||
/**************************** Type Definitions ********************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions **********************/
|
||||
|
||||
|
||||
/************************** Function Prototypes *******************************/
|
||||
|
||||
int IicSelfTestExample(u16 DeviceId);
|
||||
|
||||
/************************** Variable Definitions ******************************/
|
||||
|
||||
/*
|
||||
* The following are declared globally so they are zeroed and so they are
|
||||
* easily accessible from a debugger.
|
||||
*/
|
||||
XIic Iic; /* The driver instance for IIC Device */
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Main function to call the example. This function is not included if the
|
||||
* example is generated from the TestAppGen test tool.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TESTAPP_GEN
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Run the example, specify the device ID that is generated in
|
||||
* xparameters.h.
|
||||
*/
|
||||
Status = IicSelfTestExample(IIC_DEVICE_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function does a selftest on the IIC device and XIic driver as an
|
||||
* example.
|
||||
*
|
||||
* @param DeviceId is the XPAR_<IIC_instance>_DEVICE_ID value from
|
||||
* xparameters.h.
|
||||
*
|
||||
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int IicSelfTestExample(u16 DeviceId)
|
||||
{
|
||||
int Status;
|
||||
XIic_Config *ConfigPtr; /* Pointer to configuration data */
|
||||
|
||||
/*
|
||||
* Initialize the IIC driver so that it is ready to use.
|
||||
*/
|
||||
ConfigPtr = XIic_LookupConfig(DeviceId);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIic_CfgInitialize(&Iic, ConfigPtr, ConfigPtr->BaseAddress);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Perform a self-test to ensure that the hardware was built
|
||||
* correctly.
|
||||
*/
|
||||
Status = XIic_SelfTest(&Iic);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
506
XilinxProcessorIPLib/drivers/iic/examples/xiic_slave_example.c
Normal file
506
XilinxProcessorIPLib/drivers/iic/examples/xiic_slave_example.c
Normal file
|
@ -0,0 +1,506 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_slave_example.c
|
||||
*
|
||||
* This file consists of a Interrupt mode design example which uses the Xilinx
|
||||
* IIC device and XIic driver to exercise the slave functionality of the IIC
|
||||
* device.
|
||||
*
|
||||
* The XIic_SlaveSend() API is used to transmit the data and
|
||||
* XIic_SlaveRecv() API is used to receive the data.
|
||||
*
|
||||
* The example is tested on ML300/ML310/ML403/ML501 Xilinx boards.
|
||||
*
|
||||
* The IIC devices that are present on the Xilinx boards donot support the Master
|
||||
* functionality. This example has been tested with an off board external IIC
|
||||
* Master device and the IIC device configured as a Slave.
|
||||
*
|
||||
* This code assumes that no Operating System is being used.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a mta 03/01/06 Created.
|
||||
* 2.00a ktn 11/17/09 Updated to use the HAL APIs and replaced call to
|
||||
* XIic_Initialize API with XIic_LookupConfig and
|
||||
* XIic_CfgInitialize. Some of the macros have been
|
||||
* renamed in the IIC driver and some renamed macros are
|
||||
* used in this example.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.h"
|
||||
#include "xintc.h"
|
||||
#include "xil_exception.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_IIC_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
|
||||
#define IIC_INTR_ID XPAR_INTC_0_IIC_0_VEC_ID
|
||||
|
||||
/*
|
||||
* The following constant defines the address of the IIC device on the IIC bus.
|
||||
* Since the address is only 7 bits, this constant is the address divided by 2.
|
||||
*/
|
||||
#define SLAVE_ADDRESS 0x70 /* 0xE0 as an 8 bit number. */
|
||||
|
||||
#define RECEIVE_COUNT 25
|
||||
#define SEND_COUNT 25
|
||||
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
int IicSlaveExample();
|
||||
int SlaveWriteData(u16 ByteCount);
|
||||
int SlaveReadData(u8 *BufferPtr, u16 ByteCount);
|
||||
static int SetupInterruptSystem(XIic * IicInstPtr);
|
||||
static void StatusHandler(XIic *InstancePtr, int Event);
|
||||
static void SendHandler(XIic *InstancePtr);
|
||||
static void ReceiveHandler(XIic *InstancePtr);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
XIic IicInstance; /* The instance of the IIC device. */
|
||||
XIntc InterruptController; /* The instance of the Interrupt Controller */
|
||||
|
||||
|
||||
u8 WriteBuffer[SEND_COUNT]; /* Write buffer for writing a page. */
|
||||
u8 ReadBuffer[RECEIVE_COUNT]; /* Read buffer for reading a page. */
|
||||
|
||||
volatile u8 TransmitComplete;
|
||||
volatile u8 ReceiveComplete;
|
||||
|
||||
volatile u8 SlaveRead;
|
||||
volatile u8 SlaveWrite;
|
||||
|
||||
/************************** Function Definitions *****************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* Main function to call the IIC Slave example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Run the IIC Slave example.
|
||||
*/
|
||||
Status = IicSlaveExample();
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes and reads the data as a slave. The IIC master on the bus
|
||||
* initiates the transfers.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IicSlaveExample()
|
||||
{
|
||||
int Status;
|
||||
u8 Index;
|
||||
XIic_Config *ConfigPtr; /* Pointer to configuration data */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the IIC driver so that it is ready to use.
|
||||
*/
|
||||
ConfigPtr = XIic_LookupConfig(IIC_DEVICE_ID);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIic_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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Include the Slave functions.
|
||||
*/
|
||||
XIic_SlaveInclude();
|
||||
|
||||
/*
|
||||
* Set the Transmit, Receive and Status Handlers.
|
||||
*/
|
||||
XIic_SetStatusHandler(&IicInstance, &IicInstance,
|
||||
(XIic_StatusHandler) StatusHandler);
|
||||
XIic_SetSendHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) SendHandler);
|
||||
XIic_SetRecvHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) ReceiveHandler);
|
||||
|
||||
/*
|
||||
* Set the Address as a RESPOND type.
|
||||
*/
|
||||
Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_RESPOND_TYPE,
|
||||
SLAVE_ADDRESS);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The IIC Master on this bus should initiate the transfer
|
||||
* and write data to the slave at this instance.
|
||||
*/
|
||||
SlaveReadData(ReadBuffer, RECEIVE_COUNT);
|
||||
|
||||
for (Index = 0; Index < SEND_COUNT; Index++) {
|
||||
WriteBuffer[Index] = Index;
|
||||
}
|
||||
|
||||
/*
|
||||
* The IIC Master on this bus should initiate the transfer
|
||||
* and read data from the slave.
|
||||
*/
|
||||
SlaveWriteData(SEND_COUNT);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function reads a buffer of bytes when the IIC Master on the bus writes
|
||||
* data to the slave device.
|
||||
*
|
||||
* @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 SlaveReadData(u8 *BufferPtr, u16 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Set the defaults.
|
||||
*/
|
||||
ReceiveComplete = 1;
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Global Interrupt Enable.
|
||||
*/
|
||||
XIic_IntrGlobalEnable(IicInstance.BaseAddress);
|
||||
|
||||
/*
|
||||
* Wait for AAS interrupt and completion of data reception.
|
||||
*/
|
||||
while ((ReceiveComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
if (SlaveRead) {
|
||||
XIic_SlaveRecv(&IicInstance, ReadBuffer, RECEIVE_COUNT);
|
||||
SlaveRead = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the Global Interrupt Enable.
|
||||
*/
|
||||
XIic_IntrGlobalDisable(IicInstance.BaseAddress);
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes a buffer of bytes to the IIC bus when the IIC master
|
||||
* initiates a read operation.
|
||||
*
|
||||
* @param ByteCount contains the number of bytes in the buffer to be
|
||||
* written.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int SlaveWriteData(u16 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Set the defaults.
|
||||
*/
|
||||
TransmitComplete = 1;
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Global Interrupt Enable.
|
||||
*/
|
||||
XIic_IntrGlobalEnable(IicInstance.BaseAddress);
|
||||
|
||||
/*
|
||||
* Wait for AAS interrupt and transmission to complete.
|
||||
*/
|
||||
while ((TransmitComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
if (SlaveWrite) {
|
||||
XIic_SlaveSend(&IicInstance, WriteBuffer, SEND_COUNT);
|
||||
SlaveWrite = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the Global Interrupt Enable bit.
|
||||
*/
|
||||
XIic_IntrGlobalDisable(IicInstance.BaseAddress);
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This Status handler is called asynchronously from an interrupt context and
|
||||
* indicates the events that have occurred.
|
||||
*
|
||||
* @param InstancePtr is not used, but contains a pointer to the IIC
|
||||
* device driver instance which the handler is being called for.
|
||||
* @param Event indicates whether it is a request for a write or read.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static void StatusHandler(XIic *InstancePtr, int Event)
|
||||
{
|
||||
/*
|
||||
* Check whether the Event is to write or read the data from the slave.
|
||||
*/
|
||||
if (Event == XII_MASTER_WRITE_EVENT) {
|
||||
/*
|
||||
* Its a Write request from Master.
|
||||
*/
|
||||
SlaveRead = 1;
|
||||
} else {
|
||||
/*
|
||||
* Its a Read request from the master.
|
||||
*/
|
||||
SlaveWrite = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This Send handler is called asynchronously from an interrupt
|
||||
* context and indicates that data in the specified buffer has been sent.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static void SendHandler(XIic *InstancePtr)
|
||||
{
|
||||
TransmitComplete = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This Receive handler is called asynchronously from an interrupt
|
||||
* context and indicates that data in the specified buffer has been Received.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static void ReceiveHandler(XIic *InstancePtr)
|
||||
{
|
||||
ReceiveComplete = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This function setups the interrupt system so interrupts can occur for the
|
||||
* IIC. The function is application-specific since the actual system may or
|
||||
* may not have an interrupt controller. The IIC device could be directly
|
||||
* connected to a processor without an interrupt controller. The user should
|
||||
* modify this function to fit the application.
|
||||
*
|
||||
* @param IicInstPtr contains a pointer to the instance of the IIC which
|
||||
* is going to be connected to the interrupt controller.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static int SetupInterruptSystem(XIic * IicInstPtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
if (InterruptController.IsStarted == XIL_COMPONENT_IS_STARTED) {
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the interrupt controller driver so that it's ready to use.
|
||||
*/
|
||||
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = XIntc_Connect(&InterruptController, IIC_INTR_ID,
|
||||
(XInterruptHandler) XIic_InterruptHandler,
|
||||
IicInstPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the interrupt controller so interrupts are enabled for all
|
||||
* devices that cause interrupts.
|
||||
*/
|
||||
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupts for the IIC device.
|
||||
*/
|
||||
XIntc_Enable(&InterruptController, IIC_INTR_ID);
|
||||
|
||||
/*
|
||||
* Initialize the exception table.
|
||||
*/
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/*
|
||||
* Register the interrupt controller handler with the exception table.
|
||||
*/
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler) XIntc_InterruptHandler,
|
||||
&InterruptController);
|
||||
|
||||
/*
|
||||
* Enable non-critical exceptions.
|
||||
*/
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,394 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_tempsensor_example.c
|
||||
*
|
||||
* This file contains an interrupt based design example which uses the Xilinx
|
||||
* IIC device and driver to exercise the temperature sensor on the ML300 board.
|
||||
* This example only performs read operations (receive) from the IIC temperature
|
||||
* sensor of the platform.
|
||||
*
|
||||
* The XIic_MasterRecv() API is used to receive the data.
|
||||
*
|
||||
* This example assumes that there is an interrupt controller in the hardware
|
||||
* system and the IIC device is connected to the interrupt controller.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* 7-bit addressing is used to access the tempsensor.
|
||||
*
|
||||
* None
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a jhl 09/10/03 Created
|
||||
* 1.00a sv 05/09/05 Minor changes to comply to Doxygen and coding guidelines
|
||||
* </pre>
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/***************************** Include Files ********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.h"
|
||||
#include "xintc.h"
|
||||
#include "xil_exception.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_IIC_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
|
||||
#define INTC_IIC_INTERRUPT_ID XPAR_INTC_0_IIC_0_VEC_ID
|
||||
|
||||
|
||||
/*
|
||||
* The following constant defines the address of the IIC
|
||||
* temperature sensor device on the IIC bus. Note that since
|
||||
* the address is only 7 bits, this constant is the address divided by 2.
|
||||
*/
|
||||
#define TEMP_SENSOR_ADDRESS 0x18 /* The actual address is 0x30 */
|
||||
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
int TempSensorExample(u16 IicDeviceId, u8 TempSensorAddress,
|
||||
u8 *TemperaturePtr);
|
||||
|
||||
static int SetupInterruptSystem(XIic *IicPtr);
|
||||
|
||||
static void RecvHandler(void *CallbackRef, int ByteCount);
|
||||
|
||||
static void StatusHandler(void *CallbackRef, int Status);
|
||||
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
XIic Iic; /* The instance of the IIC device */
|
||||
|
||||
XIntc InterruptController; /* The instance of the Interrupt controller */
|
||||
|
||||
/*
|
||||
* The following structure contains fields that are used with the callbacks
|
||||
* (handlers) of the IIC driver. The driver asynchronously calls handlers
|
||||
* when abnormal events occur or when data has been sent or received. This
|
||||
* structure must be volatile to work when the code is optimized.
|
||||
*/
|
||||
volatile struct {
|
||||
int EventStatus;
|
||||
int RemainingRecvBytes;
|
||||
int EventStatusUpdated;
|
||||
int RecvBytesUpdated;
|
||||
} HandlerInfo;
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* The purpose of this function is to illustrate how to use the IIC driver to
|
||||
* read the temperature.
|
||||
*
|
||||
* @param None
|
||||
*
|
||||
* @return XST_SUCCESS if successful, XST_FAILURE if unsuccessful
|
||||
*
|
||||
* @note None
|
||||
*
|
||||
*******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
u8 TemperaturePtr;
|
||||
|
||||
/*
|
||||
* Call the TempSensorExample.
|
||||
*/
|
||||
Status = TempSensorExample(IIC_DEVICE_ID, TEMP_SENSOR_ADDRESS,
|
||||
&TemperaturePtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* The function reads the temperature of the IIC temperature sensor on the
|
||||
* IIC bus. It initializes the IIC device driver and sets it up to communicate
|
||||
* with the temperature sensor. This function does contain a loop that polls
|
||||
* for completion of the IIC processing such that it may not return if
|
||||
* interrupts or the hardware are not working.
|
||||
*
|
||||
* @param IicDeviceId is the XPAR_<IIC_instance>_DEVICE_ID value from
|
||||
* xparameters.h for the IIC Device
|
||||
* @param TempSensorAddress is the address of the Temperature Sensor device
|
||||
* on the IIC bus
|
||||
* @param TemperaturePtr is the data byte read from the temperature sensor
|
||||
*
|
||||
* @return XST_SUCCESS to indicate success, else XST_FAILURE to indicate
|
||||
* a Failure.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
*******************************************************************************/
|
||||
int TempSensorExample(u16 IicDeviceId, u8 TempSensorAddress, u8 *TemperaturePtr)
|
||||
{
|
||||
int Status;
|
||||
static int Initialized = FALSE;
|
||||
XIic_Config *ConfigPtr; /* Pointer to configuration data */
|
||||
|
||||
if (!Initialized) {
|
||||
Initialized = TRUE;
|
||||
|
||||
/*
|
||||
* Initialize the IIC driver so that it is ready to use.
|
||||
*/
|
||||
ConfigPtr = XIic_LookupConfig(IicDeviceId);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIic_CfgInitialize(&Iic, ConfigPtr,
|
||||
ConfigPtr->BaseAddress);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Setup handler to process the asynchronous events which occur,
|
||||
* the driver is only interrupt driven such that this must be
|
||||
* done prior to starting the device.
|
||||
*/
|
||||
XIic_SetRecvHandler(&Iic, (void *)&HandlerInfo, RecvHandler);
|
||||
XIic_SetStatusHandler(&Iic, (void *)&HandlerInfo,
|
||||
StatusHandler);
|
||||
|
||||
/*
|
||||
* Connect the ISR to the interrupt and enable interrupts.
|
||||
*/
|
||||
Status = SetupInterruptSystem(&Iic);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the IIC driver such that it is ready to send and
|
||||
* receive messages on the IIC interface, set the address
|
||||
* to send to which is the temperature sensor address
|
||||
*/
|
||||
XIic_Start(&Iic);
|
||||
XIic_SetAddress(&Iic, XII_ADDR_TO_SEND_TYPE, TempSensorAddress);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear updated flags such that they can be polled to indicate
|
||||
* when the handler information has changed asynchronously and
|
||||
* initialize the status which will be returned to a default value
|
||||
*/
|
||||
HandlerInfo.EventStatusUpdated = FALSE;
|
||||
HandlerInfo.RecvBytesUpdated = FALSE;
|
||||
Status = XST_FAILURE;
|
||||
|
||||
/*
|
||||
* Attempt to receive a byte of data from the temperature sensor
|
||||
* on the IIC interface, ignore the return value since this example is
|
||||
* a single master system such that the IIC bus should not ever be busy
|
||||
*/
|
||||
(void)XIic_MasterRecv(&Iic, TemperaturePtr, 1);
|
||||
|
||||
/*
|
||||
* The message is being received from the temperature sensor,
|
||||
* wait for it to complete by polling the information that is
|
||||
* updated asynchronously by interrupt processing
|
||||
*/
|
||||
while(1) {
|
||||
if(HandlerInfo.RecvBytesUpdated == TRUE) {
|
||||
/*
|
||||
* The device information has been updated for receive
|
||||
* processing,if all bytes received (1), indicate
|
||||
* success
|
||||
*/
|
||||
if (HandlerInfo.RemainingRecvBytes == 0) {
|
||||
Status = XST_SUCCESS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Any event status which occurs indicates there was an error,
|
||||
* so return unsuccessful, for this example there should be no
|
||||
* status events since there is a single master on the bus
|
||||
*/
|
||||
if (HandlerInfo.EventStatusUpdated == TRUE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function setups the interrupt system such that interrupts can occur
|
||||
* for IIC. This function is application specific since the actual system may
|
||||
* or may not have an interrupt controller. The IIC device could be directly
|
||||
* connected to a processor without an interrupt controller. The user should
|
||||
* modify this function to fit the application.
|
||||
*
|
||||
* @param IicPtr 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.
|
||||
*
|
||||
* @notes None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static int SetupInterruptSystem(XIic *IicPtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Initialize the interrupt controller driver so that it's ready to use,
|
||||
* specify the device ID that is generated in xparameters.h
|
||||
*/
|
||||
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Connect a device driver handler that will be called when an interrupt
|
||||
* for the device occurs, the device driver handler performs the
|
||||
* specific interrupt processing for the device
|
||||
*/
|
||||
Status = XIntc_Connect(&InterruptController, INTC_IIC_INTERRUPT_ID,
|
||||
XIic_InterruptHandler, IicPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the interrupt controller such that interrupts are recognized
|
||||
* and handled by the processor.
|
||||
*/
|
||||
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupts for the IIC device.
|
||||
*/
|
||||
XIntc_Enable(&InterruptController, INTC_IIC_INTERRUPT_ID);
|
||||
|
||||
/*
|
||||
* Initialize the exception table.
|
||||
*/
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/*
|
||||
* Register the interrupt controller handler with the exception table.
|
||||
*/
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler) XIntc_InterruptHandler,
|
||||
&InterruptController);
|
||||
|
||||
/*
|
||||
* Enable non-critical exceptions.
|
||||
*/
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
return XST_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This receive handler is called asynchronously from an interrupt context and
|
||||
* and indicates that data in the specified buffer was received. The byte count
|
||||
* should equal the byte count of the buffer if all the buffer was filled.
|
||||
*
|
||||
* @param CallBackRef is a pointer to the IIC device driver instance which
|
||||
* the handler is being called for.
|
||||
* @param ByteCount indicates the number of bytes remaining to be received of
|
||||
* the requested byte count. A value of zero indicates all requested
|
||||
* bytes were received.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @notes None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static void RecvHandler(void *CallbackRef, int ByteCount)
|
||||
{
|
||||
HandlerInfo.RemainingRecvBytes = ByteCount;
|
||||
HandlerInfo.RecvBytesUpdated = TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This status handler is called asynchronously from an interrupt context and
|
||||
* indicates that the conditions of the IIC bus changed. This handler should
|
||||
* not be called for the application unless an error occurs.
|
||||
*
|
||||
* @param CallBackRef is a pointer to the IIC device driver instance which the
|
||||
* handler is being called for.
|
||||
* @param Status contains the status of the IIC bus which changed.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @notes None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static void StatusHandler(void *CallbackRef, int Status)
|
||||
{
|
||||
HandlerInfo.EventStatus |= Status;
|
||||
HandlerInfo.EventStatusUpdated = TRUE;
|
||||
}
|
|
@ -0,0 +1,510 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_tenbitaddr_example.c
|
||||
*
|
||||
* This file consists of a Interrupt mode design example which uses the Xilinx
|
||||
* IIC device and XIic driver to exercise the 10-bit Address functionality of the
|
||||
* IIC device.
|
||||
*
|
||||
* The XIic_MasterSend() API is used to transmit the data and
|
||||
* XIic_MasterRecv() API is used to receive the data.
|
||||
*
|
||||
* The example is tested on ML300/ML310/ML403/ML501 Xilinx boards.
|
||||
*
|
||||
* The IIC devices that are present on the Xilinx boards donot support the 10-bit
|
||||
* functionality. This example has been tested with an off board external IIC
|
||||
* Master device and the IIC device configured as a Slave.
|
||||
*
|
||||
* This code assumes that no Operating System is being used.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* None.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00a mta 03/01/06 Created.
|
||||
* 2.00a ktn 11/17/09 Updated to use the HAL APIs and replaced call to
|
||||
* XIic_Initialize API with XIic_LookupConfig and
|
||||
* XIic_CfgInitialize. Made minor modifications as
|
||||
* per coding guidelines.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xparameters.h"
|
||||
#include "xiic.h"
|
||||
#include "xintc.h"
|
||||
#include "xil_exception.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_IIC_0_DEVICE_ID
|
||||
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
|
||||
#define IIC_INTR_ID XPAR_INTC_0_IIC_0_VEC_ID
|
||||
|
||||
/*
|
||||
* The following constant defines the address of the IIC device on the IIC bus.
|
||||
* Since the address is 10 bits, this constant is the address divided by 2.
|
||||
*/
|
||||
#define SLAVE_ADDRESS 0x270 /* 0x4E0 as an 10 bit number. */
|
||||
#define RECEIVE_COUNT 16
|
||||
#define SEND_COUNT 16
|
||||
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
int IicTenBitAddrExample();
|
||||
int TenBitAddrWriteData(u16 ByteCount);
|
||||
int TenBitAddrReadData(u8 *BufferPtr, u16 ByteCount);
|
||||
static int SetupInterruptSystem(XIic *IicInstPtr);
|
||||
static void StatusHandler(XIic *InstancePtr, int Event);
|
||||
static void SendHandler(XIic *InstancePtr);
|
||||
static void ReceiveHandler(XIic *InstancePtr);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
XIic IicInstance; /* The instance of the IIC device. */
|
||||
XIntc InterruptController; /* The instance of the Interrupt Controller */
|
||||
|
||||
|
||||
u8 WriteBuffer[SEND_COUNT]; /* Write buffer for writing a page. */
|
||||
u8 ReadBuffer[RECEIVE_COUNT]; /* Read buffer for reading a page. */
|
||||
|
||||
volatile u8 TransmitComplete;
|
||||
volatile u8 ReceiveComplete;
|
||||
|
||||
volatile u8 SlaveRead;
|
||||
volatile u8 SlaveWrite;
|
||||
|
||||
/************************** Function Definitions *****************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Main function to call the IIC Slave example.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Run the IIC Slave example for 10 bit addressing.
|
||||
*/
|
||||
Status = IicTenBitAddrExample();
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function writes and reads the data as a slave. The IIC master on the bus
|
||||
* initiates the transfers.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int IicTenBitAddrExample()
|
||||
{
|
||||
int Status;
|
||||
u8 Index;
|
||||
XIic_Config *ConfigPtr; /* Pointer to configuration data */
|
||||
|
||||
/*
|
||||
* Initialize the IIC driver so that it is ready to use.
|
||||
*/
|
||||
ConfigPtr = XIic_LookupConfig(IIC_DEVICE_ID);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
Status = XIic_CfgInitialize(&IicInstance, ConfigPtr,
|
||||
ConfigPtr->BaseAddress);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the options to enable 10-bit addressing.
|
||||
*/
|
||||
XIic_SetOptions(&IicInstance, XII_SEND_10_BIT_OPTION);
|
||||
|
||||
/*
|
||||
* Setup the Interrupt System.
|
||||
*/
|
||||
Status = SetupInterruptSystem(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Include the Slave functions.
|
||||
*/
|
||||
XIic_SlaveInclude();
|
||||
|
||||
/*
|
||||
* Set the Transmit, Receive and Status Handlers.
|
||||
*/
|
||||
XIic_SetStatusHandler(&IicInstance, &IicInstance,
|
||||
(XIic_StatusHandler) StatusHandler);
|
||||
XIic_SetSendHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) SendHandler);
|
||||
XIic_SetRecvHandler(&IicInstance, &IicInstance,
|
||||
(XIic_Handler) ReceiveHandler);
|
||||
|
||||
/*
|
||||
* Set the Address as a RESPOND type.
|
||||
*/
|
||||
Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_RESPOND_TYPE,
|
||||
SLAVE_ADDRESS);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* The IIC Master on this bus should initiate the transfer
|
||||
* and write data to the slave at this instance.
|
||||
*/
|
||||
TenBitAddrReadData(ReadBuffer, RECEIVE_COUNT);
|
||||
|
||||
for (Index = 0; Index < SEND_COUNT; Index++) {
|
||||
WriteBuffer[Index] = Index;
|
||||
}
|
||||
|
||||
/*
|
||||
* The IIC Master on this bus should initiate the transfer
|
||||
* and read data from the slave.
|
||||
*/
|
||||
TenBitAddrWriteData(SEND_COUNT);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function reads a buffer of bytes when the IIC Master on the bus writes
|
||||
* data to the slave device.
|
||||
*
|
||||
* @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 TenBitAddrReadData(u8 *BufferPtr, u16 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Set the defaults.
|
||||
*/
|
||||
ReceiveComplete = 1;
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Global Interrupt Enable.
|
||||
*/
|
||||
XIic_IntrGlobalEnable(IicInstance.BaseAddress);
|
||||
|
||||
/*
|
||||
* Wait for AAS interrupt and completion of data reception.
|
||||
*/
|
||||
while ((ReceiveComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
if (SlaveRead) {
|
||||
XIic_SlaveRecv(&IicInstance, ReadBuffer, RECEIVE_COUNT);
|
||||
SlaveRead = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the Global Interrupt Enable.
|
||||
*/
|
||||
XIic_IntrGlobalDisable(IicInstance.BaseAddress);
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function writes a buffer of bytes to the IIC bus when the IIC master
|
||||
* initiates a read operation.
|
||||
*
|
||||
* @param ByteCount contains the number of bytes in the buffer to be
|
||||
* written.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int TenBitAddrWriteData(u16 ByteCount)
|
||||
{
|
||||
int Status;
|
||||
|
||||
/*
|
||||
* Set the defaults.
|
||||
*/
|
||||
TransmitComplete = 1;
|
||||
|
||||
/*
|
||||
* Start the IIC device.
|
||||
*/
|
||||
Status = XIic_Start(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the Global Interrupt Enable.
|
||||
*/
|
||||
XIic_IntrGlobalEnable(IicInstance.BaseAddress);
|
||||
|
||||
/*
|
||||
* Wait for AAS interrupt and transmission to complete.
|
||||
*/
|
||||
while ((TransmitComplete) || (XIic_IsIicBusy(&IicInstance) == TRUE)) {
|
||||
if (SlaveWrite) {
|
||||
XIic_SlaveSend(&IicInstance, WriteBuffer, SEND_COUNT);
|
||||
SlaveWrite = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the Global Interrupt Enable bit.
|
||||
*/
|
||||
XIic_IntrGlobalDisable(IicInstance.BaseAddress);
|
||||
|
||||
/*
|
||||
* Stop the IIC device.
|
||||
*/
|
||||
Status = XIic_Stop(&IicInstance);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This Status handler is called asynchronously from an interrupt context and
|
||||
* indicates the events that have occurred.
|
||||
*
|
||||
* @param InstancePtr is not used, but contains a pointer to the IIC
|
||||
* device driver instance which the handler is being called for.
|
||||
* @param Event indicates whether it is a request for a write or read.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static void StatusHandler(XIic *InstancePtr, int Event)
|
||||
{
|
||||
/*
|
||||
* Check whether the Event is to write or read the data from the slave.
|
||||
*/
|
||||
if (Event == XII_MASTER_WRITE_EVENT) {
|
||||
/*
|
||||
* Its a Write request from Master.
|
||||
*/
|
||||
SlaveRead = 1;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Its a Read request from the master.
|
||||
*/
|
||||
SlaveWrite = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This Send handler is called asynchronously from an interrupt
|
||||
* context and indicates that data in the specified buffer has been sent.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static void SendHandler(XIic *InstancePtr)
|
||||
{
|
||||
TransmitComplete = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This Receive handler is called asynchronously from an interrupt
|
||||
* context and indicates that data in the specified buffer has been Received.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC driver instance for which
|
||||
* the handler is being called for.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static void ReceiveHandler(XIic *InstancePtr)
|
||||
{
|
||||
ReceiveComplete = 0;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This function setups the interrupt system so interrupts can occur for the
|
||||
* IIC. The function is application-specific since the actual system may or
|
||||
* may not have an interrupt controller. The IIC device could be directly
|
||||
* connected to a processor without an interrupt controller. The user should
|
||||
* modify this function to fit the application.
|
||||
*
|
||||
* @param IicInstPtr contains a pointer to the instance of the IIC which
|
||||
* is going to be connected to the interrupt controller.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
static int SetupInterruptSystem(XIic * IicInstPtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
if (InterruptController.IsStarted == XIL_COMPONENT_IS_STARTED) {
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the interrupt controller driver so that it's ready to use.
|
||||
*/
|
||||
Status = XIntc_Initialize(&InterruptController, INTC_DEVICE_ID);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 = XIntc_Connect(&InterruptController, IIC_INTR_ID,
|
||||
(XInterruptHandler) XIic_InterruptHandler,
|
||||
IicInstPtr);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the interrupt controller so interrupts are enabled for all
|
||||
* devices that cause interrupts.
|
||||
*/
|
||||
Status = XIntc_Start(&InterruptController, XIN_REAL_MODE);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the interrupts for the IIC device.
|
||||
*/
|
||||
XIntc_Enable(&InterruptController, IIC_INTR_ID);
|
||||
|
||||
/*
|
||||
* Initialize the exception table.
|
||||
*/
|
||||
Xil_ExceptionInit();
|
||||
|
||||
/*
|
||||
* Register the interrupt controller handler with the exception table.
|
||||
*/
|
||||
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
|
||||
(Xil_ExceptionHandler) XIntc_InterruptHandler,
|
||||
&InterruptController);
|
||||
|
||||
/*
|
||||
* Enable non-critical exceptions.
|
||||
*/
|
||||
Xil_ExceptionEnable();
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
27
XilinxProcessorIPLib/drivers/iic/src/Makefile
Normal file
27
XilinxProcessorIPLib/drivers/iic/src/Makefile
Normal file
|
@ -0,0 +1,27 @@
|
|||
COMPILER=
|
||||
ARCHIVER=
|
||||
CP=cp
|
||||
COMPILER_FLAGS=
|
||||
EXTRA_COMPILER_FLAGS=
|
||||
LIB=libxil.a
|
||||
|
||||
RELEASEDIR=../../../lib
|
||||
INCLUDEDIR=../../../include
|
||||
INCLUDES=-I./. -I${INCLUDEDIR}
|
||||
|
||||
INCLUDEFILES=xiic.h xiic_l.h
|
||||
LIBSOURCES=*.c
|
||||
OUTS = *.o
|
||||
|
||||
|
||||
libs:
|
||||
echo "Compiling iic"
|
||||
$(COMPILER) $(COMPILER_FLAGS) $(EXTRA_COMPILER_FLAGS) $(INCLUDES) $(LIBSOURCES)
|
||||
$(ARCHIVER) -r ${RELEASEDIR}/${LIB} ${OUTS}
|
||||
make clean
|
||||
|
||||
include:
|
||||
${CP} ${INCLUDEFILES} ${INCLUDEDIR}
|
||||
|
||||
clean:
|
||||
rm -rf ${OUTS}
|
767
XilinxProcessorIPLib/drivers/iic/src/xiic.c
Normal file
767
XilinxProcessorIPLib/drivers/iic/src/xiic.c
Normal file
|
@ -0,0 +1,767 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic.c
|
||||
*
|
||||
* Contains required functions for the XIic component. See xiic.h for more
|
||||
* information on the driver.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------
|
||||
* 1.01a rfp 10/19/01 release
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.01c rmm 05/14/03 Fixed diab compiler warnings relating to asserts.
|
||||
* 1.01d jhl 10/08/03 Added general purpose output feature
|
||||
* 1.02a jvb 12/13/05 Added CfgInitialize(), and made CfgInitialize() take
|
||||
* a pointer to a config structure instead of a device id.
|
||||
* Moved Initialize() into xiic_sinit.c, and have
|
||||
* Initialize() call CfgInitialize() after it retrieved the
|
||||
* config structure using the device id. Removed include of
|
||||
* xparameters.h along with any dependencies on xparameters.h
|
||||
* and the _g.c config table.
|
||||
* 1.02a mta 03/09/06 Added a new function XIic_IsIicBusy() which returns
|
||||
* whether IIC Bus is Busy or Free.
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 1.15a ktn 02/17/09 Fixed XIic_GetAddress() to return correct device address.
|
||||
* 1.16a ktn 07/18/09 Updated the notes in XIic_Reset function to clearly
|
||||
* indicate that only the Interrupt Registers are reset.
|
||||
* 1.16a ktn 10/16/09 Updated the notes in the XIic_SelfTest() API to mention
|
||||
* that the complete IIC core is Reset on giving a software
|
||||
* reset to the IIC core. This issue is fixed in the latest
|
||||
* version of the IIC core (some previous versions of the
|
||||
* core only reset the Interrupt Logic/Registers), please
|
||||
* see the Hw specification for further information.
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Some of the macros have been renamed to remove _m from
|
||||
* the name see the xiic_i.h and xiic_l.h file for further
|
||||
* information (Example XIic_mClearIntr is now
|
||||
* XIic_ClearIntr).
|
||||
* Some of the macros have been renamed to be consistent,
|
||||
* see the xiic_l.h file for further information
|
||||
* (Example XIIC_WRITE_IIER is renamed as XIic_WriteIier).
|
||||
* The driver has been updated to use the HAL APIs/macros.
|
||||
* 2.07a adk 18/04/13 Updated the code to avoid unused variable warnings
|
||||
* when compiling with the -Wextra -Wall flags.
|
||||
* Changes done if files xiic.c and xiic_i.h. CR:705001.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/***************************** Include Files *******************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions ***************************/
|
||||
|
||||
|
||||
/**************************** Type Definitions *****************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *******************/
|
||||
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
static void XIic_StubStatusHandler(void *CallBackRef, int ErrorCode);
|
||||
|
||||
static void XIic_StubHandler(void *CallBackRef, int ByteCount);
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Initializes a specific XIic instance. The initialization entails:
|
||||
*
|
||||
* - Initialize the driver to allow access to the device registers and
|
||||
* initialize other subcomponents necessary for the operation of the device.
|
||||
* - Default options to:
|
||||
* - 7-bit slave addressing
|
||||
* - Send messages as a slave device
|
||||
* - Repeated start off
|
||||
* - General call recognition disabled
|
||||
* - Clear messageing and error statistics
|
||||
*
|
||||
* The XIic_Start() function must be called after this function before the device
|
||||
* is ready to send and receive data on the IIC bus.
|
||||
*
|
||||
* Before XIic_Start() is called, the interrupt control must connect the ISR
|
||||
* routine to the interrupt handler. This is done by the user, and not
|
||||
* XIic_Start() to allow the user to use an interrupt controller of their choice.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @param Config is a reference to a structure containing information
|
||||
* about a specific IIC device. This function can initialize
|
||||
* multiple instance objects with the use of multiple calls giving
|
||||
* different Config information on each call.
|
||||
* @param EffectiveAddr is the device base address in the virtual memory
|
||||
* address space. The caller is responsible for keeping the
|
||||
* address mapping from EffectiveAddr to the device physical base
|
||||
* address unchanged once this function is invoked. Unexpected
|
||||
* errors may occur if the address mapping changes after this
|
||||
* function is called. If address translation is not used, use
|
||||
* Config->BaseAddress for this parameters, passing the physical
|
||||
* address instead.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS when successful
|
||||
* - XST_DEVICE_IS_STARTED indicates the device is started
|
||||
* (i.e. interrupts enabled and messaging is possible). Must stop
|
||||
* before re-initialization is allowed.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int XIic_CfgInitialize(XIic *InstancePtr, XIic_Config * Config,
|
||||
u32 EffectiveAddr)
|
||||
{
|
||||
/*
|
||||
* Asserts test the validity of selected input arguments.
|
||||
*/
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
InstancePtr->IsReady = 0;
|
||||
|
||||
/*
|
||||
* If the device is started, disallow the initialize and return a Status
|
||||
* indicating it is started. This allows the user to stop the device
|
||||
* and reinitialize, but prevents a user from inadvertently
|
||||
* initializing.
|
||||
*/
|
||||
if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) {
|
||||
return XST_DEVICE_IS_STARTED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set default values and configuration data, including setting the
|
||||
* callback handlers to stubs so the system will not crash should the
|
||||
* application not assign its own callbacks.
|
||||
*/
|
||||
InstancePtr->IsStarted = 0;
|
||||
InstancePtr->BaseAddress = EffectiveAddr;
|
||||
InstancePtr->RecvHandler = XIic_StubHandler;
|
||||
InstancePtr->RecvBufferPtr = NULL;
|
||||
InstancePtr->SendHandler = XIic_StubHandler;
|
||||
InstancePtr->SendBufferPtr = NULL;
|
||||
InstancePtr->StatusHandler = XIic_StubStatusHandler;
|
||||
InstancePtr->Has10BitAddr = Config->Has10BitAddr;
|
||||
InstancePtr->IsReady = XIL_COMPONENT_IS_READY;
|
||||
InstancePtr->Options = 0;
|
||||
InstancePtr->BNBOnly = FALSE;
|
||||
InstancePtr->GpOutWidth = Config->GpOutWidth;
|
||||
InstancePtr->IsDynamic = FALSE;
|
||||
InstancePtr->IsSlaveSetAckOff = FALSE;
|
||||
|
||||
/*
|
||||
* Reset the device.
|
||||
*/
|
||||
XIic_Reset(InstancePtr);
|
||||
|
||||
XIic_ClearStats(InstancePtr);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function starts the IIC device and driver by enabling the proper
|
||||
* interrupts such that data may be sent and received on the IIC bus.
|
||||
* This function must be called before the functions to send and receive data.
|
||||
*
|
||||
* Before XIic_Start() is called, the interrupt control must connect the ISR
|
||||
* routine to the interrupt handler. This is done by the user, and not
|
||||
* XIic_Start() to allow the user to use an interrupt controller of their choice.
|
||||
*
|
||||
* Start enables:
|
||||
* - IIC device
|
||||
* - Interrupts:
|
||||
* - Addressed as slave to allow messages from another master
|
||||
* - Arbitration Lost to detect Tx arbitration errors
|
||||
* - Global IIC interrupt
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return XST_SUCCESS always.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* The device interrupt is connected to the interrupt controller, but no
|
||||
* "messaging" interrupts are enabled. Addressed as Slave is enabled to
|
||||
* reception of messages when this devices address is written to the bus.
|
||||
* The correct messaging interrupts are enabled when sending or receiving
|
||||
* via the IicSend() and IicRecv() functions. No action is required
|
||||
* by the user to control any IIC interrupts as the driver completely
|
||||
* manages all 8 interrupts. Start and Stop control the ability
|
||||
* to use the device. Stopping the device completely stops all device
|
||||
* interrupts from the processor.
|
||||
*
|
||||
****************************************************************************/
|
||||
int XIic_Start(XIic *InstancePtr)
|
||||
{
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||||
|
||||
/*
|
||||
* Mask off all interrupts, each is enabled when needed.
|
||||
*/
|
||||
XIic_WriteIier(InstancePtr->BaseAddress, 0);
|
||||
|
||||
/*
|
||||
* Clear all interrupts by reading and rewriting exact value back.
|
||||
* Only those bits set will get written as 1 (writing 1 clears intr).
|
||||
*/
|
||||
XIic_ClearIntr(InstancePtr->BaseAddress, 0xFFFFFFFF);
|
||||
|
||||
/*
|
||||
* Enable the device.
|
||||
*/
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
XIIC_CR_ENABLE_DEVICE_MASK);
|
||||
/*
|
||||
* Set Rx FIFO Occupancy depth to throttle at
|
||||
* first byte(after reset = 0).
|
||||
*/
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET, 0);
|
||||
|
||||
/*
|
||||
* Clear and enable the interrupts needed.
|
||||
*/
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_AAS_MASK | XIIC_INTR_ARB_LOST_MASK);
|
||||
|
||||
InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED;
|
||||
InstancePtr->IsDynamic = FALSE;
|
||||
|
||||
/*
|
||||
* Enable the Global interrupt enable.
|
||||
*/
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function stops the IIC device and driver such that data is no longer
|
||||
* sent or received on the IIC bus. This function stops the device by
|
||||
* disabling interrupts. This function only disables interrupts within the
|
||||
* device such that the caller is responsible for disconnecting the interrupt
|
||||
* handler of the device from the interrupt source and disabling interrupts
|
||||
* at other levels.
|
||||
*
|
||||
* Due to bus throttling that could hold the bus between messages when using
|
||||
* repeated start option, stop will not occur when the device is actively
|
||||
* sending or receiving data from the IIC bus or the bus is being throttled
|
||||
* by this device, but instead return XST_IIC_BUS_BUSY.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS indicates all IIC interrupts are disabled.
|
||||
* No messages can be received or transmitted until XIic_Start()
|
||||
* is called.
|
||||
* - XST_IIC_BUS_BUSY indicates this device is currently engaged
|
||||
* in message traffic and cannot be stopped.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int XIic_Stop(XIic *InstancePtr)
|
||||
{
|
||||
u32 Status;
|
||||
u32 CntlReg;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
/*
|
||||
* Disable all interrupts globally.
|
||||
*/
|
||||
XIic_IntrGlobalDisable(InstancePtr->BaseAddress);
|
||||
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
|
||||
|
||||
if ((CntlReg & XIIC_CR_MSMS_MASK) ||
|
||||
(Status & XIIC_SR_ADDR_AS_SLAVE_MASK)) {
|
||||
/*
|
||||
* When this device is using the bus
|
||||
* - re-enable interrupts to finish current messaging
|
||||
* - return bus busy
|
||||
*/
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_IIC_BUS_BUSY;
|
||||
}
|
||||
|
||||
InstancePtr->IsStarted = 0;
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Resets the IIC device.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note The complete IIC core is Reset on giving a software reset to
|
||||
* the IIC core. Some previous versions of the core only reset
|
||||
* the Interrupt Logic/Registers, please refer to the HW specification
|
||||
* for futher details about this.
|
||||
*
|
||||
****************************************************************************/
|
||||
void XIic_Reset(XIic *InstancePtr)
|
||||
{
|
||||
Xil_AssertVoid(InstancePtr != NULL);
|
||||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||||
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RESETR_OFFSET,
|
||||
XIIC_RESET_MASK);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function sets the bus addresses. The addresses include the device
|
||||
* address that the device responds to as a slave, or the slave address
|
||||
* to communicate with on the bus. The IIC device hardware is built to
|
||||
* allow either 7 or 10 bit slave addressing only at build time rather
|
||||
* than at run time. When this device is a master, slave addressing can
|
||||
* be selected at run time to match addressing modes for other bus devices.
|
||||
*
|
||||
* Addresses are represented as hex values with no adjustment for the data
|
||||
* direction bit as the software manages address bit placement.
|
||||
* Example: For a 7 address written to the device of 1010 011X where X is
|
||||
* the transfer direction (send/recv), the address parameter for this function
|
||||
* needs to be 01010011 or 0x53 where the correct bit alllignment will be
|
||||
* handled for 7 as well as 10 bit devices. This is especially important as
|
||||
* the bit placement is not handled the same depending on which options are
|
||||
* used such as repeated start.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @param AddressType indicates which address is being modified, the
|
||||
* address which this device responds to on the IIC bus as a slave,
|
||||
* or the slave address to communicate with when this device is a
|
||||
* master. One of the following values must be contained in
|
||||
* this argument.
|
||||
* <pre>
|
||||
* XII_ADDR_TO_SEND_TYPE Slave being addressed by a this master
|
||||
* XII_ADDR_TO_RESPOND_TYPE Address to respond to as a slave device
|
||||
* </pre>
|
||||
*
|
||||
* @param Address contains the address to be set, 7 bit or 10 bit address.
|
||||
* A ten bit address must be within the range: 0 - 1023 and a 7 bit
|
||||
* address must be within the range 0 - 127.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS is returned if the address was successfully set.
|
||||
* - XST_IIC_NO_10_BIT_ADDRESSING indicates only 7 bit addressing
|
||||
* supported.
|
||||
* - XST_INVALID_PARAM indicates an invalid parameter was
|
||||
* specified.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* Upper bits of 10-bit address is written only when current device is built
|
||||
* as a ten bit device.
|
||||
*
|
||||
****************************************************************************/
|
||||
int XIic_SetAddress(XIic *InstancePtr, int AddressType, int Address)
|
||||
{
|
||||
u32 SendAddr;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(Address < 1023);
|
||||
|
||||
/*
|
||||
* Set address to respond to for this device into address registers.
|
||||
*/
|
||||
if (AddressType == XII_ADDR_TO_RESPOND_TYPE) {
|
||||
/*
|
||||
* Address in upper 7 bits.
|
||||
*/
|
||||
SendAddr = ((Address & 0x007F) << 1);
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_ADR_REG_OFFSET,
|
||||
SendAddr);
|
||||
|
||||
if (InstancePtr->Has10BitAddr == TRUE) {
|
||||
/*
|
||||
* Write upper 3 bits of addr to DTR only when 10 bit
|
||||
* option included in design i.e. register exists.
|
||||
*/
|
||||
SendAddr = ((Address & 0x0380) >> 7);
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_TBA_REG_OFFSET, SendAddr);
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store address of slave device being read from.
|
||||
*/
|
||||
if (AddressType == XII_ADDR_TO_SEND_TYPE) {
|
||||
InstancePtr->AddrOfSlave = Address;
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
return XST_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function gets the addresses for the IIC device driver. The addresses
|
||||
* include the device address that the device responds to as a slave, or the
|
||||
* slave address to communicate with on the bus. The address returned has the
|
||||
* same format whether 7 or 10 bits.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @param AddressType indicates which address, the address which this
|
||||
* responds to on the IIC bus as a slave, or the slave address to
|
||||
* communicate with when this device is a master. One of the
|
||||
* following values must be contained in this argument.
|
||||
* <pre>
|
||||
* XII_ADDR_TO_SEND_TYPE Slave being addressed as a master
|
||||
* XII_ADDR_TO_RESPOND_TYPE Slave address to respond to as a slave
|
||||
* </pre>
|
||||
* If neither of the two valid arguments are used, the function returns
|
||||
* the address of the slave device
|
||||
*
|
||||
* @return The address retrieved.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
u16 XIic_GetAddress(XIic *InstancePtr, int AddressType)
|
||||
{
|
||||
u8 LowAddr;
|
||||
u16 HighAddr = 0;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
/*
|
||||
* Return this device's address.
|
||||
*/
|
||||
if (AddressType == XII_ADDR_TO_RESPOND_TYPE) {
|
||||
|
||||
LowAddr = (u8) XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_ADR_REG_OFFSET);
|
||||
|
||||
if (InstancePtr->Has10BitAddr == TRUE) {
|
||||
HighAddr = (u16) XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_TBA_REG_OFFSET);
|
||||
}
|
||||
return ((HighAddr << 8) | (u16) LowAddr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Otherwise return address of slave device on the IIC bus.
|
||||
*/
|
||||
return InstancePtr->AddrOfSlave;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function sets the contents of the General Purpose Output register
|
||||
* for the IIC device driver. Note that the number of bits in this register is
|
||||
* parameterizable in the hardware such that it may not exist. This function
|
||||
* checks to ensure that it does exist to prevent bus errors, but does not
|
||||
* ensure that the number of bits in the register are sufficient for the
|
||||
* value being written (won't cause a bus error).
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @param OutputValue contains the value to be written to the register.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS if the given data is written to the GPO register.
|
||||
* - XST_NO_FEATURE if the hardware is configured such that this
|
||||
* register does not contain any bits to read or write.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int XIic_SetGpOutput(XIic *InstancePtr, u8 OutputValue)
|
||||
{
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
/*
|
||||
* If the general purpose output register is implemented by the hardware
|
||||
* then write the specified value to it, otherwise indicate an error.
|
||||
*/
|
||||
if (InstancePtr->GpOutWidth > 0) {
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_GPO_REG_OFFSET,
|
||||
OutputValue);
|
||||
return XST_SUCCESS;
|
||||
} else {
|
||||
return XST_NO_FEATURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function gets the contents of the General Purpose Output register
|
||||
* for the IIC device driver. Note that the number of bits in this register is
|
||||
* parameterizable in the hardware such that it may not exist. This function
|
||||
* checks to ensure that it does exist to prevent bus errors.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @param OutputValuePtr contains the value which was read from the
|
||||
* register.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS if the given data is read from the GPO register.
|
||||
* - XST_NO_FEATURE if the hardware is configured such that this
|
||||
* register does not contain any bits to read or write.
|
||||
*
|
||||
* The OutputValuePtr is also an output as it contains the value read.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int XIic_GetGpOutput(XIic *InstancePtr, u8 *OutputValuePtr)
|
||||
{
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(OutputValuePtr != NULL);
|
||||
|
||||
/*
|
||||
* If the general purpose output register is implemented by the hardware
|
||||
* then read the value from it, otherwise indicate an error.
|
||||
*/
|
||||
if (InstancePtr->GpOutWidth > 0) {
|
||||
*OutputValuePtr = XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_GPO_REG_OFFSET);
|
||||
return XST_SUCCESS;
|
||||
} else {
|
||||
return XST_NO_FEATURE;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* A function to determine if the device is currently addressed as a slave.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return
|
||||
* - TRUE if the device is addressed as slave.
|
||||
* - FALSE if the device is NOT addressed as slave.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
u32 XIic_IsSlave(XIic *InstancePtr)
|
||||
{
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
if ((XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET) &
|
||||
XIIC_SR_ADDR_AS_SLAVE_MASK) == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Sets the receive callback function, the receive handler, which the driver
|
||||
* calls when it finishes receiving data. The number of bytes used to signal
|
||||
* when the receive is complete is the number of bytes set in the XIic_Recv
|
||||
* function.
|
||||
*
|
||||
* The handler executes in an interrupt context such that it must minimize
|
||||
* the amount of processing performed such as transferring data to a thread
|
||||
* context.
|
||||
*
|
||||
* The number of bytes received is passed to the handler as an argument.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @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 .
|
||||
*
|
||||
****************************************************************************/
|
||||
void XIic_SetRecvHandler(XIic *InstancePtr, void *CallBackRef,
|
||||
XIic_Handler FuncPtr)
|
||||
{
|
||||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||||
Xil_AssertVoid(InstancePtr != NULL);
|
||||
Xil_AssertVoid(FuncPtr != NULL);
|
||||
|
||||
InstancePtr->RecvHandler = FuncPtr;
|
||||
InstancePtr->RecvCallBackRef = CallBackRef;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Sets the send callback function, the send handler, which the driver calls when
|
||||
* it receives confirmation of sent data. The handler executes in an interrupt
|
||||
* context such that it must minimize the amount of processing performed such
|
||||
* as transferring data to a thread context.
|
||||
*
|
||||
* @param InstancePtr the pointer to the XIic instance to be worked on.
|
||||
* @param CallBackRef the upper layer callback reference passed back when
|
||||
* the callback function is invoked.
|
||||
* @param FuncPtr the pointer to the callback function.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note The handler is called within interrupt context .
|
||||
*
|
||||
****************************************************************************/
|
||||
void XIic_SetSendHandler(XIic *InstancePtr, void *CallBackRef,
|
||||
XIic_Handler FuncPtr)
|
||||
{
|
||||
Xil_AssertVoid(InstancePtr != NULL);
|
||||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||||
Xil_AssertVoid(FuncPtr != NULL);
|
||||
|
||||
InstancePtr->SendHandler = FuncPtr;
|
||||
InstancePtr->SendCallBackRef = CallBackRef;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Sets the status callback function, the status handler, which the driver calls
|
||||
* when it encounters conditions which are not data related. The handler
|
||||
* executes in an interrupt context such that it must minimize the amount of
|
||||
* processing performed such as transferring data to a thread context. The
|
||||
* status events that can be returned are described in xiic.h.
|
||||
*
|
||||
* @param InstancePtr points to the XIic instance to be worked on.
|
||||
* @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 .
|
||||
*
|
||||
****************************************************************************/
|
||||
void XIic_SetStatusHandler(XIic *InstancePtr, void *CallBackRef,
|
||||
XIic_StatusHandler FuncPtr)
|
||||
{
|
||||
Xil_AssertVoid(InstancePtr != NULL);
|
||||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||||
Xil_AssertVoid(FuncPtr != NULL);
|
||||
|
||||
InstancePtr->StatusHandler = FuncPtr;
|
||||
InstancePtr->StatusCallBackRef = CallBackRef;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* This is a stub for the send and recv callbacks. The stub is here in case the
|
||||
* upper layers forget to set the handlers.
|
||||
*
|
||||
* @param CallBackRef is a pointer to the upper layer callback reference
|
||||
* @param ByteCount is the number of bytes sent or received
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void XIic_StubHandler(void *CallBackRef, int ByteCount)
|
||||
{
|
||||
(void) ByteCount;
|
||||
(void) CallBackRef;
|
||||
Xil_AssertVoidAlways();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* This is a stub for the asynchronous error 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 ErrorCode is the Xilinx error code, indicating the cause of
|
||||
* the error.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void XIic_StubStatusHandler(void *CallBackRef, int ErrorCode)
|
||||
{
|
||||
(void) ErrorCode;
|
||||
(void) CallBackRef;
|
||||
Xil_AssertVoidAlways();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* This is a function which tells whether Bus is Busy or free.
|
||||
*
|
||||
* @param InstancePtr points to the XIic instance to be worked on.
|
||||
*
|
||||
* @return
|
||||
* - TRUE if the Bus is Busy.
|
||||
* - FALSE if the Bus is NOT Busy.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
u32 XIic_IsIicBusy(XIic *InstancePtr)
|
||||
{
|
||||
u32 StatusReg;
|
||||
|
||||
StatusReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
|
||||
if (StatusReg & XIIC_SR_BUS_BUSY_MASK) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
572
XilinxProcessorIPLib/drivers/iic/src/xiic.h
Normal file
572
XilinxProcessorIPLib/drivers/iic/src/xiic.h
Normal file
|
@ -0,0 +1,572 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic.h
|
||||
*
|
||||
* XIic is the driver for an IIC master or slave device.
|
||||
*
|
||||
* In order to reduce the memory requirements of the driver the driver is
|
||||
* partitioned such that there are optional parts of the driver.
|
||||
* Slave, master, and multimaster features are optional such that all these files
|
||||
* are not required at the same time.
|
||||
* In order to use the slave and multimaster features of the driver, the user
|
||||
* must call functions (XIic_SlaveInclude and XIic_MultiMasterInclude)
|
||||
* to dynamically include the code. These functions may be called at any time.
|
||||
*
|
||||
* Two sets of higher level API's are available in the XIic driver that can
|
||||
* be used for Transmission/Reception in Master mode :
|
||||
* - XIic_MasterSend()/ XIic_MasterRecv() which is used in normal mode.
|
||||
* - XIic_DynMasterSend()/ XIic_DynMasterRecv() which is used in Dynamic mode.
|
||||
*
|
||||
* Similarly two sets of lower level API's are available in XIic driver that
|
||||
* can be used for Transmission/Reception in Master mode:
|
||||
* - XIic_Send()/ XIic_Recv() which is used in normal mode
|
||||
* - XIic_DynSend()/ XIic_DynRecv() which is used in Dynamic mode.
|
||||
*
|
||||
* The user should use a single set of APIs as per his requirement and
|
||||
* should not intermix them.
|
||||
*
|
||||
* All the driver APIs can be used for read, write and combined mode of
|
||||
* operations on the IIC bus.
|
||||
*
|
||||
* In the normal mode IIC support both 7-bit and 10-bit addressing, and in
|
||||
* the dynamic mode support only 7-bit addressing.
|
||||
*
|
||||
* <b>Initialization & Configuration</b>
|
||||
*
|
||||
* The XIic_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 one
|
||||
* of the following ways:
|
||||
*
|
||||
* - XIic_Initialize() - The driver looks up its own
|
||||
* configuration structure created by the tool-chain based on an ID provided
|
||||
* by the tool-chain.
|
||||
*
|
||||
* - XIic_CfgInitialize() - The driver uses a configuration structure provided
|
||||
* by the caller. If running in a system with address translation, the
|
||||
* provided virtual memory base address replaces the physical address present
|
||||
* in the configuration structure.
|
||||
*
|
||||
* <b>General Purpose Output</b>
|
||||
* The IIC hardware provides a General Purpose Output Register that allows the
|
||||
* user to connect general purpose outputs to devices, such as a write protect,
|
||||
* for an EEPROM. This register is parameterizable in the hardware such that
|
||||
* there could be zero bits in this register and in this case it will cause
|
||||
* a bus error if read or written.
|
||||
*
|
||||
* <b>Bus Throttling</b>
|
||||
*
|
||||
* The IIC hardware provides bus throttling which allows either the device, as
|
||||
* either a master or a slave, to stop the clock on the IIC bus. This feature
|
||||
* allows the software to perform the appropriate processing for each interrupt
|
||||
* without an unreasonable response restriction. With this design, it is
|
||||
* important for the user to understand the implications of bus throttling.
|
||||
*
|
||||
* <b>Repeated Start</b>
|
||||
*
|
||||
* An application can send multiple messages, as a master, to a slave device
|
||||
* and re-acquire the IIC bus each time a message is sent. The repeated start
|
||||
* option allows the application to send multiple messages without re-acquiring
|
||||
* the IIC bus for each message. The transactions involving repeated start
|
||||
* are also called combined transfers if there is Read and Write in the
|
||||
* same transaction.
|
||||
*
|
||||
* The repeated start feature works with all the API's in XIic driver.
|
||||
*
|
||||
* The Repeated Start feature also could cause the application to lock up, or
|
||||
* monopolize the IIC bus, should repeated start option be enabled and sequences
|
||||
* of messages never end(periodic data collection).
|
||||
* Also when repeated start is not disable before the last master message is
|
||||
* sent or received, will leave the bus captive to the master, but unused.
|
||||
*
|
||||
* <b>Addressing</b>
|
||||
*
|
||||
* The IIC hardware is parameterized such that it can be built for 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. The address size
|
||||
* which the hardware responds to as a slave is parameterized as 7 or 10 bits
|
||||
* but fixed by the hardware build.
|
||||
*
|
||||
* Addresses are represented as hex values with no adjustment for the data
|
||||
* direction bit as the software manages address bit placement. This is
|
||||
* especially important as the bit placement is not handled the same depending
|
||||
* on which options are used such as repeated start and 7 vs 10 bit addessing.
|
||||
*
|
||||
* <b>Data Rates</b>
|
||||
*
|
||||
* The IIC hardware is parameterized such that it can be built to support
|
||||
* data rates from DC to 400KBit. The frequency of the interrupts which
|
||||
* occur is proportional to the data rate.
|
||||
*
|
||||
* <b>Polled Mode Operation</b>
|
||||
*
|
||||
* This driver does not provide a polled mode of operation primarily because
|
||||
* polled mode which is non-blocking is difficult with the amount of
|
||||
* interaction with the hardware that is necessary.
|
||||
*
|
||||
* <b>Interrupts</b>
|
||||
*
|
||||
* The device has many interrupts which allow IIC data transactions as well
|
||||
* as bus status processing to occur.
|
||||
*
|
||||
* The interrupts are divided into two types, data and status. Data interrupts
|
||||
* indicate data has been received or transmitted while the status interrupts
|
||||
* indicate the status of the IIC bus. Some of the interrupts, such as Not
|
||||
* Addressed As Slave and Bus Not Busy, are only used when these specific
|
||||
* events must be recognized as opposed to being enabled at all times.
|
||||
*
|
||||
* Many of the interrupts are not a single event in that they are continuously
|
||||
* present such that they must be disabled after recognition or when undesired.
|
||||
* Some of these interrupts, which are data related, may be acknowledged by the
|
||||
* software by reading or writing data to the appropriate register, or must
|
||||
* be disabled. The following interrupts can be continuous rather than single
|
||||
* events.
|
||||
* - Data Transmit Register Empty/Transmit FIFO Empty
|
||||
* - Data Receive Register Full/Receive FIFO
|
||||
* - Transmit FIFO Half Empty
|
||||
* - Bus Not Busy
|
||||
* - Addressed As Slave
|
||||
* - Not Addressed As Slave
|
||||
*
|
||||
* The following interrupts are not passed directly to the application thru the
|
||||
* status callback. These are only used internally for the driver processing
|
||||
* and may result in the receive and send handlers being called to indicate
|
||||
* completion of an operation. The following interrupts are data related
|
||||
* rather than status.
|
||||
* - Data Transmit Register Empty/Transmit FIFO Empty
|
||||
* - Data Receive Register Full/Receive FIFO
|
||||
* - Transmit FIFO Half Empty
|
||||
* - Slave Transmit Complete
|
||||
*
|
||||
* <b>Interrupt To Event Mapping</b>
|
||||
*
|
||||
* The following table provides a mapping of the interrupts to the events which
|
||||
* are passed to the status handler and the intended role (master or slave) for
|
||||
* the event. Some interrupts can cause multiple events which are combined
|
||||
* together into a single status event such as XII_MASTER_WRITE_EVENT and
|
||||
* XII_GENERAL_CALL_EVENT
|
||||
* <pre>
|
||||
* Interrupt Event(s) Role
|
||||
*
|
||||
* Arbitration Lost Interrupt XII_ARB_LOST_EVENT Master
|
||||
* Transmit Error XII_SLAVE_NO_ACK_EVENT Master
|
||||
* IIC Bus Not Busy XII_BUS_NOT_BUSY_EVENT Master
|
||||
* Addressed As Slave XII_MASTER_READ_EVENT, Slave
|
||||
* XII_MASTER_WRITE_EVENT, Slave
|
||||
* XII_GENERAL_CALL_EVENT Slave
|
||||
* </pre>
|
||||
* <b>Not Addressed As Slave Interrupt</b>
|
||||
*
|
||||
* The Not Addressed As Slave interrupt is not passed directly to the
|
||||
* application thru the status callback. It is used to determine the end of
|
||||
* a message being received by a slave when there was no stop condition
|
||||
* (repeated start). It will cause the receive handler to be called to
|
||||
* indicate completion of the operation.
|
||||
*
|
||||
* <b>RTOS Independence</b>
|
||||
*
|
||||
* This driver is intended to be RTOS and processor independent. It works
|
||||
* with physical addresses only. Any needs for dynamic memory management,
|
||||
* threads or thread mutual exclusion, virtual memory, or cache control must
|
||||
* be satisfied by the layer above this driver.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.01a rfp 10/19/01 release
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.01d jhl 10/08/03 Added general purpose output feature
|
||||
* 1.01d sv 05/09/05 Changed the data being written to the Address/Control
|
||||
* Register and removed the code for testing the
|
||||
* Receive Data Register in XIic_SelfTest function of
|
||||
* xiic_selftest.c source file
|
||||
* 1.02a jvb 12/14/05 I separated dependency on the static config table and
|
||||
* xparameters.h from the driver initialization by moving
|
||||
* _Initialize and _LookupConfig to _sinit.c. I also added
|
||||
* the new _CfgInitialize routine.
|
||||
* 1.02a mta 03/09/06 Added a new function XIic_IsIicBusy() which returns
|
||||
* whether IIC Bus is Busy or Free.
|
||||
* 1.02a mta 03/09/06 Implemented Repeated Start in the Low Level Driver.
|
||||
* 1.03a mta 07/17/06 Added files to support Dynamic IIC controller in High
|
||||
* level driver. Added xiic_dyn_master.c. Added support
|
||||
* for IIC Dynamic controller in Low level driver in xiic_l.c
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 1.13b ecm 11/29/07 added BB polling loops to the DynSend and DynRecv
|
||||
* routines to handle the race condition with BNB in IISR.
|
||||
* 1.14a sdm 08/22/08 Removed support for static interrupt handlers from the MDD
|
||||
* file
|
||||
* 1.14a ecm 11/13/08 changed BB polling loops in DynRecv to handle race
|
||||
* condition, CR491889. DynSend was correct from v1.13.b
|
||||
* 1.15a ktn 02/17/09 Fixed XIic_GetAddress() to return correct device address.
|
||||
* 1.16a ktn 07/17/09 Updated the XIic_SelfTest() to test only Interrupt
|
||||
* Registers.
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.,
|
||||
* Removed the macro XIIC_RESET, XIic_Reset API should be
|
||||
* used in its place.
|
||||
* Removed the XIIC_CLEAR_STATS macro, XIic_ClearStats API
|
||||
* should be used in its place.
|
||||
* Removed the macro XIic_mEnterCriticalRegion,
|
||||
* XIic_IntrGlobalDisable should be used in its place.
|
||||
* Removed the macro XIic_mExitCriticalRegion,
|
||||
* XIic_IntrGlobalEnable should be used in its place.
|
||||
* Some of the macros have been renamed to remove _m from
|
||||
* the name see the xiic_i.h and xiic_l.h file for further
|
||||
* information (Example XIic_mClearIntr is now
|
||||
* XIic_ClearIntr).
|
||||
* Some of the macros have been renamed to be consistent,
|
||||
* see the xiic_l.h file for further information
|
||||
* (Example XIIC_WRITE_IIER is renamed as XIic_WriteIier).
|
||||
* The driver has been updated to use the HAL APIs/macros
|
||||
* (Example XASSERT_NONVOID is now Xil_AssertNonvoid)
|
||||
* 2.01a ktn 04/09/10 Updated TxErrorhandler in xiic_intr.c to be called for
|
||||
* Master Transmitter case based on Addressed As Slave (AAS)
|
||||
* bit rather than MSMS bit(CR 540199).
|
||||
* 2.02a sdm 10/08/10 Updated to disable the device at the end of the transfer,
|
||||
* using Addressed As Slave (AAS) bit when addressed as
|
||||
* slave in XIic_Send for CR565373.
|
||||
* 2.03a rkv 01/25/11 Updated in NAAS interrupt handler to support data
|
||||
* recieved less than FIFO size prior to NAAS interrupt.
|
||||
* Fixed for CR590212.
|
||||
* 2.04a sdm 07/22/11 Added IsSlaveSetAckOff flag to the instance structure.
|
||||
* This flag is set when the Slave has set the Ack Off in the
|
||||
* RecvSlaveData function (xiic_slave.c) and
|
||||
* is cleared in the NotAddrAsSlaveHandler (xiic_slave.c)
|
||||
* when the master has released the bus. This flag is
|
||||
* to be used by slave applications for recovering when it
|
||||
* has gone out of sync with the master for CR 615004.
|
||||
* Removed a compiler warning in XIic_Send (xiic_l.c)
|
||||
* 2.05a bss 02/05/12 Assigned RecvBufferPtr in XIic_MasterSend API and
|
||||
* SendBufferPtr in XIic_MasterRecv to NULL in xiic_master.c
|
||||
* 2.06a bss 02/14/13 Modified TxErrorHandler in xiic_intr.c to fix CR #686483
|
||||
* Modified xiic_eeprom_example.c to fix CR# 683509.
|
||||
* Modified bitwise OR to logical OR in
|
||||
* XIic_InterruptHandler API in xiic_intr.c.
|
||||
* 2.07a adk 18/04/13 Updated the code to avoid unused variable warnings
|
||||
* when compiling with the -Wextra -Wall flags.
|
||||
* Changes done in files xiic.c and xiic_i.h. CR:705001
|
||||
* 2.08a adk 29/07/13 In Low level driver In repeated start condition the
|
||||
* Direction of Tx bit must be disabled in recv condition
|
||||
* It Fixes the CR:685759 Changes are done in the file
|
||||
* xiic_l.c in the function XIic_Recv.
|
||||
* 3.0 adk 19/12/13 Updated as per the New Tcl API's
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef XIIC_H /* prevent circular inclusions */
|
||||
#define XIIC_H /* by using protection macros */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xil_types.h"
|
||||
#include "xil_assert.h"
|
||||
#include "xstatus.h"
|
||||
#include "xiic_l.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 bus. Each of the options
|
||||
* are bit fields such that more than one may be specified.
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* <pre>
|
||||
* XII_GENERAL_CALL_OPTION The general call option allows an IIC slave to
|
||||
* recognized the general call address. The status
|
||||
* handler is called as usual indicating the device
|
||||
* has been addressed as a slave with a general
|
||||
* call. It is the application's responsibility to
|
||||
* perform any special processing for the general
|
||||
* call.
|
||||
*
|
||||
* XII_REPEATED_START_OPTION The repeated start option allows multiple
|
||||
* messages to be sent/received on the IIC bus
|
||||
* without rearbitrating for the bus. The messages
|
||||
* are sent as a series of messages such that the
|
||||
* option must be enabled before the 1st message of
|
||||
* the series, to prevent an stop condition from
|
||||
* being generated on the bus, and disabled before
|
||||
* the last message of the series, to allow the
|
||||
* stop condition to be generated.
|
||||
*
|
||||
* XII_SEND_10_BIT_OPTION The send 10 bit option allows 10 bit addresses
|
||||
* to be sent on the bus when the device is a
|
||||
* master. The device can be configured to respond
|
||||
* as to 7 bit addresses even though it may be
|
||||
* communicating with other devices that support 10
|
||||
* bit addresses. When this option is not enabled,
|
||||
* only 7 bit addresses are sent on the bus.
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
#define XII_GENERAL_CALL_OPTION 0x00000001
|
||||
#define XII_REPEATED_START_OPTION 0x00000002
|
||||
#define XII_SEND_10_BIT_OPTION 0x00000004
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @name Status events
|
||||
*
|
||||
* The following status events occur during IIC bus processing and are passed
|
||||
* to the status callback. Each event is only valid during the appropriate
|
||||
* processing of the IIC bus. Each of these events are bit fields such that
|
||||
* more than one may be specified.
|
||||
* @{
|
||||
*/
|
||||
#define XII_BUS_NOT_BUSY_EVENT 0x00000001 /**< Bus transitioned to not busy */
|
||||
#define XII_ARB_LOST_EVENT 0x00000002 /**< Arbitration was lost */
|
||||
#define XII_SLAVE_NO_ACK_EVENT 0x00000004 /**< Slave did not ACK (had error) */
|
||||
#define XII_MASTER_READ_EVENT 0x00000008 /**< Master reading from slave */
|
||||
#define XII_MASTER_WRITE_EVENT 0x00000010 /**< Master writing to slave */
|
||||
#define XII_GENERAL_CALL_EVENT 0x00000020 /**< General call to all slaves */
|
||||
/*@}*/
|
||||
|
||||
|
||||
/*
|
||||
* The following address types are used when setting and getting the addresses
|
||||
* of the driver. These are mutually exclusive such that only one or the other
|
||||
* may be specified.
|
||||
*/
|
||||
#define XII_ADDR_TO_SEND_TYPE 1 /**< Bus address of slave device */
|
||||
#define XII_ADDR_TO_RESPOND_TYPE 2 /**< This device's bus address as slave */
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/**
|
||||
* This typedef contains configuration information for the device.
|
||||
*/
|
||||
typedef struct {
|
||||
u16 DeviceId; /**< Unique ID of device */
|
||||
u32 BaseAddress; /**< Device base address */
|
||||
int Has10BitAddr; /**< Does device have 10 bit address decoding */
|
||||
u8 GpOutWidth; /**< Number of bits in general purpose output */
|
||||
} XIic_Config;
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This callback function data type is defined to handle the asynchronous
|
||||
* processing of sent and received data of the IIC driver. The application
|
||||
* using this driver is expected to define a handler of this type to support
|
||||
* interrupt driven mode. The handlers are called in an interrupt context such
|
||||
* that minimal processing should be performed. The handler data type is
|
||||
* utilized for both send and receive handlers.
|
||||
*
|
||||
* @param CallBackRef is a 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
|
||||
* unimportant to the driver component, so it is a void pointer.
|
||||
* @param ByteCount indicates the number of bytes remaining to be sent or
|
||||
* received. A value of zero indicates that the requested number
|
||||
* of bytes were sent or received.
|
||||
*
|
||||
******************************************************************************/
|
||||
typedef void (*XIic_Handler) (void *CallBackRef, int ByteCount);
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* This callback function data type is defined to handle the asynchronous
|
||||
* processing of status events of the IIC driver. The application using
|
||||
* this driver is expected to define a handler of this type to support
|
||||
* interrupt driven mode. The handler is called in an interrupt context such
|
||||
* that minimal processing should be performed.
|
||||
*
|
||||
* @param CallBackRef is a 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
|
||||
* unimportant to the driver component, so it is a void pointer.
|
||||
* @param StatusEvent indicates one or more status events that occurred.
|
||||
* See the definition of the status events above.
|
||||
*
|
||||
********************************************************************************/
|
||||
typedef void (*XIic_StatusHandler) (void *CallBackRef, int StatusEvent);
|
||||
|
||||
/**
|
||||
* XIic statistics
|
||||
*/
|
||||
typedef struct {
|
||||
u8 ArbitrationLost;/**< Number of times arbitration was lost */
|
||||
u8 RepeatedStarts; /**< Number of repeated starts */
|
||||
u8 BusBusy; /**< Number of times bus busy status returned */
|
||||
u8 RecvBytes; /**< Number of bytes received */
|
||||
u8 RecvInterrupts; /**< Number of receive interrupts */
|
||||
u8 SendBytes; /**< Number of transmit bytes received */
|
||||
u8 SendInterrupts; /**< Number of transmit interrupts */
|
||||
u8 TxErrors; /**< Number of transmit errors (no ack) */
|
||||
u8 IicInterrupts; /**< Number of IIC (device) interrupts */
|
||||
} XIicStats;
|
||||
|
||||
/**
|
||||
* The XIic driver instance data. The user is required to allocate a
|
||||
* variable of this type for every IIC device in the system. A pointer
|
||||
* to a variable of this type is then passed to the driver API functions.
|
||||
*/
|
||||
typedef struct {
|
||||
XIicStats Stats; /**< Statistics */
|
||||
u32 BaseAddress; /**< Device base address */
|
||||
int Has10BitAddr; /**< TRUE when 10 bit addressing in design */
|
||||
int IsReady; /**< Device is initialized and ready */
|
||||
int IsStarted; /**< Device has been started */
|
||||
int AddrOfSlave; /**< Slave Address writing to */
|
||||
|
||||
u32 Options; /**< Current operating options */
|
||||
u8 *SendBufferPtr; /**< Buffer to send (state) */
|
||||
u8 *RecvBufferPtr; /**< Buffer to receive (state) */
|
||||
u8 TxAddrMode; /**< State of Tx Address transmission */
|
||||
int SendByteCount; /**< Number of data bytes in buffer (state) */
|
||||
int RecvByteCount; /**< Number of empty bytes in buffer (state) */
|
||||
|
||||
u32 BNBOnly; /**< TRUE when BNB interrupt needs to */
|
||||
/**< call callback */
|
||||
u8 GpOutWidth; /**< General purpose output width */
|
||||
|
||||
XIic_StatusHandler StatusHandler; /**< Status Handler */
|
||||
void *StatusCallBackRef; /**< Callback reference for status handler */
|
||||
XIic_Handler RecvHandler; /**< Receive Handler */
|
||||
void *RecvCallBackRef; /**< Callback reference for Recv handler */
|
||||
XIic_Handler SendHandler; /**< Send Handler */
|
||||
void *SendCallBackRef; /**< Callback reference for send handler */
|
||||
int IsDynamic; /**< TRUE when Dynamic control is used */
|
||||
int IsSlaveSetAckOff; /**< TRUE when Slave has set the ACK Off */
|
||||
|
||||
} XIic;
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
/*
|
||||
* Initialization functions in xiic_sinit.c
|
||||
*/
|
||||
int XIic_Initialize(XIic *InstancePtr, u16 DeviceId);
|
||||
XIic_Config *XIic_LookupConfig(u16 DeviceId);
|
||||
|
||||
/*
|
||||
* Functions in xiic.c
|
||||
*/
|
||||
int XIic_CfgInitialize(XIic *InstancePtr, XIic_Config *Config,
|
||||
u32 EffectiveAddr);
|
||||
|
||||
int XIic_Start(XIic *InstancePtr);
|
||||
int XIic_Stop(XIic *InstancePtr);
|
||||
|
||||
void XIic_Reset(XIic *InstancePtr);
|
||||
|
||||
int XIic_SetAddress(XIic *InstancePtr, int AddressType, int Address);
|
||||
u16 XIic_GetAddress(XIic *InstancePtr, int AddressType);
|
||||
|
||||
int XIic_SetGpOutput(XIic *InstancePtr, u8 OutputValue);
|
||||
int XIic_GetGpOutput(XIic *InstancePtr, u8 *OutputValuePtr);
|
||||
|
||||
u32 XIic_IsSlave(XIic *InstancePtr);
|
||||
|
||||
void XIic_SetRecvHandler(XIic *InstancePtr, void *CallBackRef,
|
||||
XIic_Handler FuncPtr);
|
||||
void XIic_SetSendHandler(XIic *InstancePtr, void *CallBackRef,
|
||||
XIic_Handler FuncPtr);
|
||||
void XIic_SetStatusHandler(XIic *InstancePtr, void *CallBackRef,
|
||||
XIic_StatusHandler FuncPtr);
|
||||
|
||||
/*
|
||||
* Interrupt functions in xiic_intr.c
|
||||
*/
|
||||
void XIic_InterruptHandler(void *InstancePtr);
|
||||
|
||||
/*
|
||||
* Master send and receive functions in normal mode in xiic_master.c
|
||||
*/
|
||||
int XIic_MasterRecv(XIic *InstancePtr, u8 *RxMsgPtr, int ByteCount);
|
||||
int XIic_MasterSend(XIic *InstancePtr, u8 *TxMsgPtr, int ByteCount);
|
||||
|
||||
/*
|
||||
* Master send and receive functions in dynamic mode in xiic_master.c
|
||||
*/
|
||||
int XIic_DynMasterRecv(XIic *InstancePtr, u8 *RxMsgPtr, u8 ByteCount);
|
||||
int XIic_DynMasterSend(XIic *InstancePtr, u8 *TxMsgPtr, u8 ByteCount);
|
||||
|
||||
/*
|
||||
* Dynamic IIC Core Initialization.
|
||||
*/
|
||||
int XIic_DynamicInitialize(XIic *InstancePtr);
|
||||
|
||||
/*
|
||||
* Slave send and receive functions in xiic_slave.c
|
||||
*/
|
||||
void XIic_SlaveInclude(void);
|
||||
int XIic_SlaveRecv(XIic *InstancePtr, u8 *RxMsgPtr, int ByteCount);
|
||||
int XIic_SlaveSend(XIic *InstancePtr, u8 *TxMsgPtr, int ByteCount);
|
||||
|
||||
/*
|
||||
* Statistics functions in xiic_stats.c
|
||||
*/
|
||||
void XIic_GetStats(XIic *InstancePtr, XIicStats *StatsPtr);
|
||||
void XIic_ClearStats(XIic *InstancePtr);
|
||||
|
||||
/*
|
||||
* Self test functions in xiic_selftest.c
|
||||
*/
|
||||
int XIic_SelfTest(XIic *InstancePtr);
|
||||
|
||||
/*
|
||||
* Bus busy Function in xiic.c
|
||||
*/
|
||||
u32 XIic_IsIicBusy(XIic *InstancePtr);
|
||||
|
||||
/*
|
||||
* Options functions in xiic_options.c
|
||||
*/
|
||||
void XIic_SetOptions(XIic *InstancePtr, u32 Options);
|
||||
u32 XIic_GetOptions(XIic *InstancePtr);
|
||||
|
||||
/*
|
||||
* Multi-master functions in xiic_multi_master.c
|
||||
*/
|
||||
void XIic_MultiMasterInclude(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of protection macro */
|
626
XilinxProcessorIPLib/drivers/iic/src/xiic_dyn_master.c
Normal file
626
XilinxProcessorIPLib/drivers/iic/src/xiic_dyn_master.c
Normal file
|
@ -0,0 +1,626 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_dyn_master.c
|
||||
*
|
||||
* Contains master functions for the XIic component in Dynamic controller mode.
|
||||
* This file is necessary to send or receive as a master on the IIC bus.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------------------
|
||||
* 1.03a mta 04/10/06 Created.
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs/macros. The macros
|
||||
* XIic_mDynSend7BitAddress and XIic_mDynSendStop have
|
||||
* been removed from this file as they were already
|
||||
* defined in a header file.
|
||||
* Some of the macros have been renamed to remove _m from
|
||||
* the name and Some of the macros have been renamed to be
|
||||
* consistent, see the xiic_l.h file for further information.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro includes dynamic master code such that dynamic master operations,
|
||||
* sending and receiving data, may be used. This function hooks the dynamic
|
||||
* master processing to the driver such that events are handled properly and
|
||||
* allows dynamic master processing to be optional. It must be called before any
|
||||
* functions which are contained in this file are called, such as after the
|
||||
* driver is initialized.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIIC_DYN_MASTER_INCLUDE \
|
||||
{ \
|
||||
XIic_RecvMasterFuncPtr = DynRecvMasterData; \
|
||||
XIic_SendMasterFuncPtr = DynSendMasterData; \
|
||||
}
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
static void DynRecvMasterData(XIic *InstancePtr);
|
||||
static void DynSendMasterData(XIic *InstancePtr);
|
||||
static int IsBusBusy(XIic *InstancePtr);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function sends data as a Dynamic master on the IIC bus. If the bus is
|
||||
* busy, it will indicate so and then enable an interrupt such that the status
|
||||
* handler will be called when the bus is no longer busy. The slave address is
|
||||
* sent by using XIic_DynSend7BitAddress().
|
||||
*
|
||||
* @param InstancePtr points to the Iic instance to be worked on.
|
||||
* @param TxMsgPtr points to the data to be transmitted.
|
||||
* @param ByteCount is the number of message bytes to be sent.
|
||||
*
|
||||
* @return XST_SUCCESS if successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIic_DynMasterSend(XIic *InstancePtr, u8 *TxMsgPtr, u8 ByteCount)
|
||||
{
|
||||
u32 CntlReg;
|
||||
|
||||
XIic_IntrGlobalDisable(InstancePtr->BaseAddress);
|
||||
|
||||
/*
|
||||
* Ensure that the Dynamic master processing has been included such that
|
||||
* events will be properly handled.
|
||||
*/
|
||||
XIIC_DYN_MASTER_INCLUDE;
|
||||
InstancePtr->IsDynamic = TRUE;
|
||||
|
||||
/*
|
||||
* If the busy is busy, then exit the critical region and wait for the
|
||||
* bus not to be busy. The function enables the BusNotBusy interrupt.
|
||||
*/
|
||||
if (IsBusBusy(InstancePtr)) {
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it is already a master on the bus (repeated start), the direction
|
||||
* was set to Tx which is throttling bus. The control register needs to
|
||||
* be set before putting data into the FIFO.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
if (CntlReg & XIIC_CR_MSMS_MASK) {
|
||||
CntlReg &= ~XIIC_CR_NO_ACK_MASK;
|
||||
CntlReg |= XIIC_CR_DIR_IS_TX_MASK;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
InstancePtr->Stats.RepeatedStarts++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save message state.
|
||||
*/
|
||||
InstancePtr->SendByteCount = ByteCount;
|
||||
InstancePtr->SendBufferPtr = TxMsgPtr;
|
||||
|
||||
/*
|
||||
* Send the Seven Bit address. Only 7 bit addressing is supported in
|
||||
* Dynamic mode.
|
||||
*/
|
||||
XIic_DynSend7BitAddress(InstancePtr->BaseAddress,
|
||||
InstancePtr->AddrOfSlave,
|
||||
XIIC_WRITE_OPERATION);
|
||||
|
||||
/*
|
||||
* Set the transmit address state to indicate the address has been sent
|
||||
* for communication with event driven processing.
|
||||
*/
|
||||
InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;
|
||||
|
||||
/*
|
||||
* Fill the Tx FIFO.
|
||||
*/
|
||||
if (InstancePtr->SendByteCount > 1) {
|
||||
XIic_TransmitFifoFill(InstancePtr, XIIC_MASTER_ROLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* After filling fifo, if data yet to send > 1, enable Tx <EFBFBD> empty
|
||||
* interrupt.
|
||||
*/
|
||||
if (InstancePtr->SendByteCount > 1) {
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_HALF_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear any pending Tx empty, Tx Error and then enable them.
|
||||
*/
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_ERROR_MASK |
|
||||
XIIC_INTR_TX_EMPTY_MASK);
|
||||
|
||||
/*
|
||||
* Enable the Interrupts.
|
||||
*/
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* When the IIC Tx FIFO/register goes empty, this routine is called by the
|
||||
* interrupt service routine to fill the transmit FIFO with data to be sent.
|
||||
*
|
||||
* This function also is called by the Tx <EFBFBD> empty interrupt as the data handling
|
||||
* is identical when you don't assume the FIFO is empty but use the Tx_FIFO_OCY
|
||||
* register to indicate the available free FIFO bytes.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void DynSendMasterData(XIic *InstancePtr)
|
||||
{
|
||||
u32 CntlReg;
|
||||
|
||||
/*
|
||||
* In between 1st and last byte of message, fill the FIFO with more data
|
||||
* to send, disable the 1/2 empty interrupt based upon data left to
|
||||
* send.
|
||||
*/
|
||||
if (InstancePtr->SendByteCount > 1) {
|
||||
XIic_TransmitFifoFill(InstancePtr, XIIC_MASTER_ROLE);
|
||||
|
||||
if (InstancePtr->SendByteCount < 2) {
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_HALF_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is only one byte left to send, processing differs between
|
||||
* repeated start and normal messages.
|
||||
*/
|
||||
else if (InstancePtr->SendByteCount == 1) {
|
||||
/*
|
||||
* When using repeated start, another interrupt is expected
|
||||
* after the last byte has been sent, so the message is not
|
||||
* done yet.
|
||||
*/
|
||||
if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
|
||||
XIic_WriteSendByte(InstancePtr);
|
||||
} else {
|
||||
XIic_DynSendStop(InstancePtr->BaseAddress,
|
||||
*InstancePtr->SendBufferPtr);
|
||||
|
||||
/*
|
||||
* Wait for bus to not be busy before declaring message
|
||||
* has been sent for the no repeated start operation.
|
||||
* The callback will be called from the BusNotBusy part
|
||||
* of the Interrupt handler to ensure that the message
|
||||
* is completely sent. Disable the Tx interrupts and
|
||||
* enable the BNB interrupt.
|
||||
*/
|
||||
InstancePtr->BNBOnly = FALSE;
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_TX_INTERRUPTS);
|
||||
XIic_EnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_BNB_MASK);
|
||||
}
|
||||
} else {
|
||||
if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
|
||||
/*
|
||||
* The message being sent has completed. When using
|
||||
* repeated start with no more bytes to send repeated
|
||||
* start needs to be set in the control register so
|
||||
* that the bus will still be held by this master.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_CR_REG_OFFSET);
|
||||
CntlReg |= XIIC_CR_REPEATED_START_MASK;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_CR_REG_OFFSET, CntlReg);
|
||||
|
||||
/*
|
||||
* If the message that was being sent has finished,
|
||||
* disable all transmit interrupts and call the callback
|
||||
* that was setup to indicate the message was sent,
|
||||
* with 0 bytes remaining.
|
||||
*/
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_TX_INTERRUPTS);
|
||||
InstancePtr->SendHandler(InstancePtr->SendCallBackRef,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function receives data as a master from a slave device on the IIC bus.
|
||||
* If the bus is busy, it will indicate so and then enable an interrupt such
|
||||
* that the status handler will be called when the bus is no longer busy. The
|
||||
* slave address which has been set with the XIic_SetAddress() function is the
|
||||
* address from which data is received. Receiving data on the bus performs a
|
||||
* read operation.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the Iic instance to be worked on.
|
||||
* @param RxMsgPtr is a pointer to the data to be transmitted.
|
||||
* @param ByteCount is the number of message bytes to be sent.
|
||||
*
|
||||
* @return - XST_SUCCESS indicates the message reception processes has been
|
||||
* initiated.
|
||||
* - XST_IIC_BUS_BUSY indicates the bus was in use and that the
|
||||
* BusNotBusy interrupt is enabled which will update the
|
||||
* EventStatus when the bus is no longer busy.
|
||||
* - XST_IIC_GENERAL_CALL_ADDRESS indicates the slave address is
|
||||
* set to the general call address. This is not allowed for Master
|
||||
* receive mode.
|
||||
*
|
||||
* @note The receive FIFO threshold is a zero based count such that 1
|
||||
* must be subtracted from the desired count to get the correct
|
||||
* value. When receiving data it is also necessary to not receive
|
||||
* the last byte with the prior bytes because the acknowledge must
|
||||
* be setup before the last byte is received.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIic_DynMasterRecv(XIic *InstancePtr, u8 *RxMsgPtr, u8 ByteCount)
|
||||
{
|
||||
u32 CntlReg;
|
||||
u32 RxFifoOccy;
|
||||
|
||||
/*
|
||||
* If the slave address is zero (general call) the master can't perform
|
||||
* receive operations, indicate an error.
|
||||
*/
|
||||
if (InstancePtr->AddrOfSlave == 0) {
|
||||
return XST_IIC_GENERAL_CALL_ADDRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable the Interrupts.
|
||||
*/
|
||||
XIic_IntrGlobalDisable(InstancePtr->BaseAddress);
|
||||
|
||||
/*
|
||||
* Ensure that the master processing has been included such that events
|
||||
* will be properly handled.
|
||||
*/
|
||||
XIIC_DYN_MASTER_INCLUDE;
|
||||
InstancePtr->IsDynamic = TRUE;
|
||||
|
||||
/*
|
||||
* If the busy is busy, then exit the critical region and wait for the
|
||||
* bus to not be busy, the function enables the bus not busy interrupt.
|
||||
*/
|
||||
if (IsBusBusy(InstancePtr)) {
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_IIC_BUS_BUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save message state for event driven processing.
|
||||
*/
|
||||
InstancePtr->RecvByteCount = ByteCount;
|
||||
InstancePtr->RecvBufferPtr = RxMsgPtr;
|
||||
|
||||
/*
|
||||
* Clear and enable Rx full interrupt.
|
||||
*/
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress, XIIC_INTR_RX_FULL_MASK);
|
||||
|
||||
/*
|
||||
* If already a master on the bus, the direction was set by Rx Interrupt
|
||||
* routine to Tx which is throttling bus because during Rxing, Tx reg is
|
||||
* empty = throttle. CR needs setting before putting data or the address
|
||||
* written will go out as Tx instead of receive. Start Master Rx by
|
||||
* setting CR Bits MSMS to Master and msg direction.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
if (CntlReg & XIIC_CR_MSMS_MASK) {
|
||||
/*
|
||||
* Set the Repeated Start bit in CR.
|
||||
*/
|
||||
CntlReg |= XIIC_CR_REPEATED_START_MASK;
|
||||
XIic_SetControlRegister(InstancePtr, CntlReg, ByteCount);
|
||||
|
||||
/*
|
||||
* Increment stats counts.
|
||||
*/
|
||||
InstancePtr->Stats.RepeatedStarts++;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set receive FIFO occupancy depth which must be done prior to writing
|
||||
* the address in the FIFO because the transmitter will immediately
|
||||
* start when in repeated start mode followed by the receiver such
|
||||
* that the number of bytes to receive should be set 1st.
|
||||
*/
|
||||
if (ByteCount == 1) {
|
||||
RxFifoOccy = 0;
|
||||
}
|
||||
else {
|
||||
if (ByteCount <= IIC_RX_FIFO_DEPTH) {
|
||||
RxFifoOccy = ByteCount - 2;
|
||||
} else {
|
||||
RxFifoOccy = IIC_RX_FIFO_DEPTH - 1;
|
||||
}
|
||||
}
|
||||
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET,
|
||||
RxFifoOccy);
|
||||
|
||||
/*
|
||||
* Send the Seven Bit address. Only 7 bit addressing is supported in
|
||||
* Dynamic mode and mark that the address has been sent.
|
||||
*/
|
||||
XIic_DynSend7BitAddress(InstancePtr->BaseAddress,
|
||||
InstancePtr->AddrOfSlave, XIIC_READ_OPERATION);
|
||||
InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;
|
||||
|
||||
/*
|
||||
* Send the bytecount to be received and set the stop bit.
|
||||
*/
|
||||
XIic_DynSendStop(InstancePtr->BaseAddress, ByteCount);
|
||||
|
||||
/*
|
||||
* Tx error is enabled incase the address has no device to answer
|
||||
* with Ack. When only one byte of data, must set NO ACK before address
|
||||
* goes out therefore Tx error must not be enabled as it will go off
|
||||
* immediately and the Rx full interrupt will be checked. If full, then
|
||||
* the one byte was received and the Tx error will be disabled without
|
||||
* sending an error callback msg.
|
||||
*/
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_ERROR_MASK);
|
||||
|
||||
/*
|
||||
* Enable the Interrupts.
|
||||
*/
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function is called when the receive register is full. The number
|
||||
* of bytes received to cause the interrupt is adjustable using the Receive FIFO
|
||||
* Depth register. The number of bytes in the register is read in the Receive
|
||||
* FIFO occupancy register. Both these registers are zero based values (0-15)
|
||||
* such that a value of zero indicates 1 byte.
|
||||
*
|
||||
* For a Master Receiver to properly signal the end of a message, the data must
|
||||
* be read in up to the message length - 1, where control register bits will be
|
||||
* set for bus controls to occur on reading of the last byte.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void DynRecvMasterData(XIic *InstancePtr)
|
||||
{
|
||||
u8 LoopCnt;
|
||||
u8 BytesInFifo;
|
||||
u8 BytesToRead;
|
||||
u32 CntlReg;
|
||||
|
||||
/*
|
||||
* Device is a master receiving, get the contents of the control
|
||||
* register and determine the number of bytes in fifo to be read out.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
BytesInFifo = (u8) XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_RFO_REG_OFFSET) + 1;
|
||||
|
||||
/*
|
||||
* If data in FIFO holds all data to be retrieved - 1, set NOACK and
|
||||
* disable the Tx error.
|
||||
*/
|
||||
if ((InstancePtr->RecvByteCount - BytesInFifo) == 1) {
|
||||
/*
|
||||
* Disable Tx error interrupt to prevent interrupt as this
|
||||
* device will cause it when it set NO ACK next.
|
||||
*/
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_ERROR_MASK);
|
||||
XIic_ClearIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_ERROR_MASK);
|
||||
|
||||
/*
|
||||
* Read one byte to clear a place for the last byte to be read
|
||||
* which will set the NO ACK.
|
||||
*/
|
||||
XIic_ReadRecvByte(InstancePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* If data in FIFO is all the data to be received then get the data and
|
||||
* also leave the device in a good state for the next transaction.
|
||||
*/
|
||||
else if ((InstancePtr->RecvByteCount - BytesInFifo) == 0) {
|
||||
if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
|
||||
CntlReg |= XIIC_CR_REPEATED_START_MASK;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data from the FIFO then set zero based FIFO read depth
|
||||
* for a byte.
|
||||
*/
|
||||
for (LoopCnt = 0; LoopCnt < BytesInFifo; LoopCnt++) {
|
||||
XIic_ReadRecvByte(InstancePtr);
|
||||
}
|
||||
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_RFD_REG_OFFSET, 0);
|
||||
|
||||
/*
|
||||
* Disable Rx full interrupt and write the control reg with ACK
|
||||
* allowing next byte sent to be acknowledged automatically.
|
||||
*/
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_RX_FULL_MASK);
|
||||
|
||||
/*
|
||||
* Send notification of msg Rx complete in RecvHandler callback.
|
||||
*/
|
||||
InstancePtr->RecvHandler(InstancePtr->RecvCallBackRef, 0);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Fifo data not at n-1, read all but the last byte of data
|
||||
* from the slave, if more than a FIFO full yet to receive
|
||||
* read a FIFO full.
|
||||
*/
|
||||
BytesToRead = InstancePtr->RecvByteCount - BytesInFifo - 1;
|
||||
if (BytesToRead > IIC_RX_FIFO_DEPTH) {
|
||||
BytesToRead = IIC_RX_FIFO_DEPTH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in data from the FIFO.
|
||||
*/
|
||||
for (LoopCnt = 0; LoopCnt < BytesToRead; LoopCnt++) {
|
||||
XIic_ReadRecvByte(InstancePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function checks to see if the IIC bus is busy. If so, it will enable
|
||||
* the bus not busy interrupt such that the driver is notified when the bus
|
||||
* is no longer busy.
|
||||
*
|
||||
* @param InstancePtr points to the Iic instance to be worked on.
|
||||
*
|
||||
* @return FALSE if the IIC bus is not busy else TRUE.
|
||||
*
|
||||
* @note The BusNotBusy interrupt is enabled which will update the
|
||||
* EventStatus when the bus is no longer busy.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int IsBusBusy(XIic *InstancePtr)
|
||||
{
|
||||
u32 CntlReg;
|
||||
u32 StatusReg;
|
||||
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
StatusReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
|
||||
|
||||
/*
|
||||
* If this device is already master of the bus as when using the
|
||||
* repeated start and the bus is busy setup to wait for it to not
|
||||
* be busy.
|
||||
*/
|
||||
if (((CntlReg & XIIC_CR_MSMS_MASK) == 0) && /* Not master */
|
||||
(StatusReg & XIIC_SR_BUS_BUSY_MASK)) { /* Is busy */
|
||||
/*
|
||||
* The bus is busy, clear pending BNB interrupt incase
|
||||
* previously set and then enable BusNotBusy interrupt.
|
||||
*/
|
||||
InstancePtr->BNBOnly = TRUE;
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_BNB_MASK);
|
||||
InstancePtr->Stats.BusBusy++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Initialize the IIC core for Dynamic Functionality.
|
||||
*
|
||||
* @param InstancePtr points to the Iic instance to be worked on.
|
||||
*
|
||||
* @return XST_SUCCESS if Successful else XST_FAILURE.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIic_DynamicInitialize(XIic *InstancePtr)
|
||||
{
|
||||
int Status;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
Status = XIic_DynInit(InstancePtr->BaseAddress);
|
||||
if (Status != XST_SUCCESS) {
|
||||
return XST_FAILURE;
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
89
XilinxProcessorIPLib/drivers/iic/src/xiic_g.c
Normal file
89
XilinxProcessorIPLib/drivers/iic/src/xiic_g.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_g.c
|
||||
*
|
||||
* This file contains a configuration table that specifies the configuration of
|
||||
* IIC devices in the system. Each IIC device should have an entry in this table.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------
|
||||
* 1.01a rfp 10/19/01 release
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.01d jhl 10/08/03 Added general purpose output feature
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xparameters.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/**
|
||||
* The IIC configuration table, sized by the number of instances
|
||||
* defined in xparameters.h.
|
||||
*/
|
||||
XIic_Config XIic_ConfigTable[XPAR_XIIC_NUM_INSTANCES] = {
|
||||
{
|
||||
XPAR_IIC_0_DEVICE_ID, /* Device ID for instance */
|
||||
XPAR_IIC_0_BASEADDR, /* Base address */
|
||||
XPAR_IIC_0_TEN_BIT_ADR,/* Uses 10 bit addressing */
|
||||
XPAR_IIC_0_GPO_WIDTH, /* Number of bits in GPO register */
|
||||
}
|
||||
,
|
||||
{
|
||||
XPAR_IIC_1_DEVICE_ID, /* Device ID for instance */
|
||||
XPAR_IIC_1_BASEADDR, /* Base address */
|
||||
XPAR_IIC_1_TEN_BIT_ADR /* Uses 10 bit addressing */
|
||||
XPAR_IIC_1_GPO_WIDTH, /* Number of bits in GPO register */
|
||||
}
|
||||
};
|
392
XilinxProcessorIPLib/drivers/iic/src/xiic_i.h
Normal file
392
XilinxProcessorIPLib/drivers/iic/src/xiic_i.h
Normal file
|
@ -0,0 +1,392 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_i.h
|
||||
*
|
||||
* This header file contains internal identifiers, which are those shared
|
||||
* between XIic components. The identifiers in this file are not intended for
|
||||
* use external to the driver.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.01a rfp 10/19/01 release
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 2.00a sdm 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Removed the macro XIIC_CLEAR_STATS, user has to
|
||||
* use the the XIic_ClearStats API in its place.
|
||||
* Removed the macro XIic_mEnterCriticalRegion,
|
||||
* XIic_IntrGlobalDisable should be used in its place.
|
||||
* Removed the macro XIic_mExitCriticalRegion,
|
||||
* XIic_IntrGlobalEnable should be used in its place.
|
||||
* Removed the _m prefix from all the macros
|
||||
* XIic_mSend10BitAddrByte1 is now XIic_Send10BitAddrByte1
|
||||
* XIic_mSend10BitAddrByte2 is now XIic_Send10BitAddrByte2
|
||||
* XIic_mSend7BitAddr is now XIic_Send7BitAddr
|
||||
* XIic_mDisableIntr is now XIic_DisableIntr
|
||||
* XIic_mEnableIntr is now XIic_EnableIntr
|
||||
* XIic_mClearIntr is now XIic_ClearIntr
|
||||
* XIic_mClearEnableIntr is now XIic_ClearEnableIntr
|
||||
* XIic_mFlushRxFifo is now XIic_FlushRxFifo
|
||||
* XIic_mFlushTxFifo is now XIic_FlushTxFifo
|
||||
* XIic_mReadRecvByte is now XIic_ReadRecvByte
|
||||
* XIic_mWriteSendByte is now XIic_WriteSendByte
|
||||
* XIic_mSetControlRegister is now XIic_SetControlRegister
|
||||
* 2.07a adk 18/04/13 Updated the code to avoid unused variable warnings when
|
||||
* compiling with the -Wextra -Wall flags.
|
||||
* Changes done in files xiic.c and xiic_i.h. CR:705001
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef XIIC_I_H /* prevent circular inclusions */
|
||||
#define XIIC_I_H /* by using protection macros */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xil_types.h"
|
||||
#include "xil_assert.h"
|
||||
#include "xstatus.h"
|
||||
#include "xiic.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro sends the first byte of the address for a 10 bit address during
|
||||
* both read and write operations. It takes care of the details to format the
|
||||
* address correctly.
|
||||
*
|
||||
* address = 1111_0xxD xx = address MSBits
|
||||
* D = Tx direction = 0 = write
|
||||
*
|
||||
* @param SlaveAddress contains the address of the slave to send to.
|
||||
* @param Operation indicates XIIC_READ_OPERATION or XIIC_WRITE_OPERATION
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_Send10BitAddrByte1(u16 SlaveAddress, u8 Operation);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_Send10BitAddrByte1(SlaveAddress, Operation) \
|
||||
{ \
|
||||
u8 LocalAddr = (u8)((SlaveAddress) >> 7); \
|
||||
LocalAddr = (LocalAddr & 0xF6) | 0xF0 | (Operation); \
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_DTR_REG_OFFSET, \
|
||||
(u32) LocalAddr); \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro sends the second byte of the address for a 10 bit address during
|
||||
* both read and write operations. It takes care of the details to format the
|
||||
* address correctly.
|
||||
*
|
||||
* @param SlaveAddress contains the address of the slave to send to.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature: void XIic_Send10BitAddrByte2(u16 SlaveAddress,
|
||||
* u8 Operation);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_Send10BitAddrByte2(SlaveAddress) \
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_DTR_REG_OFFSET, \
|
||||
(u32)(SlaveAddress)); \
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro sends the address for a 7 bit address during both read and write
|
||||
* operations. It takes care of the details to format the address correctly.
|
||||
*
|
||||
* @param SlaveAddress contains the address of the slave to send to.
|
||||
* @param Operation indicates XIIC_READ_OPERATION or XIIC_WRITE_OPERATION
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_Send7BitAddr(u16 SlaveAddress, u8 Operation);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_Send7BitAddr(SlaveAddress, Operation) \
|
||||
{ \
|
||||
u8 LocalAddr = (u8)(SlaveAddress << 1); \
|
||||
LocalAddr = (LocalAddr & 0xFE) | (Operation); \
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_DTR_REG_OFFSET, \
|
||||
(u32) LocalAddr); \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro disables the specified interrupts in the Interrupt enable
|
||||
* register. It is non-destructive in that the register is read and only the
|
||||
* interrupts specified is changed.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
* @param InterruptMask contains the interrupts to be disabled
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_DisableIntr(u32 BaseAddress, u32 InterruptMask);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_DisableIntr(BaseAddress, InterruptMask) \
|
||||
XIic_WriteIier((BaseAddress), \
|
||||
XIic_ReadIier(BaseAddress) & ~(InterruptMask))
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro enables the specified interrupts in the Interrupt enable
|
||||
* register. It is non-destructive in that the register is read and only the
|
||||
* interrupts specified is changed.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
* @param InterruptMask contains the interrupts to be disabled
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_EnableIntr(u32 BaseAddress, u32 InterruptMask);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_EnableIntr(BaseAddress, InterruptMask) \
|
||||
XIic_WriteIier((BaseAddress), \
|
||||
XIic_ReadIier(BaseAddress) | (InterruptMask))
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro clears the specified interrupt in the Interrupt status
|
||||
* register. It is non-destructive in that the register is read and only the
|
||||
* interrupt specified is cleared. Clearing an interrupt acknowledges it.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
* @param InterruptMask contains the interrupts to be disabled
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_ClearIntr(u32 BaseAddress, u32 InterruptMask);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_ClearIntr(BaseAddress, InterruptMask) \
|
||||
XIic_WriteIisr((BaseAddress), \
|
||||
XIic_ReadIisr(BaseAddress) & (InterruptMask))
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro clears and enables the specified interrupt in the Interrupt
|
||||
* status and enable registers. It is non-destructive in that the registers are
|
||||
* read and only the interrupt specified is modified.
|
||||
* Clearing an interrupt acknowledges it.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
* @param InterruptMask contains the interrupts to be cleared and enabled
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_ClearEnableIntr(u32 BaseAddress, u32 InterruptMask);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_ClearEnableIntr(BaseAddress, InterruptMask) \
|
||||
{ \
|
||||
XIic_WriteIisr(BaseAddress, \
|
||||
(XIic_ReadIisr(BaseAddress) & (InterruptMask))); \
|
||||
\
|
||||
XIic_WriteIier(BaseAddress, \
|
||||
(XIic_ReadIier(BaseAddress) | (InterruptMask))); \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro flushes the receive FIFO such that all bytes contained within it
|
||||
* are discarded.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC instance containing the FIFO
|
||||
* to be flushed.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_FlushRxFifo(XIic *InstancePtr);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_FlushRxFifo(InstancePtr) \
|
||||
{ \
|
||||
int LoopCnt; \
|
||||
u8 BytesToRead = XIic_ReadReg(InstancePtr->BaseAddress, \
|
||||
XIIC_RFO_REG_OFFSET) + 1; \
|
||||
for(LoopCnt = 0; LoopCnt < BytesToRead; LoopCnt++) \
|
||||
{ \
|
||||
XIic_ReadReg(InstancePtr->BaseAddress, \
|
||||
XIIC_DRR_REG_OFFSET); \
|
||||
} \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro flushes the transmit FIFO such that all bytes contained within it
|
||||
* are discarded.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC instance containing the FIFO
|
||||
* to be flushed.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_FlushTxFifo(XIic *InstancePtr);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_FlushTxFifo(InstancePtr); \
|
||||
{ \
|
||||
u32 CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, \
|
||||
XIIC_CR_REG_OFFSET); \
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET, \
|
||||
CntlReg | XIIC_CR_TX_FIFO_RESET_MASK); \
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET, \
|
||||
CntlReg); \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro reads the next available received byte from the receive FIFO
|
||||
* and updates all the data structures to reflect it.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC instance to be operated on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_ReadRecvByte(XIic *InstancePtr);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_ReadRecvByte(InstancePtr) \
|
||||
{ \
|
||||
*InstancePtr->RecvBufferPtr++ = \
|
||||
XIic_ReadReg(InstancePtr->BaseAddress, XIIC_DRR_REG_OFFSET); \
|
||||
InstancePtr->RecvByteCount--; \
|
||||
InstancePtr->Stats.RecvBytes++; \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro writes the next byte to be sent to the transmit FIFO
|
||||
* and updates all the data structures to reflect it.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC instance to be operated on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_WriteSendByte(XIic *InstancePtr);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_WriteSendByte(InstancePtr) \
|
||||
{ \
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_DTR_REG_OFFSET, \
|
||||
*InstancePtr->SendBufferPtr++); \
|
||||
InstancePtr->SendByteCount--; \
|
||||
InstancePtr->Stats.SendBytes++; \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This macro sets up the control register for a master receive operation.
|
||||
* A write is necessary if a 10 bit operation is being performed.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the IIC instance to be operated on.
|
||||
* @param ControlRegister contains the contents of the IIC device control
|
||||
* register
|
||||
* @param ByteCount contains the number of bytes to be received for the
|
||||
* master receive operation
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note Signature:
|
||||
* void XIic_SetControlRegister(XIic *InstancePtr,
|
||||
* u8 ControlRegister,
|
||||
* int ByteCount);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_SetControlRegister(InstancePtr, ControlRegister, ByteCount) \
|
||||
{ \
|
||||
(ControlRegister) &= ~(XIIC_CR_NO_ACK_MASK | XIIC_CR_DIR_IS_TX_MASK); \
|
||||
if (InstancePtr->Options & XII_SEND_10_BIT_OPTION) { \
|
||||
(ControlRegister) |= XIIC_CR_DIR_IS_TX_MASK; \
|
||||
} else { \
|
||||
if ((ByteCount) == 1) \
|
||||
{ \
|
||||
(ControlRegister) |= XIIC_CR_NO_ACK_MASK; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
extern XIic_Config XIic_ConfigTable[];
|
||||
|
||||
/* The following variables are shared across files of the driver and
|
||||
* are function pointers that are necessary to break dependencies allowing
|
||||
* optional parts of the driver to be used without condition compilation
|
||||
*/
|
||||
extern void (*XIic_AddrAsSlaveFuncPtr) (XIic *InstancePtr);
|
||||
extern void (*XIic_NotAddrAsSlaveFuncPtr) (XIic *InstancePtr);
|
||||
extern void (*XIic_RecvSlaveFuncPtr) (XIic *InstancePtr);
|
||||
extern void (*XIic_SendSlaveFuncPtr) (XIic *InstancePtr);
|
||||
extern void (*XIic_RecvMasterFuncPtr) (XIic *InstancePtr);
|
||||
extern void (*XIic_SendMasterFuncPtr) (XIic *InstancePtr);
|
||||
extern void (*XIic_ArbLostFuncPtr) (XIic *InstancePtr);
|
||||
extern void (*XIic_BusNotBusyFuncPtr) (XIic *InstancePtr);
|
||||
|
||||
void XIic_TransmitFifoFill(XIic *InstancePtr, int Role);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of protection macro */
|
443
XilinxProcessorIPLib/drivers/iic/src/xiic_intr.c
Normal file
443
XilinxProcessorIPLib/drivers/iic/src/xiic_intr.c
Normal file
|
@ -0,0 +1,443 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2006 - 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 xiic_intr.c
|
||||
*
|
||||
* Contains interrupt functions of the XIic driver. This file is required
|
||||
* for the driver.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.01a rfp 10/19/01 release
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.01c rmm 05/14/03 Fixed diab compiler warnings relating to asserts.
|
||||
* 1.03a ecm 06/22/06 Added a call to the status handler in the TxErrorHandler
|
||||
* even if the Rx buffer pointer is not set. This fix is as
|
||||
* a result of a Sony use model which did not set the Rx
|
||||
* pointer while in Master mode so it checks if MSMS == 1.
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 2.00a sdm 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs/macros.
|
||||
* Some of the macros have been renamed to remove _m from
|
||||
* the name and Some of the macros have been renamed to be
|
||||
* consistent, see the xiic_l.h file for further information.
|
||||
* 2.01a ktn 04/09/10 Updated TxErrorhandler to be called for Master Transmitter
|
||||
* case based on Addressed As Slave (AAS) bit rather than
|
||||
* MSMS bit(CR 540199).
|
||||
* 2.06a bss 02/14/13 Modified TxErrorHandler in xiic_intr.c to fix CR #686483
|
||||
* Modified bitwise OR to logical OR in
|
||||
* XIic_InterruptHandler API.
|
||||
* 2.07a adk 18/04/13 Updated the code to avoid unused variable warnings
|
||||
* when compiling with the -Wextra -Wall flags.
|
||||
* In the file xiic.c and xiic_i.h. CR:705001
|
||||
* </pre>
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
|
||||
/**************************** Type Definitions *******************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions ******************/
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
static void StubFunction(XIic *InstancePtr);
|
||||
static void TxErrorHandler(XIic *InstancePtr);
|
||||
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/* The following function pointers are used to help allow finer partitioning
|
||||
* of the driver such that some parts of it are optional. These pointers are
|
||||
* setup by functions in the optional parts of the driver.
|
||||
*/
|
||||
void (*XIic_AddrAsSlaveFuncPtr) (XIic *InstancePtr) = StubFunction;
|
||||
void (*XIic_NotAddrAsSlaveFuncPtr) (XIic *InstancePtr) = StubFunction;
|
||||
void (*XIic_RecvSlaveFuncPtr) (XIic *InstancePtr) = StubFunction;
|
||||
void (*XIic_SendSlaveFuncPtr) (XIic *InstancePtr) = StubFunction;
|
||||
void (*XIic_RecvMasterFuncPtr) (XIic *InstancePtr) = StubFunction;
|
||||
void (*XIic_SendMasterFuncPtr) (XIic *InstancePtr) = StubFunction;
|
||||
void (*XIic_ArbLostFuncPtr) (XIic *InstancePtr) = StubFunction;
|
||||
void (*XIic_BusNotBusyFuncPtr) (XIic *InstancePtr) = StubFunction;
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function is the interrupt handler for the XIic driver. This function
|
||||
* should be connected to the interrupt system.
|
||||
*
|
||||
* Only one interrupt source is handled for each interrupt allowing
|
||||
* higher priority system interrupts quicker response time.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* The XIIC_INTR_ARB_LOST_MASK and XIIC_INTR_TX_ERROR_MASK interrupts must have
|
||||
* higher priority than the other device interrupts so that the IIC device does
|
||||
* not get into a potentially confused state. The remaining interrupts may be
|
||||
* rearranged with no harm.
|
||||
*
|
||||
******************************************************************************/
|
||||
void XIic_InterruptHandler(void *InstancePtr)
|
||||
{
|
||||
u32 Status;
|
||||
u32 IntrStatus;
|
||||
u32 IntrPending;
|
||||
u32 IntrEnable;
|
||||
XIic *IicPtr = NULL;
|
||||
u32 Clear = 0;
|
||||
|
||||
/*
|
||||
* Verify that each of the inputs are valid.
|
||||
*/
|
||||
Xil_AssertVoid(InstancePtr != NULL);
|
||||
|
||||
/*
|
||||
* Convert the non-typed pointer to an IIC instance pointer
|
||||
*/
|
||||
IicPtr = (XIic *) InstancePtr;
|
||||
|
||||
/*
|
||||
* Get the interrupt Status.
|
||||
*/
|
||||
IntrPending = XIic_ReadIisr(IicPtr->BaseAddress);
|
||||
IntrEnable = XIic_ReadIier(IicPtr->BaseAddress);
|
||||
IntrStatus = IntrPending & IntrEnable;
|
||||
|
||||
/*
|
||||
* Do not processes a devices interrupts if the device has no
|
||||
* interrupts pending or the global interrupts have been disabled.
|
||||
*/
|
||||
if ((IntrStatus == 0) ||
|
||||
(XIic_IsIntrGlobalEnabled(IicPtr->BaseAddress) == FALSE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update interrupt stats and get the contents of the status register.
|
||||
*/
|
||||
IicPtr->Stats.IicInterrupts++;
|
||||
Status = XIic_ReadReg(IicPtr->BaseAddress, XIIC_SR_REG_OFFSET);
|
||||
|
||||
/*
|
||||
* Service requesting interrupt.
|
||||
*/
|
||||
if (IntrStatus & XIIC_INTR_ARB_LOST_MASK) {
|
||||
/* Bus Arbritration Lost */
|
||||
|
||||
IicPtr->Stats.ArbitrationLost++;
|
||||
XIic_ArbLostFuncPtr(IicPtr);
|
||||
|
||||
Clear = XIIC_INTR_ARB_LOST_MASK;
|
||||
} else if (IntrStatus & XIIC_INTR_TX_ERROR_MASK) {
|
||||
/* Transmit errors (no acknowledge) received */
|
||||
IicPtr->Stats.TxErrors++;
|
||||
TxErrorHandler(IicPtr);
|
||||
|
||||
Clear = XIIC_INTR_TX_ERROR_MASK;
|
||||
} else if (IntrStatus & XIIC_INTR_NAAS_MASK) {
|
||||
/* Not Addressed As Slave */
|
||||
|
||||
XIic_NotAddrAsSlaveFuncPtr(IicPtr);
|
||||
Clear = XIIC_INTR_NAAS_MASK;
|
||||
} else if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
|
||||
/* Receive register/FIFO is full */
|
||||
|
||||
IicPtr->Stats.RecvInterrupts++;
|
||||
|
||||
if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
|
||||
XIic_RecvSlaveFuncPtr(IicPtr);
|
||||
} else {
|
||||
XIic_RecvMasterFuncPtr(IicPtr);
|
||||
}
|
||||
|
||||
Clear = XIIC_INTR_RX_FULL_MASK;
|
||||
} else if (IntrStatus & XIIC_INTR_AAS_MASK) {
|
||||
/* Addressed As Slave */
|
||||
|
||||
XIic_AddrAsSlaveFuncPtr(IicPtr);
|
||||
Clear = XIIC_INTR_AAS_MASK;
|
||||
} else if (IntrStatus & XIIC_INTR_BNB_MASK) {
|
||||
/* IIC bus has transitioned to not busy */
|
||||
|
||||
/* Check if send callback needs to run */
|
||||
if (IicPtr->BNBOnly == TRUE) {
|
||||
XIic_BusNotBusyFuncPtr(IicPtr);
|
||||
IicPtr->BNBOnly = FALSE;
|
||||
} else {
|
||||
IicPtr->SendHandler(IicPtr->SendCallBackRef, 0);
|
||||
}
|
||||
|
||||
Clear = XIIC_INTR_BNB_MASK;
|
||||
|
||||
/* The bus is not busy, disable BusNotBusy interrupt */
|
||||
XIic_DisableIntr(IicPtr->BaseAddress, XIIC_INTR_BNB_MASK);
|
||||
|
||||
} else if ((IntrStatus & XIIC_INTR_TX_EMPTY_MASK) ||
|
||||
(IntrStatus & XIIC_INTR_TX_HALF_MASK)) {
|
||||
/* Transmit register/FIFO is empty or <20> empty */
|
||||
IicPtr->Stats.SendInterrupts++;
|
||||
|
||||
if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
|
||||
XIic_SendSlaveFuncPtr(IicPtr);
|
||||
} else {
|
||||
XIic_SendMasterFuncPtr(IicPtr);
|
||||
}
|
||||
|
||||
IntrStatus = XIic_ReadIisr(IicPtr->BaseAddress);
|
||||
Clear = IntrStatus & (XIIC_INTR_TX_EMPTY_MASK |
|
||||
XIIC_INTR_TX_HALF_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear Interrupts.
|
||||
*/
|
||||
XIic_WriteIisr(IicPtr->BaseAddress, Clear);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function fills the FIFO using the occupancy register to determine the
|
||||
* available space to be filled. When the repeated start option is on, the last
|
||||
* byte is withheld to allow the control register to be properly set on the last
|
||||
* byte.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @param Role indicates the role of this IIC device, a slave or a master,
|
||||
* on the IIC bus (XIIC_SLAVE_ROLE or XIIC_MASTER_ROLE).
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
void XIic_TransmitFifoFill(XIic *InstancePtr, int Role)
|
||||
{
|
||||
u8 AvailBytes;
|
||||
int LoopCnt;
|
||||
int NumBytesToSend;
|
||||
|
||||
/*
|
||||
* Determine number of bytes to write to FIFO. Number of bytes that
|
||||
* can be put into the FIFO is (FIFO depth) - (current occupancy + 1)
|
||||
* When more room in FIFO than msg bytes put all of message in the FIFO.
|
||||
*/
|
||||
AvailBytes = IIC_TX_FIFO_DEPTH -
|
||||
(u8) (XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_TFO_REG_OFFSET) + 1);
|
||||
|
||||
if (InstancePtr->SendByteCount > AvailBytes) {
|
||||
NumBytesToSend = AvailBytes;
|
||||
} else {
|
||||
/*
|
||||
* More space in FIFO than bytes in message.
|
||||
*/
|
||||
if ((InstancePtr->Options & XII_REPEATED_START_OPTION) ||
|
||||
(Role == XIIC_SLAVE_ROLE)) {
|
||||
NumBytesToSend = InstancePtr->SendByteCount;
|
||||
} else {
|
||||
NumBytesToSend = InstancePtr->SendByteCount - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill FIFO with amount determined above.
|
||||
*/
|
||||
for (LoopCnt = 0; LoopCnt < NumBytesToSend; LoopCnt++) {
|
||||
XIic_WriteSendByte(InstancePtr);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This interrupt occurs four different ways: Two as master and two as slave.
|
||||
* Master:
|
||||
* <pre>
|
||||
* (1) Transmitter (IMPLIES AN ERROR)
|
||||
* The slave receiver did not acknowledge properly.
|
||||
* (2) Receiver (Implies Tx complete)
|
||||
* Interrupt caused by setting TxAck high in the IIC to indicate to the
|
||||
* the last byte has been transmitted.
|
||||
* </pre>
|
||||
*
|
||||
* Slave:
|
||||
* <pre>
|
||||
* (3) Transmitter (Implies Tx complete)
|
||||
* Interrupt caused by master device indicating last byte of the message
|
||||
* has been transmitted.
|
||||
* (4) Receiver (IMPLIES AN ERROR)
|
||||
* Interrupt caused by setting TxAck high in the IIC to indicate Rx
|
||||
* IIC had a problem - set by this device and condition already known
|
||||
* and interrupt is not enabled.
|
||||
* </pre>
|
||||
*
|
||||
* This interrupt is enabled during Master send and receive and disabled
|
||||
* when this device knows it is going to send a negative acknowledge (Ack = No).
|
||||
*
|
||||
* Signals user of Tx error via status callback sending: XII_TX_ERROR_EVENT
|
||||
*
|
||||
* When MasterRecv has no message to send and only receives one byte of data
|
||||
* from the salve device, the TxError must be enabled to catch addressing
|
||||
* errors, yet there is not opportunity to disable TxError when there is no
|
||||
* data to send allowing disabling on last byte. When the slave sends the
|
||||
* only byte the NOAck causes a Tx Error. To disregard this as no real error,
|
||||
* when there is data in the Receive FIFO/register then the error was not
|
||||
* a device address write error, but a NOACK read error - to be ignored.
|
||||
* To work with or without FIFO's, the Rx Data interrupt is used to indicate
|
||||
* data is in the Rx register.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void TxErrorHandler(XIic *InstancePtr)
|
||||
{
|
||||
u32 IntrStatus;
|
||||
u32 CntlReg;
|
||||
|
||||
/*
|
||||
* When Sending as a slave, Tx error signals end of msg. Not Addressed
|
||||
* As Slave will handle the callbacks. this is used to only flush
|
||||
* the Tx fifo. The addressed as slave bit is gone as soon as the bus
|
||||
* has been released such that the buffer pointers are used to determine
|
||||
* the direction of transfer (send or receive).
|
||||
*/
|
||||
if (InstancePtr->RecvBufferPtr == NULL) {
|
||||
/*
|
||||
* Master Receiver finished reading message. Flush Tx fifo to
|
||||
* remove an 0xFF that was written to prevent bus throttling,
|
||||
* and disable all transmit and receive interrupts.
|
||||
*/
|
||||
XIic_FlushTxFifo(InstancePtr);
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_TX_RX_INTERRUPTS);
|
||||
|
||||
/*
|
||||
* If operating in Master mode, call status handler to indicate
|
||||
* NOACK occured.
|
||||
*/
|
||||
IntrStatus = XIic_ReadIisr(InstancePtr->BaseAddress);
|
||||
if ((IntrStatus & XIIC_INTR_AAS_MASK) == 0) {
|
||||
InstancePtr->StatusHandler(InstancePtr->
|
||||
StatusCallBackRef,
|
||||
XII_SLAVE_NO_ACK_EVENT);
|
||||
} else {
|
||||
/* Decrement the Tx Error since Tx Error interrupt
|
||||
* implies transmit complete while sending as Slave
|
||||
*/
|
||||
InstancePtr->Stats.TxErrors--;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Data in the receive register from either master or slave receive
|
||||
* When:slave, indicates master sent last byte, message completed.
|
||||
* When:master, indicates a master Receive with one byte received. When
|
||||
* a byte is in Rx reg then the Tx error indicates the Rx data was
|
||||
* recovered normally Tx errors are not enabled such that this should
|
||||
* not occur.
|
||||
*/
|
||||
IntrStatus = XIic_ReadIisr(InstancePtr->BaseAddress);
|
||||
if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
|
||||
/* Rx Reg/FIFO has data, Disable Tx error interrupts */
|
||||
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_ERROR_MASK);
|
||||
return;
|
||||
}
|
||||
|
||||
XIic_FlushTxFifo(InstancePtr);
|
||||
|
||||
/*
|
||||
* Disable and clear Tx empty, <EFBFBD> empty, Rx Full or Tx error interrupts.
|
||||
*/
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
|
||||
XIic_ClearIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
|
||||
|
||||
/* Clear MSMS as on Tx error when Rxing, the bus will be
|
||||
* stopped but MSMS bit is still set. Reset to proper state
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
CntlReg &= ~XIIC_CR_MSMS_MASK;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET, CntlReg);
|
||||
|
||||
|
||||
/*
|
||||
* Set FIFO occupancy depth = 1 so that the first byte will throttle
|
||||
* next recieve msg.
|
||||
*/
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET, 0);
|
||||
|
||||
/*
|
||||
* Call the event callback.
|
||||
*/
|
||||
InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
|
||||
XII_SLAVE_NO_ACK_EVENT);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function is a stub function that is used for the default function for
|
||||
* events that are handled optionally only when the appropriate modules are
|
||||
* linked in. Function pointers are used to handle some events to allow
|
||||
* some events to be optionally handled.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void StubFunction(XIic *InstancePtr)
|
||||
{
|
||||
(void )InstancePtr;
|
||||
Xil_AssertVoidAlways();
|
||||
}
|
1010
XilinxProcessorIPLib/drivers/iic/src/xiic_l.c
Normal file
1010
XilinxProcessorIPLib/drivers/iic/src/xiic_l.c
Normal file
File diff suppressed because it is too large
Load diff
588
XilinxProcessorIPLib/drivers/iic/src/xiic_l.h
Normal file
588
XilinxProcessorIPLib/drivers/iic/src/xiic_l.h
Normal file
|
@ -0,0 +1,588 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_l.h
|
||||
*
|
||||
* This header file contains identifiers and driver functions (or
|
||||
* macros) that can be used to access the device in normal and dynamic
|
||||
* controller mode. High-level driver functions are defined in xiic.h.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- ---- -------- -----------------------------------------------
|
||||
* 1.00b jhl 05/07/02 First release
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.01d jhl 10/08/03 Added general purpose output feature
|
||||
* 1.02a mta 03/09/06 Implemented Repeated Start in the Low Level Driver.
|
||||
* 1.03a mta 04/04/06 Implemented Dynamic IIC core routines.
|
||||
* 1.03a rpm 09/08/06 Added include of xstatus.h for completeness
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 1.16a ktn 07/18/09 Updated the notes in XIIC_RESET macro to clearly indicate
|
||||
* that only the Interrupt Registers are reset.
|
||||
* 1.16a ktn 10/16/09 Updated the notes in the XIIC_RESET macro to mention
|
||||
* that the complete IIC core is Reset on giving a software
|
||||
* reset to the IIC core. Some previous versions of the
|
||||
* core only reset the Interrupt Logic/Registers, please
|
||||
* refer to the HW specification for futher details.
|
||||
* 2.00a sdm 10/22/09 Converted all register accesses to 32 bit access,
|
||||
* the register offsets are defined to be on 32 bit boundry.
|
||||
* Removed the macro XIIC_RESET, XIic_Reset API should be
|
||||
* used in its place.
|
||||
* Some of the macros have been renamed to be consistent -
|
||||
* XIIC_GINTR_DISABLE is renamed as XIic_IntrGlobalDisable,
|
||||
* XIIC_GINTR_ENABLE is renamed as XIic_IntrGlobalEnable,
|
||||
* XIIC_IS_GINTR_ENABLED is renamed as
|
||||
* XIic_IsIntrGlobalEnabled,
|
||||
* XIIC_WRITE_IISR is renamed as XIic_WriteIisr,
|
||||
* XIIC_READ_IISR is renamed as XIic_ReadIisr,
|
||||
* XIIC_WRITE_IIER is renamed as XIic_WriteIier
|
||||
* The _m prefix in the name of the macros has been removed -
|
||||
* XIic_mClearIisr is now XIic_ClearIisr,
|
||||
* XIic_mSend7BitAddress is now XIic_Send7BitAddress,
|
||||
* XIic_mDynSend7BitAddress is now XIic_DynSend7BitAddress,
|
||||
* XIic_mDynSendStartStopAddress is now
|
||||
* XIic_DynSendStartStopAddress,
|
||||
* XIic_mDynSendStop is now XIic_DynSendStop.
|
||||
*
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef XIIC_L_H /* prevent circular inclusions */
|
||||
#define XIIC_L_H /* by using protection macros */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************** Include Files ********************************/
|
||||
|
||||
#include "xil_types.h"
|
||||
#include "xil_assert.h"
|
||||
#include "xstatus.h"
|
||||
#include "xil_io.h"
|
||||
|
||||
/************************** Constant Definitions ****************************/
|
||||
|
||||
/** @name Register Map
|
||||
*
|
||||
* Register offsets for the XIic device.
|
||||
* @{
|
||||
*/
|
||||
#define XIIC_DGIER_OFFSET 0x1C /**< Global Interrupt Enable Register */
|
||||
#define XIIC_IISR_OFFSET 0x20 /**< Interrupt Status Register */
|
||||
#define XIIC_IIER_OFFSET 0x28 /**< Interrupt Enable Register */
|
||||
#define XIIC_RESETR_OFFSET 0x40 /**< Reset Register */
|
||||
#define XIIC_CR_REG_OFFSET 0x100 /**< Control Register */
|
||||
#define XIIC_SR_REG_OFFSET 0x104 /**< Status Register */
|
||||
#define XIIC_DTR_REG_OFFSET 0x108 /**< Data Tx Register */
|
||||
#define XIIC_DRR_REG_OFFSET 0x10C /**< Data Rx Register */
|
||||
#define XIIC_ADR_REG_OFFSET 0x110 /**< Address Register */
|
||||
#define XIIC_TFO_REG_OFFSET 0x114 /**< Tx FIFO Occupancy */
|
||||
#define XIIC_RFO_REG_OFFSET 0x118 /**< Rx FIFO Occupancy */
|
||||
#define XIIC_TBA_REG_OFFSET 0x11C /**< 10 Bit Address reg */
|
||||
#define XIIC_RFD_REG_OFFSET 0x120 /**< Rx FIFO Depth reg */
|
||||
#define XIIC_GPO_REG_OFFSET 0x124 /**< Output Register */
|
||||
/* @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name Device Global Interrupt Enable Register masks (CR) mask(s)
|
||||
* @{
|
||||
*/
|
||||
#define XIIC_GINTR_ENABLE_MASK 0x80000000 /**< Global Interrupt Enable Mask */
|
||||
/* @} */
|
||||
|
||||
/** @name IIC Device Interrupt Status/Enable (INTR) Register Masks
|
||||
*
|
||||
* <b> Interrupt Status Register (IISR) </b>
|
||||
*
|
||||
* This register holds the interrupt status flags for the Spi device.
|
||||
*
|
||||
* <b> Interrupt Enable Register (IIER) </b>
|
||||
*
|
||||
* This register is used to enable interrupt sources for the IIC device.
|
||||
* Writing a '1' to a bit in this register enables the corresponding Interrupt.
|
||||
* Writing a '0' to a bit in this register disables the corresponding Interrupt.
|
||||
*
|
||||
* IISR/IIER registers have the same bit definitions and are only defined once.
|
||||
* @{
|
||||
*/
|
||||
#define XIIC_INTR_ARB_LOST_MASK 0x00000001 /**< 1 = Arbitration lost */
|
||||
#define XIIC_INTR_TX_ERROR_MASK 0x00000002 /**< 1 = Tx error/msg complete */
|
||||
#define XIIC_INTR_TX_EMPTY_MASK 0x00000004 /**< 1 = Tx FIFO/reg empty */
|
||||
#define XIIC_INTR_RX_FULL_MASK 0x00000008 /**< 1 = Rx FIFO/reg=OCY level */
|
||||
#define XIIC_INTR_BNB_MASK 0x00000010 /**< 1 = Bus not busy */
|
||||
#define XIIC_INTR_AAS_MASK 0x00000020 /**< 1 = When addr as slave */
|
||||
#define XIIC_INTR_NAAS_MASK 0x00000040 /**< 1 = Not addr as slave */
|
||||
#define XIIC_INTR_TX_HALF_MASK 0x00000080 /**< 1 = Tx FIFO half empty */
|
||||
|
||||
/**
|
||||
* All Tx interrupts commonly used.
|
||||
*/
|
||||
#define XIIC_TX_INTERRUPTS (XIIC_INTR_TX_ERROR_MASK | \
|
||||
XIIC_INTR_TX_EMPTY_MASK | \
|
||||
XIIC_INTR_TX_HALF_MASK)
|
||||
|
||||
/**
|
||||
* All interrupts commonly used
|
||||
*/
|
||||
#define XIIC_TX_RX_INTERRUPTS (XIIC_INTR_RX_FULL_MASK | XIIC_TX_INTERRUPTS)
|
||||
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @name Reset Register mask
|
||||
* @{
|
||||
*/
|
||||
#define XIIC_RESET_MASK 0x0000000A /**< RESET Mask */
|
||||
/* @} */
|
||||
|
||||
|
||||
/**
|
||||
* @name Control Register masks (CR) mask(s)
|
||||
* @{
|
||||
*/
|
||||
#define XIIC_CR_ENABLE_DEVICE_MASK 0x00000001 /**< Device enable = 1 */
|
||||
#define XIIC_CR_TX_FIFO_RESET_MASK 0x00000002 /**< Transmit FIFO reset=1 */
|
||||
#define XIIC_CR_MSMS_MASK 0x00000004 /**< Master starts Txing=1 */
|
||||
#define XIIC_CR_DIR_IS_TX_MASK 0x00000008 /**< Dir of Tx. Txing=1 */
|
||||
#define XIIC_CR_NO_ACK_MASK 0x00000010 /**< Tx Ack. NO ack = 1 */
|
||||
#define XIIC_CR_REPEATED_START_MASK 0x00000020 /**< Repeated start = 1 */
|
||||
#define XIIC_CR_GENERAL_CALL_MASK 0x00000040 /**< Gen Call enabled = 1 */
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @name Status Register masks (SR) mask(s)
|
||||
* @{
|
||||
*/
|
||||
#define XIIC_SR_GEN_CALL_MASK 0x00000001 /**< 1 = A Master issued
|
||||
* a GC */
|
||||
#define XIIC_SR_ADDR_AS_SLAVE_MASK 0x00000002 /**< 1 = When addressed as
|
||||
* slave */
|
||||
#define XIIC_SR_BUS_BUSY_MASK 0x00000004 /**< 1 = Bus is busy */
|
||||
#define XIIC_SR_MSTR_RDING_SLAVE_MASK 0x00000008 /**< 1 = Dir: Master <--
|
||||
* slave */
|
||||
#define XIIC_SR_TX_FIFO_FULL_MASK 0x00000010 /**< 1 = Tx FIFO full */
|
||||
#define XIIC_SR_RX_FIFO_FULL_MASK 0x00000020 /**< 1 = Rx FIFO full */
|
||||
#define XIIC_SR_RX_FIFO_EMPTY_MASK 0x00000040 /**< 1 = Rx FIFO empty */
|
||||
#define XIIC_SR_TX_FIFO_EMPTY_MASK 0x00000080 /**< 1 = Tx FIFO empty */
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @name Data Tx Register (DTR) mask(s)
|
||||
* @{
|
||||
*/
|
||||
#define XIIC_TX_DYN_START_MASK 0x00000100 /**< 1 = Set dynamic start */
|
||||
#define XIIC_TX_DYN_STOP_MASK 0x00000200 /**< 1 = Set dynamic stop */
|
||||
#define IIC_TX_FIFO_DEPTH 16 /**< Tx fifo capacity */
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @name Data Rx Register (DRR) mask(s)
|
||||
* @{
|
||||
*/
|
||||
#define IIC_RX_FIFO_DEPTH 16 /**< Rx fifo capacity */
|
||||
/* @} */
|
||||
|
||||
|
||||
#define XIIC_TX_ADDR_SENT 0x00
|
||||
#define XIIC_TX_ADDR_MSTR_RECV_MASK 0x02
|
||||
|
||||
|
||||
/**
|
||||
* The following constants are used to specify whether to do
|
||||
* Read or a Write operation on IIC bus.
|
||||
*/
|
||||
#define XIIC_READ_OPERATION 1 /**< Read operation on the IIC bus */
|
||||
#define XIIC_WRITE_OPERATION 0 /**< Write operation on the IIC bus */
|
||||
|
||||
/**
|
||||
* The following constants are used with the transmit FIFO fill function to
|
||||
* specify the role which the IIC device is acting as, a master or a slave.
|
||||
*/
|
||||
#define XIIC_MASTER_ROLE 1 /**< Master on the IIC bus */
|
||||
#define XIIC_SLAVE_ROLE 0 /**< Slave on the IIC bus */
|
||||
|
||||
/**
|
||||
* The following constants are used with Transmit Function (XIic_Send) to
|
||||
* specify whether to STOP after the current transfer of data or own the bus
|
||||
* with a Repeated start.
|
||||
*/
|
||||
#define XIIC_STOP 0x00 /**< Send a stop on the IIC bus after
|
||||
* the current data transfer */
|
||||
#define XIIC_REPEATED_START 0x01 /**< Donot Send a stop on the IIC bus after
|
||||
* the current data transfer */
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
#define XIic_In32 Xil_In32
|
||||
#define XIic_Out32 Xil_Out32
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Read from the specified IIC device register.
|
||||
*
|
||||
* @param BaseAddress is the base address of the device.
|
||||
* @param RegOffset is 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 XIic_ReadReg(u32 BaseAddress, u32 RegOffset);
|
||||
*
|
||||
* This macro does not do any checking to ensure that the
|
||||
* register exists if the register may be excluded due to
|
||||
* parameterization, such as the GPO Register.
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_ReadReg(BaseAddress, RegOffset) \
|
||||
XIic_In32((BaseAddress) + (RegOffset))
|
||||
|
||||
/***************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Write to the specified IIC device register.
|
||||
*
|
||||
* @param BaseAddress is the base address of the device.
|
||||
* @param RegOffset is 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 XIic_WriteReg(u32 BaseAddress, u32 RegOffset,
|
||||
* u32 RegisterValue);
|
||||
* This macro does not do any checking to ensure that the
|
||||
* register exists if the register may be excluded due to
|
||||
* parameterization, such as the GPO Register.
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_WriteReg(BaseAddress, RegOffset, RegisterValue) \
|
||||
XIic_Out32((BaseAddress) + (RegOffset), (RegisterValue))
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This macro disables all interrupts for the device by writing to the Global
|
||||
* interrupt enable register.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* void XIic_IntrGlobalDisable(u32 BaseAddress);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_IntrGlobalDisable(BaseAddress) \
|
||||
XIic_WriteReg((BaseAddress), XIIC_DGIER_OFFSET, 0)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This macro writes to the global interrupt enable register to enable
|
||||
* interrupts from the device. This function does not enable individual
|
||||
* interrupts as the Interrupt Enable Register must be set appropriately.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* void XIic_IntrGlobalEnable(u32 BaseAddress);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_IntrGlobalEnable(BaseAddress) \
|
||||
XIic_WriteReg((BaseAddress), XIIC_DGIER_OFFSET, \
|
||||
XIIC_GINTR_ENABLE_MASK)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function determines if interrupts are enabled at the global level by
|
||||
* reading the global interrupt register.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
*
|
||||
* @return
|
||||
* - TRUE if the global interrupt is enabled.
|
||||
* - FALSE if global interrupt is disabled.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* int XIic_IsIntrGlobalEnabled(u32 BaseAddress);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_IsIntrGlobalEnabled(BaseAddress) \
|
||||
(XIic_ReadReg((BaseAddress), XIIC_DGIER_OFFSET) == \
|
||||
XIIC_GINTR_ENABLE_MASK)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function sets the Interrupt status register to the specified value.
|
||||
*
|
||||
* This register implements a toggle on write functionality. The interrupt is
|
||||
* cleared by writing to this register with the bits to be cleared set to a one
|
||||
* and all others to zero. Setting a bit which is zero within this register
|
||||
* causes an interrupt to be generated.
|
||||
*
|
||||
* This function writes only the specified value to the register such that
|
||||
* some status bits may be set and others cleared. It is the caller's
|
||||
* responsibility to get the value of the register prior to setting the value
|
||||
* to prevent an destructive behavior.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
* @param Status is the value to be written to the Interrupt
|
||||
* status register.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* void XIic_WriteIisr(u32 BaseAddress, u32 Status);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_WriteIisr(BaseAddress, Status) \
|
||||
XIic_WriteReg((BaseAddress), XIIC_IISR_OFFSET, (Status))
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function gets the contents of the Interrupt Status Register.
|
||||
* This register indicates the status of interrupt sources for the device.
|
||||
* The status is independent of whether interrupts are enabled such
|
||||
* that the status register may also be polled when interrupts are not enabled.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
*
|
||||
* @return The value read from the Interrupt Status Register.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* u32 XIic_ReadIisr(u32 BaseAddress);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_ReadIisr(BaseAddress) \
|
||||
XIic_ReadReg((BaseAddress), XIIC_IISR_OFFSET)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function sets the contents of the Interrupt Enable Register.
|
||||
*
|
||||
* This function writes only the specified value to the register such that
|
||||
* some interrupt sources may be enabled and others disabled. It is the
|
||||
* caller's responsibility to get the value of the interrupt enable register
|
||||
* prior to setting the value to prevent a destructive behavior.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
* @param Enable is the value to be written to the Interrupt Enable
|
||||
* Register. Bit positions of 1 will be enabled. Bit positions of 0
|
||||
* will be disabled.
|
||||
*
|
||||
* @return None
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* void XIic_WriteIier(u32 BaseAddress, u32 Enable);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_WriteIier(BaseAddress, Enable) \
|
||||
XIic_WriteReg((BaseAddress), XIIC_IIER_OFFSET, (Enable))
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This function gets the Interrupt Enable Register contents.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
*
|
||||
* @return The contents read from the Interrupt Enable Register.
|
||||
* Bit positions of 1 indicate that the corresponding interrupt
|
||||
* is enabled. Bit positions of 0 indicate that the corresponding
|
||||
* interrupt is disabled.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* u32 XIic_ReadIier(u32 BaseAddress)
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_ReadIier(BaseAddress) \
|
||||
XIic_ReadReg((BaseAddress), XIIC_IIER_OFFSET)
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This macro clears the specified interrupt in the Interrupt status
|
||||
* register. It is non-destructive in that the register is read and only the
|
||||
* interrupt specified is cleared. Clearing an interrupt acknowledges it.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC device.
|
||||
* @param InterruptMask is the bit mask of the interrupts to be cleared.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* void XIic_ClearIisr(u32 BaseAddress, u32 InterruptMask);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_ClearIisr(BaseAddress, InterruptMask) \
|
||||
XIic_WriteIisr((BaseAddress), \
|
||||
XIic_ReadIisr(BaseAddress) & (InterruptMask))
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This macro sends the address for a 7 bit address during both read and write
|
||||
* operations. It takes care of the details to format the address correctly.
|
||||
* This macro is designed to be called internally to the drivers.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC Device.
|
||||
* @param SlaveAddress is the address of the slave to send to.
|
||||
* @param Operation indicates XIIC_READ_OPERATION or XIIC_WRITE_OPERATION
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* void XIic_Send7BitAddress(u32 BaseAddress, u8 SlaveAddress,
|
||||
* u8 Operation);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_Send7BitAddress(BaseAddress, SlaveAddress, Operation) \
|
||||
{ \
|
||||
u8 LocalAddr = (u8)(SlaveAddress << 1); \
|
||||
LocalAddr = (LocalAddr & 0xFE) | (Operation); \
|
||||
XIic_WriteReg(BaseAddress, XIIC_DTR_REG_OFFSET, LocalAddr); \
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This macro sends the address for a 7 bit address during both read and write
|
||||
* operations. It takes care of the details to format the address correctly.
|
||||
* This macro is designed to be called internally to the drivers for Dynamic
|
||||
* controller functionality.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC Device.
|
||||
* @param SlaveAddress is the address of the slave to send to.
|
||||
* @param Operation indicates XIIC_READ_OPERATION or XIIC_WRITE_OPERATION.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* void XIic_DynSend7BitAddress(u32 BaseAddress,
|
||||
* u8 SlaveAddress, u8 Operation);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_DynSend7BitAddress(BaseAddress, SlaveAddress, Operation) \
|
||||
{ \
|
||||
u8 LocalAddr = (u8)(SlaveAddress << 1); \
|
||||
LocalAddr = (LocalAddr & 0xFE) | (Operation); \
|
||||
XIic_WriteReg(BaseAddress, XIIC_DTR_REG_OFFSET, \
|
||||
XIIC_TX_DYN_START_MASK | LocalAddr); \
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This macro sends the address, start and stop for a 7 bit address during both
|
||||
* write operations. It takes care of the details to format the address
|
||||
* correctly. This macro is designed to be called internally to the drivers.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC Device.
|
||||
* @param SlaveAddress is the address of the slave to send to.
|
||||
* @param Operation indicates XIIC_WRITE_OPERATION.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* void XIic_DynSendStartStopAddress(u32 BaseAddress,
|
||||
* u8 SlaveAddress,
|
||||
* u8 Operation);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_DynSendStartStopAddress(BaseAddress, SlaveAddress, Operation) \
|
||||
{ \
|
||||
u8 LocalAddr = (u8)(SlaveAddress << 1); \
|
||||
LocalAddr = (LocalAddr & 0xFE) | (Operation); \
|
||||
XIic_WriteReg(BaseAddress, XIIC_DTR_REG_OFFSET, \
|
||||
XIIC_TX_DYN_START_MASK | XIIC_TX_DYN_STOP_MASK | \
|
||||
LocalAddr); \
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This macro sends a stop condition on IIC bus for Dynamic logic.
|
||||
*
|
||||
* @param BaseAddress is the base address of the IIC Device.
|
||||
* @param ByteCount is the number of Rx bytes received before the master.
|
||||
* doesn't respond with ACK.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note C-Style signature:
|
||||
* void XIic_DynSendStop(u32 BaseAddress, u32 ByteCount);
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIic_DynSendStop(BaseAddress, ByteCount) \
|
||||
{ \
|
||||
XIic_WriteReg(BaseAddress, XIIC_DTR_REG_OFFSET, \
|
||||
XIIC_TX_DYN_STOP_MASK | ByteCount); \
|
||||
}
|
||||
|
||||
/************************** Function Prototypes *****************************/
|
||||
|
||||
unsigned XIic_Recv(u32 BaseAddress, u8 Address,
|
||||
u8 *BufferPtr, unsigned ByteCount, u8 Option);
|
||||
|
||||
unsigned XIic_Send(u32 BaseAddress, u8 Address,
|
||||
u8 *BufferPtr, unsigned ByteCount, u8 Option);
|
||||
|
||||
unsigned XIic_DynRecv(u32 BaseAddress, u8 Address, u8 *BufferPtr, u8 ByteCount);
|
||||
|
||||
unsigned XIic_DynSend(u32 BaseAddress, u16 Address, u8 *BufferPtr,
|
||||
u8 ByteCount, u8 Option);
|
||||
|
||||
int XIic_DynInit(u32 BaseAddress);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* end of protection macro */
|
762
XilinxProcessorIPLib/drivers/iic/src/xiic_master.c
Normal file
762
XilinxProcessorIPLib/drivers/iic/src/xiic_master.c
Normal file
|
@ -0,0 +1,762 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_master.c
|
||||
*
|
||||
* Contains master functions for the XIic component. This file is necessary to
|
||||
* send or receive as a master on the IIC bus.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------
|
||||
* 1.01b jhl 03/27/02 Reparitioned the driver
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs/macros.
|
||||
* Removed the macro XIic_mEnterCriticalRegion,
|
||||
* XIic_IntrGlobalDisable should be used in its place.
|
||||
* Removed the macro XIic_mExitCriticalRegion,
|
||||
* XIic_IntrGlobalEnable should be used in its place.
|
||||
* Some of the macros have been renamed to remove _m from
|
||||
* the name and some of the macros have been renamed to be
|
||||
* consistent, see the xiic_i.h and xiic_l.h files for
|
||||
* further information
|
||||
* 2.05a bss 02/05/12 Assigned RecvBufferPtr in XIic_MasterSend API and
|
||||
* SendBufferPtr in XIic_MasterRecv NULL
|
||||
* </pre>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/***************************** Include Files *******************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions ***************************/
|
||||
|
||||
|
||||
/**************************** Type Definitions *****************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *******************/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* This macro includes master code such that master operations, sending
|
||||
* and receiving data, may be used. This function hooks the master processing
|
||||
* to the driver such that events are handled properly and allows master
|
||||
* processing to be optional. It must be called before any functions which
|
||||
* are contained in this file are called, such as after the driver is
|
||||
* initialized.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
#define XIIC_MASTER_INCLUDE \
|
||||
{ \
|
||||
XIic_RecvMasterFuncPtr = RecvMasterData; \
|
||||
XIic_SendMasterFuncPtr = SendMasterData; \
|
||||
}
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
static void SendSlaveAddr(XIic *InstancePtr);
|
||||
static void RecvMasterData(XIic *InstancePtr);
|
||||
static void SendMasterData(XIic *InstancePtr);
|
||||
static int IsBusBusy(XIic *InstancePtr);
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This function sends data as a master on the IIC bus. If the bus is busy, it
|
||||
* will indicate so and then enable an interrupt such that the status handler
|
||||
* will be called when the bus is no longer busy. The slave address which has
|
||||
* been set with the XIic_SetAddress() function is the address to which the
|
||||
* specific data is sent. Sending data on the bus performs a write operation.
|
||||
*
|
||||
* @param InstancePtr points to the Iic instance to be worked on.
|
||||
* @param TxMsgPtr points to the data to be transmitted.
|
||||
* @param ByteCount is the number of message bytes to be sent.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS indicates the message transmission has been
|
||||
* initiated.
|
||||
* - XST_IIC_BUS_BUSY indicates the bus was in use and that
|
||||
* the BusNotBusy interrupt is enabled which will update the
|
||||
* EventStatus when the bus is no longer busy.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIic_MasterSend(XIic *InstancePtr, u8 *TxMsgPtr, int ByteCount)
|
||||
{
|
||||
u32 CntlReg;
|
||||
|
||||
XIic_IntrGlobalDisable(InstancePtr->BaseAddress);
|
||||
|
||||
/*
|
||||
* Ensure that the master processing has been included such that events
|
||||
* will be properly handled.
|
||||
*/
|
||||
XIIC_MASTER_INCLUDE;
|
||||
InstancePtr->IsDynamic = FALSE;
|
||||
|
||||
/*
|
||||
* If the busy is busy, then exit the critical region and wait for the
|
||||
* bus to not be busy, the function enables the bus not busy interrupt.
|
||||
*/
|
||||
if (IsBusBusy(InstancePtr)) {
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_IIC_BUS_BUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it is already a master on the bus (repeated start), the direction
|
||||
* was set to Tx which is throttling bus. The control register needs to
|
||||
* be set before putting data into the FIFO.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
if (CntlReg & XIIC_CR_MSMS_MASK) {
|
||||
CntlReg &= ~XIIC_CR_NO_ACK_MASK;
|
||||
CntlReg |= (XIIC_CR_DIR_IS_TX_MASK |
|
||||
XIIC_CR_REPEATED_START_MASK);
|
||||
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
InstancePtr->Stats.RepeatedStarts++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save message state.
|
||||
*/
|
||||
InstancePtr->SendByteCount = ByteCount;
|
||||
InstancePtr->SendBufferPtr = TxMsgPtr;
|
||||
InstancePtr->RecvBufferPtr = NULL;
|
||||
|
||||
/*
|
||||
* Put the address into the FIFO to be sent and indicate that the
|
||||
* operation to be performed on the bus is a write operation,
|
||||
* a general call address is handled the same as a 7 bit address even
|
||||
* if 10 bit address is selected.
|
||||
* Set the transmit address state to indicate the address has been sent.
|
||||
*/
|
||||
if ((InstancePtr->Options & XII_SEND_10_BIT_OPTION) &&
|
||||
(InstancePtr->AddrOfSlave != 0)) {
|
||||
XIic_Send10BitAddrByte1(InstancePtr->AddrOfSlave,
|
||||
XIIC_WRITE_OPERATION);
|
||||
XIic_Send10BitAddrByte2(InstancePtr->AddrOfSlave);
|
||||
} else {
|
||||
XIic_Send7BitAddr(InstancePtr->AddrOfSlave,
|
||||
XIIC_WRITE_OPERATION);
|
||||
}
|
||||
/*
|
||||
* Set the transmit address state to indicate the address has been sent
|
||||
* for communication with event driven processing.
|
||||
*/
|
||||
InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;
|
||||
|
||||
/*
|
||||
* Fill remaining available FIFO with message data.
|
||||
*/
|
||||
if (InstancePtr->SendByteCount > 1) {
|
||||
XIic_TransmitFifoFill(InstancePtr, XIIC_MASTER_ROLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* After filling fifo, if data yet to send > 1, enable Tx <EFBFBD> empty
|
||||
* interrupt.
|
||||
*/
|
||||
if (InstancePtr->SendByteCount > 1) {
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_HALF_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear any pending Tx empty, Tx Error and then enable them.
|
||||
*/
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_ERROR_MASK |
|
||||
XIIC_INTR_TX_EMPTY_MASK);
|
||||
|
||||
/*
|
||||
* When repeated start not used, MSMS must be set after putting data
|
||||
* into transmit FIFO, start the transmitter.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
if ((CntlReg & XIIC_CR_MSMS_MASK) == 0) {
|
||||
CntlReg &= ~XIIC_CR_NO_ACK_MASK;
|
||||
CntlReg |= XIIC_CR_MSMS_MASK | XIIC_CR_DIR_IS_TX_MASK;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
}
|
||||
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
* This function receives data as a master from a slave device on the IIC bus.
|
||||
* If the bus is busy, it will indicate so and then enable an interrupt such
|
||||
* that the status handler will be called when the bus is no longer busy. The
|
||||
* slave address which has been set with the XIic_SetAddress() function is the
|
||||
* address from which data is received. Receiving data on the bus performs a
|
||||
* read operation.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the Iic instance to be worked on.
|
||||
* @param RxMsgPtr is a pointer to the data to be transmitted
|
||||
* @param ByteCount is the number of message bytes to be sent
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS indicates the message reception processes has
|
||||
* been initiated.
|
||||
* - XST_IIC_BUS_BUSY indicates the bus was in use and that the
|
||||
* BusNotBusy interrupt is enabled which will update the
|
||||
* EventStatus when the bus is no longer busy.
|
||||
* - XST_IIC_GENERAL_CALL_ADDRESS indicates the slave address
|
||||
* is set to the the general call address. This is not allowed
|
||||
* for Master receive mode.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* The receive FIFO threshold is a zero based count such that 1 must be
|
||||
* subtracted from the desired count to get the correct value. When receiving
|
||||
* data it is also necessary to not receive the last byte with the prior bytes
|
||||
* because the acknowledge must be setup before the last byte is received.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIic_MasterRecv(XIic *InstancePtr, u8 *RxMsgPtr, int ByteCount)
|
||||
{
|
||||
u32 CntlReg;
|
||||
u8 Temp;
|
||||
|
||||
/*
|
||||
* If the slave address is zero (general call) the master can't perform
|
||||
* receive operations, indicate an error.
|
||||
*/
|
||||
if (InstancePtr->AddrOfSlave == 0) {
|
||||
return XST_IIC_GENERAL_CALL_ADDRESS;
|
||||
}
|
||||
|
||||
XIic_IntrGlobalDisable(InstancePtr->BaseAddress);
|
||||
|
||||
/*
|
||||
* Ensure that the master processing has been included such that events
|
||||
* will be properly handled.
|
||||
*/
|
||||
XIIC_MASTER_INCLUDE;
|
||||
InstancePtr->IsDynamic = FALSE;
|
||||
|
||||
/*
|
||||
* If the busy is busy, then exit the critical region and wait for the
|
||||
* bus to not be busy, the function enables the bus not busy interrupt.
|
||||
*/
|
||||
if (IsBusBusy(InstancePtr)) {
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_IIC_BUS_BUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save message state for event driven processing.
|
||||
*/
|
||||
InstancePtr->RecvByteCount = ByteCount;
|
||||
InstancePtr->RecvBufferPtr = RxMsgPtr;
|
||||
InstancePtr->SendBufferPtr = NULL;
|
||||
|
||||
/*
|
||||
* Clear and enable Rx full interrupt if using 7 bit, If 10 bit, wait
|
||||
* until last address byte sent incase arbitration gets lost while
|
||||
* sending out address.
|
||||
*/
|
||||
if ((InstancePtr->Options & XII_SEND_10_BIT_OPTION) == 0) {
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_RX_FULL_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* If already a master on the bus, the direction was set by Rx Interrupt
|
||||
* routine to Tx which is throttling bus because during Rxing, Tx reg is
|
||||
* empty = throttle. CR needs setting before putting data or the address
|
||||
* written will go out as Tx instead of receive. Start Master Rx by
|
||||
* setting CR Bits MSMS to Master and msg direction.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
|
||||
if (CntlReg & XIIC_CR_MSMS_MASK) {
|
||||
CntlReg |= XIIC_CR_REPEATED_START_MASK;
|
||||
XIic_SetControlRegister(InstancePtr, CntlReg, ByteCount);
|
||||
|
||||
InstancePtr->Stats.RepeatedStarts++;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Set receive FIFO occupancy depth which must be done prior to writing
|
||||
* the address in the FIFO because the transmitter will immediatedly
|
||||
* start when in repeated start mode followed by the receiver such that
|
||||
* the number of bytes to receive should be set 1st.
|
||||
*/
|
||||
if (ByteCount == 1) {
|
||||
Temp = 0;
|
||||
} else {
|
||||
if (ByteCount <= IIC_RX_FIFO_DEPTH) {
|
||||
Temp = ByteCount - 2;
|
||||
} else {
|
||||
Temp = IIC_RX_FIFO_DEPTH - 1;
|
||||
}
|
||||
}
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET,
|
||||
(u32) Temp);
|
||||
|
||||
if (InstancePtr->Options & XII_SEND_10_BIT_OPTION) {
|
||||
/*
|
||||
* Send the 1st and 2nd byte of the 10 bit address of a write
|
||||
* operation, write because it's a 10 bit address.
|
||||
*/
|
||||
XIic_Send10BitAddrByte1(InstancePtr->AddrOfSlave,
|
||||
XIIC_WRITE_OPERATION);
|
||||
XIic_Send10BitAddrByte2(InstancePtr->AddrOfSlave);
|
||||
|
||||
/*
|
||||
* Set flag to indicate the next byte of the address needs to be
|
||||
* send, clear and enable Tx empty interrupt.
|
||||
*/
|
||||
InstancePtr->TxAddrMode = XIIC_TX_ADDR_MSTR_RECV_MASK;
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_EMPTY_MASK);
|
||||
} else {
|
||||
/*
|
||||
* 7 bit slave address, send the address for a read operation
|
||||
* and set the state to indicate the address has been sent.
|
||||
*/
|
||||
XIic_Send7BitAddr(InstancePtr->AddrOfSlave,
|
||||
XIIC_READ_OPERATION);
|
||||
InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tx error is enabled incase the address (7 or 10) has no device to
|
||||
* answer with Ack. When only one byte of data, must set NO ACK before
|
||||
* address goes out therefore Tx error must not be enabled as it will
|
||||
* go off immediately and the Rx full interrupt will be checked.
|
||||
* If full, then the one byte was received and the Tx error will be
|
||||
* disabled without sending an error callback msg.
|
||||
*/
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_ERROR_MASK);
|
||||
|
||||
/*
|
||||
* When repeated start not used, MSMS gets set after putting data
|
||||
* in Tx reg. Start Master Rx by setting CR Bits MSMS to Master and
|
||||
* msg direction.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
if ((CntlReg & XIIC_CR_MSMS_MASK) == 0) {
|
||||
CntlReg |= XIIC_CR_MSMS_MASK;
|
||||
XIic_SetControlRegister(InstancePtr, CntlReg, ByteCount);
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
}
|
||||
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* This function checks to see if the IIC bus is busy. If so, it will enable
|
||||
* the bus not busy interrupt such that the driver is notified when the bus
|
||||
* is no longer busy.
|
||||
*
|
||||
* @param InstancePtr points to the Iic instance to be worked on.
|
||||
*
|
||||
* @return
|
||||
* - FALSE indicates the IIC bus is not busy.
|
||||
* - TRUE indicates the bus was in use and that the BusNotBusy
|
||||
* interrupt is enabled which will update the EventStatus when
|
||||
* the bus is no longer busy.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static int IsBusBusy(XIic *InstancePtr)
|
||||
{
|
||||
u32 CntlReg;
|
||||
u32 StatusReg;
|
||||
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
StatusReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
|
||||
|
||||
/*
|
||||
* If this device is already master of the bus as when using the
|
||||
* repeated start and the bus is busy setup to wait for it to not be
|
||||
* busy.
|
||||
*/
|
||||
if (((CntlReg & XIIC_CR_MSMS_MASK) == 0) && /* Not master */
|
||||
(StatusReg & XIIC_SR_BUS_BUSY_MASK)) { /* Is busy */
|
||||
/*
|
||||
* The bus is busy, clear pending BNB interrupt incase
|
||||
* previously set and then enable BusNotBusy interrupt.
|
||||
*/
|
||||
InstancePtr->BNBOnly = TRUE;
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_BNB_MASK);
|
||||
InstancePtr->Stats.BusBusy++;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* This function sends the proper byte of the address as well as generate the
|
||||
* proper address bit fields depending on the address byte required and the
|
||||
* direction of the data (write or read).
|
||||
*
|
||||
* A master receiving has the restriction that the direction must be switched
|
||||
* from write to read when the third address byte is transmitted.
|
||||
* For the last byte of the 10 bit address, repeated start must be set prior
|
||||
* to writing the address. If repeated start options is enabled, the
|
||||
* control register is written before the address is written to the Tx reg.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* This function does read/modify/write to the device control register. Calling
|
||||
* functions must ensure critical sections are used.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void SendSlaveAddr(XIic *InstancePtr)
|
||||
{
|
||||
u32 CRreg;
|
||||
|
||||
/*
|
||||
* Set the control register for Master Receive, repeated start must be
|
||||
* set before writing the address, MSMS should be already set, don't
|
||||
* set here so if arbitration is lost or some other reason we don't
|
||||
* want MSMS set incase of error.
|
||||
*/
|
||||
CRreg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
|
||||
CRreg |= XIIC_CR_REPEATED_START_MASK;
|
||||
CRreg &= ~XIIC_CR_DIR_IS_TX_MASK;
|
||||
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET, CRreg);
|
||||
|
||||
/*
|
||||
* Send the 1st byte of the 10 bit address as a read operation, enable
|
||||
* the receive interrupt to know when data is received, assuming that
|
||||
* the receive FIFO threshold has been previously set.
|
||||
*/
|
||||
XIic_Send10BitAddrByte1(InstancePtr->AddrOfSlave, XIIC_READ_OPERATION);
|
||||
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress, XIIC_INTR_RX_FULL_MASK);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* When the IIC Tx FIFO/register goes empty, this routine is called by the
|
||||
* interrupt service routine to fill the transmit FIFO with data to be sent.
|
||||
*
|
||||
* This function also is called by the Tx <EFBFBD> empty interrupt as the data handling
|
||||
* is identical when you don't assume the FIFO is empty but use the Tx_FIFO_OCY
|
||||
* register to indicate the available free FIFO bytes.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void SendMasterData(XIic *InstancePtr)
|
||||
{
|
||||
u32 CntlReg;
|
||||
|
||||
/*
|
||||
* The device is a master on the bus. If there is still more address
|
||||
* bytes to send when in master receive operation and the slave device
|
||||
* is 10 bit addressed.
|
||||
* This requires the lower 7 bits of address to be resent when the mode
|
||||
* switches to Read instead of write (while sending addresses).
|
||||
*/
|
||||
if (InstancePtr->TxAddrMode & XIIC_TX_ADDR_MSTR_RECV_MASK) {
|
||||
/*
|
||||
* Send the 1st byte of the slave address in the read operation
|
||||
* and change the state to indicate this has been done
|
||||
*/
|
||||
SendSlaveAddr(InstancePtr);
|
||||
InstancePtr->TxAddrMode = XIIC_TX_ADDR_SENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* In between 1st and last byte of message, fill the FIFO with more data
|
||||
* to send, disable the 1/2 empty interrupt based upon data left to
|
||||
* send.
|
||||
*/
|
||||
else if (InstancePtr->SendByteCount > 1) {
|
||||
XIic_TransmitFifoFill(InstancePtr, XIIC_MASTER_ROLE);
|
||||
|
||||
if (InstancePtr->SendByteCount < 2) {
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_HALF_MASK);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If there is only one byte left to send, processing differs between
|
||||
* repeated start and normal messages.
|
||||
*/
|
||||
else if (InstancePtr->SendByteCount == 1) {
|
||||
/*
|
||||
* When using repeated start, another interrupt is expected
|
||||
* after the last byte has been sent, so the message is not
|
||||
* done yet.
|
||||
*/
|
||||
if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
|
||||
XIic_WriteSendByte(InstancePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* When not using repeated start, the stop condition must be
|
||||
* generated after the last byte is written. The bus is
|
||||
* throttled waiting for the last byte.
|
||||
*/
|
||||
else {
|
||||
/*
|
||||
* Set the stop condition before sending the last byte
|
||||
* of data so that the stop condition will be generated
|
||||
* immediately following the data another transmit
|
||||
* interrupt is not expected so the message is done.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_CR_REG_OFFSET);
|
||||
CntlReg &= ~XIIC_CR_MSMS_MASK;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
|
||||
XIic_WriteSendByte(InstancePtr);
|
||||
|
||||
/*
|
||||
* Wait for bus to not be busy before declaring message
|
||||
* has been sent for the no repeated start operation.
|
||||
* The callback will be called from the BusNotBusy part
|
||||
* of the Interrupt handler to ensure that the message
|
||||
* is completely sent.
|
||||
* Disable the Tx interrupts and enable the BNB
|
||||
* interrupt.
|
||||
*/
|
||||
|
||||
InstancePtr->BNBOnly = FALSE;
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_TX_INTERRUPTS);
|
||||
XIic_EnableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_BNB_MASK);
|
||||
|
||||
}
|
||||
} else {
|
||||
if (InstancePtr->Options & XII_REPEATED_START_OPTION) {
|
||||
|
||||
/*
|
||||
* The message being sent has completed. When using
|
||||
* repeated start with no more bytes to send repeated
|
||||
* start needs to be set in the control register so
|
||||
* that the bus will still be held by this master.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_CR_REG_OFFSET);
|
||||
CntlReg |= XIIC_CR_REPEATED_START_MASK;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_CR_REG_OFFSET, CntlReg);
|
||||
|
||||
/*
|
||||
* If the message that was being sent has finished,
|
||||
* disable all transmit interrupts and call the callback
|
||||
* that was setup to indicate the message was sent,
|
||||
* with 0 bytes remaining.
|
||||
*/
|
||||
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_TX_INTERRUPTS);
|
||||
InstancePtr->SendHandler(InstancePtr->SendCallBackRef,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function is called when the receive register is full. The number
|
||||
* of bytes received to cause the interrupt is adjustable using the Receive FIFO
|
||||
* Depth register. The number of bytes in the register is read in the Receive
|
||||
* FIFO occupancy register. Both these registers are zero based values (0-15)
|
||||
* such that a value of zero indicates 1 byte.
|
||||
*
|
||||
* For a Master Receiver to properly signal the end of a message, the data must
|
||||
* be read in up to the message length - 1, where control register bits will be
|
||||
* set for bus controls to occur on reading of the last byte.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void RecvMasterData(XIic *InstancePtr)
|
||||
{
|
||||
u8 LoopCnt;
|
||||
int BytesInFifo;
|
||||
int BytesToRead;
|
||||
u32 CntlReg;
|
||||
|
||||
/*
|
||||
* Device is a master receiving, get the contents of the control
|
||||
* register and determine the number of bytes in fifo to be read out.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
BytesInFifo = XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_RFO_REG_OFFSET) + 1;
|
||||
|
||||
/*
|
||||
* If data in FIFO holds all data to be retrieved - 1, set NOACK and
|
||||
* disable the Tx error.
|
||||
*/
|
||||
if ((InstancePtr->RecvByteCount - BytesInFifo) == 1) {
|
||||
/*
|
||||
* Disable Tx error interrupt to prevent interrupt
|
||||
* as this device will cause it when it set NO ACK next.
|
||||
*/
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_ERROR_MASK);
|
||||
XIic_ClearIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_ERROR_MASK);
|
||||
|
||||
/*
|
||||
* Write control reg with NO ACK allowing last byte to
|
||||
* have the No ack set to indicate to slave last byte read.
|
||||
*/
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
(CntlReg | XIIC_CR_NO_ACK_MASK));
|
||||
|
||||
/*
|
||||
* Read one byte to clear a place for the last byte to be read
|
||||
* which will set the NO ACK.
|
||||
*/
|
||||
XIic_ReadRecvByte(InstancePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* If data in FIFO is all the data to be received then get the data
|
||||
* and also leave the device in a good state for the next transaction.
|
||||
*/
|
||||
else if ((InstancePtr->RecvByteCount - BytesInFifo) == 0) {
|
||||
/*
|
||||
* If repeated start option is off then the master should stop
|
||||
* using the bus, otherwise hold the bus, setting repeated start
|
||||
* stops the slave from transmitting data when the FIFO is read.
|
||||
*/
|
||||
if ((InstancePtr->Options & XII_REPEATED_START_OPTION) == 0) {
|
||||
CntlReg &= ~XIIC_CR_MSMS_MASK;
|
||||
} else {
|
||||
CntlReg |= XIIC_CR_REPEATED_START_MASK;
|
||||
}
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
|
||||
/*
|
||||
* Read data from the FIFO then set zero based FIFO read depth
|
||||
* for a byte.
|
||||
*/
|
||||
for (LoopCnt = 0; LoopCnt < BytesInFifo; LoopCnt++) {
|
||||
XIic_ReadRecvByte(InstancePtr);
|
||||
}
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_RFD_REG_OFFSET, 0);
|
||||
|
||||
/*
|
||||
* Disable Rx full interrupt and write the control reg with ACK
|
||||
* allowing next byte sent to be acknowledged automatically.
|
||||
*/
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_RX_FULL_MASK);
|
||||
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
(CntlReg & ~XIIC_CR_NO_ACK_MASK));
|
||||
|
||||
/*
|
||||
* Send notification of msg Rx complete in RecvHandler callback.
|
||||
*/
|
||||
InstancePtr->RecvHandler(InstancePtr->RecvCallBackRef, 0);
|
||||
} else {
|
||||
/*
|
||||
* Fifo data not at n-1, read all but the last byte of data
|
||||
* from the slave, if more than a FIFO full yet to receive
|
||||
* read a FIFO full.
|
||||
*/
|
||||
BytesToRead = InstancePtr->RecvByteCount - BytesInFifo - 1;
|
||||
if (BytesToRead > IIC_RX_FIFO_DEPTH) {
|
||||
BytesToRead = IIC_RX_FIFO_DEPTH;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in data from the FIFO.
|
||||
*/
|
||||
for (LoopCnt = 0; LoopCnt < BytesToRead; LoopCnt++) {
|
||||
XIic_ReadRecvByte(InstancePtr);
|
||||
}
|
||||
}
|
||||
}
|
235
XilinxProcessorIPLib/drivers/iic/src/xiic_multi_master.c
Normal file
235
XilinxProcessorIPLib/drivers/iic/src/xiic_multi_master.c
Normal file
|
@ -0,0 +1,235 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_multi_master.c
|
||||
*
|
||||
* Contains multi-master functions for the XIic component. This file is
|
||||
* necessary if multiple masters are on the IIC bus such that arbitration can
|
||||
* be lost or the bus can be busy.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------
|
||||
* 1.01b jhl 3/27/02 Reparitioned the driver
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs/macros.
|
||||
* Some of the macros have been renamed to remove _m from
|
||||
* the name and some of the macros have been renamed to be
|
||||
* consistent, see the xiic_i.h and xiic_l.h files for further
|
||||
* information
|
||||
* </pre>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/***************************** Include Files *******************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions ***************************/
|
||||
|
||||
|
||||
/**************************** Type Definitions *****************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *******************/
|
||||
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
static void BusNotBusyHandler(XIic *InstancePtr);
|
||||
static void ArbitrationLostHandler(XIic *InstancePtr);
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/**
|
||||
* This function includes multi-master code such that multi-master events are
|
||||
* handled properly. Multi-master events include a loss of arbitration and
|
||||
* the bus transitioning from busy to not busy. This function allows the
|
||||
* multi-master processing to be optional. This function must be called prior
|
||||
* to allowing any multi-master events to occur, such as after the driver is
|
||||
* initialized.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
void XIic_MultiMasterInclude()
|
||||
{
|
||||
XIic_ArbLostFuncPtr = ArbitrationLostHandler;
|
||||
XIic_BusNotBusyFuncPtr = BusNotBusyHandler;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* The IIC bus busy signals when a master has control of the bus. Until the bus
|
||||
* is released, i.e. not busy, other devices must wait to use it.
|
||||
*
|
||||
* When this interrupt occurs, it signals that the previous master has released
|
||||
* the bus for another user.
|
||||
*
|
||||
* This interrupt is only enabled when the master Tx is waiting for the bus.
|
||||
*
|
||||
* This interrupt causes the following tasks:
|
||||
* - Disable Bus not busy interrupt
|
||||
* - Enable bus Ack
|
||||
* Should the slave receive have disabled acknowledgement, enable to allow
|
||||
* acknowledgment of the sending of our address to again be addresed as
|
||||
* slave
|
||||
* - Flush Rx FIFO
|
||||
* Should the slave receive have disabled acknowledgement, a few bytes may
|
||||
* be in FIFO if Rx full did not occur because of not enough byte in FIFO
|
||||
* to have caused an interrupt.
|
||||
* - Send status to user via status callback with the value:
|
||||
* XII_BUS_NOT_BUSY_EVENT
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void BusNotBusyHandler(XIic *InstancePtr)
|
||||
{
|
||||
u32 Status;
|
||||
u32 CntlReg;
|
||||
|
||||
/*
|
||||
* Should the slave receive have disabled acknowledgement,
|
||||
* enable to allow acknowledgment of the sending of our address to
|
||||
* again be addresed as slave.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
(CntlReg & ~XIIC_CR_NO_ACK_MASK));
|
||||
|
||||
/*
|
||||
* Flush Tx FIFO by toggling TxFIFOResetBit. FIFO runs normally at 0
|
||||
* Do this incase needed to Tx FIFO with more than expected if what
|
||||
* was set to Tx was less than what the Master expected - read more
|
||||
* from this slave so FIFO had junk in it.
|
||||
*/
|
||||
XIic_FlushTxFifo(InstancePtr);
|
||||
|
||||
/*
|
||||
* Flush Rx FIFO should slave Rx had a problem, sent No ack but
|
||||
* still received a few bytes. Should the slave receive have disabled
|
||||
* acknowledgement, clear Rx FIFO.
|
||||
*/
|
||||
XIic_FlushRxFifo(InstancePtr);
|
||||
|
||||
/*
|
||||
* Send Application messaging status via callbacks. Disable either Tx or
|
||||
* Receive interrupt. Which callback depends on messaging direction.
|
||||
*/
|
||||
Status = XIic_ReadIier(InstancePtr->BaseAddress);
|
||||
if (InstancePtr->RecvBufferPtr == NULL) {
|
||||
/*
|
||||
* Slave was sending data (master was reading), disable
|
||||
* all the transmit interrupts.
|
||||
*/
|
||||
XIic_WriteIier(InstancePtr->BaseAddress,
|
||||
(Status & ~XIIC_TX_INTERRUPTS));
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Slave was receiving data (master was writing) disable receive
|
||||
* interrupts.
|
||||
*/
|
||||
XIic_WriteIier(InstancePtr->BaseAddress,
|
||||
(Status & ~XIIC_INTR_RX_FULL_MASK));
|
||||
}
|
||||
|
||||
/*
|
||||
* Send Status in StatusHandler callback.
|
||||
*/
|
||||
InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
|
||||
XII_BUS_NOT_BUSY_EVENT);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* When multiple IIC devices attempt to use the bus simultaneously, only
|
||||
* a single device will be able to keep control as a master. Those devices
|
||||
* that didn't retain control over the bus are said to have lost arbitration.
|
||||
* When arbitration is lost, this interrupt occurs sigaling the user that
|
||||
* the message did not get sent as expected.
|
||||
*
|
||||
* This function, at arbitration lost:
|
||||
* - Disables Tx empty, <EFBFBD> empty and Tx error interrupts
|
||||
* - Clears any Tx empty, <EFBFBD> empty Rx Full or Tx error interrupts
|
||||
* - Clears Arbitration lost interrupt,
|
||||
* - Flush Tx FIFO
|
||||
* - Call StatusHandler callback with the value: XII_ARB_LOST_EVENT
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void ArbitrationLostHandler(XIic *InstancePtr)
|
||||
{
|
||||
/*
|
||||
* Disable Tx empty and <EFBFBD> empty and Tx error interrupts before clearing
|
||||
* them so they won't occur again.
|
||||
*/
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress, XIIC_TX_INTERRUPTS);
|
||||
|
||||
/*
|
||||
* Clear any Tx empty, <EFBFBD> empty Rx Full or Tx error interrupts.
|
||||
*/
|
||||
XIic_ClearIntr(InstancePtr->BaseAddress, XIIC_TX_INTERRUPTS);
|
||||
|
||||
XIic_FlushTxFifo(InstancePtr);
|
||||
|
||||
/*
|
||||
* Update Status via StatusHandler callback.
|
||||
*/
|
||||
InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
|
||||
XII_ARB_LOST_EVENT);
|
||||
}
|
173
XilinxProcessorIPLib/drivers/iic/src/xiic_options.c
Normal file
173
XilinxProcessorIPLib/drivers/iic/src/xiic_options.c
Normal file
|
@ -0,0 +1,173 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_options.c
|
||||
*
|
||||
* Contains options functions for the XIic component. This file is not required
|
||||
* unless the functions in this file are called.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------
|
||||
* 1.01b jhl 3/26/02 repartioned the driver
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs/macros.
|
||||
* </pre>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/***************************** Include Files *******************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions ***************************/
|
||||
|
||||
|
||||
/**************************** Type Definitions *****************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *******************/
|
||||
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function sets the options for the IIC device driver. The options control
|
||||
* how the device behaves relative to the IIC bus. If an option applies to
|
||||
* how messages are sent or received on the IIC bus, it must be set prior to
|
||||
* calling functions which send or receive data.
|
||||
*
|
||||
* To set multiple options, the values must be ORed together. To not change
|
||||
* existing options, read/modify/write with the current options using
|
||||
* XIic_GetOptions().
|
||||
*
|
||||
* <b>USAGE EXAMPLE:</b>
|
||||
*
|
||||
* Read/modify/write to enable repeated start:
|
||||
* <pre>
|
||||
* u8 Options;
|
||||
* Options = XIic_GetOptions(&Iic);
|
||||
* XIic_SetOptions(&Iic, Options | XII_REPEATED_START_OPTION);
|
||||
* </pre>
|
||||
*
|
||||
* Disabling General Call:
|
||||
* <pre>
|
||||
* Options = XIic_GetOptions(&Iic);
|
||||
* XIic_SetOptions(&Iic, Options &= ~XII_GENERAL_CALL_OPTION);
|
||||
* </pre>
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @param NewOptions are the options to be set. See xiic.h for a list of
|
||||
* the available options.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* Sending or receiving messages with repeated start enabled, and then
|
||||
* disabling repeated start, will not take effect until another master
|
||||
* transaction is completed. i.e. After using repeated start, the bus will
|
||||
* continue to be throttled after repeated start is disabled until a master
|
||||
* transaction occurs allowing the IIC to release the bus.
|
||||
* <br><br>
|
||||
* Options enabled will have a 1 in its appropriate bit position.
|
||||
*
|
||||
****************************************************************************/
|
||||
void XIic_SetOptions(XIic *InstancePtr, u32 NewOptions)
|
||||
{
|
||||
u32 CntlReg;
|
||||
|
||||
Xil_AssertVoid(InstancePtr != NULL);
|
||||
|
||||
XIic_IntrGlobalDisable(InstancePtr->BaseAddress);
|
||||
|
||||
/*
|
||||
* Update the options in the instance and get the contents of the
|
||||
* control register such that the general call option can be modified.
|
||||
*/
|
||||
InstancePtr->Options = NewOptions;
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
|
||||
/*
|
||||
* The general call option is the only option that maps directly to
|
||||
* a hardware register feature.
|
||||
*/
|
||||
if (NewOptions & XII_GENERAL_CALL_OPTION) {
|
||||
CntlReg |= XIIC_CR_GENERAL_CALL_MASK;
|
||||
} else {
|
||||
CntlReg &= ~XIIC_CR_GENERAL_CALL_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the new control register value to the register.
|
||||
*/
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET, CntlReg);
|
||||
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function gets the current options for the IIC device. Options control
|
||||
* the how the device behaves on the IIC bus. See SetOptions for more information
|
||||
* on options.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return The options of the IIC device. See xiic.h for a list of
|
||||
* available options.
|
||||
*
|
||||
* @note
|
||||
*
|
||||
* Options enabled will have a 1 in its appropriate bit position.
|
||||
*
|
||||
****************************************************************************/
|
||||
u32 XIic_GetOptions(XIic *InstancePtr)
|
||||
{
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
return InstancePtr->Options;
|
||||
}
|
158
XilinxProcessorIPLib/drivers/iic/src/xiic_selftest.c
Normal file
158
XilinxProcessorIPLib/drivers/iic/src/xiic_selftest.c
Normal file
|
@ -0,0 +1,158 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 - 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 xiic_selftest.c
|
||||
*
|
||||
* Contains selftest functions for the XIic component.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------
|
||||
* 1.01b jhl 03/26/02 repartioned the driver
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.01c sv 05/09/05 Changed the data being written to the Address/Control
|
||||
* Register and removed the code for testing the
|
||||
* Receive Data Register.
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 1.16a ktn 07/17/09 Updated the test to test only Interrupt Registers
|
||||
* as the software reset only resets the interrupt logic
|
||||
* and the Interrupt Registers are set to default values.
|
||||
* 1.16a ktn 10/16/09 Updated the notes in the XIic_SelfTest() API and
|
||||
* XIIC_RESET macro to mention that the complete IIC core
|
||||
* is Reset on giving a software reset to the IIC core.
|
||||
* Some previous versions of the core only reset the
|
||||
* Interrupt Logic/Registers, please refer to the HW
|
||||
* specification for futher details.
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs/macros.
|
||||
* Some of the macros have been renamed to remove _m from
|
||||
* the name and some of the macros have been renamed to be
|
||||
* consistent, see the xiic_i.h and xiic_l.h files for further
|
||||
* information
|
||||
* </pre>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/***************************** Include Files *******************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions ***************************/
|
||||
|
||||
|
||||
/**************************** Type Definitions *****************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *******************/
|
||||
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Runs a limited self-test on the driver/device. This test does a read/write
|
||||
* test of the Interrupt Registers There is no loopback capabilities for the
|
||||
* device such that this test does not send or receive data.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS if no errors are found
|
||||
* - XST_FAILURE if errors are found
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int XIic_SelfTest(XIic *InstancePtr)
|
||||
{
|
||||
int Status = XST_SUCCESS;
|
||||
int GlobalIntrStatus;
|
||||
u32 IntrEnableStatus;
|
||||
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||||
|
||||
/*
|
||||
* Store the Global Interrupt Register and the Interrupt Enable Register
|
||||
* contents.
|
||||
*/
|
||||
GlobalIntrStatus = XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress);
|
||||
IntrEnableStatus = XIic_ReadIier(InstancePtr->BaseAddress);
|
||||
|
||||
/*
|
||||
* Reset the device so it's in a known state and the default state of
|
||||
* the interrupt registers can be tested.
|
||||
*/
|
||||
XIic_Reset(InstancePtr);
|
||||
|
||||
if (XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress)!= 0) {
|
||||
Status = XST_FAILURE;
|
||||
}
|
||||
|
||||
if (XIic_ReadIier(InstancePtr->BaseAddress)!= 0) {
|
||||
Status = XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test Read/Write to the Interrupt Enable register.
|
||||
*/
|
||||
XIic_WriteIier(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
|
||||
if (XIic_ReadIier(InstancePtr->BaseAddress)!= XIIC_TX_RX_INTERRUPTS) {
|
||||
Status = XST_FAILURE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset device to remove the affects of the previous test.
|
||||
*/
|
||||
XIic_Reset(InstancePtr);
|
||||
|
||||
/*
|
||||
* Restore the Global Interrupt Register and the Interrupt Enable
|
||||
* Register contents.
|
||||
*/
|
||||
if (GlobalIntrStatus == TRUE) {
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
}
|
||||
XIic_WriteIier(InstancePtr->BaseAddress, IntrEnableStatus);
|
||||
|
||||
return Status;
|
||||
}
|
163
XilinxProcessorIPLib/drivers/iic/src/xiic_sinit.c
Normal file
163
XilinxProcessorIPLib/drivers/iic/src/xiic_sinit.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2005 - 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 xiic_sinit.c
|
||||
*
|
||||
* The implementation of the Xiic component's static initialzation functionality.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------
|
||||
* 1.02a jvb 10/13/05 release
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs/macros.
|
||||
* Some of the macros have been renamed to remove _m from
|
||||
* the name and some of the macros have been renamed to be
|
||||
* consistent, see the xiic_i.h and xiic_l.h files for further
|
||||
* information
|
||||
* </pre>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/***************************** Include Files *******************************/
|
||||
|
||||
#include "xstatus.h"
|
||||
#include "xparameters.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions ***************************/
|
||||
|
||||
|
||||
/**************************** Type Definitions *****************************/
|
||||
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *******************/
|
||||
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Looks up the device configuration based on the unique device ID. The table
|
||||
* IicConfigTable contains the configuration info for each device in the system.
|
||||
*
|
||||
* @param DeviceId is the unique device ID to look for
|
||||
*
|
||||
* @return A pointer to the configuration data of the device,
|
||||
* or NULL if no match is found.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
XIic_Config *XIic_LookupConfig(u16 DeviceId)
|
||||
{
|
||||
XIic_Config *CfgPtr = NULL;
|
||||
u32 Index;
|
||||
|
||||
for (Index = 0; Index < XPAR_XIIC_NUM_INSTANCES; Index++) {
|
||||
if (XIic_ConfigTable[Index].DeviceId == DeviceId) {
|
||||
CfgPtr = &XIic_ConfigTable[Index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CfgPtr;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Initializes a specific XIic instance. The initialization entails:
|
||||
*
|
||||
* - Check the device has an entry in the configuration table.
|
||||
* - Initialize the driver to allow access to the device registers and
|
||||
* initialize other subcomponents necessary for the operation of the device.
|
||||
* - Default options to:
|
||||
* - 7-bit slave addressing
|
||||
* - Send messages as a slave device
|
||||
* - Repeated start off
|
||||
* - General call recognition disabled
|
||||
* - Clear messageing and error statistics
|
||||
*
|
||||
* The XIic_Start() function must be called after this function before the device
|
||||
* is ready to send and receive data on the IIC bus.
|
||||
*
|
||||
* Before XIic_Start() is called, the interrupt control must connect the ISR
|
||||
* routine to the interrupt handler. This is done by the user, and not
|
||||
* XIic_Start() to allow the user to use an interrupt controller of their choice.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @param DeviceId is the unique id of the device controlled by this XIic
|
||||
* instance. Passing in a device id associates the generic XIic
|
||||
* instance to a specific device, as chosen by the caller or
|
||||
* application developer.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS when successful
|
||||
* - XST_DEVICE_NOT_FOUND indicates the given device id isn't found
|
||||
* - XST_DEVICE_IS_STARTED indicates the device is started
|
||||
* (i.e. interrupts enabled and messaging is possible).
|
||||
* Must stop before re-initialization is allowed.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
int XIic_Initialize(XIic *InstancePtr, u16 DeviceId)
|
||||
{
|
||||
XIic_Config *ConfigPtr; /* Pointer to configuration data */
|
||||
|
||||
/*
|
||||
* Asserts test the validity of selected input arguments.
|
||||
*/
|
||||
Xil_AssertNonvoid(InstancePtr != NULL);
|
||||
|
||||
/*
|
||||
* Lookup the device configuration in the temporary CROM table. Use this
|
||||
* configuration info down below when initializing this component.
|
||||
*/
|
||||
ConfigPtr = XIic_LookupConfig(DeviceId);
|
||||
if (ConfigPtr == NULL) {
|
||||
return XST_DEVICE_NOT_FOUND;
|
||||
}
|
||||
|
||||
return XIic_CfgInitialize(InstancePtr, ConfigPtr,
|
||||
ConfigPtr->BaseAddress);
|
||||
}
|
603
XilinxProcessorIPLib/drivers/iic/src/xiic_slave.c
Normal file
603
XilinxProcessorIPLib/drivers/iic/src/xiic_slave.c
Normal file
|
@ -0,0 +1,603 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_slave.c
|
||||
*
|
||||
* Contains slave functions for the XIic component. This file is necessary when
|
||||
* slave operations, sending and receiving data as a slave on the IIC bus,
|
||||
* are desired.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------
|
||||
* 1.01b jhl 3/26/02 repartioned the driver
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 1.15a ktn 03/18/09 Minor changes to comply to Doxygen
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs/macros.
|
||||
* Removed the macro XIic_mEnterCriticalRegion and used
|
||||
* XIic_IntrGlobalDisable int its place.
|
||||
* Removed the macro XIic_mExitCriticalRegion and used
|
||||
* XIic_IntrGlobalEnable in its place.
|
||||
* Some of the macros have been renamed to remove _m from
|
||||
* the name and some of the macros have been renamed to be
|
||||
* consistent, see the xiic_i.h and xiic_l.h files for further
|
||||
* information
|
||||
* 2.03a rkv 01/25/11 Updated in NAAS interrupt handler to support data
|
||||
* recieved less than FIFO size prior to NAAS interrupt.
|
||||
* Fixed for CR590212.
|
||||
* 2.04a sdm 07/22/11 Added IsSlaveSetAckOff flag to the instance structure.
|
||||
* The IsSlaveSetAckOff is set when the Slave has set the
|
||||
* Ack Off in the RecvSlaveData function and is cleared in the
|
||||
* NotAddrAsSlaveHandler when the master has released the
|
||||
* bus. This flag is to be used by slave applications for
|
||||
* recovering when it has gone out of sync with the master.
|
||||
* CR 615004.
|
||||
* </pre>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/***************************** Include Files *******************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions ***************************/
|
||||
|
||||
/**************************** Type Definitions *****************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *******************/
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
static void AddrAsSlaveHandler(XIic *InstancePtr);
|
||||
static void NotAddrAsSlaveHandler(XIic *InstancePtr);
|
||||
static void RecvSlaveData(XIic *InstancePtr);
|
||||
static void SendSlaveData(XIic *InstancePtr);
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function includes slave code such that slave events will be processsed.
|
||||
* It is necessary to allow slave code to be optional to reduce the size of
|
||||
* the driver. This function may be called at any time but must be prior to
|
||||
* being selected as a slave on the IIC bus. This function may be called prior
|
||||
* to the Cfg_Initialize() function and must be called before any functions in
|
||||
* this file are called.
|
||||
*
|
||||
* @param None.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
void XIic_SlaveInclude()
|
||||
{
|
||||
XIic_AddrAsSlaveFuncPtr = AddrAsSlaveHandler;
|
||||
XIic_NotAddrAsSlaveFuncPtr = NotAddrAsSlaveHandler;
|
||||
XIic_RecvSlaveFuncPtr = RecvSlaveData;
|
||||
XIic_SendSlaveFuncPtr = SendSlaveData;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function sends data as a slave on the IIC bus and should not be called
|
||||
* until an event has occurred that indicates the device has been selected by
|
||||
* a master attempting read from the slave (XII_MASTER_READ_EVENT).
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @param TxMsgPtr is a pointer to the data to be transmitted.
|
||||
* @param ByteCount is the number of message bytes to be sent.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS indicates the message transmission has been
|
||||
* initiated.
|
||||
* - XST_IIC_NOT_SLAVE indicates the device has not been
|
||||
* selected to be a slave on the IIC bus such that data
|
||||
* cannot be sent.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIic_SlaveSend(XIic *InstancePtr, u8 *TxMsgPtr, int ByteCount)
|
||||
{
|
||||
u32 IntrStatus;
|
||||
u32 Status;
|
||||
|
||||
/*
|
||||
* If the device is not a slave on the IIC bus then indicate an error
|
||||
* because data cannot be sent on the bus.
|
||||
*/
|
||||
Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
|
||||
if ((Status & XIIC_SR_ADDR_AS_SLAVE_MASK) == 0) {
|
||||
return XST_IIC_NOT_SLAVE;
|
||||
}
|
||||
|
||||
XIic_IntrGlobalDisable(InstancePtr->BaseAddress);
|
||||
|
||||
/*
|
||||
* Save message state and invalidate the receive buffer pointer to
|
||||
* indicate the direction of transfer is sending.
|
||||
*/
|
||||
InstancePtr->SendByteCount = ByteCount;
|
||||
InstancePtr->SendBufferPtr = TxMsgPtr;
|
||||
InstancePtr->RecvBufferPtr = NULL;
|
||||
|
||||
/*
|
||||
* Start sending the specified data and then interrupt processing will
|
||||
* complete it.
|
||||
*/
|
||||
XIic_TransmitFifoFill(InstancePtr, XIIC_SLAVE_ROLE);
|
||||
|
||||
/* Clear any pending Tx empty, Tx Error and interrupt then enable them.
|
||||
* The Tx error interrupt indicates when the message is complete.
|
||||
* If data remaining to be sent, clear and enable Tx <EFBFBD> empty interrupt.
|
||||
*/
|
||||
IntrStatus = (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK);
|
||||
if (InstancePtr->SendByteCount > 1) {
|
||||
IntrStatus |= XIIC_INTR_TX_HALF_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the interrupts in the status and then enable them and then
|
||||
* exit the critical region.
|
||||
*/
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress, IntrStatus);
|
||||
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function sends data as a slave on the IIC bus and should not be called
|
||||
* until an event has occurred that indicates the device has been selected by
|
||||
* a master attempting read from the slave (XII_MASTER_READ_EVENT).
|
||||
*
|
||||
* If more data is received than specified a No Acknowledge will be sent to
|
||||
* signal the Master to stop sending data. Any received data is read to prevent
|
||||
* the slave device from throttling the bus.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the Iic instance to be worked on.
|
||||
* @param RxMsgPtr is a pointer to the data to be transmitted.
|
||||
* @param ByteCount is the number of message bytes to be sent.
|
||||
*
|
||||
* @return
|
||||
* - XST_SUCCESS indicates the message transmission has been
|
||||
* initiated.
|
||||
* - XST_IIC_NOT_SLAVE indicates the device has not been selected
|
||||
* to be a slave on the IIC bus such that data cannot be received.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* The master signals the message completion differently depending on the
|
||||
* repeated start options.
|
||||
*
|
||||
* When the master is not using repeated start:
|
||||
* - Not Adressed As Slave NAAS interrupt signals the master has sent a stop
|
||||
* condition and is no longer sending data. This doesn't imply that the master
|
||||
* will not send a No Ack. It covers when the master fails to send No
|
||||
* Ackowledge before releasing the bus.
|
||||
* - Tx Error interrupt signals end of message.
|
||||
*
|
||||
* When the master is using repeated start:
|
||||
* - the Tx Error interrupt signals the master finished sending the msg.
|
||||
* - NAAS interrupt will not signal when message is complete as the
|
||||
* master may want to write or read another message with this device.
|
||||
*
|
||||
* To prevent throttling, the slave must contine to read discard the data
|
||||
* when the receive buffer is full. When unexpected bytes are received, No Ack
|
||||
* must be set and the Rx buffer continually read until either NAAS
|
||||
* or Bus Not Busy BND interrupt signals the master is no longer
|
||||
* interacting with this slave. At this point the Ack is set to ON allowing
|
||||
* this device to acknowlefge the an address sent to it for the next
|
||||
* slave message.
|
||||
*
|
||||
* The slave will always receive 1 byte before the bus is throttled causing a
|
||||
* receive pending interrupt before this routine is executed. After one byte
|
||||
* the bus will throttle. The depth is set to the proper amount immediatelly
|
||||
* allowing the master to send more bytes and then to again throttle, but at the
|
||||
* proper fifo depth. The interrupt is a level. Clearing and enabling will cause
|
||||
* the Rx interrupt to pend at the correct level.
|
||||
*
|
||||
******************************************************************************/
|
||||
int XIic_SlaveRecv(XIic *InstancePtr, u8 *RxMsgPtr, int ByteCount)
|
||||
{
|
||||
u32 Status;
|
||||
|
||||
/*
|
||||
* If the device is not a slave on the IIC bus then indicate an error
|
||||
* because data cannot be received on the bus.
|
||||
*/
|
||||
Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
|
||||
if ((Status & XIIC_SR_ADDR_AS_SLAVE_MASK) == 0) {
|
||||
return XST_IIC_NOT_SLAVE;
|
||||
}
|
||||
|
||||
XIic_IntrGlobalDisable(InstancePtr->BaseAddress);
|
||||
|
||||
/*
|
||||
* Save message state and invalidate the send buffer pointer to indicate
|
||||
* the direction of transfer is receive.
|
||||
*/
|
||||
InstancePtr->RecvByteCount = ByteCount;
|
||||
InstancePtr->RecvBufferPtr = RxMsgPtr;
|
||||
InstancePtr->SendBufferPtr = NULL;
|
||||
|
||||
/*
|
||||
* Set receive FIFO occupancy depth so the Rx interrupt will occur
|
||||
* when all bytes received or if more bytes than will fit in FIFO,
|
||||
* set to max depth.
|
||||
*/
|
||||
if (ByteCount > IIC_RX_FIFO_DEPTH) {
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET,
|
||||
IIC_RX_FIFO_DEPTH - 1);
|
||||
} else {
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET,
|
||||
ByteCount - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear and enable receive full interrupt except when the bytes to
|
||||
* receive is only 1, don't clear interrupt as it is the only one your
|
||||
* going to get.
|
||||
*/
|
||||
if (ByteCount > 1) {
|
||||
XIic_ClearIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_RX_FULL_MASK);
|
||||
}
|
||||
|
||||
XIic_EnableIntr(InstancePtr->BaseAddress, XIIC_INTR_RX_FULL_MASK);
|
||||
|
||||
XIic_IntrGlobalEnable(InstancePtr->BaseAddress);
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function is called when the IIC device is Addressed As a Slave (AAS).
|
||||
* This occurs when another device on the bus, a master, has addressed this
|
||||
* device to receive a message.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void AddrAsSlaveHandler(XIic *InstancePtr)
|
||||
{
|
||||
u32 Status;
|
||||
int CallValue;
|
||||
|
||||
/*
|
||||
* Disable AAS interrupt to clear the interrupt condition since this is
|
||||
* interrupt does not go away and enable the not addressed as a slave
|
||||
* interrrupt to tell when the master stops data transfer.
|
||||
*/
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress, XIIC_INTR_AAS_MASK);
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress, XIIC_INTR_NAAS_MASK);
|
||||
|
||||
/*
|
||||
* Determine how the slave is being addressed and call the handler to
|
||||
* notify the user of the event.
|
||||
*/
|
||||
Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
|
||||
|
||||
/*
|
||||
* Determine if the master is trying to perform a read or write
|
||||
* operation.
|
||||
*/
|
||||
if (Status & XIIC_SR_MSTR_RDING_SLAVE_MASK) {
|
||||
CallValue = XII_MASTER_READ_EVENT;
|
||||
} else {
|
||||
CallValue = XII_MASTER_WRITE_EVENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* If being addressed with general call also indicate to handler.
|
||||
*/
|
||||
if (Status & XIIC_SR_GEN_CALL_MASK) {
|
||||
CallValue |= XII_GENERAL_CALL_EVENT;
|
||||
}
|
||||
|
||||
InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef, CallValue);
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function is called when the IIC device receives Not Addressed As Slave
|
||||
* (NAAS) interrupt which indicates that the master has released the bus implying
|
||||
* a data transfer is complete.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void NotAddrAsSlaveHandler(XIic *InstancePtr)
|
||||
{
|
||||
u32 Status;
|
||||
u32 CntlReg;
|
||||
u8 BytesToRead;
|
||||
u8 LoopCnt;
|
||||
|
||||
/*
|
||||
* Disable NAAS so that the condition will not continue to interrupt
|
||||
* and enable the addressed as slave interrupt to know when a master
|
||||
* selects a slave on the bus.
|
||||
*/
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress, XIIC_INTR_NAAS_MASK);
|
||||
XIic_ClearEnableIntr(InstancePtr->BaseAddress, XIIC_INTR_AAS_MASK);
|
||||
|
||||
/*
|
||||
* Flush Tx FIFO by toggling TxFIFOResetBit. FIFO runs normally at 0
|
||||
* Do this incase needed to Tx FIFO with more than expected if what
|
||||
* was set to Tx was less than what the Master expected - read more
|
||||
* from this slave so FIFO had junk in it.
|
||||
*/
|
||||
XIic_FlushTxFifo(InstancePtr);
|
||||
|
||||
/*
|
||||
* NAAS interrupt was asserted but received data in recieve FIFO is
|
||||
* less than Rc_FIFO_PIRQ to assert an receive full interrupt,in this
|
||||
* condition as data recieved is valid we have to read data before FIFO
|
||||
* flush.
|
||||
*/
|
||||
Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
|
||||
|
||||
if (!(Status & XIIC_SR_RX_FIFO_EMPTY_MASK)) {
|
||||
BytesToRead = (XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_RFO_REG_OFFSET)) + 1;
|
||||
if (InstancePtr->RecvByteCount > BytesToRead) {
|
||||
|
||||
for (LoopCnt = 0; LoopCnt < BytesToRead; LoopCnt++) {
|
||||
XIic_ReadRecvByte(InstancePtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InstancePtr->RecvByteCount = 0;
|
||||
/*
|
||||
* Flush Rx FIFO should slave Rx had a problem, sent No ack but
|
||||
* still received a few bytes. Should the slave receive have disabled
|
||||
* acknowledgement, clear Rx FIFO.
|
||||
*/
|
||||
XIic_FlushRxFifo(InstancePtr);
|
||||
|
||||
/*
|
||||
* Set FIFO occupancy depth = 1 so that the first byte will throttle
|
||||
* next recieve msg.
|
||||
*/
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET, 0);
|
||||
|
||||
/*
|
||||
* Should the slave receive have disabled acknowledgement,
|
||||
* enable to allow acknowledgment for receipt of our address to
|
||||
* again be used as a slave.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
(CntlReg & ~XIIC_CR_NO_ACK_MASK));
|
||||
|
||||
InstancePtr->IsSlaveSetAckOff = FALSE;
|
||||
|
||||
/*
|
||||
* Which callback depends on messaging direction, the buffer pointer NOT
|
||||
* being used indicates the direction of data transfer.
|
||||
*/
|
||||
Status = XIic_ReadIier(InstancePtr->BaseAddress);
|
||||
if (InstancePtr->RecvBufferPtr == NULL) {
|
||||
/*
|
||||
* Slave was sending data so disable all transmit interrupts and
|
||||
* call the callback handler to indicate the transfer is
|
||||
* complete.
|
||||
*/
|
||||
XIic_WriteIier(InstancePtr->BaseAddress,
|
||||
(Status & ~XIIC_TX_INTERRUPTS));
|
||||
InstancePtr->SendHandler(InstancePtr->SendCallBackRef,
|
||||
InstancePtr->SendByteCount);
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Slave was receiving data so disable receive full interrupt
|
||||
* and call the callback handler to notify the transfer is
|
||||
* complete.
|
||||
*/
|
||||
XIic_WriteIier(InstancePtr->BaseAddress,
|
||||
(Status & ~XIIC_INTR_RX_FULL_MASK));
|
||||
InstancePtr->RecvHandler(InstancePtr->RecvCallBackRef,
|
||||
InstancePtr->RecvByteCount);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function handles data received from the IIC bus as a slave.
|
||||
*
|
||||
* When the slave expects more than the master has to send, the slave will stall
|
||||
* waiting for data.
|
||||
*
|
||||
* When more data is received than data expected a Nack is done to signal master
|
||||
* to stop sending data. The excess data is discarded to prevent bus throttling.
|
||||
*
|
||||
* The buffer may be full and the master continues to send data if the master
|
||||
* and slave have different message lengths. This condition is handled by sending
|
||||
* No Ack to the master and reading Rx data until the master stops sending data
|
||||
* to prevent but throttling from locking up the bus. To ever receive as a slave
|
||||
* again, must know when to renable bus ACKs. NAAS is used to detect when the
|
||||
* master is finished sending messages for any mode.
|
||||
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void RecvSlaveData(XIic *InstancePtr)
|
||||
{
|
||||
u32 CntlReg;
|
||||
u8 BytesToRead;
|
||||
u8 LoopCnt;
|
||||
u8 Temp;
|
||||
|
||||
/*
|
||||
* When receive buffer has no room for the receive data discard it.
|
||||
*/
|
||||
if (InstancePtr->RecvByteCount == 0) {
|
||||
/*
|
||||
* Set ACKnowlege OFF to signal master to stop sending data.
|
||||
*/
|
||||
CntlReg = XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_CR_REG_OFFSET);
|
||||
CntlReg |= XIIC_CR_NO_ACK_MASK;
|
||||
XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET,
|
||||
CntlReg);
|
||||
|
||||
/*
|
||||
* Set a Flag to indicate that the Slave has set the ACK Off.
|
||||
*/
|
||||
InstancePtr->IsSlaveSetAckOff = TRUE;
|
||||
|
||||
|
||||
/*
|
||||
* Clear excess received data to prevent bus throttling and set
|
||||
* receive FIFO occupancy to throttle at the 1st byte received.
|
||||
*/
|
||||
XIic_FlushRxFifo(InstancePtr);
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_RFD_REG_OFFSET, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Use occupancy count to determine how many bytes to read from the
|
||||
* FIFO, count is zero based so add 1, read that number of bytes from
|
||||
* the FIFO.
|
||||
*/
|
||||
BytesToRead = (XIic_ReadReg(InstancePtr->BaseAddress,
|
||||
XIIC_RFO_REG_OFFSET)) + 1;
|
||||
for (LoopCnt = 0; LoopCnt < BytesToRead; LoopCnt++) {
|
||||
XIic_ReadRecvByte(InstancePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set receive FIFO depth for the number of bytes to be received such
|
||||
* that a receive interrupt will occur, the count is 0 based, the
|
||||
* last byte of the message has to be received seperately to ack the
|
||||
* message.
|
||||
*/
|
||||
if (InstancePtr->RecvByteCount > IIC_RX_FIFO_DEPTH) {
|
||||
Temp = IIC_RX_FIFO_DEPTH - 1;
|
||||
} else {
|
||||
if (InstancePtr->RecvByteCount == 0) {
|
||||
Temp = 0;
|
||||
} else {
|
||||
Temp = InstancePtr->RecvByteCount - 1;
|
||||
}
|
||||
}
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_RFD_REG_OFFSET, (u32) Temp);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* This function sends data on the IIC bus as a slave.
|
||||
*
|
||||
* When message data has been sent, but the master keeps reading data, the FIFO
|
||||
* is filled to prevent bus throttling. There is no way to notify master of this
|
||||
* condition. While sending data as a slave a transmit error indicates the
|
||||
* master has completed the data transfer.
|
||||
*
|
||||
* NAAS interrupt signals when repeated start occurred and the msg is finished
|
||||
* and BNB signals when the master sent a stop.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void SendSlaveData(XIic *InstancePtr)
|
||||
{
|
||||
/*
|
||||
* When message has been sent, but master keeps reading data, must put a
|
||||
* byte in the FIFO or bus will throttle. There is no way to notify
|
||||
* master of this condition.
|
||||
*/
|
||||
if (InstancePtr->SendByteCount == 0) {
|
||||
XIic_WriteReg(InstancePtr->BaseAddress,
|
||||
XIIC_DTR_REG_OFFSET, 0xFF);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send the data by filling the transmit FIFO.
|
||||
*/
|
||||
XIic_TransmitFifoFill(InstancePtr, XIIC_SLAVE_ROLE);
|
||||
/*
|
||||
* When the amount of data remaining to send is less than the half mark
|
||||
* of the FIFO making the use of <EFBFBD> empty interrupt unnecessary,
|
||||
* disable it. Is this a problem that it's checking against 1 rather
|
||||
* than half?
|
||||
*/
|
||||
if (InstancePtr->SendByteCount < 1) {
|
||||
XIic_DisableIntr(InstancePtr->BaseAddress,
|
||||
XIIC_INTR_TX_HALF_MASK);
|
||||
}
|
||||
return;
|
||||
}
|
133
XilinxProcessorIPLib/drivers/iic/src/xiic_stats.c
Normal file
133
XilinxProcessorIPLib/drivers/iic/src/xiic_stats.c
Normal file
|
@ -0,0 +1,133 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2002 - 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 xiic_stats.c
|
||||
*
|
||||
* Contains statistics functions for the XIic component.
|
||||
*
|
||||
* <pre>
|
||||
* MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
* ----- --- ------- -----------------------------------------------
|
||||
* 1.01b jhl 3/26/02 repartioned the driver
|
||||
* 1.01c ecm 12/05/02 new rev
|
||||
* 1.13a wgr 03/22/07 Converted to new coding style.
|
||||
* 2.00a ktn 10/22/09 Converted all register accesses to 32 bit access.
|
||||
* Updated to use the HAL APIs/macros.
|
||||
* XIic_ClearStats function is updated as the
|
||||
* macro XIIC_CLEAR_STATS has been removed.
|
||||
* </pre>
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/***************************** Include Files *******************************/
|
||||
|
||||
#include "xiic.h"
|
||||
#include "xiic_i.h"
|
||||
|
||||
/************************** Constant Definitions ***************************/
|
||||
|
||||
/**************************** Type Definitions *****************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *******************/
|
||||
|
||||
/************************** Function Prototypes ****************************/
|
||||
|
||||
/************************** Variable Definitions **************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Gets a copy of the statistics for an IIC device.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
* @param StatsPtr is a pointer to a XIicStats structure which will get a
|
||||
* copy of current statistics.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
void XIic_GetStats(XIic *InstancePtr, XIicStats * StatsPtr)
|
||||
{
|
||||
u8 NumBytes;
|
||||
u8 *SrcPtr;
|
||||
u8 *DestPtr;
|
||||
|
||||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||||
Xil_AssertVoid(InstancePtr != NULL);
|
||||
Xil_AssertVoid(StatsPtr != NULL);
|
||||
|
||||
/*
|
||||
* Setup pointers to copy the stats structure
|
||||
*/
|
||||
SrcPtr = (u8 *) &InstancePtr->Stats;
|
||||
DestPtr = (u8 *) StatsPtr;
|
||||
|
||||
/*
|
||||
* Copy the current statistics to the structure passed in
|
||||
*/
|
||||
for (NumBytes = 0; NumBytes < sizeof(XIicStats); NumBytes++) {
|
||||
*DestPtr++ = *SrcPtr++;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
*
|
||||
* Clears the statistics for the IIC device by zeroing all counts.
|
||||
*
|
||||
* @param InstancePtr is a pointer to the XIic instance to be worked on.
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @note None.
|
||||
*
|
||||
****************************************************************************/
|
||||
void XIic_ClearStats(XIic *InstancePtr)
|
||||
{
|
||||
u8 NumBytes;
|
||||
u8 *DestPtr;
|
||||
|
||||
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
|
||||
Xil_AssertVoid(InstancePtr != NULL);
|
||||
|
||||
DestPtr = (u8 *)&InstancePtr->Stats;
|
||||
for (NumBytes = 0; NumBytes < sizeof(XIicStats); NumBytes++) {
|
||||
*DestPtr++ = 0;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue