Forums

Corruption on reading from EEPROM

Started by merapcb June 15, 2010
Hi. I have a AT24C512 connected to my 1612 on I2C.
I manage to write data which seems to be OK. But on reading it back, the data is corrupted (I am writing all 0x00 but get back other values).
I say "correct" and "corrupted" based on what is seen in the logic analyzer. I was using DMA but now only I2C directly, still the same.
What may be the reason? I am out of ideas what to check. Thanks.

Beginning Microcontrollers with the MSP430

Hi,

That could be all sorts of problems, but speed is the first thing that
comes to mind. Try to slow down your clock and see if that helps, these
I2C devices only do 400kbit.
Maybe a wrong order in start/stop condition, without a code snippet it
remains a wild guess...

Regards,

Hans

On Tue, 15 Jun 2010 16:05:48 -0000
"merapcb" wrote:

>
> Hi. I have a AT24C512 connected to my 1612 on I2C.
> I manage to write data which seems to be OK. But on reading it back,
> the data is corrupted (I am writing all 0x00 but get back other
> values). I say "correct" and "corrupted" based on what is seen in the
> logic analyzer. I was using DMA but now only I2C directly, still the
> same. What may be the reason? I am out of ideas what to check. Thanks.
--

merapcb wrote:
> Hi. I have a AT24C512 connected to my 1612 on I2C.
> I manage to write data which seems to be OK. But on reading it back, the data is corrupted (I am writing all 0x00 but get back other values).
> I say "correct" and "corrupted" based on what is seen in the logic analyzer. I was using DMA but now only I2C directly, still the same.
> What may be the reason? I am out of ideas what to check. Thanks.
>

Now don't hit me, but did you ground the WP pin?

Does your code verify the arrival of the acknowledge bit after each
group of eight bits? If not, do you at least see it on the scope or
logic analyzer?

--
Regards, Joerg

http://www.analogconsultants.com/

On Tue, 15 Jun 2010 23:31:20 +0200, you wrote:

>That could be all sorts of problems, but speed is the first thing that
>comes to mind. Try to slow down your clock and see if that helps, these
>I2C devices only do 400kbit.
>

