STM32 i2c slave mode address requires a left shift as the HAL does not do it.
in MBED OS slave.address() does not handle this internally as most other MCUs doesn’t seem to require this or handle it in their respective HALs.
this results in the actual i2c address being wrong.
reference: ST Community
STM32 IDE’s code generator generates something like this when using the GUI configuration tool and i2c address is set to 0x32.
So for mbed OS, since the STM32 HAL does not handle this, the address() function within I2CSlave should check if STM32 HAL is called and if true left shift the address value.
Otherwise this is how I have to use that function now: slave.address(0x25<<1);
slave’s I2CSlave::address - The address to set for the slave (least significant bit is ignored).
Therefore, all methods must already have a shifted value as an address parameter. Lets test it.
I2C Master (Nucleo-F446RE):
#include "mbed.h"
int main(){
printf("Mbed OS version %d.%d.%d\n\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);
printf("\nI2C start...\n");
I2C i2c(PB_9, PB_8);
char cmd[3] = {0x41, 0x42, 0x43};
// lets say some real address from datasheet in 7bit format is 0x50h
uint8_t addr7bit = 0x50;
printf("7bit address: 0x%02X\n",addr7bit);
// bit shift to left because parametr address of write/read must be byte = 8bits
// result will be 0xA0h - 7bits of slave address and 1 bit of direction
uint8_t addr8bit = addr7bit << 1;
printf("8bit address: 0x%02X\n", addr8bit);
// we will put 8bit into but it is still 7b
if (i2c.write(addr8bit, cmd, 3) == 0 ) {
printf("ACK at (7bit) address: 0x%02X\n", addr7bit);
}
thread_sleep_for(50);
printf("Program end\n");
}
Master debug output:
Mbed OS version 6.15.1
I2C start...
7bit address: 0x50
8bit address: 0xA0
ACK at (7bit) address: 0x50
Program end
Slave code (Nucleo-L152RE) is unchanged I2CSlava example what you also mentioned above.
Slave debug output:
Read A: ABC
That mean the slave device was addressed for write. So it seems be OK.
I can imagine that connecting an Arduino I2C master to an Mbed I2C slave can be chotick for you because both sides use different rules, but because Mbed doesn’t do it like Arduino doesn’t mean it’s wrong, or?
your testing methodology results in a double negative, you are testing STM32 HAL i2c slave and STM32 HAL i2c master. So in both cases you are not left shifting the address value causing the result to be a false positive.
Now test this against linux. Say a Pi or anything else you prefer. And use i2c-detect and you’ll get the wrong value that when left shifted will be the value you passed to the address() function.
It’s not because arduino does it, its because STM32 CUBE IDE itself does it. My example in the original post of hi2c1.Init.OwnAddress1 = (0x32*2); was not written by me but generated by the IDE.
Check attached screenshots for what STM32 CUBE IDE GUI configuration generates automatically.
There is one difference. Your examples does bit shifting automatically and Mbed does not and must be done manually. That is not a bug because it is functional and working like that for many years (longer than a Zephyr exist).
Address is always bit-shifted by user in Mbed, as I wrote. The value 0xA0 in I2CSlave example is 0x50 already bit shifted address.
I already did it two years ago. I had Nucleo-F303R8 with Mbed(6.2) I2CSlave example connected to Raspbery PI - here. I used exactly same example as above and again it works as expected. RPI saw 0x50 that is 0xA0.
Sure, its fine of it was a dev decision, but at a minimum it should be mentioned here: I2CSlave - API references and tutorials | Mbed OS 6 Documentation that the address needs to be left shifted manually (or mentally while passing the value).
The issue is that a lot of folks come from Arduino IDE and or are used to STM32 Cube IDE handling it for them. Now with Zephyr and more importantly CircutPython and MicroPython in the mix, this decision looks like an exception and not a rule.
Just a feedback from someone who tried to use MBedOS for the first time having had generous experience with the other platforms and it lead me to genuinely believe this was a bug/oversight.