cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Newbie
Newbie
3,087 Views
Registered: ‎11-11-2011

Can anyone help me with IIC ip core?

Hi,

 

I really appreciate if someone can help me, because I have been confused almost one week. Sorry for my poor English

 

I use IIC ip core under EDK. I have writen a driver, but I found it doesn't work.

I just use code like this:

send_cnt = XIic_Send(XPAR_XPS_IIC_0_BASEADDR, ADDR_DECOD, send_data, 2, XIIC_STOP);

 

So under SDK, I debug it, I found the code just stop here (inside xiic_l.c file)

 

StatusReg = XIic_ReadReg(BaseAddress, XIIC_SR_REG_OFFSET);
while ((StatusReg & XIIC_SR_BUS_BUSY_MASK) == 0) {
StatusReg = XIic_ReadReg(BaseAddress,
XIIC_SR_REG_OFFSET);
}

 

 The debug information showed: StatusReg = 64, and the whole program just stay here and no longer go any more. I checked the Xilinx IIC core pdf: http://www.xilinx.com/support/documentation/ip_documentation/xps_iic.pdf in page 16

I found this line actually check whether IIC bus busy or not. but here if I want to send the data, don't I want to make sure the bus is not busy? Is there anything wrong with Xilinx library?or what should I do to fix it?

 

Thank you very much!

 

sniu@hawk.iit.edu

0 Kudos
6 Replies
Highlighted
Newbie
Newbie
3,081 Views
Registered: ‎11-11-2011

Re: Can anyone help me with IIC ip core?

I forget to say that even I run a example iic code under installation file, the program still stop there. Thank you very much

0 Kudos
Highlighted
Visitor
Visitor
2,023 Views
Registered: ‎12-11-2012

Re: Can anyone help me with IIC ip core?

我也遇到了类似的问题 你后来是怎么解决的呢
0 Kudos
Highlighted
Visitor
Visitor
463 Views
Registered: ‎07-30-2018

Re: Can anyone help me with IIC ip core?

Did you ever figure out the answer to this problem? I have the same issue.

0 Kudos
Highlighted
Moderator
Moderator
414 Views
Registered: ‎07-31-2012

Re: Can anyone help me with IIC ip core?

Please post new query about IIC IP issue seen with details of version of core, tools and OS used.

 

Regards

Praveen


-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Highlighted
Scholar
Scholar
406 Views
Registered: ‎05-31-2012

Re: Can anyone help me with IIC ip core?

IIC can be tricky,

1 use an oscilloscope and check if SDA SCL lines are high (check if pull up is working)

2 Check if you addressed correctly the device

3 do not debug inside IIC library functions, it will loop forever

4 after you see a failure, do not try to reprogram only the code, you 'll need to restart all the board because you can't reset your slave device and the IIC bus could be always busy

0 Kudos
Highlighted
Visitor
Visitor
399 Views
Registered: ‎07-30-2018

Re: Can anyone help me with IIC ip core?

I figured out the solution. I was not setting up the transmit properly. Here are the TX and RX functions I wrote that are working:

