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

Subversion Repositories xenie

[/] [xenie/] [trunk/] [examples/] [Eth_example/] [mb_fw/] [drivers/] [iic_v3_4/] [src/] [xiic_intr.c] - Blame information for rev 4

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 DFC
/******************************************************************************
2
*
3
* Copyright (C) 2006 - 2015 Xilinx, Inc.  All rights reserved.
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining a copy
6
* of this software and associated documentation files (the "Software"), to deal
7
* in the Software without restriction, including without limitation the rights
8
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
* copies of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
11
*
12
* The above copyright notice and this permission notice shall be included in
13
* all copies or substantial portions of the Software.
14
*
15
* Use of the Software is limited solely to applications:
16
* (a) running on a Xilinx device, or
17
* (b) that interact with a Xilinx device through a bus or interconnect.
18
*
19
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
* SOFTWARE.
26
*
27
* Except as contained in this notice, the name of the Xilinx shall not be used
28
* in advertising or otherwise to promote the sale, use or other dealings in
29
* this Software without prior written authorization from Xilinx.
30
*
31
******************************************************************************/
32
/*****************************************************************************/
33
/**
34
*
35
* @file xiic_intr.c
36
* @addtogroup iic_v3_1
37
* @{
38
*
39
* Contains interrupt functions of the XIic driver.  This file is required
40
* for the driver.
41
*
42
* <pre>
43
* MODIFICATION HISTORY:
44
*
45
* Ver   Who  Date     Changes
46
* ----- ---- -------- -----------------------------------------------
47
* 1.01a rfp  10/19/01 release
48
* 1.01c ecm  12/05/02 new rev
49
* 1.01c rmm  05/14/03 Fixed diab compiler warnings relating to asserts.
50
* 1.03a ecm  06/22/06 Added a call to the status handler in the TxErrorHandler
51
*                     even if the Rx buffer pointer is not set. This fix is as
52
*                     a result of a Sony use model which did not set the Rx
53
*                     pointer while in Master mode so it checks if MSMS == 1.
54
* 1.13a wgr  03/22/07 Converted to new coding style.
55
* 2.00a sdm  10/22/09 Converted all register accesses to 32 bit access.
56
*                     Updated to use the HAL APIs/macros.
57
*                     Some of the macros have been renamed to remove _m from
58
*                     the name and Some of the macros have been renamed to be
59
*                     consistent, see the xiic_l.h file for further information.
60
* 2.01a ktn  04/09/10 Updated TxErrorhandler to be called for Master Transmitter
61
*                     case based on Addressed As Slave (AAS) bit rather than
62
*                     MSMS bit(CR 540199).
63
* 2.06a bss  02/14/13 Modified TxErrorHandler in xiic_intr.c to fix CR #686483
64
*                     Modified bitwise OR to logical OR in
65
*                     XIic_InterruptHandler API.
66
* 2.07a adk   18/04/13 Updated the code to avoid unused variable warnings
67
*                         when compiling with the -Wextra -Wall flags.
68
*                         In the file xiic.c and xiic_i.h. CR:705001
69
* </pre>
70
*
71
******************************************************************************/
72
 
73
 
74
/***************************** Include Files *********************************/
75
 
76
#include "xiic.h"
77
#include "xiic_i.h"
78
 
79
/************************** Constant Definitions *****************************/
80
 
81
 
82
/**************************** Type Definitions *******************************/
83
 
84
 
85
/***************** Macros (Inline Functions) Definitions ******************/
86
 
87
/************************** Function Prototypes ****************************/
88
 
89
static void StubFunction(XIic *InstancePtr);
90
static void TxErrorHandler(XIic *InstancePtr);
91
 
92
/************************** Variable Definitions *****************************/
93
 
94
/* The following function pointers are used to help allow finer partitioning
95
 * of the driver such that some parts of it are optional. These pointers are
96
 * setup by functions in the optional parts of the driver.
97
 */
98
void (*XIic_AddrAsSlaveFuncPtr) (XIic *InstancePtr) = StubFunction;
99
void (*XIic_NotAddrAsSlaveFuncPtr) (XIic *InstancePtr) = StubFunction;
100
void (*XIic_RecvSlaveFuncPtr) (XIic *InstancePtr) = StubFunction;
101
void (*XIic_SendSlaveFuncPtr) (XIic *InstancePtr) = StubFunction;
102
void (*XIic_RecvMasterFuncPtr) (XIic *InstancePtr) = StubFunction;
103
void (*XIic_SendMasterFuncPtr) (XIic *InstancePtr) = StubFunction;
104
void (*XIic_ArbLostFuncPtr) (XIic *InstancePtr) = StubFunction;
105
void (*XIic_BusNotBusyFuncPtr) (XIic *InstancePtr) = StubFunction;
106
 
