UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Explorer
Explorer
7,705 Views
Registered: ‎10-25-2012

Why the IIC can't be stopped?

I wrote a function to write data through IIC bus to eeprom. But the weird thing is after data sent, the IIC keeps busy which can not be stopped. I post my code as following, is there any problem in my code? Thanks.

 

int HDMIWrite(u8 *BufferPtr, u16 ByteCount)
{
int Status;

/*
* Set the defaults.
*/
TransmitComplete = 1;
IicInstance.Stats.TxErrors = 0;

/*
* Start the IIC device.
*/
Status = XIic_Start(&IicInstance);
if (Status != XST_SUCCESS) {
xil_printf("Write Start Failed!\r\n");
return XST_FAILURE;
}
xil_printf("Write Start Suceeded!\r\n");

/*
* Send the Data.
*/
Status = XIic_MasterSend(&IicInstance, BufferPtr, ByteCount);
if (Status != XST_SUCCESS) {
xil_printf("Write Send Failed!\r\n");
return XST_FAILURE;
}
xil_printf("Write Send Suceeded!\r\n");

 

 

/* Stop the IIC device.*/
Status = XIic_Stop(&IicInstance);


if (Status != XST_SUCCESS) {
xil_printf("Write Stop Failed!\r\n");
return XST_FAILURE;

}
xil_printf("Write Stop Suceeded!\r\n");
return XST_SUCCESS;

}

 

 

 

 

0 Kudos
11 Replies
Contributor
Contributor
7,691 Views
Registered: ‎05-19-2010

Re: Why the IIC can't be stopped?

Is it sending a stop bit?

 

Personally, I never had much luck trying to use the driver functions.

 

This is the code I use (from an example design, Analog devices I think)

I modified it so you use the full address (including r/w bit, which is changed as necessary) for waddr/raddr.

I also added a timeout so it doesn't freeze on read if a slave doesn't respond.

 

void iic_write(u32 daddr, u32 waddr, u32 wdata) {
	Xil_Out32((IIC_BASEADDR + 0x100), 0x002); // reset tx fifo
	Xil_Out32((IIC_BASEADDR + 0x100), 0x001); // enable iic
	Xil_Out32((IIC_BASEADDR + 0x108), (0x100 | (daddr & 0xFE))); // send slave address for write
	Xil_Out32((IIC_BASEADDR + 0x108), waddr); // send register address
	Xil_Out32((IIC_BASEADDR + 0x108), (0x200 | (wdata & 0xFF))); // send data byte with stop bit
	while ((Xil_In32(IIC_BASEADDR + 0x104) & 0x80) == 0x00) { // wait for TX FIFO empty
		delay_ms(1);
	}
}

u32 iic_read(u32 daddr, u32 raddr) {
	u32 rdata, timeout;
	Xil_Out32((IIC_BASEADDR + 0x100), 0x002); // reset tx fifo
	Xil_Out32((IIC_BASEADDR + 0x100), 0x001); // enable iic
	Xil_Out32((IIC_BASEADDR + 0x108), (0x100 | (daddr & 0xFE))); // send slave address for write
	Xil_Out32((IIC_BASEADDR + 0x108), raddr); // send register address
	Xil_Out32((IIC_BASEADDR + 0x108), (0x101 | (daddr & 0xFE))); // send slave address for read
	Xil_Out32((IIC_BASEADDR + 0x108), 0x201); // set stop after 1 data byte
	timeout = 100; // timeout
	while (((Xil_In32(IIC_BASEADDR + 0x104) & 0x40) == 0x40) && (timeout != 0)) { // wait for read FIFO not empty
		timeout--;
		delay_ms(1);
	}
	rdata = Xil_In32(IIC_BASEADDR + 0x10C) & 0xFF; // read data byte
	if (timeout == 0) {
		xil_printf("iic timed out\n\r", raddr, rdata);
		return 0xFFFFFFFF; // data not valid
	}
	return (rdata);
}

void delay_ms(u32 ms_count) {
	u32 count;
	for (count = 0; count < ((ms_count * 800000) + 1); count++) {
		asm("nop");
	}
}

 Hope that saves you some time,

 

Daniel

0 Kudos
Teacher hgleamon1
Teacher
7,685 Views
Registered: ‎11-14-2011

Re: Why the IIC can't be stopped?

I agree somewhat with what Daniel wrote.

 

I think part of the problem lies in your understanding (or not, perhaps) of the two modes of operation - Normal and Dynamic.

 

The commands you are using are for Normal operation. This implies (to me, at least), that a lot of the stages of data transfer are handled manually, i.e. you must tell the IIC controller to begin and end the transaction. The ending of the transaction, as a Master, is critical. The Master should NACK the final operation to signify the transaction has ended. I don't think you are doing this.

 

