ARMmbed / mbed-os

Arm Mbed OS is a platform operating system designed for the internet of things
https://mbed.com
Other
4.63k stars 2.96k forks source link

I2C multi-writes do not work on NUCLEO_L073RZ #15324

Open rblaze opened 1 year ago

rblaze commented 1 year ago

Description of defect

When running a code like this, only the first write happens on the affected platform. Neither second write nor STOP condition happens.

    bus.write(addr, reg, sizeof(reg), true);
    bus.write(data[0]);
    bus.stop();

On NUCLEO_F103RB writes happen as expected. I'm attaching analyzer screenshots for both.

Target(s) affected by this defect ?

NUCLEO_L073RZ, verified with logic analyzer Probably NUCLEO_L432KC as well: my firmware has the same issues on it.

Toolchain(s) (name and version) displaying this defect ?

GCC_ARM arm-none-eabi-gcc (15:10.3-2021.07-4) 10.3.1 20210621 (release)

What version of Mbed-os are you using (tag or sha) ?

b482f2dcecf14e1d1c3bc36e7f3455f9d6d11302

What version(s) of tools are you using. List all that apply (E.g. mbed-cli)

$ mbed-tools --version
7.55.0

How is this defect reproduced ?

Compile and run this program.

#include "mbed.h"

I2C bus(PB_9, PB_8);

int main()
{
    int addr = 0x77 << 1;
    char reg[1] = { 0xE0 };
    char data[1] = { 0xB6 };

    printf("Sending reset\n");

    bus.write(addr, reg, sizeof(reg), true);
    bus.write(data[0]);
    bus.stop();

    printf("Done\n");
    return 0;
}

L073R_bad_write F103RB_good_write

mbedmain commented 1 year ago

@rblaze thank you for raising this issue.Please take a look at the following comments:

What Mbed OS version are you using? It would help if you could also specify the versions of any tools you are using?

NOTE: If there are fields which are not applicable then please just add 'n/a' or 'None'. This indicates to us that at least all the fields have been considered. Please update the issue header with the missing information.

0xc0170 commented 1 year ago

cc @ARMmbed/team-st-mcd

rblaze commented 1 year ago

FWIW, doing single-byte like below writes works perfectly.

    bus.start();
    bus.write(addr);
    bus.write(reg);
    bus.write(data[0]);
    bus.stop();
rvasquez6089 commented 1 year ago

@rblaze Have you tried using arm-none-eabi-gcc 10.2.xxx?

rblaze commented 1 year ago

I didn't. 10.3 is what comes with my Ubuntu distribution. I can try downgrading, but I need to find out how.

rvasquez6089 commented 1 year ago

Oops, I was mistaken. I also use 10.3.1. I was hoping this might be a compiler issue. Have you tried writing i2c data out like this? I wonder if it has something to do with repeated start parameter in the I2C::write() function. Sounds like it could be HAL bug.

#include "mbed.h"

I2C bus(PB_9, PB_8);

int main()
{
    int addr = 0x77 << 1;
    char data[2] = { 0xE0, 0xB6 };

    printf("Sending reset\n");
    bus.write(addr, data, 2);
    printf("Done\n");
    return 0;
}
rblaze commented 1 year ago

Complete writes work just fine. It's only if I add "repeated" flag next writes and the stop condition get lost.

JohnK1987 commented 1 year ago

Hello,

families L1, F1, F2 and F4 use I2C_IP_VERSION_V1, the rest families use I2C_IP_VERSION_V2. These versions are different in I2C implementation.

So according to your description

Target(s) affected by this defect ?

NUCLEO_L073RZ, verified with logic analyzer Probably NUCLEO_L432KC as well

so all ST targets what use I2C_IP_VERSION_V2 could be affected.

BR, Jan

multiplemonomials commented 1 year ago

I am pretty sure I know what's going on here: the STMicro I2C code relies on the user calling start() before calling the single-byte write() function to set up some initial conditions. Some extra logic will probably be needed to handle this case.