Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

IIC programming for microblaze

Status
Not open for further replies.

aminbahrami

Junior Member level 3
Joined
Aug 15, 2011
Messages
25
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,580
Hi all
I am working with spartan 3a dsp 3400 board.
I create a new design with microblaze for my board.
I now want to write a simple code for IIC.
I used the following function for writing data to a register of a chip using iic.



/******************************************************************************
* This function writes a buffer of bytes to the IIC chip.
*
* @param CoreAddress contains the address of the IIC core.
* @param ChipAddress contains the address of the chip.
* @param RegAddress contains the address of the register to write to.
* @param BufferPtr contains the address of the data to write.
* @param ByteCount contains the number of bytes in the buffer to be written.
* Note that this should not exceed the page size as noted by the
* constant PAGE_SIZE.
*
* @return The number of bytes written, a value less than that which was
* specified as an input indicates an error.
*
* @note None.
*
******************************************************************************/
Xuint8 vsk_iic_write(Xuint32 IICCoreAddress, Xuint8 ChipAddress, Xuint8 RegAddress,
Xuint8 *BufferPtr, Xuint8 ByteCount)
{
Xuint8 SentByteCount;
Xuint8 WriteBuffer[IIC_PAGE_SIZE + 1];
Xuint8 Index;
Xuint8 StatusReg;

// Make sure all the Fifo's are cleared and Bus is Not busy.
do
{
StatusReg = XIo_In8(CoreAddress + XIIC_SR_REG_OFFSET);
StatusReg = StatusReg & (XIIC_SR_RX_FIFO_EMPTY_MASK |
XIIC_SR_TX_FIFO_EMPTY_MASK |
XIIC_SR_BUS_BUSY_MASK);
} while (StatusReg != (XIIC_SR_RX_FIFO_EMPTY_MASK |
XIIC_SR_TX_FIFO_EMPTY_MASK));
/*
* A temporary write buffer must be used which contains both the address
* and the data to be written, put the address in first
*/
WriteBuffer[0] = RegAddress;

/*
* Put the data in the write buffer following the address.
*/
for (Index = 0; Index < ByteCount; Index++)
{
WriteBuffer[Index + 1] = BufferPtr[Index];
}

/*
* Write data at the specified address.
*/
SentByteCount = XIic_DynSend(CoreAddress, ChipAddress, WriteBuffer,
ByteCount + 1, XIIC_STOP);
if (SentByteCount < 1) { SentByteCount = 1; }

// Return the number of bytes written.
return SentByteCount - 1;
}




But my function remains in the while loop (which is seperated with another color.)
I used a xil_printf function after line: StatusReg = XIo_In8(CoreAddress + XIIC_SR_REG_OFFSET);
to display the value of statusreg variable
but i only see statusreg=0 and function remains in do_while loop
in the next step I read the value of other registers with XIo_In8 , but it returns 0 to other registers too.
then I write 0x07 in a specific register using Xio_out8 function and i read the same register using XIo_In8 but the read value was 0!!!!!!!!!!!!!!!!!!
The above code is xilinx code for iic of my board.
can any one help me what i must do with this unction or tell me the reason of this subject?
can any one give me another code for i2c if he/she has another code for iic please
thanx
 

can any one give me another code for i2c if he/she has another code for iic please
Hi..

1, in your Xilinx folder go to \Xilinx\12.4\ISE_DS\EDK\sw\XilinxProcessorIPLib\drivers\iic_v2_02_a\examples
some examples are given..
also dont forget to change iic address and page size while testing on board..

2,XPS will generate selftest program... see the outputs in HyperTerminal..
 

Dear Sanju
do you write any program for iic ?
I want a simple code for sending and reading data.
if you have a code help me please.
 

So what value are you using for that "CoreAddress" parameter that is listed in the comment?

Code:
* This function writes a buffer of bytes to the IIC chip.
*
* @param CoreAddress contains the address of the IIC core.
 

Dear friend
thanx for your answer
Coreaddress is iic_base_address of microblaze iic.
in the first of above code I added the following code for initialization too.
Status = XIic_Initialize(&IicInstance, XPAR_IIC_0_DEVICE_ID);
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
xil_printf("\r\n I am sorry initialization is not correct\r\n");

}
XIic_Start(&IicInstance);
The initialization is done correctly .
but other parts of my code which I mentiond in previous posts dont work correctly
help me please.
 

I know, but I asked what value it has.

Put another way, did you check if you actually gave it all the correct parameters? I recall using the I2C core once, and then forgetting to properly specify the base address. That resulted in all sorts of fun. So I'd do a printf of all the parameter values there as well, just to be sure...
 
thanx
I bypassed the abbove code and wrote a new simple code myself:




#include "xparameters.h"
#include "stdio.h"
#include "xbasic_types.h"
#include "xiic_l.h"
#include "xiic.h"
#include "xio.h"

