CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

I2C Read failing

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

I2C Read failing
PostPosted: Wed Jun 02, 2021 10:06 am     Reply with quote

Hello Everyone,

I am using the I2C driver in the dsPIC33CK32MC102 acting as a Master to talk to an FPGA. I use the following: #use i2c(MASTER, I2C1, FAST, RESTART_WDT, stream=I2C_PORT1). This is on dedicated I2C ports RB8/RB9.

The goal is to read internal registers in FPGA by executing the following custom Read sequence using slave address 0x56 followed by a 16-bit memory address 0x0034 and a 16-bit Length byte 0x0001 then I want to read back 4 bytes of data from that location:

Start > 0xAD > 0x0034 > 0x0001 > Read Data1 > Read Data2 > Read Data3 > Read Data4

This is the code:
Code:

i2c_start();
i2c_write(0xAD);     // I2C slave address + write address
i2c_write(0x00);     // Write high address byte
i2c_write(0x34);     // Write low address byte
           
i2c_write(0x00);     // Write Length Field High Byte
i2c_write(0x01);     // Write Length Field Low Byte

data3 = i2c_read(TRUE);          // Read data byte 3
data2 = i2c_read(TRUE);          // Read data byte 2
data1 = i2c_read(TRUE);          // Read data byte 1
data0 = i2c_read(TRUE);          // Read data byte 0
i2c_stop();
                       
printf("Reading 4 Bytes from address 0x0034: 0xAD>>0X0034>>0X0001>>BYTE1>>BYTE2>>BYTE3>>BYTE4\r\n"); 
printf("BYTE1 = 0x%X \r\n", data3); 
printf("BYTE2 = 0x%X \r\n", data2); 
printf("BYTE3 = 0x%X \r\n", data1); 
printf("BYTE4 = 0x%X \r\n\r\n", data0);

I know normally a Read sequence is done by writing the address then issuing a reStart and then clocking the data back but due to the structure of the FPGA memory we have to do it this way.

What I see is the following: MCU sends Start > 0xAD > 0x00 then FPGA returns ACK after that last byte and the MCU for some reason does NOT send the LSB of the address >0x34 or the Length word 0x0001 but instead tries to clock back the 4 bytes of data. (I wanted to insert an image but don't know how to)

Two questions for the forum:

1. Does the I2C driver in dsPIC33CK family follows this I2C Standard Read protocol

2. If it does follow the I2C standard protocol can I modify it per my custom Read sequence above?

I appreciate if anyone can help me resolve this issue.

Thanks!
Oscar
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 02, 2021 3:05 pm     Reply with quote

Quote:
data3 = i2c_read(TRUE); // Read data byte 3
data2 = i2c_read(TRUE); // Read data byte 2
data1 = i2c_read(TRUE); // Read data byte 1
data0 = i2c_read(TRUE); // Read data byte 0
i2c_stop();

The i2c spec says the last read above should have a parameter of 0.
That's if your FPGA was designed to follow the i2c spec.
It should be like this:
Code:

data0 = i2c_read(0);          // Read data byte 0



Also, it's wrong to use 'TRUE' as a parameter. The CCS manual
says the legal parameters are 0, 1, or 2. From the manual:
Quote:

i2c_read( )

Syntax:
data = i2c_read();
data = i2c_read(ack);
data = i2c_read(stream, ack);

Parameters:
ack -Optional, defaults to 1
0 indicates do not ack
1 indicates to ack
2 slave only, indicates to not release clock at end of read. Use when i2c_isr_state()
returns 0x80
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

PostPosted: Wed Jun 02, 2021 3:22 pm     Reply with quote

Thanks for the response.

I will change out the TRUE's to 1's and last one to 0.

I have another question for you, if you please: If this MCU is the master then wouldn't setting it to 1 generate an ack back to the slave? Or does this mean that the MCU(master) will look for an ack from the slave. It's a bit confusing to me.

thanks again!
Oscar
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 02, 2021 3:59 pm     Reply with quote

When reading from an i2c slave, the master is the device that
sends an ACK or a NACK to the slave.

More explanation:
https://www.esacademy.com/en/library/technical-articles-and-documents/miscellaneous/i2c-bus/i2c-bus-events/giving-acknowledge-to-a-slave-device.html
Ttelmah



Joined: 11 Mar 2010
Posts: 19221

View user's profile Send private message

PostPosted: Thu Jun 03, 2021 12:45 am     Reply with quote

I2C, by using an 'open collector' drive, supports transfers in both directions
on each wire.
So the ''slave', can hold the clock from releasing to delay the master
(clock stretch). Then the master can receive data, by commanding the
slave to send, and sending the clocks, while the slave then drives the data
line to give data to the master. In I2C, all transfers have a ACK or NACK,
which is generated by the receiving device. So when the master is receiving,
it is the master that must ACK/NACK.
For transmissions it is the slave that sends this. For reception, it is the
master.
The rmaster device, when receiving, 'ACK's all but the last byte. This byte
has a NACK. This is a marker to the slave device to say that this is the end
of the packet. It is this that releases the toggle in the slave device to switch
it back to receiving.
Many slaves will automatically reset this, when they see a 'stop'. However
a lot do not. On any device where this is not done, not sending this last
NACK, can result in the slave state machine becoming stuck.....
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

PostPosted: Thu Jun 03, 2021 7:23 am     Reply with quote

Thanks for this additional insight.
Much appreciated fellows.
Oscar
robleso7473



Joined: 25 Mar 2009
Posts: 47

View user's profile Send private message

PostPosted: Fri Jun 04, 2021 8:18 am     Reply with quote

I'm back!

I still have an issue when executing a read command where after the high address byte below the MCU will not send out the next byte 0x34, it simply ignores the next 3 writes to 0x34, 0x00 and 0x01 and goes straight into reading data1 and data0.

Is the I2C Read function designed to only push out one 8-bit address value prior to clocking back data?

i2c_start();
i2c_write(0xAD); // I2C slave address + write address
i2c_write(0x00); // Write high address byte
i2c_write(0x34); // Write low address byte
i2c_write(0x00); // Write Length byte 1
i2c_write(0x01); // Write Length byte 0
data1 = i2c_read(1); // Read data byte 1
data0 = i2c_read(1); // Read data byte 0
i2c_stop();
}

I want to post an image of the I2C transaction from my Saleae logic analyzer but don't know how to paste it on here - can you help?

Thanks for support,
Oscar
Ttelmah



Joined: 11 Mar 2010
Posts: 19221

View user's profile Send private message

PostPosted: Fri Jun 04, 2021 8:26 am     Reply with quote

This is where a restart is used.

The sequence has to be:

start
write device address set to write.
write the register addresses (however many bytes are needed)
trigger a 'restart' (send a start without a stop)
write the device address set to read
Now read the bytes nacking the last one.
stop.

The point is that after an address is sent with the 'read' flag, only reads
are allowed. To set a address you have to do a write transaction, then
turn the bus around with the restart, and the read flag.

To your question:
Quote:

Is the I2C Read function designed to only push out one 8-bit address value prior to clocking back data?


The answer is totally 'yes'. This is all I2C allows.
After the read address is sent, only reads can be done. There can be
no transmissions after this. You only turn the bus to 'read', once you have
already sent all transmissions that are needed.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group