libpynq (release 5EWC0-2023 version 0.2.1 of 2023-09-01 11:02)
Loading...
Searching...
No Matches
xiic_l.c
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 ******************************************************************************/
5
6/*****************************************************************************/
70/***************************** Include Files *******************************/
71#define _DEFAULT_SOURCE
72#include <unistd.h>
73
74#include "xiic_l.h"
75#include "xil_types.h"
76
77/************************** Constant Definitions ***************************/
78
79/**************************** Type Definitions *****************************/
80
81/***************** Macros (Inline Functions) Definitions *******************/
82
83/************************** Function Prototypes ****************************/
84
85static unsigned RecvData(UINTPTR BaseAddress, u8 *BufferPtr, unsigned ByteCount,
86 u8 Option);
87static unsigned SendData(UINTPTR BaseAddress, u8 *BufferPtr, unsigned ByteCount,
88 u8 Option);
89
90/************************** Variable Definitions **************************/
91
92/****************************************************************************/
113unsigned XIic_Recv(UINTPTR BaseAddress, u8 Address, u8 *BufferPtr,
114 unsigned ByteCount, u8 Option) {
115 u32 CntlReg;
116 unsigned RemainingByteCount;
117 volatile u32 StatusReg;
118
119 /* Tx error is enabled in case the address (7 or 10) has no device to
120 * answer with Ack. When only one byte of data, must set NO ACK before
121 * address goes out therefore Tx error must not be enabled as it will go
122 * off immediately and the Rx full interrupt will be checked. If full,
123 * then the one byte was received and the Tx error will be disabled
124 * without sending an error callback msg
125 */
128
129 /* Set receive FIFO occupancy depth for 1 byte (zero based) */
130 XIic_WriteReg(BaseAddress, XIIC_RFD_REG_OFFSET, 0);
131
132 /* Check to see if already Master on the Bus.
133 * If Repeated Start bit is not set send Start bit by setting MSMS bit
134 * else Send the address
135 */
136 CntlReg = XIic_ReadReg(BaseAddress, XIIC_CR_REG_OFFSET);
137 if ((CntlReg & XIIC_CR_REPEATED_START_MASK) == 0) {
138 /* 7 bit slave address, send the address for a read operation
139 * and set the state to indicate the address has been sent
140 */
141 XIic_Send7BitAddress(BaseAddress, Address, XIIC_READ_OPERATION);
142
143 /* MSMS gets set after putting data in FIFO. Start the master
144 * receive operation by setting CR Bits MSMS to Master, if the
145 * buffer is only one byte, then it should not be acknowledged
146 * to indicate the end of data
147 */
149 if (ByteCount == 1) {
150 CntlReg |= XIIC_CR_NO_ACK_MASK;
151 }
152
153 /* Write out the control register to start receiving data and
154 * call the function to receive each byte into the buffer
155 */
156 XIic_WriteReg(BaseAddress, XIIC_CR_REG_OFFSET, CntlReg);
157
158 /* Clear the latched interrupt status for the bus not busy bit
159 * which must be done while the bus is busy
160 */
161 StatusReg = XIic_ReadReg(BaseAddress, XIIC_SR_REG_OFFSET);
162
163 while ((StatusReg & XIIC_SR_BUS_BUSY_MASK) == 0) {
164 StatusReg = XIic_ReadReg(BaseAddress, XIIC_SR_REG_OFFSET);
165 }
166
168 } else {
169 /* Before writing 7bit slave address the Direction of Tx bit
170 * must be disabled
171 */
172 CntlReg &= ~XIIC_CR_DIR_IS_TX_MASK;
173 if (ByteCount == 1) {
174 CntlReg |= XIIC_CR_NO_ACK_MASK;
175 }
176 XIic_WriteReg(BaseAddress, XIIC_CR_REG_OFFSET, CntlReg);
177 /* Already owns the Bus indicating that its a Repeated Start
178 * call. 7 bit slave address, send the address for a read
179 * operation and set the state to indicate the address has been
180 * sent
181 */
182 XIic_Send7BitAddress(BaseAddress, Address, XIIC_READ_OPERATION);
183 }
184 /* Try to receive the data from the IIC bus */
185
186 RemainingByteCount = RecvData(BaseAddress, BufferPtr, ByteCount, Option);
187
188 CntlReg = XIic_ReadReg(BaseAddress, XIIC_CR_REG_OFFSET);
189 if ((CntlReg & XIIC_CR_REPEATED_START_MASK) == 0) {
190 /* The receive is complete, disable the IIC device if the Option
191 * is to release the Bus after Reception of data and return the
192 * number of bytes that was received
193 */
194 XIic_WriteReg(BaseAddress, XIIC_CR_REG_OFFSET, 0);
195 }
196
197 /* Wait until I2C bus is freed, exit if timed out. */
198 if (XIic_WaitBusFree(BaseAddress) != XST_SUCCESS) {
199 return 0;
200 }
201
202 /* Return the number of bytes that was received */
203 return ByteCount - RemainingByteCount;
204}
205
206/******************************************************************************
207 *
208 * Receive the specified data from the device that has been previously addressed
209 * on the IIC bus. This function assumes that the 7 bit address has been sent
210 * and it should wait for the transmit of the address to complete.
211 *
212 * @param BaseAddress contains the base address of the IIC device.
213 * @param BufferPtr points to the buffer to hold the data that is
214 * received.
215 * @param ByteCount is the number of bytes to be received.
216 * @param Option indicates whether to hold or free the bus after reception
217 * of data, XIIC_STOP = end with STOP condition,
218 * XIIC_REPEATED_START = don't end with STOP condition.
219 *
220 * @return The number of bytes remaining to be received.
221 *
222 * @note
223 *
224 * This function does not take advantage of the receive FIFO because it is
225 * designed for minimal code space and complexity. It contains loops that
226 * that could cause the function not to return if the hardware is not working.
227 *
228 * This function assumes that the calling function will disable the IIC device
229 * after this function returns.
230 *
231 ******************************************************************************/
232static unsigned RecvData(UINTPTR BaseAddress, u8 *BufferPtr, unsigned ByteCount,
233 u8 Option) {
234 u32 CntlReg;
235 u32 IntrStatusMask;
236 u32 IntrStatus;
237
238 /* Attempt to receive the specified number of bytes on the IIC bus */
239
240 while (ByteCount > 0) {
241 /* Setup the mask to use for checking errors because when
242 * receiving one byte OR the last byte of a multibyte message an
243 * error naturally occurs when the no ack is done to tell the
244 * slave the last byte
245 */
246 if (ByteCount == 1) {
248 } else {
251 }
252
253 /* Wait for the previous transmit and the 1st receive to
254 * complete by checking the interrupt status register of the
255 * IPIF
256 */
257 while (1) {
258 IntrStatus = XIic_ReadIisr(BaseAddress);
259 if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
260 break;
261 }
262 /* Check the transmit error after the receive full
263 * because when sending only one byte transmit error
264 * will occur because of the no ack to indicate the end
265 * of the data
266 */
267 if (IntrStatus & IntrStatusMask) {
268 return ByteCount;
269 }
270 }
271
272 CntlReg = XIic_ReadReg(BaseAddress, XIIC_CR_REG_OFFSET);
273
274 /* Special conditions exist for the last two bytes so check for
275 * them. Note that the control register must be setup for these
276 * conditions before the data byte which was already received is
277 * read from the receive FIFO (while the bus is throttled
278 */
279 if (ByteCount == 1) {
280 if (Option == XIIC_STOP) {
281
282 /* If the Option is to release the bus after the
283 * last data byte, it has already been read and
284 * no ack has been done, so clear MSMS while
285 * leaving the device enabled so it can get off
286 * the IIC bus appropriately with a stop
287 */
290 }
291 }
292
293 /* Before the last byte is received, set NOACK to tell the slave
294 * IIC device that it is the end, this must be done before
295 * reading the byte from the FIFO
296 */
297 if (ByteCount == 2) {
298 /* Write control reg with NO ACK allowing last byte to
299 * have the No ack set to indicate to slave last byte
300 * read
301 */
303 CntlReg | XIIC_CR_NO_ACK_MASK);
304 }
305
306 /* Read in data from the FIFO and unthrottle the bus such that
307 * the next byte is read from the IIC bus
308 */
309 *BufferPtr++ = (u8)XIic_ReadReg(BaseAddress, XIIC_DRR_REG_OFFSET);
310
311 if ((ByteCount == 1) && (Option == XIIC_REPEATED_START)) {
312
313 /* RSTA bit should be set only when the FIFO is
314 * completely Empty.
315 */
319 }
320
321 /* Clear the latched interrupt status so that it will be updated
322 * with the new state when it changes, this must be done after
323 * the receive register is read
324 */
328 ByteCount--;
329 }
330
331 if (Option == XIIC_STOP) {
332
333 /* If the Option is to release the bus after Reception of data,
334 * wait for the bus to transition to not busy before returning,
335 * the IIC device cannot be disabled until this occurs. It
336 * should transition as the MSMS bit of the control register was
337 * cleared before the last byte was read from the FIFO
338 */
339 while (1) {
340 if (XIic_ReadIisr(BaseAddress) & XIIC_INTR_BNB_MASK) {
341 break;
342 }
343 }
344 }
345
346 return ByteCount;
347}
348
349/****************************************************************************/
369unsigned XIic_Send(UINTPTR BaseAddress, u8 Address, u8 *BufferPtr,
370 unsigned ByteCount, u8 Option) {
371 unsigned RemainingByteCount;
372 u32 ControlReg;
373 volatile u32 StatusReg;
374
375 /* Wait until I2C bus is freed, exit if timed out. */
376 if (XIic_WaitBusFree(BaseAddress) != XST_SUCCESS) {
377 return 0;
378 }
379
380 /* Check to see if already Master on the Bus.
381 * If Repeated Start bit is not set send Start bit by setting
382 * MSMS bit else Send the address.
383 */
384 ControlReg = XIic_ReadReg(BaseAddress, XIIC_CR_REG_OFFSET);
385 if ((ControlReg & XIIC_CR_REPEATED_START_MASK) == 0) {
386 /*
387 * Put the address into the FIFO to be sent and indicate
388 * that the operation to be performed on the bus is a
389 * write operation
390 */
391 XIic_Send7BitAddress(BaseAddress, Address, XIIC_WRITE_OPERATION);
392 /* Clear the latched interrupt status so that it will
393 * be updated with the new state when it changes, this
394 * must be done after the address is put in the FIFO
395 */
399
400 /*
401 * MSMS must be set after putting data into transmit FIFO,
402 * indicate the direction is transmit, this device is master
403 * and enable the IIC device
404 */
408
409 /*
410 * Clear the latched interrupt
411 * status for the bus not busy bit which must be done while
412 * the bus is busy
413 */
414 StatusReg = XIic_ReadReg(BaseAddress, XIIC_SR_REG_OFFSET);
415 while ((StatusReg & XIIC_SR_BUS_BUSY_MASK) == 0) {
416 StatusReg = XIic_ReadReg(BaseAddress, XIIC_SR_REG_OFFSET);
417 }
418
420 } else {
421 /*
422 * Already owns the Bus indicating that its a Repeated Start
423 * call. 7 bit slave address, send the address for a write
424 * operation and set the state to indicate the address has
425 * been sent.
426 */
427 XIic_Send7BitAddress(BaseAddress, Address, XIIC_WRITE_OPERATION);
428 }
429
430 /* Send the specified data to the device on the IIC bus specified by the
431 * the address
432 */
433 RemainingByteCount = SendData(BaseAddress, BufferPtr, ByteCount, Option);
434
435 ControlReg = XIic_ReadReg(BaseAddress, XIIC_CR_REG_OFFSET);
436 if ((ControlReg & XIIC_CR_REPEATED_START_MASK) == 0) {
437 /*
438 * The Transmission is completed, disable the IIC device if
439 * the Option is to release the Bus after transmission of data
440 * and return the number of bytes that was received. Only wait
441 * if master, if addressed as slave just reset to release
442 * the bus.
443 */
444 if ((ControlReg & XIIC_CR_MSMS_MASK) != 0) {
446 (ControlReg & ~XIIC_CR_MSMS_MASK));
447 }
448
449 if ((XIic_ReadReg(BaseAddress, XIIC_SR_REG_OFFSET) &
451 XIic_WriteReg(BaseAddress, XIIC_CR_REG_OFFSET, 0);
452 } else {
453 StatusReg = XIic_ReadReg(BaseAddress, XIIC_SR_REG_OFFSET);
454 while ((StatusReg & XIIC_SR_BUS_BUSY_MASK) != 0) {
455 StatusReg = XIic_ReadReg(BaseAddress, XIIC_SR_REG_OFFSET);
456 }
457 }
458 }
459
460 return ByteCount - RemainingByteCount;
461}
462
463/******************************************************************************
464 *
465 * Send the specified buffer to the device that has been previously addressed
466 * on the IIC bus. This function assumes that the 7 bit address has been sent
467 * and it should wait for the transmit of the address to complete.
468 *
469 * @param BaseAddress contains the base address of the IIC device.
470 * @param BufferPtr points to the data to be sent.
471 * @param ByteCount is the number of bytes to be sent.
472 * @param Option indicates whether to hold or free the bus after
473 * transmitting the data.
474 *
475 * @return The number of bytes remaining to be sent.
476 *
477 * @note
478 *
479 * This function does not take advantage of the transmit FIFO because it is
480 * designed for minimal code space and complexity. It contains loops that
481 * that could cause the function not to return if the hardware is not working.
482 *
483 ******************************************************************************/
484static unsigned SendData(UINTPTR BaseAddress, u8 *BufferPtr, unsigned ByteCount,
485 u8 Option) {
486 u32 IntrStatus;
487
488 /*
489 * Send the specified number of bytes in the specified buffer by polling
490 * the device registers and blocking until complete
491 */
492 while (ByteCount > 0) {
493 /*
494 * Wait for the transmit to be empty before sending any more
495 * data by polling the interrupt status register
496 */
497 while (1) {
498 IntrStatus = XIic_ReadIisr(BaseAddress);
499
502 return ByteCount;
503 }
504
505 if (IntrStatus & XIIC_INTR_TX_EMPTY_MASK) {
506 break;
507 }
508 }
509 /* If there is more than one byte to send then put the
510 * next byte to send into the transmit FIFO
511 */
512 if (ByteCount > 1) {
513 XIic_WriteReg(BaseAddress, XIIC_DTR_REG_OFFSET, *BufferPtr++);
514 } else {
515 if (Option == XIIC_STOP) {
516 /*
517 * If the Option is to release the bus after
518 * the last data byte, Set the stop Option
519 * before sending the last byte of data so
520 * that the stop Option will be generated
521 * immediately following the data. This is
522 * done by clearing the MSMS bit in the
523 * control register.
524 */
527 }
528
529 /*
530 * Put the last byte to send in the transmit FIFO
531 */
532 XIic_WriteReg(BaseAddress, XIIC_DTR_REG_OFFSET, *BufferPtr++);
533
534 if (Option == XIIC_REPEATED_START) {
536 /*
537 * Wait for the transmit to be empty before
538 * setting RSTA bit.
539 */
540 while (1) {
541 IntrStatus = XIic_ReadIisr(BaseAddress);
542 if (IntrStatus & XIIC_INTR_TX_EMPTY_MASK) {
543 /*
544 * RSTA bit should be set only
545 * when the FIFO is completely
546 * Empty.
547 */
552 break;
553 }
554 }
555 }
556 }
557
558 /*
559 * Clear the latched interrupt status register and this must be
560 * done after the transmit FIFO has been written to or it won't
561 * clear
562 */
564
565 /*
566 * Update the byte count to reflect the byte sent and clear
567 * the latched interrupt status so it will be updated for the
568 * new state
569 */
570 ByteCount--;
571 }
572
573 if (Option == XIIC_STOP) {
574 /*
575 * If the Option is to release the bus after transmission of
576 * data, Wait for the bus to transition to not busy before
577 * returning, the IIC device cannot be disabled until this
578 * occurs. Note that this is different from a receive operation
579 * because the stop Option causes the bus to go not busy.
580 */
581 while (1) {
582 if (XIic_ReadIisr(BaseAddress) & XIIC_INTR_BNB_MASK) {
583 break;
584 }
585 }
586 }
587
588 return ByteCount;
589}
590
591/*****************************************************************************
592 *
593 * This is a function which tells whether the I2C bus is busy or free.
594 *
595 * @param BaseAddr is the base address of the I2C core to work on.
596 *
597 * @return
598 * - TRUE if the bus is busy.
599 * - FALSE if the bus is NOT busy.
600 *
601 * @note None.
602 *
603 ******************************************************************************/
604u32 XIic_CheckIsBusBusy(UINTPTR BaseAddress) {
605 u32 StatusReg;
606
607 StatusReg = XIic_ReadReg(BaseAddress, XIIC_SR_REG_OFFSET);
608 if (StatusReg & XIIC_SR_BUS_BUSY_MASK) {
609 return TRUE;
610 } else {
611 return FALSE;
612 }
613}
614
615/******************************************************************************/
628u32 XIic_WaitBusFree(UINTPTR BaseAddress) {
629 u32 BusyCount = 0;
630
631 while (XIic_CheckIsBusBusy(BaseAddress)) {
632 if (BusyCount++ > 10000) {
633 return XST_FAILURE;
634 }
635 usleep(100);
636 }
637
638 return XST_SUCCESS;
639}
u32 XIic_CheckIsBusBusy(UINTPTR BaseAddress)
Definition xiic_l.c:11
unsigned XIic_Recv(UINTPTR BaseAddress, u8 Address, u8 *BufferPtr, unsigned ByteCount, u8 Option)
Definition xiic_l.c:2
unsigned XIic_Send(UINTPTR BaseAddress, u8 Address, u8 *BufferPtr, unsigned ByteCount, u8 Option)
Definition xiic_l.c:4
u32 XIic_WaitBusFree(UINTPTR BaseAddress)
Definition xiic_l.c:12
#define XIIC_CR_REG_OFFSET
Definition xiic_l.h:82
#define XIIC_SR_BUS_BUSY_MASK
Definition xiic_l.h:168
#define XIIC_INTR_BNB_MASK
Definition xiic_l.h:120
#define XIIC_CR_REPEATED_START_MASK
Definition xiic_l.h:154
#define XIIC_DTR_REG_OFFSET
Definition xiic_l.h:84
#define XIIC_CR_NO_ACK_MASK
Definition xiic_l.h:153
#define XIic_WriteReg(BaseAddress, RegOffset, RegisterValue)
Definition xiic_l.h:270
#define XIic_Send7BitAddress(BaseAddress, SlaveAddress, Operation)
Definition xiic_l.h:453
#define XIIC_DRR_REG_OFFSET
Definition xiic_l.h:85
#define XIIC_WRITE_OPERATION
Definition xiic_l.h:202
#define XIIC_SR_REG_OFFSET
Definition xiic_l.h:83
#define XIIC_INTR_TX_ERROR_MASK
Definition xiic_l.h:117
#define XIIC_CR_ENABLE_DEVICE_MASK
Definition xiic_l.h:149
#define XIIC_SR_ADDR_AS_SLAVE_MASK
Definition xiic_l.h:165
#define XIic_ReadReg(BaseAddress, RegOffset)
Definition xiic_l.h:247
#define XIIC_READ_OPERATION
Definition xiic_l.h:201
#define XIIC_INTR_ARB_LOST_MASK
Definition xiic_l.h:116
#define XIIC_INTR_RX_FULL_MASK
Definition xiic_l.h:119
#define XIIC_STOP
Definition xiic_l.h:216
#define XIIC_RFD_REG_OFFSET
Definition xiic_l.h:90
#define XIIC_INTR_TX_EMPTY_MASK
Definition xiic_l.h:118
#define XIIC_REPEATED_START
Definition xiic_l.h:219
#define XIIC_CR_DIR_IS_TX_MASK
Definition xiic_l.h:152
#define XIic_ReadIisr(BaseAddress)
Definition xiic_l.h:371
#define XIic_ClearIisr(BaseAddress, InterruptMask)
Definition xiic_l.h:432
#define XIIC_CR_MSMS_MASK
Definition xiic_l.h:151