#define FMC_CARD_IIC_BASE_ADDRESS XPAR_IIC_EEPROM_BASEADDR
#define IIC_FMC_MUX_ADDR 0x74
XIic IicInstance; /* The instance of the IIC device. */
int Status;
Xuint8 WriteBuffer[2];
Xuint8 ReadBuffer[2];


//====================================================

int main (void) {

WriteBuffer[0]=0x04;

/*

* Initialize the IIC driver so that it is ready to use.

*/
Status=XIic_Initialize(&IicInstance,XPAR_IIC_0_DEVICE_ID);
if (Status!=XST_SUCCESS){
xil_printf("\r\n failure in initialization \r\n");
return XST_FAILURE;
}


XIic_Start(&IicInstance);

Status=XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE, IIC_FMC_MUX_ADDR);
if (Status!=XST_SUCCESS){
xil_printf("\r\n failure in Set address \r\n");
return XST_FAILURE;

}

//write data
XIic_MasterSend(&IicInstance,WriteBuffer,1);
if (Status!=XST_SUCCESS){
xil_printf("\r\n failure in write data \r\n");
return XST_FAILURE;
}

xil_printf("\r\n S U C C E S S\r\n");
//read the written data
XIic_MasterRecv(&IicInstance,ReadBuffer,1);
if (Status!=XST_SUCCESS){
xil_printf("\r\n failure in read data \r\n");
return XST_FAILURE;
}


if (Status==XST_SUCCESS){
xil_printf("\r\nread data=%d\r\n",ReadBuffer[0]);
}



}





I have no error for this code. (XST_SUCCESS for all stages)

I wrote 0x04 into a slave and I then read it.
but read value is 0 and is not 0x04 which I sent to slave.
I am confused!!!!!!!!!!
can you help me plz?
 

Not sure if I understand what you are trying to do here.

Going by the code snippets, I am guessing...

You have an external i2c chip (the i2c slave) that is at address IIC_FMC_MUX_ADDR = 0x74.

You send it 1 byte, and 1 byte only, with value 0x04. So over the wire you would expect to see this 0x74 byte going out followed by the 0x04 byte (and the start + stop + acks and such). If you really don't know what the hell is going on you can always scope these connections. Or put a chipscope on it.

Other than that, WHY should you get a 0x04 value on a 1 byte read? I know what you just said, but where in the datasheet for whatever it is you have there does it say that on a read it should give back the value you just wrote to the base addr?

Does it specifically mention that it has a writeable register at 0x74, that you can then later read back at 0x75 or something? I am not sure, but it could be that you are assuming things that are not necessarily the case.

So, WHY do you feel you should get a 0x04 as a result from that read? Where in the datasheet does it describe this readback functionality?
 

hi
thanx
I want to send and read data using microblaze.
plz tell me is my procedure correct?
1- iic initialize
2- iic start
3- icc set address
4- icc write
??
I have another question :
any i2c chip may have several registers.
each register has its address in chip.
how can I write to a specific register of a specific chip.
in my code i only read and write to or from a chip. but not to or from a specific register of that chip
how can I write or read from a specific register of a chip?
driver functions such as iic_mastersend iic_masterrev and... have not such ability.
it is said in API for i2c that I can only send or read from a specific chip.
Did you work with i2c yourself?
 

how can I write to a specific register of a specific chip.

You usually send the register address right after the addressm and you have received an ACK from the slave.

So suppose that your chip whatever it is has 16 registers, and you want to send that 0x04 value to register number then over the wire you would send:

0x74 (adress the slave) , 0x07 (specify register), 0x04 (data value)

And from the point of view of you microblaze you would have to put the "0x07 0x04" in your WriteBuffer, and then do a 2 byte write.

But info on writing (and readback) of the internal registers should really all be in the datasheet.
 
thanx for your answer
my iic chip is pca9546a and it is said in its datasheet that i can read the internal register value of this chip.!!!!!
 

Okay, did a quick check of the datasheet.

About that 0x74 address ... what are the A0, A1 and A2 lines connected to on your pca9546a chip?


Wait, silly test .... what if you send a byte to the wrong address on purpose. So as to prevent making wrong assumptions here.

So for the moment change it to:
Code:
#define IIC_FMC_MUX_ADDR 0x93

And then rerun the thing. What kind of status do you get then? The exact same or different? If it gives you the same messages then you have other problems. :p Because it should obviously give you an error.

Other than that, yes if I read it correctly then you should be able to readout the status register.
 
  • Like
Reactions: aminbahrami

    aminbahrami

    Points: 2
    Helpful Answer Positive Rating
    V

    Points: 2
    Helpful Answer Positive Rating
hi
thanx for all of your answers
excuse me for my many questions.
you said how to write to a specific register but you did not say anything about reading the value of specific register of a specific chip.
I did what you said. the chip address is correct.
writing to a wrong address has not any problem.!!!!!!!!!!!!!!!!!!!!!!
but reding has the same problem.(failure in reading)
 
Last edited:

writing to a wrong address has not any problem.!!!!!!!!!!!!!!!!!!!!!!

