espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.72k stars 7.43k forks source link

SPI I2C synchronization issue #4580

Closed waqasqammar closed 3 years ago

waqasqammar commented 3 years ago

Hello everyone. I am developing an application that uses both the SPI and I2C. Also I am using both the cores. but I am facing an error no matter what I do. I tried to use one core also without any freeRtos but even then it is happening. the error is esp-idf/components/freertos/queue.c:1446 (xQueueGenericReceive)- assert failed!

Now I trace back the address and here is what I got.

0x400928a4: invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:155
0x40092ad5: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:170
0x4008ecaf: xQueueGenericReceive at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1446 (discriminator 2)
0x400df321: spiTransaction at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-spi.c:722 (discriminator 1)
0x400d513d: SPIClass::beginTransaction(SPISettings) at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\libraries\SPI\src/SPI.cpp:135
0x400dbb65: ADS1298::ADS1298x::readDataContinous() at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\libraries\SPI\src/SPI.h:32
 (inlined by) ADS1298::ADS1298x::readDataContinous() at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/lib\ADS1298x/ADS1298x.cpp:74
0x400d26e8: handleInterrupt() at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/src/main.cpp:1521
0x40081101: __onPinInterrupt at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-gpio.c:220
0x400856e9: _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1154
0x4000bfed: ?? ??:0
0x4009015d: vTaskExitCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c:4274
0x4008f610: xEventGroupWaitBits at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/event_groups.c:427
0x400de372: i2cProcQueue at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-i2c.c:1279
0x400de717: i2cWrite at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-i2c.c:1621
0x400d494d: TwoWire::writeTransmission(unsigned short, unsigned char*, unsigned short, bool) at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src/Wire.cpp:133
0x400d49a1: TwoWire::endTransmission(bool) at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src/Wire.cpp:158
0x40178e1e: Adafruit_I2CDevice::write(unsigned char*, unsigned int, bool, unsigned char*, unsigned int) at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/.pio\libdeps\esp32dev\Adafruit BusIO/Adafruit_I2CDevice.cpp:128
0x40178bcd: Adafruit_BusIO_Register::write(unsigned char*, unsigned char) at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/.pio\libdeps\esp32dev\Adafruit BusIO/Adafruit_BusIO_Register.cpp:101
0x40178c43: Adafruit_BusIO_Register::write(unsigned int, unsigned char) at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/.pio\libdeps\esp32dev\Adafruit BusIO/Adafruit_BusIO_Register.cpp:137 (discriminator 2)
0x400db1e2: Adafruit_ICM20X::_setBank(unsigned char) at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/.pio\libdeps\esp32dev\Adafruit ICM20X/Adafruit_ICM20X.cpp:380
0x400db32c: Adafruit_ICM20X::_read() at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/.pio\libdeps\esp32dev\Adafruit ICM20X/Adafruit_ICM20X.cpp:330
0x400db350: Adafruit_ICM20X::getEvent(sensors_event_t*, sensors_event_t*, sensors_event_t*, sensors_event_t*) at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/.pio\libdeps\esp32dev\Adafruit ICM20X/Adafruit_ICM20X.cpp:237
0x400d2cfe: updateICM2() at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/src/main.cpp:1093
0x400d3086: TaskImu(void*) at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/src/main.cpp:2298
0x4008efe1: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:143

another time I got

0x400928a4: invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:155
0x40092ad5: abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:170
0x4008ecaf: xQueueGenericReceive at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1446 (discriminator 2)
0x400df361: spiTransaction at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-spi.c:731
0x400d517d: SPIClass::write(unsigned char) at ??:?
0x400dbba5: ADS1298::ADS1298x::readDataContinous() at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/lib\ADS1298x/ADS1298x.cpp:83 (discriminator 2)
0x400d26fc: handleInterrupt() at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/src/main.cpp:1523
0x40081101: __onPinInterrupt at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-gpio.c:220
0x400856e9: _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1154
0x4000bfed: ?? ??:0
0x4009015d: vTaskExitCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c:4274
0x4008f610: xEventGroupWaitBits at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/event_groups.c:427
0x400de3b2: i2cProcQueue at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-i2c.c:1322
0x400de7d5: yield at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-misc.c:48
0x400d49ad: TwoWire::endTransmission(bool) at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src/Wire.cpp:159
0x400d4a61: TwoWire::requestFrom(unsigned short, unsigned char, bool) at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src/Wire.cpp:188
0x400d4af9: __static_initialization_and_destruction_0 at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src/Wire.cpp:371
 (inlined by) _GLOBAL__sub_I__ZN7TwoWireC2Eh at C:\users\waqas\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src/Wire.cpp:371