107
/*****************************************************************************/
108
/**
109
*
110
* This function is the interrupt handler for the XIic driver. This function
111
* should be connected to the interrupt system.
112
*
113
* Only one interrupt source is handled for each interrupt allowing
114
* higher priority system interrupts quicker response time.
115
*
116
* @param        InstancePtr is a pointer to the XIic instance to be worked on.
117
*
118
* @return       None.
119
*
120
* @internal
121
*
122
* The XIIC_INTR_ARB_LOST_MASK and XIIC_INTR_TX_ERROR_MASK interrupts must have
123
* higher priority than the other device interrupts so that the IIC device does
124
* not get into a potentially confused state. The remaining interrupts may be
125
* rearranged with no harm.
126
*
127
******************************************************************************/
128
void XIic_InterruptHandler(void *InstancePtr)
129
{
130
        u32 Status;
131
        u32 IntrStatus;
132
        u32 IntrPending;
133
        u32 IntrEnable;
134
        XIic *IicPtr = NULL;
135
        u32 Clear = 0;
136
 
137
        /*
138
         * Verify that each of the inputs are valid.
139
         */
140
        Xil_AssertVoid(InstancePtr != NULL);
141
 
142
        /*
143
         * Convert the non-typed pointer to an IIC instance pointer
144
         */
145
        IicPtr = (XIic *) InstancePtr;
146
 
147
        /*
148
         * Get the interrupt Status.
149
         */
150
        IntrPending = XIic_ReadIisr(IicPtr->BaseAddress);
151
        IntrEnable = XIic_ReadIier(IicPtr->BaseAddress);
152
        IntrStatus = IntrPending & IntrEnable;
153
 
154
        /*
155
         * Do not processes a devices interrupts if the device has no
156
         * interrupts pending or the global interrupts have been disabled.
157
         */
158
        if ((IntrStatus == 0) ||
159
                (XIic_IsIntrGlobalEnabled(IicPtr->BaseAddress) == FALSE)) {
160
                return;
161
        }
162
 
163
        /*
164
         * Update interrupt stats and get the contents of the status register.
165
         */
166
        IicPtr->Stats.IicInterrupts++;
167
        Status = XIic_ReadReg(IicPtr->BaseAddress, XIIC_SR_REG_OFFSET);
168
 
169
        /*
170
         * Service requesting interrupt.
171
         */
172
        if (IntrStatus & XIIC_INTR_ARB_LOST_MASK) {
173
                /* Bus Arbritration Lost */
174
 
175
                IicPtr->Stats.ArbitrationLost++;
176
                XIic_ArbLostFuncPtr(IicPtr);
177
 
178
                Clear = XIIC_INTR_ARB_LOST_MASK;
179
        } else if (IntrStatus & XIIC_INTR_TX_ERROR_MASK) {
180
                /* Transmit errors (no acknowledge) received */
181
                IicPtr->Stats.TxErrors++;
182
                TxErrorHandler(IicPtr);
183
 
184
                Clear = XIIC_INTR_TX_ERROR_MASK;
185
        } else if (IntrStatus & XIIC_INTR_NAAS_MASK) {
186
                /* Not Addressed As Slave */
187
 
188
                XIic_NotAddrAsSlaveFuncPtr(IicPtr);
189
                Clear = XIIC_INTR_NAAS_MASK;
190
        } else if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
191
                /* Receive register/FIFO is full */
192
 
193
                IicPtr->Stats.RecvInterrupts++;
194
 
195
                if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
196
                        XIic_RecvSlaveFuncPtr(IicPtr);
197
                } else {
198
                        XIic_RecvMasterFuncPtr(IicPtr);
199
                }
200
 
201
                Clear = XIIC_INTR_RX_FULL_MASK;
202
        } else if (IntrStatus & XIIC_INTR_AAS_MASK) {
203
                /* Addressed As Slave */
204
 
205
                XIic_AddrAsSlaveFuncPtr(IicPtr);
206
                Clear = XIIC_INTR_AAS_MASK;
207
        } else if (IntrStatus & XIIC_INTR_BNB_MASK) {
208
                /* IIC bus has transitioned to not busy */
209
 
210
                /* Check if send callback needs to run */
211
                if (IicPtr->BNBOnly == TRUE) {
212
                        XIic_BusNotBusyFuncPtr(IicPtr);
213
                        IicPtr->BNBOnly = FALSE;
214
                } else {
215
                        IicPtr->SendHandler(IicPtr->SendCallBackRef, 0);
216
                }
217
 
218
                Clear = XIIC_INTR_BNB_MASK;
219
 
220
                /* The bus is not busy, disable BusNotBusy interrupt */
221
                XIic_DisableIntr(IicPtr->BaseAddress, XIIC_INTR_BNB_MASK);
222
 
223
        } else if ((IntrStatus & XIIC_INTR_TX_EMPTY_MASK) ||
224
                 (IntrStatus & XIIC_INTR_TX_HALF_MASK)) {
225
                /* Transmit register/FIFO is empty or � empty */
226
                IicPtr->Stats.SendInterrupts++;
227
 
228
                if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
229
                        XIic_SendSlaveFuncPtr(IicPtr);
230
                } else {
231
                        XIic_SendMasterFuncPtr(IicPtr);
232
                }
