This commit is contained in:
2025-05-20 20:33:12 -05:00
parent 8a1a6ea770
commit fcb291590b
104 changed files with 63299 additions and 45045 deletions

View File

@@ -13,49 +13,49 @@
<AddressSpace Name="microblaze_bd_i_microblaze_0.microblaze_bd_i_microblaze_0_local_memory_dlmb_bram_if_cntlr" Begin="0" End="32767">
<AddressSpaceRange Name="microblaze_bd_i_microblaze_0.microblaze_bd_i_microblaze_0_local_memory_dlmb_bram_if_cntlr" Begin="0" End="32767" CoreMemory_Width="0" MemoryType="RAM_SP" MemoryConfiguration="">
<BusBlock>
<BitLane MemType="RAMB36" Placement="X6Y46" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y9" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="7" LSB="4"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X5Y44" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y10" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="3" LSB="0"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X6Y44" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y14" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="15" LSB="12"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X6Y43" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y13" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="11" LSB="8"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X5Y46" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y6" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="23" LSB="20"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X5Y45" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y5" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="19" LSB="16"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X6Y45" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y11" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="31" LSB="28"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X6Y41" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y7" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="27" LSB="24"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
@@ -69,97 +69,97 @@
<AddressSpace Name="microblaze_bd_i_ddr4_0_inst_u_ddr4_mem_intfc_u_ddr_cal_riu_mcs0_inst_microblaze_I.microblaze_bd_i_ddr4_0_inst_u_ddr4_mem_intfc_u_ddr_cal_riu_mcs0_inst_dlmb_cntlr" Begin="0" End="65535">
<AddressSpaceRange Name="microblaze_bd_i_ddr4_0_inst_u_ddr4_mem_intfc_u_ddr_cal_riu_mcs0_inst_microblaze_I.microblaze_bd_i_ddr4_0_inst_u_ddr4_mem_intfc_u_ddr_cal_riu_mcs0_inst_dlmb_cntlr" Begin="0" End="65535" CoreMemory_Width="0" MemoryType="RAM_SP" MemoryConfiguration="">
<BusBlock>
<BitLane MemType="RAMB36" Placement="X0Y9" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X2Y24" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="7" LSB="6"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y7" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X2Y25" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="5" LSB="4"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y11" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y24" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="3" LSB="2"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y14" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y22" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="1" LSB="0"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y6" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y25" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="15" LSB="14"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y5" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y24" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="13" LSB="12"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y7" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y26" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="11" LSB="10"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y6" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y25" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="9" LSB="8"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y13" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y19" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="23" LSB="22"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y13" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X2Y19" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="21" LSB="20"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y10" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y17" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="19" LSB="18"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y9" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y20" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="17" LSB="16"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y13" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X2Y21" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="31" LSB="30"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y12" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y18" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="29" LSB="28"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y14" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y22" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="27" LSB="26"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y11" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y18" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="25" LSB="24"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>

Binary file not shown.

View File