Such parts also (I don't know about the AT24C512, though) may
have a minimum rate, as well. So don't go slower or faster
than the datasheet permits.

Jon
Jon Kirwan wrote:
> On Tue, 15 Jun 2010 23:31:20 +0200, you wrote:
>
>> That could be all sorts of problems, but speed is the first thing that
>> comes to mind. Try to slow down your clock and see if that helps, these
>> I2C devices only do 400kbit.
>> Such parts also (I don't know about the AT24C512, though) may
> have a minimum rate, as well. So don't go slower or faster
> than the datasheet permits.
>

Also, on this part the maximum speed is highly supply voltage dependent.

--
Regards, Joerg

http://www.analogconsultants.com/

On Tue, 15 Jun 2010 16:23:57 -0700, Jg wrote:

>Now don't hit me, but did you ground the WP pin?

If it is left floating, it's tied internally towards ground I
think. But yes. I haven't used these parts and have never
tried to operate a part that was externally write protected.
I wonder if they even 'acknowledge' a write, if they are
protected. Do you know one way or the other? I'm curious,
now.

>Does your code verify the arrival of the acknowledge bit after each
>group of eight bits? If not, do you at least see it on the scope or
>logic analyzer?

I think that's pretty vital to check and should be one of the
first questions asked. So I agree with this.

I might scope out the entire transaction and print it out for
hand analysis and perhaps also consider driving a second pair
of pins in parallel, with a resistor divider tied so as to
cause a floating pin to look mid-range, and drive them as
well just to be sure there isn't something else going on.

Anyway, the first cut should be to divide this up into either
software or hardware. I tend to assume these I2C parts work
as advertized and I haven't encountered any difficulties
wiring them up... even in cases where I had a longish set of
wires going to a flying IC hanging at the end just for a
quick test. And I tend to also assume that microcontroller
pins similarly work as advertized. [If there is something
really unusual going on (heavy switching of inductors, x-ray
machine nearby, etc) I usually know about that, but that
isn't this case so far as the OP mentioned.] So I would tend
to assume this is very likely a software issue. But even
there your recommendation helps. It's the right step.

Single master I2C is easily driven, bit-bang, with a state
machine that ping-pongs between allowing SCL or SDA to be
modified (or read in the case of SDA) and uses four timer
events per clock cycle.

Jon
My clock is 300KHz which is within the rated speed of up to 1MHz for this part. And yes, WS is tied to ground...
And yes, I can see the ACK after each group of 8 bits.
:-(

> Now don't hit me, but did you ground the WP pin?
>
> Does your code verify the arrival of the acknowledge bit after each
> group of eight bits? If not, do you at least see it on the scope or
> logic analyzer?
>
> --
> Regards, Joerg
>
> http://www.analogconsultants.com/
>

merapcb wrote:
> My clock is 300KHz which is within the rated speed of up to 1MHz for this part. And yes, WS is tied to ground...
> And yes, I can see the ACK after each group of 8 bits.
> :-(
>

I'm curious, do you really think you have to use the I2C peripheral to
log to the eeprom? Sure, there may be situations where you can't
sacrafice UP time, (so little to gain), but I can't imagine that true
for most apps. The last time I interfaced a new eeprom with bitbang, I
didn't even bother to brake out a scope, it just worked.

From there, I can't imagine a problem talking to the like of the
24cxxx. And from my experience of making a slave with the I2C as a
peripheral, I would never bother to use it for a master. To wit, it may
have been all my stupidity, but why fight it?



But as it seems you can't get the I2C to master properly, I will follow
with interest!

Best, Dan.

--- In m..., Dan Bloomquist wrote:

> I'm curious, do you really think you have to use the I2C peripheral to
> log to the eeprom?

Well, I need to have a few peripherals that use I2C (like RTC) so I just thought it was the way to go.... Also I have never bit-banged I2C from a regular I/O pin.

I agree that it should be straight forward, and actually the RTC is working, I just don't know why the EEPROM is getting corrupted.

Am posting the code.... :

-------------------------------

#include "Common_Def.h"
#include "Controller.h"
#define ALLOCATE
#include "I2C_EEPROM.h"

void vI2CInit(void)
{
P3SEL = (SDA + SCL); // select module function for the used I2C pins
P3DIR &= ~(SDA + SCL);

U0CTL |= I2C+SYNC; //Select I2C mode with SWRST=1
U0CTL &= ~I2CEN; //disable the I2C module
//Configure the I2C module with I2CEN=0 :
// U0CTL default settings:
// 7-bit addressing, no DMA, no feedback
I2CTCTL = I2CTRX+I2CSSEL_2; // byte mode, repeat mode, clock source = SMCLK,
// transmit mode
I2CSA = 0x50; // Slave Address
I2COA = 0x22; // own address.
I2CPSC = 0x00; // I2C clock = clock source/1
I2CSCLH = 0x03; // SCL high period = 5*I2C clock
I2CSCLL = 0x03; // SCL low period = 5*I2C clock
U0CTL |= I2CEN; // I2CEN via software
}

void vI2CEEPROMWrite(U8 Len)
{
while(I2CDCTL&I2CBUSY); // wait until I2C module has finished all operations

// /*Device address and Write operation*/
// I2CSA = 0x68;

U0CTL |= MST; // define Master Mode
I2CIFG &= ~TXRDYIFG;
I2CIE = TXRDYIE; // enable Transmit ready interrupt

u8TxCounter = 0; //Reset the transmit counter

I2CNDAT = Len; //Length of the data

I2CTCTL |= I2CTRX; // I2CTRX=0 => Transmit Mode (R/W bit = 1)

/*Set as Tx mode, Enable Start and Stop condition*/
I2CTCTL |= I2CTRX + I2CSTT + I2CSTP;
}

void vI2CEEPROMRead(U8 Len)
{
while(I2CDCTL&I2CBUSY); // wait until I2C module has finished all operations

U0CTL |= MST; // define Master Mode

I2CIFG &= ~ARDYIFG; // clear Access ready interrupt flag
I2CIFG &= ~RXRDYIFG;

I2CIE = RXRDYIE; // enable Receive ready interrupt

I2CTCTL &= ~I2CTRX; // I2CTRX=0 => Receive Mode (R/W bit = 1)

u8TxCounter = 0;

I2CNDAT = Len; //Length of the data

I2CTCTL |= I2CSTT+I2CSTP; //Enable START and STOP condition

while(I2CDCTL&I2CBUSY); // wait until I2C module has finished all operations

}

void vLocateEEPROMReadAddr(U8 Len)
{
while(I2CDCTL&I2CBUSY); // wait until I2C module has finished all operations

U0CTL |= MST; // define Master Mode

u8TxCounter = 0;

I2CNDAT = Len; //1 byte should be transmitted
I2CIFG &= ~TXRDYIFG; //Clear Transmit ready interrupt flag
I2CIE = TXRDYIE; //enable Transmit ready interrupt

I2CTCTL |= I2CTRX; // I2CTRX=0 => Transmit Mode (R/W bit = 1)

I2CTCTL |= I2CTRX + I2CSTT + I2CSTP; //Set as Transmitter, enable START and
// STOP condition
}

/*-----*/
#pragma vector=USART0TX_VECTOR
__interrupt void ISR_I2C(void)
{
switch (I2CIV)
{
case I2CIV_RXRDY: /* Receive ready (RXRDYIFG) */
{
I2CReadBuffer[u8TxCounter+2]=I2CDRB; // store received data in buffer
u8TxCounter++;
break;
}
case I2CIV_TXRDY: /* Transmit ready (TXRDYIFG) */
{
I2CDRB = I2CBuffer[u8TxCounter++];

if (u8TxCounter == I2CNDAT)
{
I2CIE &= ~TXRDYIE; // disable interrupts
}
break;
}
case I2CIV_ARDY: /* Access ready (ARDYIFG) */
{
I2CIFG &= ~ARDYIFG; // clear Access ready interrupt flag
break;
}
case I2CIV_AL: /* Arbitration lost (ALIFG) */
case I2CIV_NACK: /* No acknowledge (NACKIFG) */
case I2CIV_OA: /* Own address (OAIFG) */
case I2CIV_GC: /* General call (GCIFG) */
case I2CIV_STT: /* Start condition (STTIFG) */
break;
}
}