233
 
234
                IntrStatus = XIic_ReadIisr(IicPtr->BaseAddress);
235
                Clear = IntrStatus & (XIIC_INTR_TX_EMPTY_MASK |
236
                                          XIIC_INTR_TX_HALF_MASK);
237
        }
238
 
239
        /*
240
         * Clear Interrupts.
241
         */
242
        XIic_WriteIisr(IicPtr->BaseAddress, Clear);
243
}
244
 
245
/******************************************************************************
246
*
247
* This function fills the FIFO using the occupancy register to determine the
248
* available space to be filled. When the repeated start option is on, the last
249
* byte is withheld to allow the control register to be properly set on the last
250
* byte.
251
*
252
* @param        InstancePtr is a pointer to the XIic instance to be worked on.
253
*
254
* @param        Role indicates the role of this IIC device, a slave or a master,
255
*               on the IIC bus (XIIC_SLAVE_ROLE or XIIC_MASTER_ROLE).
256
*
257
* @return       None.
258
*
259
* @note         None.
260
*
261
******************************************************************************/
262
void XIic_TransmitFifoFill(XIic *InstancePtr, int Role)
263
{
264
        u8 AvailBytes;
265
        int LoopCnt;
266
        int NumBytesToSend;
267
 
268
        /*
269
         * Determine number of bytes to write to FIFO. Number of bytes that
270
         * can be put into the FIFO is (FIFO depth) - (current occupancy + 1)
271
         * When more room in FIFO than msg bytes put all of message in the FIFO.
272
         */
273
        AvailBytes = IIC_TX_FIFO_DEPTH -
274
                        (u8) (XIic_ReadReg(InstancePtr->BaseAddress,
275
                                        XIIC_TFO_REG_OFFSET) + 1);
276
 
277
        if (InstancePtr->SendByteCount > AvailBytes) {
278
                NumBytesToSend = AvailBytes;
279
        } else {
280
                /*
281
                 * More space in FIFO than bytes in message.
282
                 */
283
                if ((InstancePtr->Options & XII_REPEATED_START_OPTION) ||
284
                        (Role == XIIC_SLAVE_ROLE)) {
285
                        NumBytesToSend = InstancePtr->SendByteCount;
286
                } else {
287
                        NumBytesToSend = InstancePtr->SendByteCount - 1;
288
                }
289
        }
290
 
291
        /*
292
         * Fill FIFO with amount determined above.
293
         */
294
        for (LoopCnt = 0; LoopCnt < NumBytesToSend; LoopCnt++) {
295
                XIic_WriteSendByte(InstancePtr);
296
        }
297
}
298
 
