]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/iicps_v2_1/src/xiicps_slave.c
Remove obsolete MPU demos.
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / iicps_v2_1 / src / xiicps_slave.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2014 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 * @file xiicps_slave.c
35 * @addtogroup iicps_v2_1
36 * @{
37 *
38 * Handles slave transfers
39 *
40 * <pre> MODIFICATION HISTORY:
41 *
42 * Ver   Who Date     Changes
43 * ----- --  -------- ---------------------------------------------
44 * 1.00a jz  01/30/10 First release
45 * 1.04a kpc 08/30/13 Avoid buffer overwrite in SlaveRecvData function
46 *
47 * </pre>
48 *
49 ******************************************************************************/
50
51 /***************************** Include Files *********************************/
52 #include "xiicps.h"
53
54 /************************** Constant Definitions *****************************/
55
56 /**************************** Type Definitions *******************************/
57
58 /***************** Macros (Inline Functions) Definitions *********************/
59
60 /************************** Function Prototypes ******************************/
61 extern int TransmitFifoFill(XIicPs *InstancePtr);
62
63 static int SlaveRecvData(XIicPs *InstancePtr);
64
65 /************************* Variable Definitions *****************************/
66
67 /*****************************************************************************/
68 /**
69 * This function sets up the device to be a slave.
70 *
71 * @param        InstancePtr is a pointer to the XIicPs instance.
72 * @param        SlaveAddr is the address of the slave we are receiving from.
73 *
74 * @return       None.
75 *
76 * @note
77 *       Interrupt is always enabled no matter the tranfer is interrupt-
78 *       driven or polled mode. Whether device will be interrupted or not
79 *       depends on whether the device is connected to an interrupt
80 *       controller and interrupt for the device is enabled.
81 *
82 ****************************************************************************/
83 void XIicPs_SetupSlave(XIicPs *InstancePtr, u16 SlaveAddr)
84 {
85         volatile u32 ControlReg;
86         u32 BaseAddr;
87
88         Xil_AssertVoid(InstancePtr != NULL);
89         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
90         Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);
91
92         BaseAddr = InstancePtr->Config.BaseAddress;
93
94         ControlReg = XIicPs_In32(BaseAddr + XIICPS_CR_OFFSET);
95
96         /*
97          * Set up master, AckEn, nea and also clear fifo.
98          */
99         ControlReg |= XIICPS_CR_ACKEN_MASK | XIICPS_CR_CLR_FIFO_MASK;
100         ControlReg |= XIICPS_CR_NEA_MASK;
101         ControlReg &= ~XIICPS_CR_MS_MASK;
102
103         XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
104                           ControlReg);
105
106         XIicPs_DisableAllInterrupts(BaseAddr);
107
108         XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
109                           XIICPS_ADDR_OFFSET, SlaveAddr);
110
111         return;
112 }
113
114 /*****************************************************************************/
115 /**
116 * This function setup a slave interrupt-driven send. It set the repeated
117 * start for the device is the tranfer size is larger than FIFO depth.
118 * Data processing for the send is initiated by the interrupt handler.
119 *
120 * @param        InstancePtr is a pointer to the XIicPs instance.
121 * @param        MsgPtr is the pointer to the send buffer.
122 * @param        ByteCount is the number of bytes to be sent.
123 *
124 * @return       None.
125 *
126 * @note         This send routine is for interrupt-driven transfer only.
127 *
128 ****************************************************************************/
129 void XIicPs_SlaveSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount)
130 {
131         u32 BaseAddr;
132
133         /*
134          * Assert validates the input arguments
135          */
136         Xil_AssertVoid(InstancePtr != NULL);
137         Xil_AssertVoid(MsgPtr != NULL);
138         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
139
140
141         BaseAddr = InstancePtr->Config.BaseAddress;
142         InstancePtr->SendBufferPtr = MsgPtr;
143         InstancePtr->SendByteCount = ByteCount;
144         InstancePtr->RecvBufferPtr = NULL;
145
146         XIicPs_EnableInterrupts(BaseAddr,
147                         XIICPS_IXR_DATA_MASK | XIICPS_IXR_COMP_MASK |
148                         XIICPS_IXR_TO_MASK | XIICPS_IXR_NACK_MASK |
149                         XIICPS_IXR_TX_OVR_MASK);
150 }
151
152 /*****************************************************************************/
153 /**
154 * This function setup a slave interrupt-driven receive.
155 * Data processing for the receive is handled by the interrupt handler.
156 *
157 * @param        InstancePtr is a pointer to the XIicPs instance.
158 * @param        MsgPtr is the pointer to the receive buffer.
159 * @param        ByteCount is the number of bytes to be received.
160 *
161 * @return       None.
162 *
163 * @note         This routine is for interrupt-driven transfer only.
164 *
165 ****************************************************************************/
166 void XIicPs_SlaveRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount)
167 {
168         /*
169          * Assert validates the input arguments.
170          */
171         Xil_AssertVoid(InstancePtr != NULL);
172         Xil_AssertVoid(MsgPtr != NULL);
173         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
174
175
176         InstancePtr->RecvBufferPtr = MsgPtr;
177         InstancePtr->RecvByteCount = ByteCount;
178         InstancePtr->SendBufferPtr = NULL;
179
180         XIicPs_EnableInterrupts(InstancePtr->Config.BaseAddress,
181                         XIICPS_IXR_DATA_MASK | XIICPS_IXR_COMP_MASK |
182                         XIICPS_IXR_NACK_MASK | XIICPS_IXR_TO_MASK |
183                         XIICPS_IXR_RX_OVR_MASK | XIICPS_IXR_RX_UNF_MASK);
184
185 }
186
187 /*****************************************************************************/
188 /**
189 * This function sends  a buffer in polled mode as a slave.
190 *
191 * @param        InstancePtr is a pointer to the XIicPs instance.
192 * @param        MsgPtr is the pointer to the send buffer.
193 * @param        ByteCount is the number of bytes to be sent.
194 *
195 * @return
196 *               - XST_SUCCESS if everything went well.
197 *               - XST_FAILURE if master sends us data or master terminates the
198 *               transfer before all data has sent out.
199 *
200 * @note         This send routine is for polled mode transfer only.
201 *
202 ****************************************************************************/
203 int XIicPs_SlaveSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount)
204 {
205         volatile u32 IntrStatusReg;
206         volatile u32 StatusReg;
207         u32 BaseAddr;
208         int Tmp;
209         int BytesToSend;
210         int Error = 0;
211
212         /*
213          * Assert validates the input arguments.
214          */
215         Xil_AssertNonvoid(InstancePtr != NULL);
216         Xil_AssertNonvoid(MsgPtr != NULL);
217         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
218
219         BaseAddr = InstancePtr->Config.BaseAddress;
220         InstancePtr->SendBufferPtr = MsgPtr;
221         InstancePtr->SendByteCount = ByteCount;
222
223         /*
224          * Use RXRW bit in status register to wait master to start a read.
225          */
226         StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
227         while (((StatusReg & XIICPS_SR_RXRW_MASK) == 0) && (!Error)) {
228
229                 /*
230                  * If master tries to send us data, it is an error.
231                  */
232                 if (StatusReg & XIICPS_SR_RXDV_MASK) {
233                         Error = 1;
234                 }
235
236                 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
237         }
238
239         if (Error) {
240                 return XST_FAILURE;
241         }
242
243         /*
244          * Clear the interrupt status register.
245          */
246         IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
247         XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
248
249         /*
250          * Send data as long as there is more data to send and
251          * there are no errors.
252          */
253         while ((InstancePtr->SendByteCount > 0) && (!Error)){
254
255                 /*
256                  * Find out how many can be sent.
257                  */
258                 BytesToSend = InstancePtr->SendByteCount;
259                 if (BytesToSend > XIICPS_FIFO_DEPTH) {
260                         BytesToSend = XIICPS_FIFO_DEPTH;
261                 }
262
263                 for(Tmp = 0; Tmp < BytesToSend; Tmp ++) {
264                         XIicPs_SendByte(InstancePtr);
265                 }
266
267                 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
268
269                 /*
270                  * Wait for master to read the data out of fifo.
271                  */
272                 while (((StatusReg & XIICPS_SR_TXDV_MASK) != 0) && (!Error)) {
273
274                         /*
275                          * If master terminates the transfer before all data is
276                          * sent, it is an error.
277                          */
278                         IntrStatusReg = XIicPs_ReadReg(BaseAddr,
279                         XIICPS_ISR_OFFSET);
280                         if (IntrStatusReg & XIICPS_IXR_NACK_MASK) {
281                                 Error = 1;
282                         }
283
284                         /* Clear ISR.
285                          */
286                         XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
287                                                 IntrStatusReg);
288
289                         StatusReg = XIicPs_ReadReg(BaseAddr,
290                                         XIICPS_SR_OFFSET);
291                 }
292         }
293
294         if (Error) {
295                 return XST_FAILURE;
296         }
297
298         return XST_SUCCESS;
299 }
300 /*****************************************************************************/
301 /**
302 * This function receives a buffer in polled mode as a slave.
303 *
304 * @param        InstancePtr is a pointer to the XIicPs instance.
305 * @param        MsgPtr is the pointer to the receive buffer.
306 * @param        ByteCount is the number of bytes to be received.
307 *
308 * @return
309 *               - XST_SUCCESS if everything went well.
310 *               - XST_FAILURE if timed out.
311 *
312 * @note         This receive routine is for polled mode transfer only.
313 *
314 ****************************************************************************/
315 int XIicPs_SlaveRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount)
316 {
317         volatile u32 IntrStatusReg;
318         volatile u32 StatusReg;
319         u32 BaseAddr;
320
321         /*
322          * Assert validates the input arguments.
323          */
324         Xil_AssertNonvoid(InstancePtr != NULL);
325         Xil_AssertNonvoid(MsgPtr != NULL);
326         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
327
328         BaseAddr = InstancePtr->Config.BaseAddress;
329         InstancePtr->RecvBufferPtr = MsgPtr;
330         InstancePtr->RecvByteCount = ByteCount;
331
332         StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
333
334         /*
335          * Clear the interrupt status register.
336          */
337         IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
338         XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
339
340         /*
341          * Clear the status register.
342          */
343         StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
344         XIicPs_WriteReg(BaseAddr, XIICPS_SR_OFFSET, StatusReg);
345
346         StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
347         while (InstancePtr->RecvByteCount > 0) {
348
349                 /* Wait for master to put data */
350                 while ((StatusReg & XIICPS_SR_RXDV_MASK) == 0) {
351                     StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
352
353                         /*
354                          * If master terminates the transfer before we get all
355                          * the data or the master tries to read from us,
356                          * it is an error.
357                          */
358                         IntrStatusReg = XIicPs_ReadReg(BaseAddr,
359                                                 XIICPS_ISR_OFFSET);
360                         if ((IntrStatusReg & (XIICPS_IXR_DATA_MASK |
361                                         XIICPS_IXR_COMP_MASK)) &&
362                                 ((StatusReg & XIICPS_SR_RXDV_MASK) == 0) &&
363                                 (InstancePtr->RecvByteCount > 0)) {
364
365                                 return XST_FAILURE;
366                         }
367
368                         /*
369                          * Clear the interrupt status register.
370                          */
371                         XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
372                         IntrStatusReg);
373                 }
374
375                 /*
376                  * Read all data from FIFO.
377                  */
378                 while ((StatusReg & XIICPS_SR_RXDV_MASK) &&
379                          (InstancePtr->RecvByteCount > 0)){
380
381                         XIicPs_RecvByte(InstancePtr);
382
383                         StatusReg = XIicPs_ReadReg(BaseAddr,
384                                 XIICPS_SR_OFFSET);
385                 }
386         }
387
388         return XST_SUCCESS;
389 }
390
391 /*****************************************************************************/
392 /**
393 * The interrupt handler for slave mode. It does the protocol handling for
394 * the interrupt-driven transfers.
395 *
396 * Completion events and errors are signaled to upper layer for proper
397 * handling.
398 *
399 * <pre>
400 *
401 * The interrupts that are handled are:
402 * - DATA
403 *       If the instance is sending, it means that the master wants to read more
404 *       data from us. Send more data, and check whether we are done with this
405 *       send.
406 *
407 *       If the instance is receiving, it means that the master has writen
408 *       more data to us. Receive more data, and check whether we are done with
409 *       with this receive.
410 *
411 * - COMP
412 *       This marks that stop sequence has been sent from the master, transfer
413 *       is about to terminate. However, for receiving, the master may have
414 *       written us some data, so receive that first.
415 *
416 *       It is an error if the amount of transfered data is less than expected.
417 *
418 * - NAK
419 *       This marks that master does not want our data. It is for send only.
420 *
421 * - Other interrupts
422 *       These interrupts are marked as error.
423 *
424 * </pre>
425 *
426 * @param        InstancePtr is a pointer to the XIicPs instance.
427 *
428 * @return       None.
429 *
430 * @note         None.
431 *
432 ****************************************************************************/
433 void XIicPs_SlaveInterruptHandler(XIicPs *InstancePtr)
434 {
435         volatile u32 IntrStatusReg;
436         u32 IsSend = 0;
437         u32 StatusEvent = 0;
438         int LeftOver;
439         u32 BaseAddr;
440
441         /*
442          * Assert validates the input arguments.
443          */
444         Xil_AssertVoid(InstancePtr != NULL);
445         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
446
447         BaseAddr = InstancePtr->Config.BaseAddress;
448
449         /*
450          * Read the Interrupt status register.
451          */
452         IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
453
454         /*
455          * Write the status back to clear the interrupts so no events are missed
456          * while processing this interrupt.
457          */
458         XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
459
460         /*
461          * Use the Mask register AND with the Interrupt Status register so
462          * disabled interrupts are not processed.
463          */
464         IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET));
465
466         /*
467          * Determine whether the device is sending.
468          */
469         if (InstancePtr->RecvBufferPtr == NULL) {
470                 IsSend = 1;
471         }
472
473         /* Data interrupt
474          *
475          * This means master wants to do more data transfers.
476          * Also check for completion of transfer, signal upper layer if done.
477          */
478         if (0 != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) {
479                 if (IsSend) {
480                         LeftOver = TransmitFifoFill(InstancePtr);
481                                 /*
482                                  * We may finish send here
483                                  */
484                                 if (LeftOver == 0) {
485                                         StatusEvent |=
486                                                 XIICPS_EVENT_COMPLETE_SEND;
487                                 }
488                 } else {
489                         LeftOver = SlaveRecvData(InstancePtr);
490
491                         /* We may finish the receive here */
492                         if (LeftOver == 0) {
493                                 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
494                         }
495                 }
496         }
497
498         /*
499          * Complete interrupt.
500          *
501          * In slave mode, it means the master has done with this transfer, so
502          * we signal the application using completion event.
503          */
504         if (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK)) {
505                 if (IsSend) {
506                         if (InstancePtr->SendByteCount > 0) {
507                                 StatusEvent |= XIICPS_EVENT_ERROR;
508                         }else {
509                                 StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
510                         }
511                 } else {
512                         LeftOver = SlaveRecvData(InstancePtr);
513                         if (LeftOver > 0) {
514                                 StatusEvent |= XIICPS_EVENT_ERROR;
515                         } else {
516                                 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
517                         }
518                 }
519         }
520
521         /*
522          * Nack interrupt, pass this information to application.
523          */
524         if (0 != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
525                 StatusEvent |= XIICPS_EVENT_NACK;
526         }
527
528         /*
529          * All other interrupts are treated as error.
530          */
531         if (0 != (IntrStatusReg & (XIICPS_IXR_TO_MASK |
532                                 XIICPS_IXR_RX_UNF_MASK |
533                                 XIICPS_IXR_TX_OVR_MASK |
534                                 XIICPS_IXR_RX_OVR_MASK))){
535
536                 StatusEvent |= XIICPS_EVENT_ERROR;
537         }
538
539         /*
540          * Signal application if there are any events.
541          */
542         if (0 != StatusEvent) {
543                 InstancePtr->StatusHandler(InstancePtr->CallBackRef,
544                                            StatusEvent);
545         }
546 }
547
548 /*****************************************************************************/
549 /*
550 *
551 * This function handles continuation of receiving data. It is invoked
552 * from interrupt handler.
553 *
554 * @param        InstancePtr is a pointer to the XIicPs instance.
555 *
556 * @return       Number of bytes still expected by the instance.
557 *
558 * @note         None.
559 *
560 ****************************************************************************/
561 static int SlaveRecvData(XIicPs *InstancePtr)
562 {
563         volatile u32 StatusReg;
564         u32 BaseAddr;
565
566         BaseAddr = InstancePtr->Config.BaseAddress;
567
568         StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
569
570         while ((StatusReg & XIICPS_SR_RXDV_MASK) &&
571                         (InstancePtr->RecvByteCount > 0)) {
572                 XIicPs_RecvByte(InstancePtr);
573                 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
574         }
575
576         return InstancePtr->RecvByteCount;
577 }
578
579 /** @} */