problem with i2c -> timing

50 views
Skip to first unread message

Juri Pospelow

unread,
Jan 25, 2017, 5:22:26 AM1/25/17
to simavr
hello,

My i2c and i2c_test code is different than with you.
I make:
I write address in eeprom and then without stop read from this address, with: I2cStart-> WriteByte (0xa1) -> ReadByte, and
I GET:
TWI status as TW_REP_START after writing the byte (address for external EEPROM). Built-in counter shows me that this state appears 6 times.
I expect:
for example: TW_MR_SLA_ACK. This code works fine on HW.
I mean, when switching from write mode to read mode, simulator takes more time or it sends abnormally old state several times
at this moment.

And so i can't test my code in your simulator.


Best wishes Juri

hovercraft-google

unread,
Jan 26, 2017, 2:44:55 AM1/26/17
to simavr
Could you please post entire source code of your test case?

Juri Pospelow

unread,
Jan 26, 2017, 4:04:07 AM1/26/17
to simavr

this is a test:

    ret = i2cWrite(i2c, dev, addr_buf, sizeof(addr_buf), false);
    TEST_ASSERT_EQUAL_MESSAGE(0, ret, "write rd address");

    ret = i2cRead(i2c, dev, buf, len, true);
    TEST_ASSERT_EQUAL_MESSAGE(0, ret, "read data");


this is a code:


OPTIMIZE
int8_t i2cRead(I2C *dev, int16_t address, uint8_t *buffer, i2c_cnt_size count, bool stop) {
    bool nack;

    if (!i2cStart(dev)) {
        return i2cFailure(dev, -1, "Read start");
    }
    if (!i2cWriteByte(dev, address|1, &nack)) {
        return i2cFailure(dev, -2, "Read send addr");
    }
    if (nack) {
        return i2cFailure(dev, -3, "Read addr nack");
    }
    return i2cReadMore(dev, buffer, count, stop);
}


OPTIMIZE
int8_t i2cWrite(I2C *dev, int16_t address, const uint8_t *buffer, i2c_cnt_size count, bool stop) {
    bool nack;

// putstr("i2cWrite: count: "); putu(count); putstr("stop: "); putu(stop); putstr("dev: "); putu((uint32_t)dev); putstr("address: "); putu(address); putstr("\n");

    if (!i2cStart(dev)) {
        return i2cFailure(dev, -1, "Write start");
    }
    if (!i2cWriteByte(dev, address, &nack)) {
        return i2cFailure(dev, -2, "Write send addr");
    }
    if (nack) {
        return i2cFailure(dev, -3, count ? "Write addr nack" : NULL);
    }
    return i2cWriteMore(dev, buffer, count, stop);
}



Low Level:

bool i2cWriteByte(I2C* bus, uint8_t byte, bool* nack)
{
    LOG_M();
    (void) bus;
/* Send data to the previously addressed device */
    TWDR = byte;
    TWCR = _BV(TWINT) | _BV(TWEN);

/* Wait until transmission completed */
    while (!(TWCR & _BV(TWINT))) {
        if(TW_STATUS == TW_MT_ARB_LOST){
            printf("I2C Arbitration lost\n");
            return false;
        }
    }

    static unsigned cnt, tmp;
    while(TW_STATUS == TW_REP_START){  <----------------------------------- here is counter, and here must not be been TW_REP_START! , without this while() - i get error message from my test!
        ++cnt;
        tmp = byte;
    }

    if((TW_STATUS != TW_MT_SLA_ACK) && (TW_STATUS != TW_MR_SLA_ACK) && (TW_STATUS != TW_MT_DATA_ACK)) {
        *nack = 1;
    } else {
        *nack = 0;
    }
 // *nack = !(TW_STATUS == TW_MT_SLA_ACK || TW_STATUS == TW_MT_DATA_ACK || TW_STATUS == TW_MR_SLA_ACK || TW_STATUS == TW_REP_START);
    // *nack=0;
    // if(byte == 0xa1) printf("s: 0x%02x, nack= %d \n", TW_STATUS, *nack);
    if(cnt) printf("cnt: %d, tmp= %d \n", cnt, tmp);
    printf("TWS: 0x%02x \n", TW_STATUS);
    return true;
}

here i expteted
TW_REP_START:
bool i2cStart(I2C* bus)
{
    LOG_M();
    (void) bus;
/* Send START condition */
    TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);

/* Wait until transmission completed */
    while (!(TWCR & _BV(TWINT)))
        ;

    if ((TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START))
        return false;

    return true;
}

A full version you can see in attachment.
I add external eeprom (i2c_eeprom) to µC (run_avr) and call test with run_avr :run_avr -ff -m atmega1280 -f 8000000 sim_i2test.hex -v -v.

sim_i2test.c
i2c_avr.c
i2c.c

Juri Pospelow

unread,
Jan 26, 2017, 4:55:01 AM1/26/17
to simavr
of anorther hand, you can get the same problem if you add benchmarkt test to your test.
see attachment.
if you call with: run_avr atmega1280_i2ctest.axf -v -v

then you can see:

avr_twi_write a4 START:1 STOP:0 ACK:0 INT:1 TWSR:28 (state 0d)
>>>>> I2C REstart
_avr_twi_status_set 10
avr_twi_write 84 START:0 STOP:0 ACK:0 INT:1 TWSR:10 (state 11)
I2C Master address a1
eeprom received start
avr_twi_irq_input 01a10800
I2C received ACK:1
_avr_twi_status_set 40
twst: 0x10..  --------------------------------------- < here Restart again !!!!!!!!!!
ERORR start..
avr_twi_write 84 START:0 STOP:0 ACK:0 INT:1 TWSR:40 (state 2d)
I2C READ byte from a1
state 25 want 20
eeprom READ data 0x01a8: ff

atmega1280_i2ctest.c
twimaster.c

hovercraft-google

unread,
Jan 26, 2017, 7:22:51 AM1/26/17
to simavr
Ok, I will study it, but it will require some time.
Thank you for detailed description.
Reply all
Reply to author
Forward
0 new messages