Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

I2C Slave does not work (STM32F103) #2585

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
AndKe opened this issue Dec 1, 2024 · 28 comments
Closed

I2C Slave does not work (STM32F103) #2585

AndKe opened this issue Dec 1, 2024 · 28 comments
Labels
invalid This doesn't seem right

Comments

@AndKe
Copy link

AndKe commented Dec 1, 2024

Describe the bug
I2C slave does not recieve requests.

To Reproduce

#include <Wire.h>
long lastms;
volatile int x = 0;
volatile int y = 0;

static void receiveEvent(int howMany) {
  x = Wire.read();
}

static void requestEvent() {
  y = 1;
}

void setup() {
  Serial.begin(115200);

  pinMode(PB6, INPUT); //PB6=SCL
  pinMode(PB7, INPUT); //PB7=setSDA
  pinMode(PC13, OUTPUT);

  Wire.setSCL(PB6);
  Wire.setSDA(PB7);
  Wire.begin(11);                // join i2c bus as slave
  //Wire.onRequest(requestEvent);  // register event
  Wire.onReceive(receiveEvent);  // register event
  lastms = millis();
}

void loop() {
  if (millis() > lastms + 1000) {
    Serial.print("-");
    lastms = millis();

  }
  if (x != 0) {
    Serial.print("U:0x");
    Serial.println(x, HEX);
    //digitalWrite(PC13,!digitalRead(PC13));
    x = 0;
  }
  if (y != 0) {
    Serial.println("V");
    y = 0;
  }
}

Steps to reproduce the behavior:

  1. Run the code om STM32F103Cx
  2. the code expects requests from master to address x0xB / 11d
  3. I see the data requests using a oscolloscope/logic analyzer on PB6/PB7
  4. The software outputs only "-"

Expected behavior
I'd expect it to work like it does on Atmega/atmel controllers - where this code works. see arduino/ArduinoCore-API#241

Than I rebuilt it all using Arduino Core 2.9.0 (current release)
On Core 2.9.0 - the PB6 is at least not pulled low - which is good, but it still does not work.

image

Desktop (please complete the following information):

  • OS: Linux Ubuntu24.10
  • Arduino IDE version: 2.3.3
  • STM32 core version: 2.9.0
  • Tools menu settings if not the default: [e.g. Newlib Standard, No Serial]
  • Upload method: SWD

Board (please complete the following information):

  • Name: Bluepill STM32F103C8
  • Hardware Revision: n/a
  • Extra hardware used if any: -
@fpistm
Copy link
Member

fpistm commented Dec 1, 2024

Do you have pullup resistors on each I2c lines?

@AndKe
Copy link
Author

AndKe commented Dec 1, 2024

Yes, and - I can see the I2C packets using an oscilloscope on the pins. (decoded on the scope)
Plus : for simple troubleshooting I hooked it up on a breadboard. When I do the very same setup, but switch the blackpill an Atmega based arduino boards - it works.

@fpistm
Copy link
Member

fpistm commented Dec 1, 2024

Could you share the master example?

@AndKe
Copy link
Author

AndKe commented Dec 1, 2024

@fpistm unable, the master is Ardupilot (which is open source)- if you have some hardware that can run Ardupilot, and configure BATT_MONITOR 5 - then you have that I2C traffic too.

The traffic is really nothing special - it is all about spotting a normal 7-bit address that is being interrogated by a master. I bet this is reproducible with a ny simple Arduino program that tried to read data from a I2C device (just set the address to the same on both ends.)

@AndKe
Copy link
Author

AndKe commented Dec 2, 2024

Please see attached communication capture with device 0xB - the capture should clarify any questions you might have about protocol/timing etc. it is captured using Saleae logic analyzer, which is perfectly multi-platform with nice software: https://www.saleae.com/pages/downloads

BMSEmu Boot.zip

@fpistm
Copy link
Member

fpistm commented Dec 2, 2024

Thanks for inputs. I will try to test on my side but don't know when as I'm fully busy on other tasks.

@AndKe
Copy link
Author

AndKe commented Dec 2, 2024

Thank you, I am really stuck on this one, I "modernized" previous design (Atmega32u4) by dropping in STM32F103, and now - with plenty of new PCB's manufactured, I am stuck with this issue.
I have previously had projects with STM32F103C8 and CB acting as master without any issues.

@AndKe
Copy link
Author

AndKe commented Dec 2, 2024

Additional information; the exactly same happens when SCL=PB10 and SDA=PB11

