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