losing my mind over i2c interfacing to 24lc00 eeprom

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

losing my mind over i2c interfacing to 24lc00 eeprom

Jump to solution
10,596 Views
steve_fae
Senior Contributor I

Using PE example, got communication between FRDM board and 24LC00 but can't seem to write a read accurately.

First I do a block write then block read using typical example for I2C component.

volatile bool DataReceivedFlg = FALSE;

volatile bool DataTransmittedFlg = FALSE;

uint8_t OutData[4] = {0x00U, 0x01U, 0x02U, 0x03U};                /* Initialization of output data buffer */

uint8_t InpData[16];

LDD_TError Error;

LDD_TDeviceData *MyI2CPtr;


pastedImage_1.png

First picture is writing of data to device, only two values the first being address zero, second data value of 1. 

Second picture is writing of control word and address zero to device in prep of reading

Third picture is the read

1 Solution
8,252 Views
steve_fae
Senior Contributor I

I think I have discovered the true problem.  The 24LC00 doesn't support sequential or page write.  It does support sequential read.  The app note I have been studying made it seem that all24LCxx devices supported some sort of page write. 

This is for the 24LC00

3575_3575.png

this is the 24LC01

3576_3576.png

View solution in original post

0 Kudos
Reply
43 Replies
4,543 Views
JimDon
Senior Contributor III

This is how you must write to this device:

1. Send the device address (0xA0 on the line) byte with RD/WR = 0.

WARNING: IIRC PE left shifts the device address, so instead of 0xA0 you may need to set the address as 0x50 look at the code.

2, If nacked give up or go back to 1.

3. Send the  "word" address only the lower 4 bits are used.

4. Send the data.

5. Send stop.

ACKNOWLEDGE POLLING

loop on sending 1. and getting a NACK.

http://ww1.microchip.com/downloads/en/DeviceDoc/21178H.pdf

0 Kudos
Reply
4,543 Views
steve_fae
Senior Contributor I

Hey Jim, if you look at my attached scope shots its all there.  I am getting the ACKs and I believe the s.w. creates the correct START and STOP sequences.  But I am definitely missing something. 

0 Kudos
Reply
4,543 Views
JimDon
Senior Contributor III

Not seeing an attachment.

0 Kudos
Reply
4,543 Views
steve_fae
Senior Contributor I

Jim, you must view my original message under activity vs. inbox.  Viewing it in the inbox view, you don't see any attachments.  That was driving me crazy when I first started using this community.

0 Kudos
Reply
4,543 Views
JimDon
Senior Contributor III

Oh, I see - well I see you write the control byte and address but I don't see a read on the scope.

The read should send the control byte (as a read) the read a byte, so you should really see 4 bytes transferred.

0 Kudos
Reply
4,543 Views
steve_fae
Senior Contributor I

The last picture should show the read.

Sent from Steve Cohen's blackberry

(818)261-1033

0 Kudos
Reply
4,543 Views
JimDon
Senior Contributor III

I did not see the third trace.

I think that on the final read, you should test for an error. You should get a NACK because the eeprom should be still writing. It looks like you get an ACK, but still you do need to test for NACK after writing and attempting to read.

Just retry the read until error comes back 0 (or get the error code when the done flag is set, not sure how PE handles this). Look on page 9 of the PDF link I posted.

According to that a write can take 4ms.

Also, make Avnet get one of these: Saleae Logic. .

0 Kudos
Reply
4,543 Views
steve_fae
Senior Contributor I

The third trace was on the second page of the PPT file. 

0 Kudos
Reply
4,543 Views
JimDon
Senior Contributor III

Yes, I did see it.

As I said, even if this is not your problem, the code is logically incorrect. After the write you MUST check for NACK as this is what indicates the device is still writing. You then need to resend the address write. EEPROMs are relatively slow. I have "talked" to EEPROM on I2C many times and I assure this must be done.

Please read the pdf as I suggested, if you have not done so, it will make this clear.

Why do you init the I2C again?

Here is what I see as wrong - after the second write I don't see a stop. I also do not understand why the second write is acked, it should be  nacked.

From the PDF:

"Since the device will not acknowledge during a write

cycle, this can be used to determine when the cycle is

complete (this feature can be used to maximize bus

throughput). Once the Stop condition for a Write

command has been issued from the master, the device

initiates the internally timed write cycle. ACK polling

can be initiated immediately. This involves the master

sending a Start condition followed by the control byte

for a Write command (R/W = 0). If the device is still

busy with the write cycle, then no ACK will be returned.

If no ACK is returned, then the Start bit and control byte

must be re-sent. If the cycle is complete, then the

device will return the ACK and the master can then

proceed with the next Read or Write command. See

Figure 7-1 for flow diagram."

Also I recommend that you not use power point to upload as some users do not have it. If needs be, paste the images together in paint, or save as a pdf.

0 Kudos
Reply
4,543 Views
steve_fae
Senior Contributor I

Thanks Jim for your help.  I am just not used to Kinetis yet.

I am trying the higher level component since it breaks it down more then the LDD.  And in the typical example they actually provide typical usage for an eeprom.  The only problem is I didn't know where to enable Cpu_Delay100US(100); which they use in between the write and then read of the eeprom.

pastedImage_5.png

here is my write

TransmitComplete = 0;

err = I2C2_SelectSlave(0x50);         

buffer[0] = 0;                            //storage address