@AndKe
Copy link
Author

AndKe commented Dec 2, 2024

@fpistm I understand that you are busy, but is there some way to ...motivate... you or another competent contributor here to solve this?

@fpistm
Copy link
Member

fpistm commented Dec 3, 2024

Just a question you said you used a BluePill but you select a blackpill on your screenshot ?

@AndKe
Copy link
Author

AndKe commented Dec 3, 2024

Yes, the blackpill is an error on my side.
The device in question is something that did not work as I2C slave after being ported from Atmega32U4 And all issues here are about STM32F103C8T6. be it on my hardware, or Bluepill.

After much troubleshooting I made this test app above, and ran it on Atmega32u4 for comparsion/to verify it.
Then I also moved from my board to an actual bluepill (just to easily test on PB10/PB11) .
During the compilations for various targets, I must have messed it up.
I will retest that once I get home, in about 2 hours.

BTW: I have also tried to build it on VSCode w/platformio (and Arduino library) - with same results. So me trying both Arduino and all that are kind of desperate attempts to make it work :)

@AndKe
Copy link
Author

AndKe commented Dec 3, 2024

@fpistm corrected, and I can confirm that setting "Bluepill" as target did not change the result.

@ItsXor
Copy link

ItsXor commented Dec 4, 2024

I can confirm this issue exists.
Only input I can give is that Wire Slave sometimes accepts data right after reset, maybe first 300ms.
This issue is not present in other core (https://github.com/rogerclarkmelbourne/Arduino_STM32).
Would love this to be resolved because SimpleFOC only works with this core, but I can't control my Bluepill as I2C slave simultaneously.

@AndKe
Copy link
Author

AndKe commented Dec 4, 2024

@ItsXor Thank you! - for making me doubt my sanity. I started to wonder how this was possible, without anyone spotting it before.
I would love to know what can be brought over from that core into PlatformIO (as my project is really there, and I do not really know if PlatformIO can somehow use that core without much hacking.
On the other hand, I just hope one of the skilled STM engineers can trow together a fix soon.

@AndKe
Copy link
Author

AndKe commented Dec 7, 2024

@fpistm Dear STM - please note: "all I want for Christmas is a fix for I2C Slave" - this is the losest "writing to Santa" i ever did. :)

@fpistm
Copy link
Member

fpistm commented Dec 12, 2024

Will try to work on this soon anyway any help will be appreciated.

@AndKe
Copy link
Author

AndKe commented Dec 12, 2024

@fpistm very glad to hear that. Unfortunately I won't be of much help nailing the issue(insufficient skills in the area), but I definitely can help testing or running a debug build.

@fpistm
Copy link
Member

fpistm commented Dec 17, 2024

@AndKe
I've start to check your issue.
What is exactly your issue?
Your talk about:

2- the code expects requests from master to address x0xB / 11d

but onRequest is comment on your code and see no Wire.write on your code?
So I don't understand your issue.

I've tested all the examples from Wire for Master (send/receive) and Slave(send/receive) and they work.

@fpistm
Copy link
Member

fpistm commented Dec 17, 2024

Here test sketch:

Master
#include <Wire.h>

#define I2C_ADDR  11

static byte x = 1;

void setup()
{
  Wire.begin();        // join i2c bus (address optional for master)
  Serial.begin(9600);  // start serial for output
}

void loop()
{
  Wire.requestFrom(I2C_ADDR, 1);  // request 1 bytes from slave device

  while(Wire.available())         // slave may send less than requested
  {
    char c = Wire.read();         // receive a byte as character
    Serial.println(c, HEX);              // print the character
  }

  delay(10);

  Wire.beginTransmission(I2C_ADDR); // transmit to device
  Wire.write(x);                    // sends one byte
  Wire.endTransmission();           // stop transmitting
  x++;

  delay(500);
}
Slave based on your sketch
#include <Wire.h>
long lastms;
volatile int x = 0;
volatile int y = 0;

static void receiveEvent(int howMany) {
  x = Wire.read();
}

static void requestEvent() {
  Wire.write(y++);
}

void setup() {
  Serial.begin(115200);
  Wire.begin(11);                // join i2c bus as slave
  Wire.onRequest(requestEvent);  // register event
  Wire.onReceive(receiveEvent);  // register event
  lastms = millis();
}

void loop() {
  if (millis() > lastms + 1000) {
    Serial.print("-");
    lastms = millis();

  }
  if (x != 0) {
    Serial.printf("U:0x %x\n", x);
    x = 0;
  }
}

Note that I've clean up useless thing and optimize the slave. When you get the request you have to send it immediately else you missed the target.

@fpistm fpistm added the invalid This doesn't seem right label Dec 17, 2024
@AndKe
Copy link
Author

AndKe commented Dec 17, 2024

@fpistm I believe that the commented Wire.onRequest(requestEvent) part was just another desperate test.
The main issue is that when acting as slave, (recieving traffic) the device just kept holding SCL low "forever".

I uploaded the "Slave based on your sketch" that you posted,
On the bus, I have a ArduPilot I2C as master. it is requesting data:
image

Please note how the SCL is suddenly kept low indefinitely.

Then another capture: the F103 is running fine for several selconds, and then I connect the I2C bus (where the master is talking to it.)
image

Please note that in both cases: the F103 is the one that is stuck keeping the SCL low - intil reset - disconnecting master leaves a fully functional I2C master.

Please see the Saleae logic capture - Saleae capture.zip
You can open the files using https://www.saleae.com/pages/downloads the tool is multiplatform and free.

When SCL is stuck low like that, the "-" is no longer printed. (most likely the device is crashed/hung/looped at that point)

@fpistm
Copy link
Member

fpistm commented Dec 17, 2024

Please test sketches provided.
I can't reproduce.

And what is your full setup. You talk about Ardupilot but it seems to be a dedicated software.

What does the Ardupilot software does? Are you sure I2C @ used by the master to request data is the correct one?

@AndKe
Copy link
Author

AndKe commented Dec 17, 2024

@fpistm
Ardupilot project: https://github.com/ArduPilot/ardupilot
It uses I2C quite much for all kinds of internal sensors, but usually has an external I2C bus for less-critical devices.
To be precise: this is the part I am trying to communicate with: https://github.com/ArduPilot/ardupilot/blob/master/libraries/AP_BattMonitor/AP_BattMonitor_SMBus_Solo.cpp

Yes, I've been emulating that BMS for several years using Atmega 328 and Atmega32u4 with Arduino libraries.
This whole issue started as I discovered that compiling my code for STM32F103
(I have used STM32 for many other projects, as I2C master, and it always worked fine)

That's why we are now trying to do basic stuff like trying to see a write requests as a slave.

I loaded master sketch on another STM32F103 - but it does not generate I2C traffic. (both lines remain high)

Here is my slave firmware:
I2C_test_slave.ino.zip
And my master firmware:
I2C-test-master.ino.zip

Maybe there's something with the toolchain/build environment?
The fact is that I first had trouble with this in VSCode + PlatformIO , then tried Arduino IDE (now 2.3.4) - and I see no difference. That's why I thought this is related to the wire library.

@fpistm
Copy link
Member

fpistm commented Dec 17, 2024

With pullup on each I2C lines?

@AndKe
Copy link
Author

AndKe commented Dec 17, 2024

yes, 10k to 5v for both, of course.

@fpistm
Copy link
Member

fpistm commented Dec 17, 2024

Usually 4.7k and stm32 is 3.3v even if gpio are 5v tolerant.

@AndKe
Copy link
Author

AndKe commented Dec 17, 2024

I know, but this is not the issue here, I do not see some odd levels when looking at the signals with an oscilloscope, crisp and clear - (when there is something to see) my choice is simply because some of the autopilots use 5v buffers for I/O and then 10k is standard.
Did you find some hardware to install Ardupilot on? - or run my binary ? / does your master-build cause any I2C traffic?

@fpistm
Copy link
Member

fpistm commented Dec 18, 2024

I've tested your slave binary and it works on a BluePillF103C8 (with a genuine STM32F103C8) and it works.

does your master-build cause any I2C traffic?

As stated it works...
My setup is simple 2 boards with I2C lines wired (with 4.7K PU on each I2C lines), GND interconnected and that's all.

Request from the master:
image
then 10 ms later sent from the Master:
image

Did you find some hardware to install Ardupilot on?

No, I have no such hardware and will not go further while the basic example not working on your side.
Do you used genuine STM32? Please use 4.7K or less but no 10K....

@fpistm
Copy link
Member

fpistm commented Dec 18, 2024

Finally I've tested with an Ardunio UNO as master (5V) and BluePill with your slave binary and it works.

@stm32duino stm32duino locked and limited conversation to collaborators Dec 18, 2024
@fpistm fpistm converted this issue into discussion #2608 Dec 18, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
invalid This doesn't seem right
Projects
Development

No branches or pull requests

3 participants