0x400dbcd1: STC3100::read() at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/lib\STC3100/STC3100.cpp:76
0x400dbd09: STC3100::read() at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/lib\STC3100/STC3100.cpp:87
0x400d30ca: TaskImu(void*) at D:\work-freelance\Mindfield\Firmware_Desgin\eSense_FW/src/main.cpp:2324
0x4008efe1: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:143

This is suggesting something(Adafruit ICM20X or stc3100) was going on using i2c and an interrupt happen (handleInterrupt) and the SPI transaction happens and it failed. Now I don't know how to resolve this issue I have tried many things but I couldn't solve it.

void  handleInterrupt()
{
  ads.readDataContinous(); // do a SPI transcetion
  isrData.ch[BIOPOTENTIAL::CH1] = ads.getAverage(ADS1298::CH1_CH3_AVG);
  isrData.ch[BIOPOTENTIAL::CH2] = ads.getAverage(ADS1298::CH2_CH4_AVG);
  xQueueSendFromISR(adsDataQueue, (void*)&isrData, &xHigherPriorityTaskWoken ); // this queue is further processed on core0
  portYIELD_FROM_ISR( );
}

this is ISR of a digital pin that is executed every 500usec. I need specific timing which is why I am executing this SPI related code in the ISR. I have tried not to execute this and tried using semaphore, notification to notify from ISR to a separate task that does this calculation but that didn't satisfied the timing it requires. so I am doing this now in ISR.

here is the my task.

void TaskImu(void* pvParameters)
{
  esp_task_wdt_add(NULL);
  uint32_t imuValueCounter = 0; 
  bool updateICMflag = false;
  uint32_t counter = 0;
  uint32_t timing = 0;
  while(1)
  {
      updateICMflag = updateICM2(); // uses i2c Adafruit ICM library
      if(imuValueCounter == 5)
      {
        fuelGauge.read(); // uses i2c STC3100 IC and custome library
        if(updateICMflag)
        {
          writeImuData2(true, true);
        }
        imuValueCounter = 0;
      }
      else
      {
        imuValueCounter++;
        if(updateICMflag)
        {
          writeImuData2(false, true);
        }
      }
      vTaskDelay(pdMS_TO_TICKS(500));
      esp_task_wdt_reset();
  }
}

This task is running at core1 with stack size 2000 and priority is 1. Another task is running at core1 with priority 2. Both the task uses 500ms delay for blocking and switching between these two.

The queue data from ISR is processed on core 0 with a task of priority 8 and is the only task that is being executed on core0. it also uses BLE.

Kindly advise me on how to deal with this situation. I would be very thankful.

lbernstone commented 3 years ago

Don't interact with hardware in an ISR. Set a flag variable or semaphore and process it in your main loop (or another task).

stale[bot] commented 3 years ago

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

rfx77 commented 3 years ago

Similar situation here: I do Lora with interrupt-receive. in the main loop i update a oled display. when i do not use a delay (to reproduce error) i get this stacktrace every minute or so when i use a delay it is not often but still happens.

/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1446 (xQueueGenericReceive)- assert failed!
abort() was called at PC 0x4008abfb on core 1