Well, that is bad news. Because now you know that no matter what bullshit you send, your send routine always tells you "everything went fine!" , even when it doesn't.

but reding has the same problem.(failure in reading)

Oi?!? failure in reading? Or succes in reading, but the wrong value. Small distinction....

you said how to write to a specific register but you did not say anything about reading the value of specific register of a specific chip.

Mmmh? Just read the datasheet. That is where I got it. Don't have it in front of me, bu I remember from reading that this chip only has 1 single register. So all the writes you do to that chip are to that register. Same story for reading. If that is not clear enough, please read the datasheet since that mentions it more clearly than my lazy few sentences...

Also you didnt answer this one:

How are the A0, A1 and A2 pins connected on you hardware?
 
dear friend
I am completely understand what you say. I am not a beginner in electronics and fpga and coding.
but I am confused with this problem.
my board is s3 adsp 3400 and I cant use oscope for ensuring the i2c signals.(because of the board structure)
you are right. my chip has only one register.
but I need to know it for my other devices(after responding from this step)
yes these pins are connected in my board.
excuse me.
I had a mistake in my code. I modified it and I now have failure in reading.
 
Last edited:

yes these pins are connected in my board.

Very astute. Now to what voltage levels are these 3 pins connected? You know, to verify that you are actually using the correct address. Since we have by now figured out the the returned status code of the write function is not all that useful.

Another thing, have you actually taken a look at the signal with a scope? That can sometimes take you all of 10 minutes and result in an a-hah! moment. A whole lot easier than 453897345 posts here.

I would not be at all surprised if you don't get an ACK on that write....

---------- Post added at 14:59 ---------- Previous post was at 14:57 ----------

my board is s3 adsp 3400 and I cant use oscope for ensuring the i2c signals.(because of the board structure)

I find that hard to believe. Can you see the pca9546a chip package? If so, scope the sda/scl there and see what you can see....
 
sorry for more questions
the address of chip is mentioned in board catalogue. be sure from correctness of chip address.
ok.
I will test tomorrow. and I then tell you the result.
note please to all of my works. please
the board has two parts:main board and video board
my board supports 2 i2c. one for fmc card(video card) and one for the main board
when I created microblaze in edk(the board is supported with bsb), I understood that created design has only one i2c.
I checked the ucf demos of board and i understood that creted i2c is for main board.
but I need i2c for video board . because I wanted to run camera of video board.
then I modified the i2c pins in ucf and then generated netlist and bitstream.now, i2c pins of fpga access the i2c pins of video board. then I created my C code that you saw.
is any thing correct from beginning to now.
 

Try

Code:
#define IIC_FMC_MUX_ADDR 0xE8

Just for the fun of it. That's just the address left shifted 1 bit. Not sure if it the case with this library, but I've seen i2c routines that expect you to to take the 7 bit address and left shift it 1 bit. Not sure if it will help, but easy enough to try. Anyways if that does not work I'd really try to put a scope on it. If you cannot do that, then try chipscope.
 

Dear my friend
I saw the signals on board.
I write a loop using while that frequently writes on my chip.
we have signal and data.
but we cant read the true value which we sent
I feel my code is not correct for reading the value.
we had two states for two codes.
state 1: if we write to the chip and then we use XIic_Start(&IicInstance); function again before reading , it failures.
state1:


//after writing
xil_printf("\r\n S U C C E S S\r\n");
Status=XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE, IIC_FMC_MUX_ADDR);
if (Status!=XST_SUCCESS){
xil_printf("\r\n failure in Set address \r\n");
return XST_FAILURE;

}

// //read the written data
//Status=XIic_Start(&IicInstance);
//if (Status!=XST_SUCCESS){
// xil_printf("\r\n failure in restart data \r\n");
// return XST_FAILURE;
// }
Status=XIic_MasterRecv(&IicInstance,ReadBuffer,1);
if (Status!=XST_SUCCESS){
xil_printf("\r\n failure in read data \r\n");
return XST_FAILURE;
}




but in state 2 , if we dont use from that function again after reading we will read the incorrect value.
state 2:





xil_printf("\r\n S U C C E S S\r\n");
Status=XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE, IIC_FMC_MUX_ADDR);
if (Status!=XST_SUCCESS){
xil_printf("\r\n failure in Set address \r\n");
return XST_FAILURE;

}

//read the written data
Status=XIic_Start(&IicInstance);
if (Status!=XST_SUCCESS){
xil_printf("\r\n failure in restart data \r\n");
return XST_FAILURE;
}
Status=XIic_MasterRecv(&IicInstance,ReadBuffer,1);
if (Status!=XST_SUCCESS){
xil_printf("\r\n failure in read data \r\n");
return XST_FAILURE;
}




***I used set address again (for reading) because the datasheet of chip says that for reading internal register, firstly the chip address must be sent.
 

I'm not really certain if I follow.

Do you maybe have a chipscope trace or oscilloscope trace that shows the scl/sda lines during these operations you describe?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top