@@ -0,0 +1,589 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic.h
* @addtogroup Overview
* @{
* @details
*
* 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 addressing.
*
* <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 through 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 through 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
* received 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
* 3.1 adk 01/08/15 When configured as a slave return the actual number of
* bytes have been received/sent by the Master
* to the user callback (CR: 828504). Changes are made in the
* file xiic_slave.c.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototype of XIic_CfgInitialize API.
* 3.2 sd 18/02/16 In Low level driver in repeated start condition
* NACK for last byte is added. Changes are done in
* XIic_Recv for CR# 862303
* 3.3 sk 06/17/16 Added bus busy checks for slave send/recv and master
* send/recv.
* 3.3 als 06/27/16 XIic_IsIicBusy now a wrapper for XIic_CheckIsBusBusy.
* 3.4 ms 01/23/17 Added xil_printf statement in main function for all
* examples to ensure that "Successfully ran" and "Failed"
* strings are available in all examples. This is a fix
* for CR-965028.
* ms 03/17/17 Added readme.txt file in examples folder for doxygen
* generation.
* ms 04/05/17 Modified Comment lines in functions of iic
* examples to recognize it as documentation block
* for doxygen generation.
* </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 */
UINTPTR 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 */
UINTPTR 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 *********************/
/*****************************************************************************
*
* This is a function which tells whether the I2C 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.
*
******************************************************************************/
static inline u32 XIic_IsIicBusy(XIic *InstancePtr)
{
return XIic_CheckIsBusBusy(InstancePtr->BaseAddress);
}
/************************** 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,
UINTPTR 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 */
/** @} */

View File

@@ -0,0 +1,369 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_i.h
* @addtogroup Overview
* @{
*
* 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 */
/** @} */

View File

@@ -0,0 +1,571 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/****************************************************************************/
/**
*
* @file xiic_l.h
* @addtogroup Overview
* @{
*
* 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 further 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 boundary.
* 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.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototypes of XIic_Recv, XIic_Send,
* XIic_DynRecv, XIic_DynSend and XIic_DynInit APIs.
* 3.3 als 06/27/16 Added Low-level XIic_CheckIsBusBusy API.
* 3.3 als 06/27/16 Added low-level XIic_WaitBusFree API.
* </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(UINTPTR BaseAddress, u8 Address,
u8 *BufferPtr, unsigned ByteCount, u8 Option);
unsigned XIic_Send(UINTPTR BaseAddress, u8 Address,
u8 *BufferPtr, unsigned ByteCount, u8 Option);
unsigned XIic_DynRecv(UINTPTR BaseAddress, u8 Address, u8 *BufferPtr, u8 ByteCount);
unsigned XIic_DynSend(UINTPTR BaseAddress, u16 Address, u8 *BufferPtr,
u8 ByteCount, u8 Option);
int XIic_DynInit(UINTPTR BaseAddress);
u32 XIic_CheckIsBusBusy(UINTPTR BaseAddress);
u32 XIic_WaitBusFree(UINTPTR BaseAddress);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/** @} */

View File

@@ -2,14 +2,14 @@
#define XPARAMETERS_H /* by using protection macros */
/* Definitions for bus frequencies */
#define XPAR_CPU_M_AXI_DP_FREQ_HZ 150000000
#define XPAR_CPU_M_AXI_DP_FREQ_HZ 125000000
/******************************************************************/
/* Canonical definitions for bus frequencies */
/******************************************************************/
#define XPAR_CPU_CORE_CLOCK_FREQ_HZ 150000000
#define XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ 150000000
#define XPAR_CPU_CORE_CLOCK_FREQ_HZ 125000000
#define XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ 125000000
/******************************************************************/
@@ -61,7 +61,7 @@
#define XPAR_MICROBLAZE_0_ENDIANNESS 1
#define XPAR_MICROBLAZE_0_FAULT_TOLERANT 0
#define XPAR_MICROBLAZE_0_FPU_EXCEPTION 1
#define XPAR_MICROBLAZE_0_FREQ 150000000
#define XPAR_MICROBLAZE_0_FREQ 125000000
#define XPAR_MICROBLAZE_0_FSL_EXCEPTION 0
#define XPAR_MICROBLAZE_0_FSL_LINKS 0
#define XPAR_MICROBLAZE_0_IADDR_SIZE 32
@@ -288,7 +288,7 @@
#define XPAR_MICROBLAZE_ENDIANNESS 1
#define XPAR_MICROBLAZE_FAULT_TOLERANT 0
#define XPAR_MICROBLAZE_FPU_EXCEPTION 1
#define XPAR_MICROBLAZE_FREQ 150000000
#define XPAR_MICROBLAZE_FREQ 125000000
#define XPAR_MICROBLAZE_FSL_EXCEPTION 0
#define XPAR_MICROBLAZE_FSL_LINKS 0
#define XPAR_MICROBLAZE_IADDR_SIZE 32
@@ -496,8 +496,8 @@
#define PLATFORM_MB
/******************************************************************/
#define STDIN_BASEADDRESS 0x40000000
#define STDOUT_BASEADDRESS 0x40000000
#define STDIN_BASEADDRESS 0x41400000
#define STDOUT_BASEADDRESS 0x41400000
/******************************************************************/
@@ -909,7 +909,30 @@
/******************************************************************/
#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13
/* Definitions for driver IIC */
#define XPAR_XIIC_NUM_INSTANCES 1
/* Definitions for peripheral AXI_IIC_0 */
#define XPAR_AXI_IIC_0_DEVICE_ID 0
#define XPAR_AXI_IIC_0_BASEADDR 0x40110000
#define XPAR_AXI_IIC_0_HIGHADDR 0x4011FFFF
#define XPAR_AXI_IIC_0_TEN_BIT_ADR 0
#define XPAR_AXI_IIC_0_GPO_WIDTH 1
/******************************************************************/
/* Canonical definitions for peripheral AXI_IIC_0 */
#define XPAR_IIC_0_DEVICE_ID XPAR_AXI_IIC_0_DEVICE_ID
#define XPAR_IIC_0_BASEADDR 0x40110000
#define XPAR_IIC_0_HIGHADDR 0x4011FFFF
#define XPAR_IIC_0_TEN_BIT_ADR 0
#define XPAR_IIC_0_GPO_WIDTH 1
/******************************************************************/
#define XPAR_INTC_MAX_NUM_INTR_INPUTS 14
#define XPAR_XINTC_HAS_IPR 1
#define XPAR_XINTC_HAS_SIE 1
#define XPAR_XINTC_HAS_CIE 1
@@ -921,10 +944,10 @@
#define XPAR_MICROBLAZE_0_AXI_INTC_DEVICE_ID 0
#define XPAR_MICROBLAZE_0_AXI_INTC_BASEADDR 0x40010000
#define XPAR_MICROBLAZE_0_AXI_INTC_HIGHADDR 0x4001FFFF
#define XPAR_MICROBLAZE_0_AXI_INTC_KIND_OF_INTR 0xFFFFFBC9
#define XPAR_MICROBLAZE_0_AXI_INTC_KIND_OF_INTR 0xFFFFDBC9
#define XPAR_MICROBLAZE_0_AXI_INTC_HAS_FAST 1
#define XPAR_MICROBLAZE_0_AXI_INTC_IVAR_RESET_VALUE 0x0000000000000010
#define XPAR_MICROBLAZE_0_AXI_INTC_NUM_INTR_INPUTS 13
#define XPAR_MICROBLAZE_0_AXI_INTC_NUM_INTR_INPUTS 14
#define XPAR_MICROBLAZE_0_AXI_INTC_NUM_SW_INTR 0
#define XPAR_MICROBLAZE_0_AXI_INTC_ADDR_WIDTH 32
@@ -961,6 +984,8 @@
#define XPAR_MICROBLAZE_0_AXI_INTC_QSPI_FLASH_IP2INTC_IRPT_INTR 11U
#define XPAR_SYSTEM_PPS_MASK 0X001000U
#define XPAR_MICROBLAZE_0_AXI_INTC_SYSTEM_PPS_INTR 12U
#define XPAR_AXI_IIC_0_IIC2INTC_IRPT_MASK 0X002000U
#define XPAR_MICROBLAZE_0_AXI_INTC_AXI_IIC_0_IIC2INTC_IRPT_INTR 13U
/******************************************************************/
@@ -968,10 +993,10 @@
#define XPAR_INTC_0_DEVICE_ID XPAR_MICROBLAZE_0_AXI_INTC_DEVICE_ID
#define XPAR_INTC_0_BASEADDR 0x40010000U
#define XPAR_INTC_0_HIGHADDR 0x4001FFFFU
#define XPAR_INTC_0_KIND_OF_INTR 0xFFFFFBC9U
#define XPAR_INTC_0_KIND_OF_INTR 0xFFFFDBC9U
#define XPAR_INTC_0_HAS_FAST 1U
#define XPAR_INTC_0_IVAR_RESET_VALUE 0x0000000000000010U
#define XPAR_INTC_0_NUM_INTR_INPUTS 13U
#define XPAR_INTC_0_NUM_INTR_INPUTS 14U
#define XPAR_INTC_0_NUM_SW_INTR 0U
#define XPAR_INTC_0_ADDR_WIDTH 32U
#define XPAR_INTC_0_INTC_TYPE 0U
@@ -986,6 +1011,7 @@
#define XPAR_INTC_0_SPI_1_VEC_ID XPAR_MICROBLAZE_0_AXI_INTC_AXI_QUAD_SPI_1_IP2INTC_IRPT_INTR
#define XPAR_INTC_0_LLFIFO_0_VEC_ID XPAR_MICROBLAZE_0_AXI_INTC_AXI_FIFO_MM_S_0_INTERRUPT_INTR
#define XPAR_INTC_0_SPI_2_VEC_ID XPAR_MICROBLAZE_0_AXI_INTC_QSPI_FLASH_IP2INTC_IRPT_INTR
#define XPAR_INTC_0_IIC_0_VEC_ID XPAR_MICROBLAZE_0_AXI_INTC_AXI_IIC_0_IIC2INTC_IRPT_INTR
/******************************************************************/
@@ -1161,7 +1187,7 @@
#define XPAR_AXI_TIMER_0_DEVICE_ID 0U
#define XPAR_AXI_TIMER_0_BASEADDR 0x40030000U
#define XPAR_AXI_TIMER_0_HIGHADDR 0x4003FFFFU
#define XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ 150000000U
#define XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ 125000000U
/******************************************************************/
@@ -1175,7 +1201,7 @@
/******************************************************************/
/* Definitions for driver UARTLITE */
#define XPAR_XUARTLITE_NUM_INSTANCES 1U
#define XPAR_XUARTLITE_NUM_INSTANCES 2U
/* Definitions for peripheral AXI_UARTLITE_0 */
#define XPAR_AXI_UARTLITE_0_DEVICE_ID 0U
@@ -1196,5 +1222,25 @@
#define XPAR_UARTLITE_0_DATA_BITS 8U
/* Definitions for peripheral MDM_1 */
#define XPAR_MDM_1_DEVICE_ID 1U
#define XPAR_MDM_1_BASEADDR 0x41400000U
#define XPAR_MDM_1_HIGHADDR 0x41400FFFU
#define XPAR_MDM_1_BAUDRATE 0U
#define XPAR_MDM_1_USE_PARITY 0U
#define XPAR_MDM_1_ODD_PARITY 0U
#define XPAR_MDM_1_DATA_BITS 0U
/* Canonical definitions for peripheral MDM_1 */
#define XPAR_UARTLITE_1_DEVICE_ID 1U
#define XPAR_UARTLITE_1_BASEADDR 0x41400000U
#define XPAR_UARTLITE_1_HIGHADDR 0x41400FFFU
#define XPAR_UARTLITE_1_BAUDRATE 0U
#define XPAR_UARTLITE_1_USE_PARITY 0U
#define XPAR_UARTLITE_1_ODD_PARITY 0U
#define XPAR_UARTLITE_1_DATA_BITS 0U
/******************************************************************/
#endif /* end of protection macro */

View File

@@ -0,0 +1,39 @@
DRIVER_LIB_VERSION = 1.0
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
CC_FLAGS = $(COMPILER_FLAGS)
ECC_FLAGS = $(EXTRA_COMPILER_FLAGS)
RELEASEDIR=../../../lib/
INCLUDEDIR=../../../include/
INCLUDES=-I./. -I$(INCLUDEDIR)
SRCFILES:=$(wildcard *.c)
OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c))))
libs: $(OBJECTS)
DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d)
include $(wildcard $(DEPFILES))
include $(wildcard ../../../../dep.mk)
$(RELEASEDIR)%.o: %.c
${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@
.PHONY: include
include: $(addprefix $(INCLUDEDIR),$(wildcard *.h))
$(INCLUDEDIR)%.h: %.h
$(CP) $< $@
clean:
rm -rf ${OBJECTS}
rm -rf $(DEPFILES)

View File

@@ -0,0 +1,722 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic.c
* @addtogroup Overview
* @{
*
* 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.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototype of XIic_CfgInitialize API.
* 3.3 als 06/27/16 XIic_IsIicBusy now static inline in xiic.h.
* 3.8 rna 11/30/20 Corrected the order of Assert in XIic_SetRecvHandler.
* </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,
UINTPTR 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 further 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 != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
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();
}
/** @} */

View File

@@ -0,0 +1,589 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic.h
* @addtogroup Overview
* @{
* @details
*
* 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 addressing.
*
* <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 through 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 through 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
* received 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
* 3.1 adk 01/08/15 When configured as a slave return the actual number of
* bytes have been received/sent by the Master
* to the user callback (CR: 828504). Changes are made in the
* file xiic_slave.c.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototype of XIic_CfgInitialize API.
* 3.2 sd 18/02/16 In Low level driver in repeated start condition
* NACK for last byte is added. Changes are done in
* XIic_Recv for CR# 862303
* 3.3 sk 06/17/16 Added bus busy checks for slave send/recv and master
* send/recv.
* 3.3 als 06/27/16 XIic_IsIicBusy now a wrapper for XIic_CheckIsBusBusy.
* 3.4 ms 01/23/17 Added xil_printf statement in main function for all
* examples to ensure that "Successfully ran" and "Failed"
* strings are available in all examples. This is a fix
* for CR-965028.
* ms 03/17/17 Added readme.txt file in examples folder for doxygen
* generation.
* ms 04/05/17 Modified Comment lines in functions of iic
* examples to recognize it as documentation block
* for doxygen generation.
* </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 */
UINTPTR 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 */
UINTPTR 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 *********************/
/*****************************************************************************
*
* This is a function which tells whether the I2C 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.
*
******************************************************************************/
static inline u32 XIic_IsIicBusy(XIic *InstancePtr)
{
return XIic_CheckIsBusBusy(InstancePtr->BaseAddress);
}
/************************** 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,
UINTPTR 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 */
/** @} */

View File

@@ -0,0 +1,603 @@
/******************************************************************************
* Copyright (C) 2006 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_dyn_master.c
* @addtogroup Overview
* @{
*
* 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 <20> 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 <20> 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 in case 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 in case
* 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;
}
/** @} */

View File

@@ -0,0 +1,33 @@
/*******************************************************************
*
* CAUTION: This file is automatically generated by HSI.
* Version: 2022.2
* DO NOT EDIT.
*
* Copyright (C) 2010-2025 Xilinx, Inc. All Rights Reserved.
* SPDX-License-Identifier: MIT
*
* Description: Driver configuration
*
*******************************************************************/
#include "xparameters.h"
#include "xiic.h"
/*
* The configuration table for devices
*/
XIic_Config XIic_ConfigTable[XPAR_XIIC_NUM_INSTANCES] =
{
{
XPAR_AXI_IIC_0_DEVICE_ID,
XPAR_AXI_IIC_0_BASEADDR,
XPAR_AXI_IIC_0_TEN_BIT_ADR,
XPAR_AXI_IIC_0_GPO_WIDTH
}
};

View File

@@ -0,0 +1,369 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_i.h
* @addtogroup Overview
* @{
*
* 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 */
/** @} */

View File

@@ -0,0 +1,431 @@
/******************************************************************************
* Copyright (C) 2006 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_intr.c
* @addtogroup Overview
* @{
*
* 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
* 3.9 gm 08/02/22 Modified handling of XIIC_INTR_RX_FULL_MASK in xiic_intr.c
* to fix CR #1119930 handling RX FULL interrupt before
* TX error interrupt and clearing TX error interrupt while
* handling RX FULL interrupt when receive byte count is one,
* because here the TX error interrupt indicate NACK, not
* actually TX error.
*
* </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_RX_FULL_MASK) {
/* Receive register/FIFO is full */
if((IicPtr->RecvByteCount == 1) && (IntrStatus & XIIC_INTR_TX_ERROR_MASK)) {
XIic_WriteIisr(IicPtr->BaseAddress, XIIC_INTR_TX_ERROR_MASK);
}
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_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_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 occurred.
*/
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, <20> 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 receive 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();
}
/** @} */

View File

@@ -0,0 +1,571 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/****************************************************************************/
/**
*
* @file xiic_l.h
* @addtogroup Overview
* @{
*
* 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 further 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 boundary.
* 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.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototypes of XIic_Recv, XIic_Send,
* XIic_DynRecv, XIic_DynSend and XIic_DynInit APIs.
* 3.3 als 06/27/16 Added Low-level XIic_CheckIsBusBusy API.
* 3.3 als 06/27/16 Added low-level XIic_WaitBusFree API.
* </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(UINTPTR BaseAddress, u8 Address,
u8 *BufferPtr, unsigned ByteCount, u8 Option);
unsigned XIic_Send(UINTPTR BaseAddress, u8 Address,
u8 *BufferPtr, unsigned ByteCount, u8 Option);
unsigned XIic_DynRecv(UINTPTR BaseAddress, u8 Address, u8 *BufferPtr, u8 ByteCount);
unsigned XIic_DynSend(UINTPTR BaseAddress, u16 Address, u8 *BufferPtr,
u8 ByteCount, u8 Option);
int XIic_DynInit(UINTPTR BaseAddress);
u32 XIic_CheckIsBusBusy(UINTPTR BaseAddress);
u32 XIic_WaitBusFree(UINTPTR BaseAddress);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/** @} */

View File

@@ -0,0 +1,739 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_master.c
* @addtogroup Overview
* @{
*
* 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 <20> 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 in case 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 in case 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 in case
* 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 in case 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 <20> 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);
}
}
}
/** @} */

