Skip to content
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

ESP32-S2 I2C getting stuck in write loop after first ACK #5470

Closed
caternuson opened this issue Jul 27, 2021 · 28 comments · Fixed by #5683
Closed

ESP32-S2 I2C getting stuck in write loop after first ACK #5470

caternuson opened this issue Jul 27, 2021 · 28 comments · Fixed by #5683
Assignees

Comments

@caternuson
Copy link
Contributor

Hardware:

Board: Adafruit FunHouse
Core Installation version: 2.0.0-rc1
IDE name: Arduino IDE 1.8.13
Flash Frequency: 80Mhz
PSRAM enabled: yes
Upload Speed: 921600
Computer OS: Ubuntu

Description:

Can not initialize the included I2C sensors (DPS310 and AHT20). Attempting an I2C scan results in board reset cycling.

Sketch:

You can probably see this by using any ESP32-S2 board, wiring up something to I2C, and running the I2C scanner sketch.

Example shown here is for attempting to directly use the DPS310 sensor, which is at 0x77. Library here.

#include <Adafruit_DPS310.h>

Adafruit_DPS310 dps;

void setup() {
  Serial.begin(9600);
  while (!Serial) delay(10);
  Serial.println("DPS310 Test.");
  
  if (! dps.begin_I2C()) {
    Serial.println("Failed to find DPS");
    while (1) yield();
  }
  Serial.println("DPS OK!");
}

void loop() {
}

Debug Messages:

This is a run time issue. Code compiles and uploads fine. Serial monitor output FWIW:
Screenshot from 2021-07-27 13-30-19

Here is what is happening on the I2C bus. A write is initiated and the sensor ACKs:
Screenshot from 2021-07-27 13-32-41

Then it goes into an infinite loop writing out 0x00.
Screenshot from 2021-07-27 13-34-34

Those 0x00 writes only stop when the board finally resets at some point.

@marcboon
Copy link

I'm using a SSD1306 OLED display on a ESP32S2-Saola-1 board, with the same 2.0.0-rc1 core version, and the I2C works fine, using the Adafruit SSD1306 library.

@chegewara
Copy link
Contributor

After checking this board schematics and Wire library i would say it is expected it wont work. What is interesting is that you are getting anything with logic analyzer.
That board is using pins 33 and 34 for I2C which are not standard I2C pins.
Another interesting thing is this adafruit sef-test code which is the same and seems it should work:
https://learn.adafruit.com/adafruit-funhouse/arduino-self-test-example

My suggestion is to:

Wire.begin(34, 33);
...
dps.begin_I2C(0x77, &Wire);

@caternuson
Copy link
Contributor Author

Wouldn't it end up using the pins defined in the variants file:

static const uint8_t SDA = 34;
static const uint8_t SCL = 33;

when it gets here for SDA:
sdaPin = SDA; //use Default Pin

and here for SCL:
sclPin = SCL; // use Default pin

@chegewara
Copy link
Contributor

@caternuson Yes, as long as you pick the correct board variant.

@caternuson
Copy link
Contributor Author

The Arduino IDE was set to Tools -> Board -> ESP32 Arduino -> Adafruit FunHouse. Is there an additional step?

@chegewara
Copy link
Contributor

chegewara commented Aug 11, 2021

That should be enough, but just in case i would test i2c_scanner with explicit pins in Wire.begin(34, 33).
Im not saying it will fix your problem, but who knows.

PS never trust code that you didnt write and test personally, including all libraries and arduino-esp32

@caternuson
Copy link
Contributor Author

This I2C scanner sketch:

#include <Wire.h>

void setup()
{
  Wire.begin(34, 33);
  Serial.begin(9600);
  while (!Serial);
  Serial.println("\nI2C Scanner");
}


void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknown error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}

Results in this in the Serial Monitor:
Screenshot from 2021-08-11 13-36-39

And this on the I2C bus:
Screenshot from 2021-08-11 13-38-23

Once it gets to the first address with a device and gets an ACK, it gets stuck in same loop mentioned in first post above.

Here's the last address (0x37) without a device:
Screenshot from 2021-08-11 13-40-34