/*****************************************************************************/
/**
* This function writes a buffer of bytes to the IIC bus.
*
* @param	AX_IIC_BASE_ADDRESS contains the base address of the AXI IIC Block. This is not the same as the device ID.
* @param	i2c_device_address contains the address of the device we will be transmitting to
* @param    internal_register_address is the address of the register inside of IC we would like to write to
* @param	tx_buf contains the number of bytes in the buffer to be transmitted (typically a register address we want to read)
* @param	tx_size contains the number of bytes in tx_buf
*
* @return
* 		-XST_SUCCESS if Successful else XST_FAILURE.
*
*
******************************************************************************/
int PL_AXI_I2C_TX(int AX_IIC_BASE_ADDRESS, u8 i2c_device_address, u8 internal_register_address, u8 *tx_buf, u16 tx_size)
{
	volatile unsigned SentByteCount;
	volatile unsigned AckByteCount;
	u8 WriteBuffer[sizeof(internal_register_address) + tx_size];
	int Index;

	/*
	 * A temporary write buffer must be used which contains both the address
	 * and the data to be written, put the address in first based upon the
	 * size of the address for the EEPROM.
	 */
	WriteBuffer[0] = (u8)(internal_register_address);

	/*
	 * Put the data in the write buffer following the address.
	 */
	for (Index = 0; Index < tx_size; Index++) {
		WriteBuffer[sizeof(internal_register_address) + Index] = tx_buf[Index];
	}

	/*
	 * Set the address register to the specified address by writing
	 * the address to the device, this must be tried until it succeeds
	 * because a previous write to the device could be pending and it
	 * will not ack until that write is complete.
	 */
	do {
		SentByteCount = XIic_Send(AX_IIC_BASE_ADDRESS,
					i2c_device_address,
					(u8 *)&internal_register_address, sizeof(internal_register_address),
					XIIC_STOP);
		if (SentByteCount != sizeof(internal_register_address)) {

			/* Send is aborted so reset Tx FIFO */
			XIic_WriteReg(AX_IIC_BASE_ADDRESS,  XIIC_CR_REG_OFFSET,
					XIIC_CR_TX_FIFO_RESET_MASK);
			XIic_WriteReg(AX_IIC_BASE_ADDRESS, XIIC_CR_REG_OFFSET,
					XIIC_CR_ENABLE_DEVICE_MASK);
		}

	} while (SentByteCount != sizeof(internal_register_address));
	/*
	 * Write a page of data at the specified address to the EEPROM.
	 */
	SentByteCount = XIic_Send(AX_IIC_BASE_ADDRESS, i2c_device_address,
				  WriteBuffer, sizeof(internal_register_address) + tx_size,
				  XIIC_STOP);

	/*
	 * Wait for the write to be complete by trying to do a write and
	 * the device will not ack if the write is still active.
	 */
	do {
		AckByteCount = XIic_Send(AX_IIC_BASE_ADDRESS, i2c_device_address,
					(u8 *)&internal_register_address, sizeof(internal_register_address),
					XIIC_STOP);
		if (AckByteCount != sizeof(internal_register_address)) {

			/* Send is aborted so reset Tx FIFO */
			XIic_WriteReg(AX_IIC_BASE_ADDRESS,  XIIC_CR_REG_OFFSET,
					XIIC_CR_TX_FIFO_RESET_MASK);
			XIic_WriteReg(AX_IIC_BASE_ADDRESS, XIIC_CR_REG_OFFSET,
					XIIC_CR_ENABLE_DEVICE_MASK);
		}

	} while (AckByteCount != sizeof(internal_register_address));

	/*
	 * Return success if number of bytes written includes size of i2c_device_address
	 * and tx_size
	 */
	if(SentByteCount != (sizeof(internal_register_address)+tx_size)){
		return XST_FAILURE;
	}
	return XST_SUCCESS;
}

/*****************************************************************************/
/**
* This function writes a buffer of bytes and reads the returned bytes on IIC bus.
*
* @param	AXI_IIC_BASE_ADDRESS contains the base address of the AXI IIC Block. This is not the same as the device ID.
* @param	i2c_device_address contains the address of the device we will be transmitting to
* @param    internal_register_address is the address of the register inside of IC we would like to read from
* @param	rx_buf contains the number of bytes in the buffer to be received
* @param	rx_size contains the number of bytes in rx_buf
*
* @return
* 		-XST_SUCCESS if Successful else XST_FAILURE.
*
*
******************************************************************************/
int PL_AXI_I2C_TX_RX(int AX_IIC_BASE_ADDRESS, u8 i2c_device_address, u8 internal_register_address, u8 *rx_buf, u16 rx_size)
{
	volatile unsigned ReceivedByteCount;
	u16 StatusReg;

	/*
	 * Set the address register to the specified address by writing
	 * the address to the device, this must be tried until it succeeds
	 * because a previous write to the device could be pending and it
	 * will not ack until that write is complete.
	 *
	 * A repeated stat condition is manditory for certain ICs
	 */
	do {
		StatusReg = XIic_ReadReg(AX_IIC_BASE_ADDRESS, XIIC_SR_REG_OFFSET);
		if(!(StatusReg & XIIC_SR_BUS_BUSY_MASK)) {
			ReceivedByteCount = XIic_Send(AX_IIC_BASE_ADDRESS,
							i2c_device_address,
							(u8 *)&internal_register_address,
							sizeof(internal_register_address),
							XIIC_REPEATED_START);

			if (ReceivedByteCount != sizeof(internal_register_address)) {

				/* Send is aborted so reset Tx FIFO */
				XIic_WriteReg(AX_IIC_BASE_ADDRESS,
						XIIC_CR_REG_OFFSET,
						XIIC_CR_TX_FIFO_RESET_MASK);
				XIic_WriteReg(AX_IIC_BASE_ADDRESS,
						XIIC_CR_REG_OFFSET,
						XIIC_CR_ENABLE_DEVICE_MASK);
			}
		}

	} while (ReceivedByteCount != sizeof(internal_register_address));

	/*
	 * Read the number of bytes at the specified internal address.
	 */
	ReceivedByteCount = XIic_Recv(AX_IIC_BASE_ADDRESS, i2c_device_address,
					rx_buf, rx_size, XIIC_STOP);

	/*
	 * See if we got all byes back that we expected.
	 */
	if(ReceivedByteCount != rx_size){
		return XST_FAILURE;
	}
	return XST_SUCCESS;
}
0 Kudos