It is not possible to see what your BufferPtr contains but you need to handle the beginning and ending of the transaction correctly (note that the Stop function just disables the device and doesn't gracefully terminate the transaction).

 

Personally, I think the Dynamic mode is easiest as it involves so little User interaction. Subsequently, you could try the command:

 

XIic_DynMasterSend (XIic *InstancePtr, u8 *TxMsgPtr, u8 ByteCount);

 

instead and see if it gives different results. I also note that you don't run through the configuration and initialisation functions prior to starting the device. I would recommend this.

 

As a proviso to all of this, I will admit (as I have done in the past) that I gave up on Xilinx's API through repeated failures and wrote my own, much like Daniel's but at a higher level of abstraction. I would only recommend this if you have a pretty good handle on what that involves and how to handle possible errors.

 

Regards,

 

Howard

 

----------
"That which we must learn to do, we learn by doing." - Aristotle
0 Kudos
Explorer
Explorer
7,671 Views
Registered: ‎10-25-2012

Re: Why the IIC can't be stopped?

Thanks very much Daniel. I want to try your functions. I need to be clear with your function interface.

1. void iic_write(u32 daddr, u32 waddr, u32 wdata), "daddr" is the 8 bits (full address) slave address you want to write, right?

2. waddr is the address inside the device while wdata is the data you want to write, right?

3. IIC_BASEADDR is the base address of IIC bus in Microblaze, which should be a 32bits number, right?

Thanks very much.
0 Kudos
Explorer
Explorer
7,671 Views
Registered: ‎10-25-2012

Re: Why the IIC can't be stopped?

Hi Howard, thanks for answer. Firstly, I answered your question, In my BufferPtr, it contains 2 u8 number, one is the device address and another is the data I wan to sent.

I have following questions:

1. The Master should NACK the final operation to signify the transaction has ended. I don't think you are doing this.
So how should I to make the master NACK the final operation to signify the transaction has ended?

I will try to use XIic_DynMasterSend (XIic *InstancePtr, u8 *TxMsgPtr, u8 ByteCount); to see what happened.

Thanks.
0 Kudos
Explorer
Explorer
7,665 Views
Registered: ‎10-25-2012

Re: Why the IIC can't be stopped?

It may be better to attach my completed code in this thread.  So in function "int HDMIWrite(u8 *BufferPtr, u16 ByteCount)"

 

The IIC can't be stopped with function "XIic_Stop(&IicInstance)"

0 Kudos
Teacher hgleamon1
Teacher
7,662 Views
Registered: ‎11-14-2011

Re: Why the IIC can't be stopped?

So how should I to make the master NACK the final operation to signify the transaction has ended?

You have read the XPS IIC datasheet, haven't you? It's all in there ...

----------
"That which we must learn to do, we learn by doing." - Aristotle
0 Kudos
Explorer
Explorer
7,656 Views
Registered: ‎10-25-2012

Re: Why the IIC can't be stopped?

No.... I even don't know there is a datasheet for IIC in XPS.....

Let me search that....
0 Kudos
Teacher hgleamon1
Teacher
7,653 Views
Registered: ‎11-14-2011

Re: Why the IIC can't be stopped?

In XPS, for all Xilinx IP, you can right-click on the IP and choose "Read Datasheet" (or words to that effect).

 

Seriously, how could you possibly be thinking of designing with and using peripherals without knowing about them !?!?

----------
"That which we must learn to do, we learn by doing." - Aristotle
0 Kudos
Explorer
Explorer
7,649 Views
Registered: ‎10-25-2012

Re: Why the IIC can't be stopped?

The first time I touch the embedded system in Xilinx FPGA is using ZYNQ chip. In zynq, it seems most peripheral is hard logic built with ARM. So when I switch to Microblaze, I did not change my mind that all the peripherals are Xilinx cores, I should read their datasheets.

I am 100% new to embedded system and now struggle to learn without any guides……
0 Kudos
Contributor
Contributor
2,794 Views
Registered: ‎05-19-2010

Re: Why the IIC can't be stopped?

1. void iic_write(u32 daddr, u32 waddr, u32 wdata), "daddr" is the 8 bits (full address) slave address you want to write, right? 
Yes


2. waddr is the address inside the device while wdata is the data you want to write, right?
Yes

eg iic_write(0xB0, 0x06, 0x37); will write 0x37 to register 0x06 in the slave with full ID 0xB0


3. IIC_BASEADDR is the base address of IIC bus in Microblaze, which should be a 32bits number, right?
I am using Zynq, but it should be the same. Base address comes from here:

#include "xparameters.h"

#define IIC_BASEADDR XPAR_AXI_IIC_0_BASEADDR

 

Daniel

0 Kudos
Explorer
Explorer
2,791 Views
Registered: ‎10-25-2012

Re: Why the IIC can't be stopped?

Thanks to confirm my understanding, watman.

I try to put your functions into my codes. I am surprised to find that even using iic_write(), my code stuck in iic_write(). Now I doubt whether there is something wrong in my embedded system design. I will investigate this.

Thanks very much.
0 Kudos