And the next address (0x38) which does have a device:
Screenshot from 2021-08-11 13-41-31

The write sequence cutoff in that capture continues forever:
Screenshot from 2021-08-11 13-43-58

@chegewara
Copy link
Contributor

@caternuson I dont have this board, so my question:

  • does this board use native USB?
    After selecting the board in arduino IDE i can see it is enabling USB CDC, so i am guessing it does.

I did some test with custom board that is using native USB and I2C on pins 16/17 works fine, then i changed I2C pins to 33/34 and code stuck. Next test i performed with saola and both tests passed.

@me-no-dev I am suspecting some conflict between I2C on particular pins and native USB.

@caternuson Could you perform one more test (it may be not easy):

  • please change USB CDC enable on boot => disable
    OR
  • Serial over UART
    i dont know which one option exists in RC1
    You will not see any logs, but you should see change with logic analyzer. Thanks

@caternuson
Copy link
Contributor Author

@chegewara Thanks for looking at this. Yep, it's native USB. Here's what the Arduino IDE looks like with RC1:
esp32s2_sercon

Sorry, not sure I follow your suggested next test. Tried switching to the UART0 option, but seeing the same results in the logic analyzer. Were you suggesting something else? Happy to test whatever. Also, FWIW, the only other ESP32-S2 board I currently have access to is an Unexpected Maker FeatherS2.

@chegewara
Copy link
Contributor

chegewara commented Aug 11, 2021

Actually i want to correct myself. Previous test was without any I2C device connected.
After connecting I2C 4x20 display and scanner app to test it on arduino-esp32 master i have this crash on pins 16/17:

Guru Meditation Error: Core  0 panic'ed (Interrupt wdt timeout on CPU0). 

Core  0 register dump:
PC      : 0x4002a028  PS      : 0x00060034  A0      : 0x800251fc  A1      : 0x3ffc02a0  
A2      : 0x3ffcd5c0  A3      : 0x3ffc02dc  A4      : 0x3ffc02d4  A5      : 0x00000000  
A6      : 0x00000000  A7      : 0x3ffcd60c  A8      : 0x8002a0fc  A9      : 0x3ffc0290  
A10     : 0x00060023  A11     : 0x00000001  A12     : 0x00060021  A13     : 0x3ffcd5c0  
A14     : 0x00000001  A15     : 0x00000001  SAR     : 0x0000001f  EXCCAUSE: 0x00000005  
EXCVADDR: 0x00000000  LBEG    : 0x00060021  LEND    : 0x3ffcd5c0  LCOUNT  : 0x40026408  
Core  0 was running in ISR context:
EPC1    : 0x40088377  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x4002a028
Decoding stack results
0x4002a025: xQueueGenericSendFromISR at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c line 984
0x400251f9: i2c_isr_handler_default at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/i2c.c line 506
0x4002b479: xTaskGetCurrentTaskHandleForCPU at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c line 4477
0x400839e7: i2c_master_cmd_begin at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/driver/i2c.c line 1491
0x400813f0: i2cWrite at /home/chegewara/Documents/arduino-1.8.13/hardware/espressif/esp32/cores/esp32/esp32-hal-i2c.c line 1846
0x400811f5: TwoWire::endTransmission(bool) at /home/chegewara/Documents/arduino-1.8.13/hardware/espressif/esp32/libraries/Wire/src/Wire.cpp line 150
0x40081269: TwoWire::endTransmission() at /home/chegewara/Documents/arduino-1.8.13/hardware/espressif/esp32/libraries/Wire/src/Wire.cpp line 333
0x4008100d: Scanner() at /home/chegewara/demos/arduino/i2c_scanner/i2c_scanner.ino line 27
0x4008109d: setup() at /home/chegewara/demos/arduino/i2c_scanner/i2c_scanner.ino line 14
0x40081c9a: loopTask(void*) at /home/chegewara/Documents/arduino-1.8.13/hardware/espressif/esp32/cores/esp32/main.cpp line 38

To make sure my tests are full i also tested with esp-idf example on master branch and all works fine.

@chegewara
Copy link
Contributor

