OpenCores
URL https://opencores.org/ocsvn/xenie/xenie/trunk

Subversion Repositories xenie

[/] [xenie/] [trunk/] [examples/] [Eth_example/] [mb_fw/] [xenie_eth_test_womtd/] [src/] [iic_wrap.c] - Rev 4

Compare with Previous | Blame | View Log

 
/******************************************************************************
**
** (C) Copyright 2013 DFC Design, s.r.o., Brno, Czech Republic
** Author: Marek Kvas (m.kvas@dspfpga.com)
**
****************************************************************************
**
** This file is part of Xenia Ethernet Example project.
** 
** Xenia Ethernet Example project is free software: you can 
** redistribute it and/or modify it under the terms of 
** the GNU Lesser General Public License as published by the Free 
** Software Foundation, either version 3 of the License, or
** (at your option) any later version.
** 
** Xenia Ethernet Example project is distributed in the hope that 
** it will be useful, but WITHOUT ANY WARRANTY; without even 
** the implied warranty of MERCHANTABILITY or FITNESS FOR A 
** PARTICULAR PURPOSE.  See the GNU Lesser General Public License 
** for more details.
** 
** You should have received a copy of the GNU Lesser General Public 
** License along with Xenia Ethernet Example project.  If not, 
** see <http://www.gnu.org/licenses/>.
*******************************************************************************
**
** This is a wrapper for Xilinx IIC driver in interrupt mode.
**
*******************************************************************************
*/
 
 
#include "iic_wrap.h"
#include "timers.h"
 
static void RecvHandler(void *CallbackRef, int ByteCount)
{
	struct iic_wrap_dev *dev = (struct iic_wrap_dev *)CallbackRef;
 
	dev->hi.unprocessed_bytes = ByteCount;
	dev->hi.finished = 1;
	dev->hi.rcv_stat++;
}
 
static void SendHandler(void *CallbackRef, int ByteCount)
{
	struct iic_wrap_dev *dev = (struct iic_wrap_dev *)CallbackRef;
 
	dev->hi.unprocessed_bytes = ByteCount;
	dev->hi.finished = 1;
	dev->hi.snd_star++;
}
 
static void StatusHandler(void *CallbackRef, int Status)
{
	struct iic_wrap_dev *dev = (struct iic_wrap_dev *)CallbackRef;
 
	/* As we are single master, when this is called, it is always wrong */
	dev->hi.error = Status;
	dev->hi.finished = 1;
	dev->hi.stat_stat++;
}
 
/*
 * Initialize underlying iic controller and wrapper structures.
 */
int iic_wrap_init(struct iic_wrap_dev *dev, u16 IicDeviceId)
{
	int Status;
	XIic_Config *ConfigPtr;	/* Pointer to configuration data */
 
	/* Clear the device structure */
	memset(dev, 0, sizeof(*dev));
 
	/*
	 * Initialize the IIC driver so that it is ready to use.
	 */
	ConfigPtr = XIic_LookupConfig(IicDeviceId);
	if (ConfigPtr == NULL) {
		return -1;
	}
 
	Status = XIic_CfgInitialize(&dev->iic, ConfigPtr,
					ConfigPtr->BaseAddress);
	if (Status != XST_SUCCESS) {
		return -1;
	}
 
	/*
	 * Setup handler to process the asynchronous events which occur,
	 * the driver is only interrupt driven such that this must be
	 * done prior to starting the device.
	 */
	XIic_SetRecvHandler(&dev->iic, (void *)dev, RecvHandler);
	XIic_SetSendHandler(&dev->iic, (void *)dev, SendHandler);
	XIic_SetStatusHandler(&dev->iic, (void *)dev, StatusHandler);
 
	return 0;
}
 
/*
 * Send message on I2C bus with timeout.
 * Returns 0 on success, negative number otherwise.
 */
int iic_wrap_send_timeout(struct iic_wrap_dev *dev, u8 addr, u8 *tx_msg, int length, int timeout_ms)
{
	int ret;
	/* If device is not started, do it */
	if (!dev->started) {
		dev->started = 1;
		XIic_Start(&dev->iic);
	}
 
	dev->hi.error = 0;
	dev->hi.finished = 0;
	dev->hi.op_started = 1;
	dev->hi.end_tstmp = timers_ms_now() + timeout_ms;
 
	XIic_SetAddress(&dev->iic, XII_ADDR_TO_SEND_TYPE, addr);
	/* If busy, retry until timeout */
	/* TODO: There is a bug xilinx driver in busy signaling. Make fix part of project */
	do {
		ret = XIic_DynMasterSend(&dev->iic, tx_msg, length);
	} while ((ret != XST_SUCCESS) && (timers_ms_now() < dev->hi.end_tstmp));
 
	while (!dev->hi.finished) {
		if (timers_ms_now() > dev->hi.end_tstmp) {
			dev->hi.op_started = 0;
			return -1;
		}
	}
 
	/* check for errors */
	if(dev->hi.error || dev->hi.unprocessed_bytes) {
		dev->hi.op_started = 0;
		return -1;
	}
 
	/* Success */
	dev->hi.op_started = 0;
	return 0;
}
 
/*
 * Receive message on I2C bus with timeout.
 * Returns 0 on success, negative number otherwise.
 */
int iic_wrap_recv_timeout(struct iic_wrap_dev *dev, u8 addr, u8 *rx_msg, int length, int timeout_ms)
{
	int ret;
 
	/* If device is not started, do it */
	if (!dev->started) {
		dev->started = 1;
		XIic_Start(&dev->iic);
	}
 
	dev->hi.error = 0;
	dev->hi.finished = 0;
	dev->hi.op_started = 1;
	dev->hi.end_tstmp = timers_ms_now() + timeout_ms;
 
	XIic_SetAddress(&dev->iic, XII_ADDR_TO_SEND_TYPE, addr);
	do {
		ret = XIic_DynMasterRecv(&dev->iic, rx_msg, length);
	} while ((ret != XST_SUCCESS) && (timers_ms_now() < dev->hi.end_tstmp));
 
	while (!dev->hi.finished) {
		if (timers_ms_now() > dev->hi.end_tstmp) {
			dev->hi.op_started = 0;
			return -1;
		}
	}
 
	/* check for errors */
	if(dev->hi.error || dev->hi.unprocessed_bytes) {
		dev->hi.op_started = 0;
		return -1;
	}
 
	/* Success */
	dev->hi.op_started = 0;
	return 0;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.