View File

@@ -0,0 +1,211 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_multi_master.c
* @addtogroup Overview
* @{
*
* 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.
*
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XIic_MultiMasterInclude(void)
{
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 addressed 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 addressed 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 in case 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, <20> empty and Tx error interrupts
* - Clears any Tx empty, <20> 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 <20> 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, <20> 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);
}
/** @} */

View File

@@ -0,0 +1,150 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_options.c
* @addtogroup Overview
* @{
*
* 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;
}
/** @} */

View File

@@ -0,0 +1,135 @@
/******************************************************************************
* Copyright (C) 2012 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_selftest.c
* @addtogroup Overview
* @{
*
* 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 further 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;
}
/** @} */

View File

@@ -0,0 +1,140 @@
/******************************************************************************
* Copyright (C) 2005 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_sinit.c
* @addtogroup Overview
* @{
*
* The implementation of the Xiic component's static initialization 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);
}
/** @} */

View File

@@ -0,0 +1,599 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_slave.c
* @addtogroup Overview
* @{
*
* 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
* received 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.
* 3.1 adk 01/08/15 When configured as a slave return the actual number of
* bytes have been received/sent by the Master
* to the user callback (CR: 828504).
* 3.7 rna 10/06/20 Flush the RxFIFO in NAAS handler only when the FIFO is not
* empty and the controller is still in NAAS state.
* </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 processed.
* 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.
*
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XIic_SlaveInclude(void)
{
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 <20> 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 Addressed 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
* Acknowledge 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 immediately
* 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
* interrupt 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;
u32 TxFifoOcy;
/*
* 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);
/*
* In the slave transmitter case pass the actual number of
* bytes being recievd by the master to the user callback.
*/
Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
TxFifoOcy = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_TFO_REG_OFFSET);
if (!(Status & XIIC_SR_TX_FIFO_EMPTY_MASK)) {
InstancePtr->SendByteCount = InstancePtr->Stats.SendBytes -
(TxFifoOcy+1) ;
} else {
InstancePtr->SendByteCount = InstancePtr->Stats.SendBytes;
}
/*
* Flush Tx FIFO by toggling TxFIFOResetBit. FIFO runs normally at 0
* Do this in case 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 receive FIFO is
* less than Rc_FIFO_PIRQ to assert an receive full interrupt,in this
* condition as data received 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);
}
} else if (!(Status & XIIC_SR_ADDR_AS_SLAVE_MASK)) {
/*
* 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 receive 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);
}
InstancePtr->RecvByteCount = 0;
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 acknowledge 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 separately 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 <20> 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;
}
/** @} */

View File

@@ -0,0 +1,110 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_stats.c
* @addtogroup Overview
* @{
*
* 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;
}
}
/** @} */