buffer[1] = 0x10;                       //data

err = I2C2_SendBlock(buffer, 2, &sent); //send storage address and data to the EEPROM

while(!TransmitComplete){}              //wait for communication completition, this flag set in interrupt routine

err = I2C2_SendStop();                  //Send STOP condition


send command 0x50, address 0, data 0x10 then send stop.  Page 7 of Microchip AN974

pastedImage_6.png

pastedImage_2.png

for read I stopped the processor then trigger scope again since I didn't feel like putzing around with s.w. delay.

buffer[0] = 0;

err = I2C2_SendBlock(buffer, 1, &sent);

while(!TransmitComplete){}

err = I2C2_RecvChar(&data);

send command with WRITE, address withWRITE, then read but that doesn't follow the data sheet!!!!!

after control byte sent with WRITE, then address with WRITE, need to generate START with control again and READ, then data is read correctly.


so I need to figure out how to do this with the component methods available. 

pastedImage_7.png

pastedImage_4.png

0 Kudos
Reply
4,543 Views
steve_fae
Senior Contributor I

So before crashing I tried this code instead to generate a restart during the read.

3538_3538.png

But the restart in the middle of the READ process isn't a real START.  The control word with WRITE and address with WRITE goes out fine.  But err = I2C2_SelectSlave(0x51); creates a mess.  Its not a valid start.  I saw a message saying using the freq divider for the i2c clock can cause problems during a restart.  Maybe there is an errata of some sort. 

3558_3558.png

0 Kudos
Reply
4,543 Views
JimDon
Senior Contributor III

Send I2C2_SelectSlave(0x51); is way wrong. If you look at the code, it shifts it left then sets the R/W bit (if it is a read).

When you set 0x50, it actually goes out as 0xA0. Not sure where the idea to left shift the set slave address comes from but PE is not the only one to do it.

Here is the article on the silicon error, don't know if it applies to your case:

KL25Z and I2C: Missing Repeated Start Condition | MCU on Eclipse

0 Kudos
Reply
4,543 Views
steve_fae
Senior Contributor I

OMFG, I think the bug is exactly what I have been chasing.  I had to remind my old brain about I2C which took a few days, but last night it was obvious that I am experiencing the same disease.

Laughing out loud, here is my current settings

pastedImage_0.png

4,543 Views
steve_fae
Senior Contributor I

Yeah I see now how 0x51 couldn't work.  Got to find which PE command does a start condition + READ.

pastedImage_0.png

}
DeviceDataPrv->SlaveAddr = (uint8_t)((uint8_t)Addr << 0x01U); /* Set slave address */
DeviceDataPrv->SerFlag &= (uint8_t)~(GENERAL_CALL | ADDR_10); /* Clear the general call flag and 10-bit address mode flag */
DeviceDataPrv->SerFlag |= ADDR_7; /* Set 7-bit address mode flag */
0 Kudos
Reply
4,543 Views
JimDon
Senior Contributor III

You should look at the PE code, I am pretty sure all that should be done there.

Also, now that you have fixed the repeated start condition, go back to what you had.

4,543 Views
steve_fae
Senior Contributor I

Unless I am cheating, I think it works now.  I just informed my two customers who are about to do the same thing what the work around it.  Thanks Jim. Now need to see what PE provides for timer delays for Kinetis like 100usec delays. 

0 Kudos
Reply
4,544 Views
JimDon
Senior Contributor III

I'd make a better test. I would write address in address (e.g.. 1=1 2=2 etc) for all 16 locations, read it back then test it.

I still think you should test for NACK instead of the delay,otherwise it may only work under some conditions.

0 Kudos
Reply
4,544 Views
steve_fae
Senior Contributor I

Agreed, I will test a few bytes, then look for the NACK to make sure I am not on the hairy edge. Thanks again for the link, I was about to wonder if I would ever get i2c to work.

0 Kudos
Reply
4,544 Views
steve_fae
Senior Contributor I

Jim, I am following exactly the typical example code:  I archived the project and am attaching. With you pointing out the bug,  I did make the suggested changes.  Just for testing I put a ton of delays after writing the block before reading.  Doesn't fix it. See below what I read back. 

3563_3563.png

this shows the tail end of the write cycle, the STOP condition only occurs at the end

3564_3564.png

I am basically trying to read and write this data to the eeprom.  the first byte of course is used for the address.

uint8_t OutData[5] = {0x00U, 0xaaU, 0x55U, 0xa5U, 0x5aU};            /* Initialization of output data buffer */

I confirmed there are no stop conditions during the block write before the end.

Basically this next capture is after the control word is send with WRITE and address zero, it shows the proper START with read by following your suggestion about the clock path choice

3559_3559.png

this shows the tail end of the write block showing the data did go out correctly

3560_3560.png

And this shows the tail end of the block read.  I do see two spikes but they are not within the clocks. 

3561_3561.png

3562_3562.png

0 Kudos
Reply
4,544 Views
JimDon
Senior Contributor III

Some other advise - always cycle power between test runs. If you stop the debugger while you were reading data back you can  leave the device is a bad state, when it is driving SDA low, and is expecting clocks from the mcu, but  the mcu has been reset. The mcu sees SDA low and will just error out. This is much  more likely to happen in a tight test loop as you have.

And you should be testing the return codes and have a break point in I2C2_OnError.

0 Kudos
Reply