Skip to content

I2C bus stuck after enable/disable I2C master mode #2081

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
brightproject opened this issue Jul 21, 2023 · 1 comment
Closed

I2C bus stuck after enable/disable I2C master mode #2081

brightproject opened this issue Jul 21, 2023 · 1 comment
Labels
invalid This doesn't seem right

Comments

@brightproject
Copy link

brightproject commented Jul 21, 2023

I am using the following hardware:

  1. stm32f401ccu6+ mpu9250 (or rather 6500 - without a magnetometer)
  2. esp32 + mpu9250 (or rather 6500 - without a magnetometer)
    Software:
  3. arduino IDE 1.8.19
  4. example code from here.
    I know for sure that my MPU9250 is fake and does not have a magnetometer.
    But ... now I am conducting an experiment, I take ESP32 + MPU9250 and STM32F4 + MPU9250.
    I flash these two microcontrollers with the same code, of course, for STM32 I choose the core, and for ESP32 I choose the core.
    These cores have different wire.cpp files.
    But the point is not that, on each microcontroller, I compare with the help of a logic analyzer what happens on the I2C bus when the microcontroller communicates with the MPU9250 board.
    So, when I run the code on STM32 + MPU9250, packet transmission starts on the I2C bus.
    The first packet has 3 bytes, then after 99.6ms another packet of 31 bytes, and then after 2.9ms the last packet of 30 bytes and with that all activity on the bus stops.
    In this case, of course, the MPU9250 does not transmit any data to the bus, and nothing is output to the serial.
    stm32f4+mpu9250
    It is impossible to make screenshots in detail, because it is very small and you get a lot of information.
    When I load the code into ESP32 + MPU9250, miracles happen.
    Firstly, the data from the MPU9250 board goes to the serial port.
    Of course, the magnetometer does not give anything - because it does not exist!
    Скриншот 20-07-2023 21 21 56
    But, what is going on on the I2C bus?
    And what happens on the bus is approximately the same as on the STM32F4 bus, only there are differences.
    esp32+mpu9250
    Packet transmission also starts with 3 bytes, and is similar to the packet in STM32F4.
    Then, after 99.3 ms, there is also a packet of 31 bytes and it is similar to the packet in STM32F4.
    But the next packet is different ... it consists of 26 bytes, i.e. 4 bytes shorter than STM32F4.
    Data from the signal analyzer of the third package from STM32F4 + MPU9250 below
    stm32f4_30_bytes
    Data on the I2C bus on the STM32F4
1.
write to 0x68 ack data: 0x6B 0x80 
2.
write to 0x68 ack data: 0x6B 0x00 
write to 0x68 ack data: 0x1D 0x48 
write to 0x68 ack data: 0x1B 0x18 
write to 0x68 ack data: 0x1C 0x00 
write to 0x68 ack data: 0x1A 0x03 
write to 0x68 ack data: 0x19 0x13 
write to 0x68 ack data: 0x1A 0x04 
write to 0x68 ack data: 0x38 0x00 
write to 0x68 ack data: 0x6A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x6A 0x00 
3.
write to 0x68 ack data: 0x37 0x82 
write to 0x0C nak
read to 0x0C nak
write to 0x0D nak
read to 0x0D nak
write to 0x0E nak
read to 0x0E nak
write to 0x0F nak
read to 0x0F nak
write to 0x68 ack data: 0x34 0x04 
write to 0x68 ack data: 0x6B 0x40 
write to 0x68 ack data: 0x6C 0x3F 
write to 0x68 ack data: 0x6A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x64 0x10 
write to 0x68 ack data: 0x6A 0x00 
Stop

Data from the signal analyzer of the third package from ESP32 + MPU9250 below
esp32_26_bytes
Data on the I2C bus on the ESP32 in table