View File

@@ -84,6 +84,10 @@ XIntc_Config XIntc_ConfigTable[] =
XNullHandler,
(void *) XNULL
},
{
XNullHandler,
(void *) XNULL
},
{
XNullHandler,
(void *) XNULL

View File

@@ -29,6 +29,14 @@ XUartLite_Config XUartLite_ConfigTable[] =
XPAR_UARTLITE_0_USE_PARITY,
XPAR_UARTLITE_0_ODD_PARITY,
XPAR_UARTLITE_0_DATA_BITS
},
{
XPAR_UARTLITE_1_DEVICE_ID,
XPAR_UARTLITE_1_BASEADDR,
XPAR_UARTLITE_1_BAUDRATE,
XPAR_UARTLITE_1_USE_PARITY,
XPAR_UARTLITE_1_ODD_PARITY,
XPAR_UARTLITE_1_DATA_BITS
}
};

View File

@@ -6,8 +6,8 @@ BEGIN OS
PARAMETER OS_NAME = freertos10_xilinx
PARAMETER OS_VER = 1.12
PARAMETER PROC_INSTANCE = microblaze_0
PARAMETER stdin = axi_uartlite_0
PARAMETER stdout = axi_uartlite_0
PARAMETER stdin = mdm_1
PARAMETER stdout = mdm_1
PARAMETER total_heap_size = 2097152
END
@@ -139,6 +139,18 @@ BEGIN DRIVER
PARAMETER HW_INSTANCE = qspi_flash
END
BEGIN DRIVER
PARAMETER DRIVER_NAME = iic
PARAMETER DRIVER_VER = 3.9
PARAMETER HW_INSTANCE = axi_iic_0
END
BEGIN DRIVER
PARAMETER DRIVER_NAME = uartlite
PARAMETER DRIVER_VER = 3.7
PARAMETER HW_INSTANCE = mdm_1
END
BEGIN LIBRARY
PARAMETER LIBRARY_NAME = lwip211

View File