299
/*****************************************************************************/
300
/**
301
*
302
* This interrupt occurs four different ways: Two as master and two as slave.
303
* Master:
304
* <pre>
305
*  (1) Transmitter (IMPLIES AN ERROR)
306
*      The slave receiver did not acknowledge properly.
307
*  (2) Receiver (Implies Tx complete)
308
*      Interrupt caused by setting TxAck high in the IIC to indicate to the
309
*      the last byte has been transmitted.
310
* </pre>
311
*
312
* Slave:
313
* <pre>
314
*  (3) Transmitter (Implies Tx complete)
315
*      Interrupt caused by master device indicating last byte of the message
316
*      has been transmitted.
317
*  (4) Receiver (IMPLIES AN ERROR)
318
*      Interrupt caused by setting TxAck high in the IIC to indicate Rx
319
*      IIC had a problem - set by this device and condition already known
320
*      and interrupt is not enabled.
321
* </pre>
322
*
323
* This interrupt is enabled during Master send and receive and disabled
324
* when this device knows it is going to send a negative acknowledge (Ack = No).
325
*
326
* Signals user of Tx error via status callback sending: XII_TX_ERROR_EVENT
327
*
328
* When MasterRecv has no message to send and only receives one byte of data
329
* from the salve device, the TxError must be enabled to catch addressing
330
* errors, yet there is not opportunity to disable TxError when there is no
331
* data to send allowing disabling on last byte. When the slave sends the
332
* only byte the NOAck causes a Tx Error. To disregard this as no real error,
333
* when there is data in the Receive FIFO/register then the error was not
334
* a device address write error, but a NOACK read error - to be ignored.
335
* To work with or without FIFO's, the Rx Data interrupt is used to indicate
336
* data is in the Rx register.
337
*
338
* @param        InstancePtr is a pointer to the XIic instance to be worked on.
339
*
340
* @return       None.
341
*
342
******************************************************************************/
343
static void TxErrorHandler(XIic *InstancePtr)
344
{
345
        u32 IntrStatus;
346
        u32 CntlReg;
347
 
348
        /*
349
         * When Sending as a slave, Tx error signals end of msg. Not Addressed
350
         * As Slave will handle the callbacks. this is used to only flush
351
         * the Tx fifo. The addressed as slave bit is gone as soon as the bus
352
         * has been released such that the buffer pointers are used to determine
353
         * the direction of transfer (send or receive).
354
         */
355
        if (InstancePtr->RecvBufferPtr == NULL) {
356
                /*
357
                 * Master Receiver finished reading message. Flush Tx fifo to
358
                 * remove an 0xFF that was written to prevent bus throttling,
359
                 * and disable all transmit and receive interrupts.
360
                 */
361
                XIic_FlushTxFifo(InstancePtr);
362
                XIic_DisableIntr(InstancePtr->BaseAddress,
363
                                  XIIC_TX_RX_INTERRUPTS);
364
 
365
                /*
366
                 * If operating in Master mode, call status handler to indicate
367
                 * NOACK occured.
368
                 */
369
                IntrStatus = XIic_ReadIisr(InstancePtr->BaseAddress);
370
                if ((IntrStatus & XIIC_INTR_AAS_MASK) == 0) {
371
                        InstancePtr->StatusHandler(InstancePtr->
372
                                                   StatusCallBackRef,
373
                                                   XII_SLAVE_NO_ACK_EVENT);
374
                } else {
375
                        /* Decrement the Tx Error since Tx Error interrupt
376
                         * implies transmit complete while sending as Slave
377
                         */
378
                         InstancePtr->Stats.TxErrors--;
379
                }
380
 
381
                return;
382
        }
383
 
384
        /*
385
         * Data in the receive register from either master or slave receive
386
         * When:slave, indicates master sent last byte, message completed.
387
         * When:master, indicates a master Receive with one byte received. When
388
         * a byte is in Rx reg then the Tx error indicates the Rx data was
389
         * recovered normally Tx errors are not enabled such that this should
390
         * not occur.
391
         */
392
        IntrStatus = XIic_ReadIisr(InstancePtr->BaseAddress);
393
        if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
394
                /* Rx Reg/FIFO has data,  Disable Tx error interrupts */
395
 
396
                XIic_DisableIntr(InstancePtr->BaseAddress,
397
                                  XIIC_INTR_TX_ERROR_MASK);
398
                return;
399
        }
400
 
401
        XIic_FlushTxFifo(InstancePtr);
402
 
403
        /*
404
         * Disable and clear Tx empty, � empty, Rx Full or Tx error interrupts.
405
         */
406
        XIic_DisableIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
407
        XIic_ClearIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
408
 
409
        /* Clear MSMS as on Tx error when Rxing, the bus will be
410
         * stopped but MSMS bit is still set. Reset to proper state
411
         */
412
        CntlReg = XIic_ReadReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET);
413
        CntlReg &= ~XIIC_CR_MSMS_MASK;
414
        XIic_WriteReg(InstancePtr->BaseAddress, XIIC_CR_REG_OFFSET, CntlReg);
415
 
416
 
417
        /*
418
         * Set FIFO occupancy depth = 1 so that the first byte will throttle
419
         * next recieve msg.
420
         */
421
        XIic_WriteReg(InstancePtr->BaseAddress, XIIC_RFD_REG_OFFSET, 0);
422
 
423
        /*
424
         * Call the event callback.
425
         */
426
        InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
427
                                   XII_SLAVE_NO_ACK_EVENT);
428
}
429
 
430
/*****************************************************************************/
431
/**
432
*
433
* This function is a stub function that is used for the default function for
434
* events that are handled optionally only when the appropriate modules are
435
* linked in.  Function pointers are used to handle some events to allow
436
* some events to be optionally handled.
437
*
438
* @param        InstancePtr is a pointer to the XIic instance to be worked on.
439
*
440
******************************************************************************/
441
static void StubFunction(XIic *InstancePtr)
442
{
443
        (void )InstancePtr;
444
        Xil_AssertVoidAlways();
445
}
446
/** @} */

powered by: WebSVN 2.1.0

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