1.
write to 0x68 ack data: 0x6B 0x80 
2.
write to 0x68 ack data: 0x6B 0x00 
write to 0x68 ack data: 0x1D 0x48 
write to 0x68 ack data: 0x1B 0x18 
write to 0x68 ack data: 0x1C 0x00 
write to 0x68 ack data: 0x1A 0x03 
write to 0x68 ack data: 0x19 0x13 
write to 0x68 ack data: 0x1A 0x04 
write to 0x68 ack data: 0x38 0x00 
write to 0x68 ack data: 0x6A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x6A 0x00 
3.
write to 0x68 ack data: 0x37 0x82 
write to 0x0C nak
write to 0x0D nak
write to 0x0E nak
write to 0x0F nak
write to 0x68 ack data: 0x34 0x04 
write to 0x68 ack data: 0x6B 0x40 
write to 0x68 ack data: 0x6C 0x3F 
write to 0x68 ack data: 0x6A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x64 0x10 
write to 0x68 ack data: 0x6A 0x00 
4.
write to 0x68 ack data: 0x6B 0x01 
write to 0x68 ack data: 0x6C 0x00 
write to 0x68 ack data: 0x6A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x64 0x11 
write to 0x68 ack data: 0x6A 0x20 
5.
write to 0x68 ack data: 0x6B 0x01 
write to 0x68 ack data: 0x6C 0x00 
write to 0x68 ack data: 0x6A 
read to 0x68 ack data: 0x20
write to 0x68 ack data: 0x64 0x11 
write to 0x68 ack data: 0x6A 0x20 
6. Data...
write to 0x68 ack data: 0x1A 0x06 
write to 0x68 ack data: 0x19 0x63 
write to 0x68 ack data: 0x34 0x00 
write to 0x68 ack data: 0x34 0x00 
write to 0x68 ack data: 0x3A 
read to 0x68 ack data: 0x05
write to 0x68 ack data: 0x3B 
read to 0x68 ack data: 0xDE 0xF8 0xCE 0x50 0xEF 0x08
write to 0x68 ack data: 0x43 
read to 0x68 ack data: 0xFF 0xB3 0x00 0x2B 0x00 0x1D
write to 0x68 ack data: 0x49 
read to 0x68 ack data: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
write to 0x68 ack data: 0x3A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x3A 

ESP32 on the left, STM32F4 on the right.
Скриншот 21-07-2023 09 40 39
For STM32F4, communication on the I2C bus ends with 3 packets.
For ESP32 after three packet of data, activity on the I2C bus continues .
After the third packet of data, after 49.9 ms there is a packet of data consisting of 16 bytes, and then, also after 49.9 ms, another packet of data consisting of 16 bytes.
esp32_data
Well, then, after 50.1 ms, the actual data transfer from the MPU9250 begins and this data is output to the ESP32 serial port.
esp32_data_all
I don't understand what's wrong with my STM32F4 or MPU9250?
The I2C bus on STM32F4 works, but stops working.
@fpistm everything works for you ...
I noticed that in the wire.cpp file of the ESP32 there is no bit shift to the left for the device address, in the wire.cpp file of the STM core this happens.

  ownAddress = address << 1;

  _i2c.isMaster = (address == MASTER_ADDRESS) ? 1 : 0;

  _i2c.generalCall = (generalCall == true) ? 1 : 0;

  _i2c.NoStretchMode = (NoStretchMode == true) ? 1 : 0;

  recoverBus(); // in case I2C bus (device) is stuck after a reset for example

  i2c_custom_init(&_i2c, 100000, I2C_ADDRESSINGMODE_7BIT, ownAddress);

I tried to remove the bit shift of the address, but there are no changes in the work.
Only a different address is written to the I2C bus, apparently in the ESP32 core, the device address is shifted elsewhere(or file) in order to have a 7-bit address.
...
Termination of activity on the I2C bus occurs after the execution of the code