@@ -0,0 +1,589 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic.h
* @addtogroup Overview
* @{
* @details
*
* 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 addressing.
*
* <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 through 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 through 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
* received 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
* 3.1 adk 01/08/15 When configured as a slave return the actual number of
* bytes have been received/sent by the Master
* to the user callback (CR: 828504). Changes are made in the
* file xiic_slave.c.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototype of XIic_CfgInitialize API.
* 3.2 sd 18/02/16 In Low level driver in repeated start condition
* NACK for last byte is added. Changes are done in
* XIic_Recv for CR# 862303
* 3.3 sk 06/17/16 Added bus busy checks for slave send/recv and master
* send/recv.
* 3.3 als 06/27/16 XIic_IsIicBusy now a wrapper for XIic_CheckIsBusBusy.
* 3.4 ms 01/23/17 Added xil_printf statement in main function for all
* examples to ensure that "Successfully ran" and "Failed"
* strings are available in all examples. This is a fix
* for CR-965028.
* ms 03/17/17 Added readme.txt file in examples folder for doxygen
* generation.
* ms 04/05/17 Modified Comment lines in functions of iic
* examples to recognize it as documentation block
* for doxygen generation.
* </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 */
UINTPTR 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 */
UINTPTR 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 *********************/
/*****************************************************************************
*
* This is a function which tells whether the I2C 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.
*
******************************************************************************/
static inline u32 XIic_IsIicBusy(XIic *InstancePtr)
{
return XIic_CheckIsBusBusy(InstancePtr->BaseAddress);
}
/************************** 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,
UINTPTR 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 */
/** @} */

View File

@@ -0,0 +1,369 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_i.h
* @addtogroup Overview
* @{
*
* 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 */
/** @} */

View File

@@ -0,0 +1,571 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/****************************************************************************/
/**
*
* @file xiic_l.h
* @addtogroup Overview
* @{
*
* 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 further 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 boundary.
* 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.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototypes of XIic_Recv, XIic_Send,
* XIic_DynRecv, XIic_DynSend and XIic_DynInit APIs.
* 3.3 als 06/27/16 Added Low-level XIic_CheckIsBusBusy API.
* 3.3 als 06/27/16 Added low-level XIic_WaitBusFree API.
* </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(UINTPTR BaseAddress, u8 Address,
u8 *BufferPtr, unsigned ByteCount, u8 Option);
unsigned XIic_Send(UINTPTR BaseAddress, u8 Address,
u8 *BufferPtr, unsigned ByteCount, u8 Option);
unsigned XIic_DynRecv(UINTPTR BaseAddress, u8 Address, u8 *BufferPtr, u8 ByteCount);
unsigned XIic_DynSend(UINTPTR BaseAddress, u16 Address, u8 *BufferPtr,
u8 ByteCount, u8 Option);
int XIic_DynInit(UINTPTR BaseAddress);
u32 XIic_CheckIsBusBusy(UINTPTR BaseAddress);
u32 XIic_WaitBusFree(UINTPTR BaseAddress);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/** @} */

View File

@@ -2,14 +2,14 @@
#define XPARAMETERS_H /* by using protection macros */
/* Definitions for bus frequencies */
#define XPAR_CPU_M_AXI_DP_FREQ_HZ 150000000
#define XPAR_CPU_M_AXI_DP_FREQ_HZ 125000000
/******************************************************************/
/* Canonical definitions for bus frequencies */
/******************************************************************/
#define XPAR_CPU_CORE_CLOCK_FREQ_HZ 150000000
#define XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ 150000000
#define XPAR_CPU_CORE_CLOCK_FREQ_HZ 125000000
#define XPAR_MICROBLAZE_CORE_CLOCK_FREQ_HZ 125000000
/******************************************************************/
@@ -61,7 +61,7 @@
#define XPAR_MICROBLAZE_0_ENDIANNESS 1
#define XPAR_MICROBLAZE_0_FAULT_TOLERANT 0
#define XPAR_MICROBLAZE_0_FPU_EXCEPTION 1
#define XPAR_MICROBLAZE_0_FREQ 150000000
#define XPAR_MICROBLAZE_0_FREQ 125000000
#define XPAR_MICROBLAZE_0_FSL_EXCEPTION 0
#define XPAR_MICROBLAZE_0_FSL_LINKS 0
#define XPAR_MICROBLAZE_0_IADDR_SIZE 32
@@ -288,7 +288,7 @@
#define XPAR_MICROBLAZE_ENDIANNESS 1
#define XPAR_MICROBLAZE_FAULT_TOLERANT 0
#define XPAR_MICROBLAZE_FPU_EXCEPTION 1
#define XPAR_MICROBLAZE_FREQ 150000000
#define XPAR_MICROBLAZE_FREQ 125000000
#define XPAR_MICROBLAZE_FSL_EXCEPTION 0
#define XPAR_MICROBLAZE_FSL_LINKS 0
#define XPAR_MICROBLAZE_IADDR_SIZE 32
@@ -913,7 +913,30 @@
/******************************************************************/
#define XPAR_INTC_MAX_NUM_INTR_INPUTS 13
/* Definitions for driver IIC */
#define XPAR_XIIC_NUM_INSTANCES 1
/* Definitions for peripheral AXI_IIC_0 */
#define XPAR_AXI_IIC_0_DEVICE_ID 0
#define XPAR_AXI_IIC_0_BASEADDR 0x40110000
#define XPAR_AXI_IIC_0_HIGHADDR 0x4011FFFF
#define XPAR_AXI_IIC_0_TEN_BIT_ADR 0
#define XPAR_AXI_IIC_0_GPO_WIDTH 1
/******************************************************************/
/* Canonical definitions for peripheral AXI_IIC_0 */
#define XPAR_IIC_0_DEVICE_ID XPAR_AXI_IIC_0_DEVICE_ID
#define XPAR_IIC_0_BASEADDR 0x40110000
#define XPAR_IIC_0_HIGHADDR 0x4011FFFF
#define XPAR_IIC_0_TEN_BIT_ADR 0
#define XPAR_IIC_0_GPO_WIDTH 1
/******************************************************************/
#define XPAR_INTC_MAX_NUM_INTR_INPUTS 14
#define XPAR_XINTC_HAS_IPR 1
#define XPAR_XINTC_HAS_SIE 1
#define XPAR_XINTC_HAS_CIE 1
@@ -925,10 +948,10 @@
#define XPAR_MICROBLAZE_0_AXI_INTC_DEVICE_ID 0
#define XPAR_MICROBLAZE_0_AXI_INTC_BASEADDR 0x40010000
#define XPAR_MICROBLAZE_0_AXI_INTC_HIGHADDR 0x4001FFFF
#define XPAR_MICROBLAZE_0_AXI_INTC_KIND_OF_INTR 0xFFFFFBC9
#define XPAR_MICROBLAZE_0_AXI_INTC_KIND_OF_INTR 0xFFFFDBC9
#define XPAR_MICROBLAZE_0_AXI_INTC_HAS_FAST 1
#define XPAR_MICROBLAZE_0_AXI_INTC_IVAR_RESET_VALUE 0x0000000000000010
#define XPAR_MICROBLAZE_0_AXI_INTC_NUM_INTR_INPUTS 13
#define XPAR_MICROBLAZE_0_AXI_INTC_NUM_INTR_INPUTS 14
#define XPAR_MICROBLAZE_0_AXI_INTC_NUM_SW_INTR 0
#define XPAR_MICROBLAZE_0_AXI_INTC_ADDR_WIDTH 32
@@ -965,6 +988,8 @@
#define XPAR_MICROBLAZE_0_AXI_INTC_QSPI_FLASH_IP2INTC_IRPT_INTR 11U
#define XPAR_SYSTEM_PPS_MASK 0X001000U
#define XPAR_MICROBLAZE_0_AXI_INTC_SYSTEM_PPS_INTR 12U
#define XPAR_AXI_IIC_0_IIC2INTC_IRPT_MASK 0X002000U
#define XPAR_MICROBLAZE_0_AXI_INTC_AXI_IIC_0_IIC2INTC_IRPT_INTR 13U
/******************************************************************/
@@ -972,10 +997,10 @@
#define XPAR_INTC_0_DEVICE_ID XPAR_MICROBLAZE_0_AXI_INTC_DEVICE_ID
#define XPAR_INTC_0_BASEADDR 0x40010000U
#define XPAR_INTC_0_HIGHADDR 0x4001FFFFU
#define XPAR_INTC_0_KIND_OF_INTR 0xFFFFFBC9U
#define XPAR_INTC_0_KIND_OF_INTR 0xFFFFDBC9U
#define XPAR_INTC_0_HAS_FAST 1U
#define XPAR_INTC_0_IVAR_RESET_VALUE 0x0000000000000010U
#define XPAR_INTC_0_NUM_INTR_INPUTS 13U
#define XPAR_INTC_0_NUM_INTR_INPUTS 14U
#define XPAR_INTC_0_NUM_SW_INTR 0U
#define XPAR_INTC_0_ADDR_WIDTH 32U
#define XPAR_INTC_0_INTC_TYPE 0U
@@ -990,6 +1015,7 @@
#define XPAR_INTC_0_SPI_1_VEC_ID XPAR_MICROBLAZE_0_AXI_INTC_AXI_QUAD_SPI_1_IP2INTC_IRPT_INTR
#define XPAR_INTC_0_LLFIFO_0_VEC_ID XPAR_MICROBLAZE_0_AXI_INTC_AXI_FIFO_MM_S_0_INTERRUPT_INTR
#define XPAR_INTC_0_SPI_2_VEC_ID XPAR_MICROBLAZE_0_AXI_INTC_QSPI_FLASH_IP2INTC_IRPT_INTR
#define XPAR_INTC_0_IIC_0_VEC_ID XPAR_MICROBLAZE_0_AXI_INTC_AXI_IIC_0_IIC2INTC_IRPT_INTR
/******************************************************************/
@@ -1165,7 +1191,7 @@
#define XPAR_AXI_TIMER_0_DEVICE_ID 0U
#define XPAR_AXI_TIMER_0_BASEADDR 0x40030000U
#define XPAR_AXI_TIMER_0_HIGHADDR 0x4003FFFFU
#define XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ 150000000U
#define XPAR_AXI_TIMER_0_CLOCK_FREQ_HZ 125000000U
/******************************************************************/
@@ -1179,7 +1205,7 @@
/******************************************************************/
/* Definitions for driver UARTLITE */
#define XPAR_XUARTLITE_NUM_INSTANCES 1U
#define XPAR_XUARTLITE_NUM_INSTANCES 2U
/* Definitions for peripheral AXI_UARTLITE_0 */
#define XPAR_AXI_UARTLITE_0_DEVICE_ID 0U
@@ -1200,5 +1226,25 @@
#define XPAR_UARTLITE_0_DATA_BITS 8U
/* Definitions for peripheral MDM_1 */
#define XPAR_MDM_1_DEVICE_ID 1U
#define XPAR_MDM_1_BASEADDR 0x41400000U
#define XPAR_MDM_1_HIGHADDR 0x41400FFFU
#define XPAR_MDM_1_BAUDRATE 0U
#define XPAR_MDM_1_USE_PARITY 0U
#define XPAR_MDM_1_ODD_PARITY 0U
#define XPAR_MDM_1_DATA_BITS 0U
/* Canonical definitions for peripheral MDM_1 */
#define XPAR_UARTLITE_1_DEVICE_ID 1U
#define XPAR_UARTLITE_1_BASEADDR 0x41400000U
#define XPAR_UARTLITE_1_HIGHADDR 0x41400FFFU
#define XPAR_UARTLITE_1_BAUDRATE 0U
#define XPAR_UARTLITE_1_USE_PARITY 0U
#define XPAR_UARTLITE_1_ODD_PARITY 0U
#define XPAR_UARTLITE_1_DATA_BITS 0U
/******************************************************************/
#endif /* end of protection macro */

View File

@@ -0,0 +1,39 @@
DRIVER_LIB_VERSION = 1.0
COMPILER=
ARCHIVER=
CP=cp
COMPILER_FLAGS=
EXTRA_COMPILER_FLAGS=
LIB=libxil.a
CC_FLAGS = $(COMPILER_FLAGS)
ECC_FLAGS = $(EXTRA_COMPILER_FLAGS)
RELEASEDIR=../../../lib/
INCLUDEDIR=../../../include/
INCLUDES=-I./. -I$(INCLUDEDIR)
SRCFILES:=$(wildcard *.c)
OBJECTS = $(addprefix $(RELEASEDIR), $(addsuffix .o, $(basename $(wildcard *.c))))
libs: $(OBJECTS)
DEPFILES := $(SRCFILES:%.c=$(RELEASEDIR)%.d)
include $(wildcard $(DEPFILES))
include $(wildcard ../../../../dep.mk)
$(RELEASEDIR)%.o: %.c
${COMPILER} $(CC_FLAGS) $(ECC_FLAGS) $(INCLUDES) $(DEPENDENCY_FLAGS) $< -o $@
.PHONY: include
include: $(addprefix $(INCLUDEDIR),$(wildcard *.h))
$(INCLUDEDIR)%.h: %.h
$(CP) $< $@
clean:
rm -rf ${OBJECTS}
rm -rf $(DEPFILES)

View File

@@ -0,0 +1,722 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic.c
* @addtogroup Overview
* @{
*
* 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.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototype of XIic_CfgInitialize API.
* 3.3 als 06/27/16 XIic_IsIicBusy now static inline in xiic.h.
* 3.8 rna 11/30/20 Corrected the order of Assert in XIic_SetRecvHandler.
* </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,
UINTPTR 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 further 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 != NULL);
Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
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();
}
/** @} */

View File

@@ -0,0 +1,589 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic.h
* @addtogroup Overview
* @{
* @details
*
* 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 addressing.
*
* <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 through 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 through 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
* received 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
* 3.1 adk 01/08/15 When configured as a slave return the actual number of
* bytes have been received/sent by the Master
* to the user callback (CR: 828504). Changes are made in the
* file xiic_slave.c.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototype of XIic_CfgInitialize API.
* 3.2 sd 18/02/16 In Low level driver in repeated start condition
* NACK for last byte is added. Changes are done in
* XIic_Recv for CR# 862303
* 3.3 sk 06/17/16 Added bus busy checks for slave send/recv and master
* send/recv.
* 3.3 als 06/27/16 XIic_IsIicBusy now a wrapper for XIic_CheckIsBusBusy.
* 3.4 ms 01/23/17 Added xil_printf statement in main function for all
* examples to ensure that "Successfully ran" and "Failed"
* strings are available in all examples. This is a fix
* for CR-965028.
* ms 03/17/17 Added readme.txt file in examples folder for doxygen
* generation.
* ms 04/05/17 Modified Comment lines in functions of iic
* examples to recognize it as documentation block
* for doxygen generation.
* </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 */
UINTPTR 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 */
UINTPTR 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 *********************/
/*****************************************************************************
*
* This is a function which tells whether the I2C 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.
*
******************************************************************************/
static inline u32 XIic_IsIicBusy(XIic *InstancePtr)
{
return XIic_CheckIsBusBusy(InstancePtr->BaseAddress);
}
/************************** 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,
UINTPTR 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 */
/** @} */

View File

@@ -0,0 +1,603 @@
/******************************************************************************
* Copyright (C) 2006 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_dyn_master.c
* @addtogroup Overview
* @{
*
* 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 <20> 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 <20> 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 in case 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 in case
* 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;
}
/** @} */

View File

@@ -0,0 +1,33 @@
/*******************************************************************
*
* CAUTION: This file is automatically generated by HSI.
* Version: 2022.2
* DO NOT EDIT.
*
* Copyright (C) 2010-2025 Xilinx, Inc. All Rights Reserved.
* SPDX-License-Identifier: MIT
*
* Description: Driver configuration
*
*******************************************************************/
#include "xparameters.h"
#include "xiic.h"
/*
* The configuration table for devices
*/
XIic_Config XIic_ConfigTable[XPAR_XIIC_NUM_INSTANCES] =
{
{
XPAR_AXI_IIC_0_DEVICE_ID,
XPAR_AXI_IIC_0_BASEADDR,
XPAR_AXI_IIC_0_TEN_BIT_ADR,
XPAR_AXI_IIC_0_GPO_WIDTH
}
};

View File

@@ -0,0 +1,369 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_i.h
* @addtogroup Overview
* @{
*
* 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 */
/** @} */

View File

@@ -0,0 +1,431 @@
/******************************************************************************
* Copyright (C) 2006 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_intr.c
* @addtogroup Overview
* @{
*
* 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
* 3.9 gm 08/02/22 Modified handling of XIIC_INTR_RX_FULL_MASK in xiic_intr.c
* to fix CR #1119930 handling RX FULL interrupt before
* TX error interrupt and clearing TX error interrupt while
* handling RX FULL interrupt when receive byte count is one,
* because here the TX error interrupt indicate NACK, not
* actually TX error.
*
* </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_RX_FULL_MASK) {
/* Receive register/FIFO is full */
if((IicPtr->RecvByteCount == 1) && (IntrStatus & XIIC_INTR_TX_ERROR_MASK)) {
XIic_WriteIisr(IicPtr->BaseAddress, XIIC_INTR_TX_ERROR_MASK);
}
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_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_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 occurred.
*/
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, <20> 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 receive 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();
}
/** @} */

View File

@@ -0,0 +1,571 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/****************************************************************************/
/**
*
* @file xiic_l.h
* @addtogroup Overview
* @{
*
* 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 further 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 boundary.
* 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.
* 3.2 sk 11/10/15 Used UINTPTR instead of u32 for Baseaddress CR# 867425.
* Changed the prototypes of XIic_Recv, XIic_Send,
* XIic_DynRecv, XIic_DynSend and XIic_DynInit APIs.
* 3.3 als 06/27/16 Added Low-level XIic_CheckIsBusBusy API.
* 3.3 als 06/27/16 Added low-level XIic_WaitBusFree API.
* </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(UINTPTR BaseAddress, u8 Address,
u8 *BufferPtr, unsigned ByteCount, u8 Option);
unsigned XIic_Send(UINTPTR BaseAddress, u8 Address,
u8 *BufferPtr, unsigned ByteCount, u8 Option);
unsigned XIic_DynRecv(UINTPTR BaseAddress, u8 Address, u8 *BufferPtr, u8 ByteCount);
unsigned XIic_DynSend(UINTPTR BaseAddress, u16 Address, u8 *BufferPtr,
u8 ByteCount, u8 Option);
int XIic_DynInit(UINTPTR BaseAddress);
u32 XIic_CheckIsBusBusy(UINTPTR BaseAddress);
u32 XIic_WaitBusFree(UINTPTR BaseAddress);
#ifdef __cplusplus
}
#endif
#endif /* end of protection macro */
/** @} */

View File

@@ -0,0 +1,739 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_master.c
* @addtogroup Overview
* @{
*
* 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 <20> 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 in case 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 in case 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 in case
* 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 in case 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 <20> 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);
}
}
}
/** @} */