Backtrace: 0x4008e724:0x3ffbe660 0x4008e951:0x3ffbe680 0x4008abfb:0x3ffbe6a0 0x400d5901:0x3ffbe6e0 0x400d2930:0x3ffbe700 0x400d309d:0x3ffbe730 0x400d30d0:0x3ffbe750 0x400d370d:0x3ffbe770 0x400810ea:0x3ffbe790 0x40081139:0x3ffbe7b0 0x4008758d:0x3ffbe7d0 0x4000bfed:0x3ffb1e30 0x4008c005:0x3ffb1e40 0x4008b4d4:0x3ffb1e60 0x400d4d42:0x3ffb1e90 0x400d515b:0x3ffb1ec0 0x400d2581:0x3ffb1ee0 0x400d25d5:0x3ffb1f00 0x400d2741:0x3ffb1f20 0x400d1958:0x3ffb1f40 0x400d1cf8:0x3ffb1f60 0x400d1da1:0x3ffb1f90 0x400d65ed:0x3ffb1fb0 0x4008aed5:0x3ffb1fd0
  #0  0x4008e724:0x3ffbe660 in invoke_abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:707
  #1  0x4008e951:0x3ffbe680 in abort at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp32/panic.c:707
  #2  0x4008abfb:0x3ffbe6a0 in xQueueGenericReceive at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:1996
  #3  0x400d5901:0x3ffbe6e0 in spiTransaction at C:\users\rauscherf\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-spi.c:283
  #4  0x400d2930:0x3ffbe700 in SPIClass::beginTransaction(SPISettings) at C:\users\rauscherf\.platformio\packages\framework-arduinoespressif32\libraries\SPI\src/SPI.cpp:270
  #5  0x400d309d:0x3ffbe730 in LoRaClass::singleTransfer(unsigned char, unsigned char) at C:\users\rauscherf\Documents\Arduino\libraries\LoRa\src/LoRa.cpp:391 (discriminator 4)
  #6  0x400d30d0:0x3ffbe750 in LoRaClass::readRegister(unsigned char) at C:\users\rauscherf\Documents\Arduino\libraries\LoRa\src/LoRa.cpp:391 (discriminator 4)
  #7  0x400d370d:0x3ffbe770 in LoRaClass::handleDio0Rise() at C:\users\rauscherf\Documents\Arduino\libraries\LoRa\src/LoRa.cpp:391 (discriminator 4)
  #8  0x400810ea:0x3ffbe790 in LoRaClass::onDio0Rise() at C:\users\rauscherf\Documents\Arduino\libraries\LoRa\src/LoRa.cpp:391 (discriminator 4)
  #9  0x40081139:0x3ffbe7b0 in __onPinInterrupt at C:\users\rauscherf\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-gpio.c:274
  #10 0x4008758d:0x3ffbe7d0 in _xt_lowint1 at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/xtensa_vectors.S:1154
  #11 0x4000bfed:0x3ffb1e30 in ?? ??:0
  #12 0x4008c005:0x3ffb1e40 in vTaskExitCritical at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/tasks.c:3507
  #13 0x4008b4d4:0x3ffb1e60 in xEventGroupWaitBits at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/event_groups.c:338
  #14 0x400d4d42:0x3ffb1e90 in i2cProcQueue at C:\users\rauscherf\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-i2c.c:1279
  #15 0x400d515b:0x3ffb1ec0 in i2cWrite at C:\users\rauscherf\.platformio\packages\framework-arduinoespressif32\cores\esp32/esp32-hal-i2c.c:1621
  #16 0x400d2581:0x3ffb1ee0 in TwoWire::writeTransmission(unsigned short, unsigned char*, unsigned short, bool) at C:\users\rauscherf\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src/Wire.cpp:368
  #17 0x400d25d5:0x3ffb1f00 in TwoWire::endTransmission(bool) at C:\users\rauscherf\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src/Wire.cpp:368
  #18 0x400d2741:0x3ffb1f20 in TwoWire::endTransmission() at C:\users\rauscherf\.platformio\packages\framework-arduinoespressif32\libraries\Wire\src/Wire.cpp:368
  #19 0x400d1958:0x3ffb1f40 in Adafruit_SSD1306::display() at src/Adafruit_SSD1306.cpp:519 (discriminator 2)
  #20 0x400d1cf8:0x3ffb1f60 in task_loop(void*) at src/GPSMain.cpp:90
  #21 0x400d1da1:0x3ffb1f90 in loop() at src/GPSMain.cpp:90
  #22 0x400d65ed:0x3ffb1fb0 in loopTask(void*) at C:\users\rauscherf\.platformio\packages\framework-arduinoespressif32\cores\esp32/main.cpp:19
  #23 0x4008aed5:0x3ffb1fd0 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)

Rebooting...

With no delay the issue is reproduceable because it happens every minute or so. (see last line of code)

here is my code:


#include <Arduino.h>
#include <TinyGPS++.h>
#include "axp20x.h"
#include <SPI.h>
#include <LoRa.h>
#include <Wire.h>  
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32

AXP20X_Class axp;

#define OLED_RESET 4

Adafruit_SSD1306 display(OLED_RESET);

#define SS      18   // GPIO18 -- SX1278's CS
#define RST     14   // GPIO14 -- SX1278's RESET
#define DI0     26   // GPIO26 -- SX1278's IRQ(Interrupt Request)
#define BAND  433125000

byte msgCount = 0;            // count of outgoing messages
byte localAddress = 0xBA;     // address of this device
byte destination = 0xFF;      // destination to send to
long lastSendTime = 0;        // last send time
int interval = 2000;          // interval between sends

int counter = 0;

void doRcv(int len);

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

  Wire.begin(21, 22);
  if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
    Serial.println("AXP192 Begin PASS");
  } else {
    Serial.println("AXP192 Begin FAIL");
  }

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C, 0, 22, 21, 800000);
  display.clearDisplay();

  axp.setPowerOutPut(AXP192_LDO2, AXP202_ON);

  LoRa.setPins(SS,RST,DI0);
  if (!LoRa.begin(BAND)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
//  LoRa.onReceive(onReceive);
//  LoRa.enableCrc();
  LoRa.setSyncWord(0xAA);
  LoRa.setTxPower(0);
  LoRa.setSpreadingFactor(12);
  LoRa.setSignalBandwidth(125E3);
  LoRa.setCodingRate4(8);
  //LoRa.setGain(1);

  LoRa.onReceive(doRcv);
  LoRa.receive();

  Serial.println("init ok");
}

long last1 = millis();
long last2 = last1;
long d_pt = 100;
long d_ms = 60000;
String lastvolt[4];
long curr = 0;

const char* circle = "-\\|/";
int pos = 0;

char buffer[1024];

void doRcv(int len) {
  int recipient = LoRa.read();
  byte sender = LoRa.read();
  byte incomingMsgId = LoRa.read();
  byte incomingLength = LoRa.read();

  String incoming = "";

  while (LoRa.available()) {
    incoming += (char)LoRa.read();
  }

  lastvolt[0] = lastvolt[1];
  lastvolt[1] = lastvolt[2];
  lastvolt[2] = lastvolt[3];
  lastvolt[3] = incoming;

  int rssi = LoRa.packetRssi();
  float snr =  LoRa.packetSnr();
  sprintf(buffer, "%d %4.1f: %s", rssi, snr, incoming.c_str());
  Serial.println(buffer);

}

void loop() {

  curr = millis();

  display.clearDisplay();
  display.setTextColor(WHITE);

  display.setTextSize(1);

  display.setCursor(0,0);
  display.print(lastvolt[0].substring(0,20));
  display.setCursor(0,0);
  display.print(String(circle[pos]));
  display.setCursor(0,8);
  display.println(lastvolt[1].substring(0,20));
  display.setCursor(0,16);
  display.println(lastvolt[2].substring(0,20));
  display.setCursor(0,24);
  display.println(lastvolt[3].substring(0,20));

  display.display();

  pos++;
  if (pos > 3) pos =0;
  last2 = curr;

  //delay(100);    // Comment out this delay to reproduce the problem
}

My Board is a T-Beam with Lora. I use PlatformIO

stale[bot] commented 3 years ago

[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.

stale[bot] commented 3 years ago

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

stale[bot] commented 3 years ago

[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.