Pack 1
write to 0x68 ack data: 0x6B 0x80  //inv_mpu.c string 652 pwr_mgmt_1
Pack 2
write to 0x68 ack data: 0x6B 0x00  //inv_mpu.c 658 pwr_mgmt_1
write to 0x68 ack data: 0x1D 0x48  //inv_mpu.c 668 accel_cfg2
write to 0x68 ack data: 0x1B 0x18  //inv_mpu.c 1171 gyro_cfg
write to 0x68 ack data: 0x1C 0x00  //inv_mpu.c 1236 accel_cfg
write to 0x68 ack data: 0x1A 0x03  //inv_mpu.c 1305/1368 lpf
write to 0x68 ack data: 0x19 0x13  //inv_mpu.c 1358 rate_div
write to 0x68 ack data: 0x1A 0x04  //inv_mpu.c 1361 lpf
write to 0x68 ack data: 0x38 0x00  //inv_mpu.c 579 int_enable
write to 0x68 ack data: 0x6A       //user_ctrl, mpu_set_bypass
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x6A 0x00  //user_ctrl
Pack 3
write to 0x68 ack data: 0x37 0x82 //inv_mpu.c 2868 mpu_set_bypass(1)
/* Find compass. Possible addresses range from 0x0C to 0x0F. */
write to 0x0C nak                 //inv_mpu.c 2871 find compass - no
read to 0x0C nak
write to 0x0D nak
read to 0x0D nak
write to 0x0E nak
read to 0x0E nak
write to 0x0F nak
read to 0x0F nak//Compass not found
write to 0x68 ack data: 0x34 0x04 //inv_mpu.c 1408 s4_ctrl
write to 0x68 ack data: 0x6B 0x40 
write to 0x68 ack data: 0x6C 0x3F 
write to 0x68 ack data: 0x6A 
read to 0x68 ack data: 0x00
write to 0x68 ack data: 0x64 0x10 //inv_mpu.c 1614 s1_do
write to 0x68 ack data: 0x6A 0x00 //inv_mpu.c 1617
Stop

Simple code works great on stm32f401ccu6+ mpu9250

#include "Wire.h"
const int MPU_addr = 0x68; // sensor address
// data array
// [accX, accY, accZ, temp, gyrX, gyrY, gyrZ]
// acc - acceleration, gyr - angular velocity, temp - temperature (raw)
int16_t data[7];  
void setup() {
  // initialization
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up)
  Wire.endTransmission(true);
  
  Serial.begin(115200);
}
void loop() {
  getData();  // get data
  // print
  for (byte i = 0; i < 7; i++) {
    Serial.print(data[i]);
    Serial.print('\t');
  }
  Serial.println();
  delay(200);
}
void getData() {
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers
  for (byte i = 0; i < 7; i++) {
    data[i] = Wire.read() << 8 | Wire.read();
  }
}

and I get raw data ACCEL_XOUT_H on I2C

write to 0x68 ack data: 0x6B 0x00 
write to 0x68 ack data: 0x3B 
read to 0x68 ack data: 0xF2 0x4C 0x00 0xC8 0x41 0x88 0x0E 0x20 0xFD 0xAB 0x01 0x93 0x00 0x9A
write to 0x68 ack data: 0x3B 
read to 0x68 ack data: 0xF2 0x68 0x00 0xA0 0x41 0x7C 0x0E 0x70 0xFD 0xBA 0x01 0x86 0x00 0xB8
write to 0x68 ack data: 0x3B 
read to 0x68 ack data: 0xF2 0x50 0x00 0xAC 0x41 0x8C 0x0E 0x70 0xFD 0xA0 0x01 0x8E 0x00 0xAC
write to 0x68 ack data: 0x3B 
read to 0x68 ack data: 0xF2 0x34 0x00 0xD0 0x41 0x20 0x0E 0x50 0xFD 0xA5 0x01 0x74 0x00 0xA1
write to 0x68 ack data: 0x3B 
read to 0x68 ack data: 0xF2 0x90 0x00 0x90 0x41 0x94 0x0E 0x40 0xFD 0xA2 0x01 0x6B 0x00 0xBB
write to 0x68 ack data: 0x3B 
read to 0x68 ack data: 0xF2 0x98 0x01 0x10 0x41 0x7C 0x0E 0x50 0xFD 0x97 0x01 0x6D 0x00 0xE1

and Serial.
Скриншот 21-07-2023 15 53 25
I also found that the core uses a not very fresh Wire library, but everything works for others, it doesn’t work only with my hardware (I have 3 BlackPills).
What could be the problem?

@fpistm fpistm added the invalid This doesn't seem right label Jul 21, 2023
@fpistm
Copy link
Member

fpistm commented Jul 21, 2023

Hi @brightproject
please stop to open several issue around your issue.
I will not invest more time around this. If you are able to have small sketch without any external library which show an issue with e this core and Wire implementation, I would be happy to fix.
The third party library you used is not for STM32 and probably it requires some update.

@fpistm fpistm closed this as completed Jul 21, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

2 participants