View File

@@ -0,0 +1,211 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_multi_master.c
* @addtogroup Overview
* @{
*
* 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.
*
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XIic_MultiMasterInclude(void)
{
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 addressed 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 addressed 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 in case 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, <20> empty and Tx error interrupts
* - Clears any Tx empty, <20> 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 <20> 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, <20> 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);
}
/** @} */

View File

@@ -0,0 +1,150 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_options.c
* @addtogroup Overview
* @{
*
* 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;
}
/** @} */

View File

@@ -0,0 +1,135 @@
/******************************************************************************
* Copyright (C) 2012 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_selftest.c
* @addtogroup Overview
* @{
*
* 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 further 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;
}
/** @} */

View File

@@ -0,0 +1,140 @@
/******************************************************************************
* Copyright (C) 2005 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_sinit.c
* @addtogroup Overview
* @{
*
* The implementation of the Xiic component's static initialization 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);
}
/** @} */

View File

@@ -0,0 +1,599 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_slave.c
* @addtogroup Overview
* @{
*
* 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
* received 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.
* 3.1 adk 01/08/15 When configured as a slave return the actual number of
* bytes have been received/sent by the Master
* to the user callback (CR: 828504).
* 3.7 rna 10/06/20 Flush the RxFIFO in NAAS handler only when the FIFO is not
* empty and the controller is still in NAAS state.
* </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 processed.
* 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.
*
*
* @return None.
*
* @note None.
*
******************************************************************************/
void XIic_SlaveInclude(void)
{
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 <20> 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 Addressed 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
* Acknowledge 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 immediately
* 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
* interrupt 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;
u32 TxFifoOcy;
/*
* 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);
/*
* In the slave transmitter case pass the actual number of
* bytes being recievd by the master to the user callback.
*/
Status = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_SR_REG_OFFSET);
TxFifoOcy = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_TFO_REG_OFFSET);
if (!(Status & XIIC_SR_TX_FIFO_EMPTY_MASK)) {
InstancePtr->SendByteCount = InstancePtr->Stats.SendBytes -
(TxFifoOcy+1) ;
} else {
InstancePtr->SendByteCount = InstancePtr->Stats.SendBytes;
}
/*
* Flush Tx FIFO by toggling TxFIFOResetBit. FIFO runs normally at 0
* Do this in case 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 receive FIFO is
* less than Rc_FIFO_PIRQ to assert an receive full interrupt,in this
* condition as data received 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);
}
} else if (!(Status & XIIC_SR_ADDR_AS_SLAVE_MASK)) {
/*
* 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 receive 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);
}
InstancePtr->RecvByteCount = 0;
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 acknowledge 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 separately 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 <20> 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;
}
/** @} */

