Description
Hi everybody,
i am currently trying to implement an I2C connection between an ESP32-WROVER and a Raspberry Pi Pico (RP2040). The ESP is configured as master and shall request data from the Pico which is configured as slave. Besides requesting data the master also sends data to the slave.
After encountering some issues that the I2C communication is not working properly i created a minimal example for master and slave where the problem still occurs. Regularly the I2C times out (diagnosed by ESP via Debug messages and Logic analyzer - see below) and no data can be transmitted anymore. Pullups of SDA/SCL should be fine with 3K3.
First the program-code of the slave, then some measures&measurements i already took/did and in the end the despaired beg for help finding the problem which i assume in the I2C implementation.
Slave (Pico) Code:
#include <Arduino.h>
#include <Wire.h>
#define DATABYTES 6
unsigned long lastLEDToggle = 0;
#define LED_INTERVAL 750
bool LEDstatus = HIGH;
#define I2C_SLAVE_ADDRESS 0x18
MbedI2C myI2C(14, 15);
uint8_t tmpRcvdData[DATABYTES];
uint8_t tmpRcvdDataInc;
uint8_t writeBuffer[DATABYTES] = {0x12};
void initCommunication();
void setupCommunication();
void onReceive(int numBytes);
void onRequest();
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
setupCommunication();
}
void loop() {
if (millis() - lastLEDToggle > LED_INTERVAL) {
digitalWrite(LED_BUILTIN, LEDstatus);
LEDstatus = !LEDstatus;
lastLEDToggle = millis();
}
}
void setupCommunication() {
initCommunication();
myI2C.onReceive(onReceive);
myI2C.onRequest(onRequest);
}
void initCommunication() {
myI2C.begin(I2C_SLAVE_ADDRESS);
myI2C.setClock(800000);
}
void onReceive(int numBytes) {
tmpRcvdDataInc = 0;
while (myI2C.available() && tmpRcvdDataInc < DATABYTES) {
tmpRcvdData[tmpRcvdDataInc] = myI2C.read();
tmpRcvdDataInc++;
}
while (myI2C.available() ) {
myI2C.read(); // clear buffer
}
}
void onRequest() {
myI2C.write(writeBuffer, DATABYTES);
}
What did i try already?
- Changing the interval of requests and writings by the master: I varied between 200 ms and 10 secs without any change of the problem besides it adapts of course to the varied time
- Implement a delay between requests and writes on master side: Even with stopping requests and first writing few secs after last request (and other way around) the problem is not solved
- Vary the I2C frequency: Changing between 100 kHz and 800 kHz did not make any difference
- Try only requesting or only writing: If i only write from master to slave or only do requests the problem does not occur but that does not fit to my use case
Measurements & Logs
ESP Debug message incl. some serial output i had on master side:
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8
Requesting Slave
Slave answered 12 0 0 0 0 0
Requesting Slave
Slave answered 12 0 0 0 0 0
Requesting Slave
Slave answered 12 0 0 0 0 0
Requesting Slave
Slave answered 12 0 0 0 0 0
Writing Slave
Requesting Slave
[D][esp32-hal-i2c.c:1353] i2cProcQueue(): Gross Timeout Dead start=0x4e59, end=0x4e8b, =50, max=50 error=1
[E][esp32-hal-i2c.c:318] i2cDumpI2c(): i2c=0x3ffbdbb4
[I][esp32-hal-i2c.c:319] i2cDumpI2c(): dev=0x60013000 date=0x16042000
[I][esp32-hal-i2c.c:321] i2cDumpI2c(): lock=0x3ffb844c
[I][esp32-hal-i2c.c:323] i2cDumpI2c(): num=0
[I][esp32-hal-i2c.c:324] i2cDumpI2c(): mode=1
[I][esp32-hal-i2c.c:325] i2cDumpI2c(): stage=3
[I][esp32-hal-i2c.c:326] i2cDumpI2c(): error=1
[I][esp32-hal-i2c.c:327] i2cDumpI2c(): event=0x3ffb84d4 bits=0
[I][esp32-hal-i2c.c:328] i2cDumpI2c(): intr_handle=0x3ffb8508
[I][esp32-hal-i2c.c:329] i2cDumpI2c(): dq=0x3ffb84b0
[I][esp32-hal-i2c.c:330] i2cDumpI2c(): queueCount=1
[I][esp32-hal-i2c.c:331] i2cDumpI2c(): queuePos=0
[I][esp32-hal-i2c.c:332] i2cDumpI2c(): errorByteCnt=-1
[I][esp32-hal-i2c.c:333] i2cDumpI2c(): errorQueue=0
[I][esp32-hal-i2c.c:334] i2cDumpI2c(): debugFlags=0x00000000
[I][esp32-hal-i2c.c:311] i2cDumpDqData(): Debug Buffer not Enabled
[I][esp32-hal-i2c.c:354] i2cDumpInts(): Debug Buffer not Enabled
0
Requesting Slave
[I][esp32-hal-i2c.c:1138] i2cProcQueue(): Bus busy, reinit
[W][esp32-hal-i2c.c:1419] i2cCheckLineState(): invalid state sda(21)=0, scl(22)=1
[D][esp32-hal-i2c.c:1427] i2cCheckLineState(): Recovered after 3 Cycles
[D][esp32-hal-i2c.c:1353] i2cProcQueue(): Gross Timeout Dead start=0x52cf, end=0x5301, =50, max=50 error=1
[E][esp32-hal-i2c.c:318] i2cDumpI2c(): i2c=0x3ffbdbb4
[I][esp32-hal-i2c.c:319] i2cDumpI2c(): dev=0x60013000 date=0x16042000
[I][esp32-hal-i2c.c:321] i2cDumpI2c(): lock=0x3ffb844c
[I][esp32-hal-i2c.c:323] i2cDumpI2c(): num=0
[I][esp32-hal-i2c.c:324] i2cDumpI2c(): mode=1
[I][esp32-hal-i2c.c:325] i2cDumpI2c(): stage=3
[I][esp32-hal-i2c.c:326] i2cDumpI2c(): error=1
[I][esp32-hal-i2c.c:327] i2cDumpI2c(): event=0x3ffb84d4 bits=0
[I][esp32-hal-i2c.c:328] i2cDumpI2c(): intr_handle=0x3ffb8508
[I][esp32-hal-i2c.c:329] i2cDumpI2c(): dq=0x3ffb84b0
[I][esp32-hal-i2c.c:330] i2cDumpI2c(): queueCount=1
[I][esp32-hal-i2c.c:331] i2cDumpI2c(): queuePos=0
[I][esp32-hal-i2c.c:332] i2cDumpI2c(): errorByteCnt=-1
[I][esp32-hal-i2c.c:333] i2cDumpI2c(): errorQueue=0
[I][esp32-hal-i2c.c:334] i2cDumpI2c(): debugFlags=0x00000000
[I][esp32-hal-i2c.c:311] i2cDumpDqData(): Debug Buffer not Enabled
[I][esp32-hal-i2c.c:354] i2cDumpInts(): Debug Buffer not Enabled
0
Requesting Slave
[I][esp32-hal-i2c.c:1138] i2cProcQueue(): Bus busy, reinit
[W][esp32-hal-i2c.c:1419] i2cCheckLineState(): invalid state sda(21)=1, scl(22)=0
[D][esp32-hal-i2c.c:1427] i2cCheckLineState(): Recovered after 1 Cycles
[E][esp32-hal-i2c.c:1434] i2cCheckLineState(): Bus Invalid State, TwoWire() Can't init sda=1, scl=0
0
Requesting Slave
[D][esp32-hal-i2c.c:1344] i2cProcQueue(): Busy Timeout start=0x5b36, end=0x5b68, =50, max=50 error=1
[E][esp32-hal-i2c.c:318] i2cDumpI2c(): i2c=0x3ffbdbb4
[I][esp32-hal-i2c.c:319] i2cDumpI2c(): dev=0x60013000 date=0x16042000
[I][esp32-hal-i2c.c:321] i2cDumpI2c(): lock=0x3ffb844c
[I][esp32-hal-i2c.c:323] i2cDumpI2c(): num=0
[I][esp32-hal-i2c.c:324] i2cDumpI2c(): mode=1
[I][esp32-hal-i2c.c:325] i2cDumpI2c(): stage=3
[I][esp32-hal-i2c.c:326] i2cDumpI2c(): error=1
[I][esp32-hal-i2c.c:327] i2cDumpI2c(): event=0x3ffb84d4 bits=0
[I][esp32-hal-i2c.c:328] i2cDumpI2c(): intr_handle=0x3ffb8508
[I][esp32-hal-i2c.c:329] i2cDumpI2c(): dq=0x3ffb84b0
[I][esp32-hal-i2c.c:330] i2cDumpI2c(): queueCount=1
[I][esp32-hal-i2c.c:331] i2cDumpI2c(): queuePos=0
[I][esp32-hal-i2c.c:332] i2cDumpI2c(): errorByteCnt=0
[I][esp32-hal-i2c.c:333] i2cDumpI2c(): errorQueue=0
[I][esp32-hal-i2c.c:334] i2cDumpI2c(): debugFlags=0x00000000
[I][esp32-hal-i2c.c:311] i2cDumpDqData(): Debug Buffer not Enabled
[I][esp32-hal-i2c.c:354] i2cDumpInts(): Debug Buffer not Enabled
[W][esp32-hal-i2c.c:1419] i2cCheckLineState(): invalid state sda(21)=1, scl(22)=0
[D][esp32-hal-i2c.c:1427] i2cCheckLineState(): Recovered after 1 Cycles
[E][esp32-hal-i2c.c:1434] i2cCheckLineState(): Bus Invalid State, TwoWire() Can't init sda=1, scl=0
The I2C can only be reset correctly after first restarting the Pico and then the ESP32.
I also checked the bus with a Logic analyzer:
Blue: SDA / Red: SCL
As promised here: Please help me :) - for me it looks like the I2C implementation has some issue with the I2C drivers of the Pico.