K22F and (why not) K64F I2C ack bug

18 Oct 2014


got a new board, the K22F, i tried to talk to the onboard FXOS8700CQ mag/accel sensor with no luck. On the K22F the mag i2c addr is 1C, while in K64F it's 1D, the weird thing was the mbed i2c api ret ok for all slave addr except for 1C (!?!?!!?)

The bug is about the hal apis mistaking ack for nack. The K22F and K64F mcu referencce manual tells I2C status reg bit0 "RXAK" is like this:

Receive Acknowledge
0 Acknowledge signal was received after the completion of one byte of data transmission on the bus
1 No acknowledge signal detected

So it's a nack flag, but i2c_api.c mistakes nack with ack http://developer.mbed.org/users/mbed_official/code/mbed-src/file/d73ca02bc818/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/i2c_api.c

// check if we received the ACK or not
    return I2C_HAL_GetStatusFlag(i2c_addrs[obj->instance], kI2CReceivedNak) ? 0 : 1;

swap the 0:1 to 1:0 and problem solved.

I've not a K64F to try, but code is the same and reference manual tells the same, so i would expect K64F also can't talk to its FXOS with actual mbed-src release.

Hope it helps.

18 Oct 2014

What you write is what the code should be doing if I see it correctly. Possibly confusion is what it should be returning, which is a bit mixed up:

The complete write function returns 0 on success, 1 on failure. The byte write returns 1 on ACK, 0 on NACK.

20 Oct 2014

Yes, it seems they messedup the i2c_byte_write return also in other freescale platforms, but if it just works no one is going to check the writebyte return:) Different thing for the buffer write/read, if the ack/nack are flipped, these function will exit after writing the slave addr, returning a "I2C_ERROR_NO_SLAVE" if the slave is present and does ack back.

For KLXX platform the nack flag is checked correctly btw, so the do_write rets 0=ok

// check if we received the ACK or not
return obj->i2c->S & I2C_S_RXAK_MASK ? 1 : 0; 

and again the i2c_byte_write does not return 0 (mbed api directly forward this return code, but in docs it should return 0=ok)