View File

@@ -0,0 +1,110 @@
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
*
* @file xiic_stats.c
* @addtogroup Overview
* @{
*
* 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;
}
}
/** @} */

View File

@@ -84,6 +84,10 @@ XIntc_Config XIntc_ConfigTable[] =
XNullHandler,
(void *) XNULL
},
{
XNullHandler,
(void *) XNULL
},
{
XNullHandler,
(void *) XNULL

View File

@@ -29,6 +29,14 @@ XUartLite_Config XUartLite_ConfigTable[] =
XPAR_UARTLITE_0_USE_PARITY,
XPAR_UARTLITE_0_ODD_PARITY,
XPAR_UARTLITE_0_DATA_BITS
},
{
XPAR_UARTLITE_1_DEVICE_ID,
XPAR_UARTLITE_1_BASEADDR,
XPAR_UARTLITE_1_BAUDRATE,
XPAR_UARTLITE_1_USE_PARITY,
XPAR_UARTLITE_1_ODD_PARITY,
XPAR_UARTLITE_1_DATA_BITS
}
};

View File

@@ -138,4 +138,16 @@ BEGIN DRIVER
PARAMETER HW_INSTANCE = system_management_wiz_0
END
BEGIN DRIVER
PARAMETER DRIVER_NAME = iic
PARAMETER DRIVER_VER = 3.9
PARAMETER HW_INSTANCE = axi_iic_0
END
BEGIN DRIVER
PARAMETER DRIVER_NAME = uartlite
PARAMETER DRIVER_VER = 3.7
PARAMETER HW_INSTANCE = mdm_1
END

View File

@@ -138,4 +138,16 @@ BEGIN DRIVER
PARAMETER HW_INSTANCE = system_management_wiz_0
END
BEGIN DRIVER
PARAMETER DRIVER_NAME = iic
PARAMETER DRIVER_VER = 3.9
PARAMETER HW_INSTANCE = axi_iic_0
END
BEGIN DRIVER
PARAMETER DRIVER_NAME = uartlite
PARAMETER DRIVER_VER = 3.7
PARAMETER HW_INSTANCE = mdm_1
END

View File