@caternuson It is bug in arduino-esp32 and has to be fixed

@caternuson
Copy link
Contributor Author

@chegewara Thanks. Need any more info or tests from me?

@chegewara
Copy link
Contributor

@me-no-dev I think this is breaking PR, but didnt confirmed yet:
5502879

@chegewara
Copy link
Contributor

@caternuson There is simple temporary fix for the issue that allows to run scan and probably I2C too.
Try this fix on your local arduino-esp32:

i2c_err_t i2cWrite(i2c_t * i2c, uint16_t address, uint8_t* buff, uint16_t size, bool sendStop, uint16_t timeOutMillis){
	esp_err_t ret = ESP_OK;
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
    if(size) 
        i2c_master_write(cmd, buff, size, ACK_CHECK_EN);
    //if send stop?
    i2c_master_stop(cmd);
    ret = i2c_master_cmd_begin(i2c->num, cmd, timeOutMillis / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    return ret;
}

https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-i2c.c#L1846-L1857

@caternuson
Copy link
Contributor Author

@chegewara That seems to work. I tweaked the scanner sketch slightly to have the begin call just be:

Wire.begin();

just to test that the variant info is working as expected as well.

With your BSP changes above, now get this (expected) output in Serial Monitor:
Screenshot from 2021-08-11 16-53-22

Logic trace is also as expected:
Screenshot from 2021-08-11 16-59-56

@me-no-dev
Copy link
Member

if(size) is the change? @chegewara

@chegewara
Copy link
Contributor

chegewara commented Aug 12, 2021

if(size) is the change? @chegewara

yes, but i am not sure if this is complete fix, tested only with i2c_scanner

@me-no-dev
Copy link
Member

at least it fixes scan :) I would have thought that IDF would handle this situation...

@me-no-dev
Copy link
Member

@chegewara want to add this fix as PR?

@chegewara
Copy link
Contributor

Thats possible. I tested IDF with this example just to perform scan:
https://github.com/espressif/esp-idf/tree/master/examples/peripherals/i2c/i2c_tools

Since the fail is when IDF function is performing write with 0 length buffer it may be issue with IDF.

@chegewara want to add this fix as PR?

no, thanks but no. i feel offended by espressif, so no more PRs

@SuGlider
Copy link
Collaborator

@caternuson
Please check Arduino Core 2.0.0 PR #5664
This is a complete I2C Wire refactorng. Success reported on #4729 and on the PR itself #5664.
It may solve the issue as well.

@caternuson
Copy link
Contributor Author

@SuGlider Is that an alternative to #5528? That's been merged and fixed this issue as well.

@SuGlider
Copy link
Collaborator

SuGlider commented Sep 14, 2021

@caternuson
It is the whole fix, including i2c scan and a better way to send reStart and other i2c events.

This PR will be merged to main line soon, replacing #5528

@caternuson
Copy link
Contributor Author

@SuGlider Tested #5664 and it works with an I2C scanner and the DPS310 test sketch if original post above.

Just to make sure I tested correctly, here are the general steps taken:

  • Install ESP32 BSP 2.0.0 via Arduino IDE Boards Manager
  • Cloned this repo git clone ... to a temporary location
  • Fetched the PR code git fetch origin pull/5664/head:pr5664
  • Checkout those changes git checkout pr5664
  • Manually copied the 4 files into the appropriate location under .arduino15/packages/esp32/hardware/esp32/2.0.0
  • Compiled/upload sketches via Arduino IDE

@SuGlider
Copy link
Collaborator

Yes, perfect.
Happy that everything worked as expected.

Thanks for taking time to test it and report back here!

@me-no-dev
Copy link
Member

Hi could you please re-test with this new PR: #5683

@me-no-dev me-no-dev assigned me-no-dev and unassigned SuGlider Sep 20, 2021
@caternuson
Copy link
Contributor Author

@me-no-dev Tested #5683 on Funhouse with I2C scanner sketch and DP310 test sketch. Same basic tests as above. Both sketches ran as expected.

@me-no-dev
Copy link
Member

Thanks @caternuson !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants