1 /******************************************************************************
3 * Copyright (C) 2010 - 2016 Xilinx, Inc. All rights reserved.
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:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
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.
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
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.
31 ******************************************************************************/
32 /*****************************************************************************/
34 * @file xiicps_slave.c
35 * @addtogroup iicps_v3_5
38 * Handles slave transfers
40 * <pre> MODIFICATION HISTORY:
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 * 3.00 sk 01/31/15 Modified the code according to MISRAC 2012 Compliant.
47 * 3.3 kvn 05/05/16 Modified latest code for MISRA-C:2012 Compliance.
51 ******************************************************************************/
53 /***************************** Include Files *********************************/
56 /************************** Constant Definitions *****************************/
58 /**************************** Type Definitions *******************************/
60 /***************** Macros (Inline Functions) Definitions *********************/
62 /************************** Function Prototypes ******************************/
63 extern s32 TransmitFifoFill(XIicPs *InstancePtr);
65 static s32 SlaveRecvData(XIicPs *InstancePtr);
67 /************************* Variable Definitions *****************************/
69 /*****************************************************************************/
71 * This function sets up the device to be a slave.
73 * @param InstancePtr is a pointer to the XIicPs instance.
74 * @param SlaveAddr is the address of the slave we are receiving from.
79 * Interrupt is always enabled no matter the tranfer is interrupt-
80 * driven or polled mode. Whether device will be interrupted or not
81 * depends on whether the device is connected to an interrupt
82 * controller and interrupt for the device is enabled.
84 ****************************************************************************/
85 void XIicPs_SetupSlave(XIicPs *InstancePtr, u16 SlaveAddr)
90 Xil_AssertVoid(InstancePtr != NULL);
91 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
92 Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);
94 BaseAddr = InstancePtr->Config.BaseAddress;
96 ControlReg = XIicPs_In32(BaseAddr + XIICPS_CR_OFFSET);
99 * Set up master, AckEn, nea and also clear fifo.
101 ControlReg |= (u32)XIICPS_CR_ACKEN_MASK | (u32)XIICPS_CR_CLR_FIFO_MASK;
102 ControlReg |= (u32)XIICPS_CR_NEA_MASK;
103 ControlReg &= (u32)(~XIICPS_CR_MS_MASK);
105 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
108 XIicPs_DisableAllInterrupts(BaseAddr);
110 XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
111 XIICPS_ADDR_OFFSET, (u32)SlaveAddr);
116 /*****************************************************************************/
118 * This function setup a slave interrupt-driven send. It set the repeated
119 * start for the device is the tranfer size is larger than FIFO depth.
120 * Data processing for the send is initiated by the interrupt handler.
122 * @param InstancePtr is a pointer to the XIicPs instance.
123 * @param MsgPtr is the pointer to the send buffer.
124 * @param ByteCount is the number of bytes to be sent.
128 * @note This send routine is for interrupt-driven transfer only.
130 ****************************************************************************/
131 void XIicPs_SlaveSend(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
136 * Assert validates the input arguments
138 Xil_AssertVoid(InstancePtr != NULL);
139 Xil_AssertVoid(MsgPtr != NULL);
140 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
143 BaseAddr = InstancePtr->Config.BaseAddress;
144 InstancePtr->SendBufferPtr = MsgPtr;
145 InstancePtr->SendByteCount = ByteCount;
146 InstancePtr->RecvBufferPtr = NULL;
148 XIicPs_EnableInterrupts(BaseAddr,
149 (u32)XIICPS_IXR_DATA_MASK | (u32)XIICPS_IXR_COMP_MASK |
150 (u32)XIICPS_IXR_TO_MASK | (u32)XIICPS_IXR_NACK_MASK |
151 (u32)XIICPS_IXR_TX_OVR_MASK);
154 /*****************************************************************************/
156 * This function setup a slave interrupt-driven receive.
157 * Data processing for the receive is handled by the interrupt handler.
159 * @param InstancePtr is a pointer to the XIicPs instance.
160 * @param MsgPtr is the pointer to the receive buffer.
161 * @param ByteCount is the number of bytes to be received.
165 * @note This routine is for interrupt-driven transfer only.
167 ****************************************************************************/
168 void XIicPs_SlaveRecv(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
171 * Assert validates the input arguments.
173 Xil_AssertVoid(InstancePtr != NULL);
174 Xil_AssertVoid(MsgPtr != NULL);
175 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
178 InstancePtr->RecvBufferPtr = MsgPtr;
179 InstancePtr->RecvByteCount = ByteCount;
180 InstancePtr->SendBufferPtr = NULL;
182 XIicPs_EnableInterrupts(InstancePtr->Config.BaseAddress,
183 (u32)XIICPS_IXR_DATA_MASK | (u32)XIICPS_IXR_COMP_MASK |
184 (u32)XIICPS_IXR_NACK_MASK | (u32)XIICPS_IXR_TO_MASK |
185 (u32)XIICPS_IXR_RX_OVR_MASK | (u32)XIICPS_IXR_RX_UNF_MASK);
189 /*****************************************************************************/
191 * This function sends a buffer in polled mode as a slave.
193 * @param InstancePtr is a pointer to the XIicPs instance.
194 * @param MsgPtr is the pointer to the send buffer.
195 * @param ByteCount is the number of bytes to be sent.
198 * - XST_SUCCESS if everything went well.
199 * - XST_FAILURE if master sends us data or master terminates the
200 * transfer before all data has sent out.
202 * @note This send routine is for polled mode transfer only.
204 ****************************************************************************/
205 s32 XIicPs_SlaveSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
213 s32 Status = (s32)XST_SUCCESS;
218 * Assert validates the input arguments.
220 Xil_AssertNonvoid(InstancePtr != NULL);
221 Xil_AssertNonvoid(MsgPtr != NULL);
222 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
224 BaseAddr = InstancePtr->Config.BaseAddress;
225 InstancePtr->SendBufferPtr = MsgPtr;
226 InstancePtr->SendByteCount = ByteCount;
229 * Use RXRW bit in status register to wait master to start a read.
231 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
232 Result = (((u32)(StatusReg & XIICPS_SR_RXRW_MASK) == (u32)0x0U) &&
234 while (Result != FALSE) {
237 * If master tries to send us data, it is an error.
239 if ((StatusReg & XIICPS_SR_RXDV_MASK) != 0x0U) {
243 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
244 Result = (((u32)(StatusReg & XIICPS_SR_RXRW_MASK) == (u32)0x0U) &&
249 Status = (s32)XST_FAILURE;
253 * Clear the interrupt status register.
255 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
256 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
259 * Send data as long as there is more data to send and
260 * there are no errors.
262 Value = (InstancePtr->SendByteCount > (s32)0) &&
264 while (Value != FALSE) {
267 * Find out how many can be sent.
269 BytesToSend = InstancePtr->SendByteCount;
270 if (BytesToSend > (s32)(XIICPS_FIFO_DEPTH)) {
271 BytesToSend = (s32)(XIICPS_FIFO_DEPTH);
274 for(Tmp = 0; Tmp < BytesToSend; Tmp ++) {
275 XIicPs_SendByte(InstancePtr);
278 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
281 * Wait for master to read the data out of fifo.
283 while (((StatusReg & XIICPS_SR_TXDV_MASK) != (u32)0x00U) &&
287 * If master terminates the transfer before all data is
288 * sent, it is an error.
290 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
292 if ((IntrStatusReg & XIICPS_IXR_NACK_MASK) != 0x0U) {
298 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
301 StatusReg = XIicPs_ReadReg(BaseAddr,
304 Value = ((InstancePtr->SendByteCount > (s32)0) &&
309 Status = (s32)XST_FAILURE;
314 /*****************************************************************************/
316 * This function receives a buffer in polled mode as a slave.
318 * @param InstancePtr is a pointer to the XIicPs instance.
319 * @param MsgPtr is the pointer to the receive buffer.
320 * @param ByteCount is the number of bytes to be received.
323 * - XST_SUCCESS if everything went well.
324 * - XST_FAILURE if timed out.
326 * @note This receive routine is for polled mode transfer only.
328 ****************************************************************************/
329 s32 XIicPs_SlaveRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
337 * Assert validates the input arguments.
339 Xil_AssertNonvoid(InstancePtr != NULL);
340 Xil_AssertNonvoid(MsgPtr != NULL);
341 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
343 BaseAddr = InstancePtr->Config.BaseAddress;
344 InstancePtr->RecvBufferPtr = MsgPtr;
345 InstancePtr->RecvByteCount = ByteCount;
347 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
350 * Clear the interrupt status register.
352 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
353 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
356 * Clear the status register.
358 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
359 XIicPs_WriteReg(BaseAddr, XIICPS_SR_OFFSET, StatusReg);
361 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
362 Count = InstancePtr->RecvByteCount;
363 while (Count > (s32)0) {
365 /* Wait for master to put data */
366 while ((StatusReg & XIICPS_SR_RXDV_MASK) == 0U) {
367 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
370 * If master terminates the transfer before we get all
371 * the data or the master tries to read from us,
374 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
376 if (((IntrStatusReg & (XIICPS_IXR_DATA_MASK |
377 XIICPS_IXR_COMP_MASK))!=0x0U) &&
378 ((StatusReg & XIICPS_SR_RXDV_MASK) == 0U) &&
379 ((InstancePtr->RecvByteCount > 0) != 0x0U)) {
381 return (s32)XST_FAILURE;
385 * Clear the interrupt status register.
387 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
392 * Read all data from FIFO.
394 while (((StatusReg & XIICPS_SR_RXDV_MASK)!=0x0U) &&
395 ((InstancePtr->RecvByteCount > 0) != 0x0U)){
397 XIicPs_RecvByte(InstancePtr);
399 StatusReg = XIicPs_ReadReg(BaseAddr,
402 Count = InstancePtr->RecvByteCount;
405 return (s32)XST_SUCCESS;
408 /*****************************************************************************/
410 * The interrupt handler for slave mode. It does the protocol handling for
411 * the interrupt-driven transfers.
413 * Completion events and errors are signaled to upper layer for proper
418 * The interrupts that are handled are:
420 * If the instance is sending, it means that the master wants to read more
421 * data from us. Send more data, and check whether we are done with this
424 * If the instance is receiving, it means that the master has writen
425 * more data to us. Receive more data, and check whether we are done with
429 * This marks that stop sequence has been sent from the master, transfer
430 * is about to terminate. However, for receiving, the master may have
431 * written us some data, so receive that first.
433 * It is an error if the amount of transfered data is less than expected.
436 * This marks that master does not want our data. It is for send only.
439 * These interrupts are marked as error.
443 * @param InstancePtr is a pointer to the XIicPs instance.
449 ****************************************************************************/
450 void XIicPs_SlaveInterruptHandler(XIicPs *InstancePtr)
454 u32 StatusEvent = 0U;
459 * Assert validates the input arguments.
461 Xil_AssertVoid(InstancePtr != NULL);
462 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
464 BaseAddr = InstancePtr->Config.BaseAddress;
467 * Read the Interrupt status register.
469 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
472 * Write the status back to clear the interrupts so no events are missed
473 * while processing this interrupt.
475 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
478 * Use the Mask register AND with the Interrupt Status register so
479 * disabled interrupts are not processed.
481 IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET));
484 * Determine whether the device is sending.
486 if (InstancePtr->RecvBufferPtr == NULL) {
492 * This means master wants to do more data transfers.
493 * Also check for completion of transfer, signal upper layer if done.
495 if ((u32)0U != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) {
496 if (IsSend != 0x0U) {
497 LeftOver = TransmitFifoFill(InstancePtr);
499 * We may finish send here
503 XIICPS_EVENT_COMPLETE_SEND;
506 LeftOver = SlaveRecvData(InstancePtr);
508 /* We may finish the receive here */
510 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
516 * Complete interrupt.
518 * In slave mode, it means the master has done with this transfer, so
519 * we signal the application using completion event.
521 if (0U != (IntrStatusReg & XIICPS_IXR_COMP_MASK)) {
522 if (IsSend != 0x0U) {
523 if (InstancePtr->SendByteCount > 0) {
524 StatusEvent |= XIICPS_EVENT_ERROR;
526 StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
529 LeftOver = SlaveRecvData(InstancePtr);
531 StatusEvent |= XIICPS_EVENT_ERROR;
533 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
539 * Nack interrupt, pass this information to application.
541 if (0U != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
542 StatusEvent |= XIICPS_EVENT_NACK;
546 * All other interrupts are treated as error.
548 if (0U != (IntrStatusReg & (XIICPS_IXR_TO_MASK |
549 XIICPS_IXR_RX_UNF_MASK |
550 XIICPS_IXR_TX_OVR_MASK |
551 XIICPS_IXR_RX_OVR_MASK))){
553 StatusEvent |= XIICPS_EVENT_ERROR;
557 * Signal application if there are any events.
559 if ((u32)0U != StatusEvent) {
560 InstancePtr->StatusHandler(InstancePtr->CallBackRef,
565 /*****************************************************************************/
568 * This function handles continuation of receiving data. It is invoked
569 * from interrupt handler.
571 * @param InstancePtr is a pointer to the XIicPs instance.
573 * @return Number of bytes still expected by the instance.
577 ****************************************************************************/
578 static s32 SlaveRecvData(XIicPs *InstancePtr)
583 BaseAddr = InstancePtr->Config.BaseAddress;
585 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
587 while (((StatusReg & XIICPS_SR_RXDV_MASK)!=0x0U) &&
588 ((InstancePtr->RecvByteCount > 0) != 0x0U)) {
589 XIicPs_RecvByte(InstancePtr);
590 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
593 return InstancePtr->RecvByteCount;