@@ -1 +1 @@
{"platformName":"top","sprVersion":"2.0","mode":"gui","dsaType":"Fixed","platformDesc":"top","platHandOff":"/home/bkiedinger/projects/castelion/radar_alinx_kintex/top.xsa","platIntHandOff":"<platformDir>/hw/top.xsa","deviceType":"FPGA","platIsPrebuiltAutogen":"false","platIsNoBootBsp":"false","hasFsblMakeHasChanges":"false","hasPmufwMakeHasChanges":"false","platPreBuiltFlag":false,"platformSamplesDir":"","platActiveSys":"top","systems":[{"systemName":"top","systemDesc":"top","sysIsBootAutoGen":"true","systemDispName":"top","sysActiveDom":"freertos10_xilinx_microblaze_0","sysDefaultDom":"standalone_microblaze_0","domains":[{"domainName":"freertos10_xilinx_microblaze_0","domainDispName":"freertos10_xilinx_microblaze_0","domainDesc":"freertos10_xilinx_microblaze_0","processors":"microblaze_0","os":"freertos10_xilinx","sdxOs":"freertos10_xilinx","debugEnable":"False","domRuntimes":["cpp"],"swRepo":"","mssOsVer":"1.12","mssFile":"","md5Digest":"4ecd151474f27fc8b8562416c0fb32e1","compatibleApp":"","domType":"mssDomain","arch":"32-bit","appSettings":{"appCompilerFlags":"","appLinkerFlags":""},"addedLibs":["lwip211:1.8"],"libOptions":{"freertos10_xilinx":{"total_heap_size":"2097152","libOptionNames":["total_heap_size"]},"lwip211":{"api_mode":"SOCKET_API","default_tcp_recvmbox_size":"4096","dhcp_does_arp_check":"true","lwip_dhcp":"true","lwip_tcpip_core_locking_input":"true","mem_size":"524288","memp_n_pbuf":"1024","memp_n_tcp_seg":"1024","memp_num_netbuf":"4096","n_rx_descriptors":"512","n_tx_descriptors":"512","pbuf_pool_size":"16384","tcp_ip_rx_checksum_offload":"true","tcp_ip_tx_checksum_offload":"true","tcp_snd_buf":"65535","tcp_wnd":"65535","tcpip_mbox_size":"4096","libOptionNames":["api_mode","default_tcp_recvmbox_size","dhcp_does_arp_check","lwip_dhcp","lwip_tcpip_core_locking_input","mem_size","memp_n_pbuf","memp_n_tcp_seg","memp_num_netbuf","n_rx_descriptors","n_tx_descriptors","pbuf_pool_size","tcp_ip_rx_checksum_offload","tcp_ip_tx_checksum_offload","tcp_snd_buf","tcp_wnd","tcpip_mbox_size"]},"libsContainingOptions":["freertos10_xilinx","lwip211"]},"prebuiltLibs":{"prebuiltIncPath":[],"prebuiltLibPath":[]},"isolation":{}},{"domainName":"standalone_microblaze_0","domainDispName":"standalone_microblaze_0","domainDesc":"standalone_microblaze_0","processors":"microblaze_0","os":"standalone","sdxOs":"standalone","debugEnable":"False","domRuntimes":["cpp"],"swRepo":"","mssOsVer":"8.0","mssFile":"","md5Digest":"566ad595ea0892fd7544859e032a3719","compatibleApp":"","domType":"mssDomain","arch":"32-bit","appSettings":{"appCompilerFlags":"","appLinkerFlags":""},"addedLibs":[],"libOptions":{"libsContainingOptions":[]},"prebuiltLibs":{"prebuiltIncPath":[],"prebuiltLibPath":[]},"isolation":{}}]}]}
{"platformName":"top","sprVersion":"2.0","mode":"gui","dsaType":"Fixed","platformDesc":"top","platHandOff":"/home/bkiedinger/projects/castelion/radar_alinx_kintex/top.xsa","platIntHandOff":"<platformDir>/hw/top.xsa","deviceType":"FPGA","platIsPrebuiltAutogen":"false","platIsNoBootBsp":"false","hasFsblMakeHasChanges":"false","hasPmufwMakeHasChanges":"false","platPreBuiltFlag":false,"platformSamplesDir":"","platActiveSys":"top","systems":[{"systemName":"top","systemDesc":"top","sysIsBootAutoGen":"true","systemDispName":"top","sysActiveDom":"freertos10_xilinx_microblaze_0","sysDefaultDom":"standalone_microblaze_0","domains":[{"domainName":"freertos10_xilinx_microblaze_0","domainDispName":"freertos10_xilinx_microblaze_0","domainDesc":"freertos10_xilinx_microblaze_0","processors":"microblaze_0","os":"freertos10_xilinx","sdxOs":"freertos10_xilinx","debugEnable":"False","domRuntimes":["cpp"],"swRepo":"","mssOsVer":"1.12","mssFile":"","md5Digest":"b936724655c64fcfe17fbda77eb413eb","compatibleApp":"","domType":"mssDomain","arch":"32-bit","appSettings":{"appCompilerFlags":"","appLinkerFlags":""},"addedLibs":["lwip211:1.8"],"libOptions":{"freertos10_xilinx":{"stdin":"mdm_1","stdout":"mdm_1","total_heap_size":"2097152","libOptionNames":["stdin","stdout","total_heap_size"]},"lwip211":{"api_mode":"SOCKET_API","default_tcp_recvmbox_size":"4096","dhcp_does_arp_check":"true","lwip_dhcp":"true","lwip_tcpip_core_locking_input":"true","mem_size":"524288","memp_n_pbuf":"1024","memp_n_tcp_seg":"1024","memp_num_netbuf":"4096","n_rx_descriptors":"512","n_tx_descriptors":"512","pbuf_pool_size":"16384","tcp_ip_rx_checksum_offload":"true","tcp_ip_tx_checksum_offload":"true","tcp_snd_buf":"65535","tcp_wnd":"65535","tcpip_mbox_size":"4096","libOptionNames":["api_mode","default_tcp_recvmbox_size","dhcp_does_arp_check","lwip_dhcp","lwip_tcpip_core_locking_input","mem_size","memp_n_pbuf","memp_n_tcp_seg","memp_num_netbuf","n_rx_descriptors","n_tx_descriptors","pbuf_pool_size","tcp_ip_rx_checksum_offload","tcp_ip_tx_checksum_offload","tcp_snd_buf","tcp_wnd","tcpip_mbox_size"]},"libsContainingOptions":["freertos10_xilinx","lwip211"]},"prebuiltLibs":{"prebuiltIncPath":[],"prebuiltLibPath":[]},"isolation":{}},{"domainName":"standalone_microblaze_0","domainDispName":"standalone_microblaze_0","domainDesc":"standalone_microblaze_0","processors":"microblaze_0","os":"standalone","sdxOs":"standalone","debugEnable":"False","domRuntimes":["cpp"],"swRepo":"","mssOsVer":"8.0","mssFile":"","md5Digest":"c7a3ff64e4f9fb39fec5475cd7ffa1a7","compatibleApp":"","domType":"mssDomain","arch":"32-bit","appSettings":{"appCompilerFlags":"","appLinkerFlags":""},"addedLibs":[],"libOptions":{"libsContainingOptions":[]},"prebuiltLibs":{"prebuiltIncPath":[],"prebuiltLibPath":[]},"isolation":{}}]}]}

View File

@@ -77,3 +77,16 @@ platform generate -domains
platform active {top}
platform config -updatehw {/home/bkiedinger/projects/castelion/radar_alinx_kintex/top.xsa}
platform generate -domains
platform active {top}
platform config -updatehw {/home/bkiedinger/projects/castelion/radar_alinx_kintex/top.xsa}
platform generate
platform active {top}
platform config -updatehw {/home/bkiedinger/projects/castelion/radar_alinx_kintex/top.xsa}
platform generate
bsp reload
bsp config stdin "mdm_1"
bsp config stdout "mdm_1"
bsp write
bsp reload
catch {bsp regenerate}
platform generate -domains freertos10_xilinx_microblaze_0

View File

@@ -13,49 +13,49 @@
<AddressSpace Name="microblaze_bd_i_microblaze_0.microblaze_bd_i_microblaze_0_local_memory_dlmb_bram_if_cntlr" Begin="0" End="32767">
<AddressSpaceRange Name="microblaze_bd_i_microblaze_0.microblaze_bd_i_microblaze_0_local_memory_dlmb_bram_if_cntlr" Begin="0" End="32767" CoreMemory_Width="0" MemoryType="RAM_SP" MemoryConfiguration="">
<BusBlock>
<BitLane MemType="RAMB36" Placement="X6Y46" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y9" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="7" LSB="4"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X5Y44" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y10" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="3" LSB="0"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X6Y44" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y14" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="15" LSB="12"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X6Y43" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y13" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="11" LSB="8"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X5Y46" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y6" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="23" LSB="20"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X5Y45" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y5" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="19" LSB="16"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X6Y45" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y11" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="31" LSB="28"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X6Y41" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X6Y7" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="27" LSB="24"/>
<AddressRange Begin="0" End="8191"/>
<BitLayout pattern=""/>
@@ -69,97 +69,97 @@
<AddressSpace Name="microblaze_bd_i_ddr4_0_inst_u_ddr4_mem_intfc_u_ddr_cal_riu_mcs0_inst_microblaze_I.microblaze_bd_i_ddr4_0_inst_u_ddr4_mem_intfc_u_ddr_cal_riu_mcs0_inst_dlmb_cntlr" Begin="0" End="65535">
<AddressSpaceRange Name="microblaze_bd_i_ddr4_0_inst_u_ddr4_mem_intfc_u_ddr_cal_riu_mcs0_inst_microblaze_I.microblaze_bd_i_ddr4_0_inst_u_ddr4_mem_intfc_u_ddr_cal_riu_mcs0_inst_dlmb_cntlr" Begin="0" End="65535" CoreMemory_Width="0" MemoryType="RAM_SP" MemoryConfiguration="">
<BusBlock>
<BitLane MemType="RAMB36" Placement="X0Y9" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X2Y24" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="7" LSB="6"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y7" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X2Y25" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="5" LSB="4"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y11" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y24" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="3" LSB="2"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y14" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y22" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="1" LSB="0"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y6" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y25" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="15" LSB="14"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y5" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y24" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="13" LSB="12"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y7" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y26" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="11" LSB="10"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y6" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y25" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="9" LSB="8"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X0Y13" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y19" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="23" LSB="22"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y13" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X2Y19" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="21" LSB="20"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y10" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y17" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="19" LSB="18"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y9" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y20" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="17" LSB="16"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y13" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X2Y21" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="31" LSB="30"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y12" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y18" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="29" LSB="28"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X1Y14" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X0Y22" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="27" LSB="26"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>
<Parity ON="false" NumBits="0"/>
</BitLane>
<BitLane MemType="RAMB36" Placement="X2Y11" Read_Width="0" SLR_INDEX="-1">
<BitLane MemType="RAMB36" Placement="X1Y18" Read_Width="0" SLR_INDEX="-1">
<DataWidth MSB="25" LSB="24"/>
<AddressRange Begin="0" End="16383"/>
<BitLayout pattern=""/>

Binary file not shown.