KL25Z I2C read command(s) bugged?

This forum topic has been closed.

10 Apr 2013

Just posting it here to make sure it is noticed. I don't actually have the KL25Z, so maybe I am just mistaken, however in response to this question: https://mbed.org/questions/808/Cant-read-I2C-data-on-FRDM-KL25Z/, I checked the I2C source code and it seems to me to be incorrect for proper operation of both read commands, unless the 'complete' read command is used with a stop at the end. Granted that is roughly 99% of the use cases, but still.

Quote:

Doing a single byte read is done by calling the i2c_byte_read C function, which is defined as:

int i2c_byte_read(i2c_t *obj, int last) {
    char data;
    i2c_do_read(obj, &data, last);
    return data;
}

So that simply consists of the i2c_do_read function being called. All nice and we lived happily ever after. However, the i2c_do_read function is only half a function:

static int i2c_do_read(i2c_t *obj, char * data, int last) {
    if (last)
        i2c_send_nack(obj);
    else
        i2c_send_ack(obj);
 
    *data = (obj->i2c->D & 0xFF);
 
    // start rx transfer and wait the end of the transfer
    return i2c_wait_end_rx_transfer(obj);
}

This one took me a bit to figure out. It first either sets or removes the ACK bit. Makes sense. However then it reads from the I2C register, even though it hasn't started transfer yet. And then it waits till the transfer is complete, even though we already read the data. But with a bit of looking through the reference manual and later the other read function (the one I used in the beginning here, which does appear to be functional), it slowly started to make sense.

The first read is a dummy read. The other read function simply throws away the data that comes from that. This is only used to initiate the read process. I still don't really get how the ACK/NACK stuff works, if it isn't set correctly the KL25 will keep the SCL line low, which is exactly what you see. However I am fairly certain also the other read function doesn't work when it ends with a repeated start condition: according to the datasheet you should put it in TX mode before initiating your last read to the data register, otherwise it will initiate yet another read. The mbed code doesn't do this. If it ends with a stop condition it will put the peripheral in slave mode, that should also prevent starting another master receive cycle. However when it doesn't end in a stop condition this won't work either most likely.

But without either a Freescale board or a logic analyzer I can't test all that myself :P

Btw @ mbed guys, checking after every do_read if the function returns the expected 0 is nice, but you do know that function is hardcoded to return 0?

05 Jun 2013

Hi Erik

/media/uploads/b34196/iic_acks.jpg

these tiny functions are not sending anything, just configures the register prior to the IIC transfer.

Pavel

05 Jun 2013

I realise(d) that, however it works quite a bit different than the NXP implementation. Anyway the issue there was here has been fixed a bit ago.

20 Aug 2013

Erik is right, this issue has been fixed, so I'm going to close this.