int i2c_byte_write(i2c_t *obj, int data) {
    // set tx mode
    obj->i2c->C1 |= I2C_C1_TX_MASK;
    return !i2c_do_write(obj, (data & 0xFF));
06 Nov 2014


I completely overlooked this problem. Can you add this to github issues https://github.com/mbedmicro/mbed/issues Wtih description provided here. If not, I can do it.

Update: I'll add an issue there with link to here, if you want to provide more details, feel free to add more or send a pull request with a fix.


Regards, 0xc0170

06 Nov 2014

I didn't get around to checking this out (okay I forgot to), but still weird this would be bugged, how did it ever pass the tests if it cannot properly check ACK?

06 Nov 2014

Here's an issue I created, please provide some detail description there. I am not certain I understood it correctly where is the issue.

Link to an issue https://github.com/mbedmicro/mbed/issues/661.

@Geremia, can you provide some more information there, based on this thread. Why does it work on K64F which shares the same code for I2c?

06 Nov 2014

Sorry my dsl is down so atm i can just clarify. i2c_wait_end_tx_transfer fails because of flipped interpretation of tha nack flag. So the i2c_do_write always fails, which is no problem for the simple writebyte, but is problematic in the i2c_write because it calls the dowrite several time, at first when writing the slave addrs an thats why i observed that all slave addr talks success with inexistent slaves while fails when the slave addr is correct. I dont know but could be the precompiled fxos8700 libs works, i'm referring to it just because i send i2c cmds to it. Ive not a k64f, does i2c works with actual mbed-src? Not an old precompiled fxso lib i mean

Edit: When i tell it fails with I2C_ERROR_NO_SLAVE is because i modified the mbed api to return back the real fail value, not only true/false, and it turns out a success for any inexistent slave addr and a I2C_ERROR_NO_SLAVE when the slave addr was correct, so slave acked back but the bug flipped the result. Take a look at src file line 100 and trace back till the I2C_ERROR_NO_SLAVE error

07 Nov 2014

Martin Kojtal wrote:

Why does it work on K64F which shares the same code for I2c?

Don't know about K64F and automatic tests, but it's a quick check: how many slaves does the K64F find whith this simple code? K22F finds 126 (inexistent) slaves, and does not see at all the only existent one (0x1C).

// I2CU - Search for devices on an I2C bus
// Copyright (c) 2009, sford
// Released under the MIT License: http://mbed.org/license/mit
// Goes through each device address, seeing if it gets a response
//  - for every device if finds, it prints the 8-bit address
//  - if the program hangs, the bus isn't working (check pull-ups etc)
//  - if it doesn't find your device, check power/bus wiring etc
#include "mbed.h"

Serial pc(USBTX, USBRX);
//I2C i2c(PTB3, PTB2); // K22F sda, scl
I2C i2c(PTE25, PTE24); // K64F sda, scl

int main() {
    pc.baud (115200);
    pc.printf("I2CU! Searching for I2C devices...\r\n");
    int count = 0;
    for (int address=0; address<256; address+=2) {
        if (!i2c.write(address, NULL, 0)) { // 0 returned is ok
            pc.printf(" - I2C device found at address 0x%02X\r\n", address>>1);
    pc.printf("%d devices found\r\n", count);

About github, with no offense and sorry for my bad english, i personally think it should be used by few skilled people (not me), to avoid domino effect issues.

07 Nov 2014

Geremia, I'm having problems with I2C right now, but don't yet know if it has anything to do with what you've reported. I just ran I2C under mbed library r89, and my K64F board sees 0 devices.

Correction, now I see 0x00 and 0x3A for some reason.

My problem right now is with a specific device (I2C mux) where I send it a command and my scope indicates that a NACK was generated by the mux, but the mbed I2C library detects an ACK.

07 Nov 2014

Flipped ack/nack is what i'm talking about and since it affects the i2c hal, i would suppose you are facing the same issue, so....if you have time, you could try to compile the code i pasted above and see if it finds 1 device (the onboard mag/accel) or if it finds 126 devices (bugged), just to confirm K64F affected too (it uses the verysame i2c_api.c as for K22F, so why not?). In case it turns out to be bugged (126 devices), import mbed-src and remove mbed lib, open /targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/i2c_api.c and change @line 100 to:

// check if we received the ACK or not
    return I2C_HAL_GetStatusFlag(i2c_addrs[obj->instance], kI2CReceivedNak) ? 1 : 0;
07 Nov 2014

Geremia, I had a typo - I *was* running I2CU with mbed r89 when I found those two devices at 0x00 and 0x3A. At the moment, I imagine that 0x3A is the left-justified equivalent of 0x1D, which is a valid address for the FXOS8700Q.

07 Nov 2014

Ok, this is weird and probably not at all helpful to you. In the process of debugging my I2C problems, I hooked up a device (BlinkM) that I had working fine before. I couldn't get any commands to work. I then ran I2CU (compiled against r89 and r88 of the mbed library), and both of them found 128 devices.

I then decided to pull the USB connection to do a complete power cycle, and now I only see the previous two devices at 0x00 and 0x3A. That said, once I plugged my BlinkM modules, I still couldn't get them to work. :(

07 Nov 2014

I will change that part but still does not work! ... which could be the problem ?? I do not mind moving the card do not change the results will have to change some frequency or something?

07 Nov 2014

r89 is dated 12 september, looking at mbed-src of 11 and 12 september i can see the i2c hal for K64F is correct, don't know at which mbed-src revision they changed, and don't know the mbed vs mbed-src revision relationship. Anyway, if you compile I2CU with latest mbed or latest mbed-src, you should have 126 devices, right?

btw, to fix the single byte write, change also @line 235, remove the negation, as pointed by Erik. The signle byte is sent, but if you evaluate the return, you get a false.

return i2c_do_write(obj, (data & 0xFF));
07 Nov 2014

Argh, I apologize for the error. I thought it was r89, but I've just finished some other tests and I am using r88. I have identified a bug in r91 that affects me, but is not related to your problem.

What's screwing me up is that the projects I'm importing (like I2CU) seem to be built using a particular revision of the mbed library, but it's not possible (at least not straightforward to those new to DVCS systems) to go to the latest revision. For example, if you click on mbed under I2CU, and then show Revisions, you'll see r89 at the latest... so I had thought when I was working in other apps that they were also using r89, when in reality they were using r91. I need to be more aware of this in the future.

I tried to update mbed in I2CU, but when I click Update, I get an error dialog that just says "[object Object]" and all I can do is close it. Do you have a way to manually update the mbed library in I2CU? I can test it once I know how to do that...

07 Nov 2014

Ok, that was a dumb question, I just deleted and re-added and was able to get the latest version.

07 Nov 2014

Geremia, you are correct. With r91, I2CU returns 126 devices on the K64F as well. Clearly, I should stay away from this revision until things get sorted out. I'll look over some of the things you've mentioned to see if they make sense as far as resolving the issue goes.

12 Nov 2014

Meanwhile this bug has been fixed by swapping it around as Geremia mentioned, mbed-src has the fix, next mbed release will have it too.

I guess currently I am the one who mainly does K22F/K64F stuff, and was busy IRL lately, causing this to take quite long :).

12 Nov 2014

@Erik, "I guess currently I am the one who mainly does K22F/K64F stuff, and was busy IRL lately, causing this to take quite long :)."

I am not included,huh?

12 Nov 2014

Well then whats your excuse for not fixing it faster :P

Don't worry, you may do all the ethernet crap ;)

Edit: If I say here Martin is the master of all K22F/K64F boards he is gonna send me a Renesas board.

12 Nov 2014
12 Nov 2014

@Geremia, ah this one should be tracked via github. I'll create an issue there, and can fix it based on your fix. have to review it. Thanks !

12 Nov 2014

Github is more likely to get the correct people aware :). STM targets are mainly done by STM themselves. I don't have either of the targets where you got oscillators issue on, so definately can't help you there.

But the PortIn, without looking up how PortIn does it, DigitalIn/Out always reads back the input register on all targets afaik. And if I understand your post correctly thats also what the STM one does. Unless you shorted your output when it is in output mode that should give the same result anyway.

If it is done different there is also a grey area: What should be done when it is in open drain mode? Technically it is an output mode, but half of the time it isn't driving anything and you might want to read back the state.

12 Nov 2014

Martin, the clock issues are of 2 kind: Kenji Arai refers to RTC LSE clock source (rise timeout to 5 seconds to fix it), while i'm referring to HSI default when HSE not present (use "const" instead of "IO const", otherwise compiler will make it volatile, store in ram, ram probably messed up after HSE fails to init, default to HSI, HSI init hangs).

About PortOut (out), i don't remember well actually, but other targets read the input reg, which is unusefull, i know, it's only usefull to check if you have (or going to have) a flamed pin when direction is out.

01 Mar 2017

I'm checking in here on this old thread to see if the new mbed code doesn't have a problem after the OS5 update. I can't get an I2CSlave to receive and ACK a byte at all, but it will send just fine.

I'm essentially using the I2CSlave example code from the mbed OS reference (https://docs.mbed.com/docs/mbed-os-api-reference/en/latest/APIs/interfaces/digital/I2CSlave/), but I'm using a K64F with the slave on I2C1 (PTC11 and PTC10).

On an oscilloscope, I can see the address ACK, I can see the master ACK when the slave writes, but the slave will not ACK when written to by the master, e.g. slave.read(&buf[0], 1). I flip the blue LED when in the I2CSlave::WriteAddressed case of the switch, and the LED changes, then the code hangs on the read statement. I know it hangs because I try flipping the LED back directly after the read, but it stays on.

Has anyone else seen any issues with this?


- Just Gary

03 Mar 2017

...So I tried my code on an LPC1768 (after changing the pin numbers) and it works fine....

This smacks of a library problem for the K64F.