Skip to content

Blocking code on Core 0 slows I2C #5882

@raphael-bmec-co

Description

@raphael-bmec-co

Hardware:

Board: ESP32-D0WD-V3 (revision 3) custom board.
Core Installation version: 1.0.5 AND 2.0.0
IDE name: Platform.io with Clion AND Arduino IDE.
Flash Frequency: 40Mhz.
PSRAM enabled: Either.
Upload Speed: 921600
Computer OS: Windows 10

Description:

I2C communication slows drastically when core 0 is blocked. The results of testing alternate cores are shown below.

I am assuming that the I2C interrupts are handled on core 0 and/or that there is a task on core 0 that handles the I2C? I am aware that the issue would go away if the blocking code was moved to core 1. However, in the case of WiFi/BLE we have no control over this.

The I2C interrupts should be running on the core from which Wire was begun. Moreover, I have tried editing the esp32-hal-i2c.c to increase the priority of the I2C interrupts from ESP_INTR_FLAG_LOWMED to forced ESP_INTR_FLAG_LEVEL3 AND clearing the ESP_INTR_FLAG_SHARED flag but this has no effect. Furthermore, reducing the blocking tasks priority seems to improve the situation as shown below. This leads me to believe there is a handler task pinned to core 0 that is not getting run time?

Looking forward to some feedback. It would be great if we could move whatever is slowing down the I2C to core 1?

@stickbreaker maybe this is a simple one for you to answer?

Core 0 blocked, I2c on core 1, arduino on core 1
blocked 50050us (core 0 task priority 6, core 1 task priority 6)
blocked 1463us (core 0 task priority 1, core 1 task priority 6)
unblocked 473us

Core 1 blocked, I2c on core 0, arduino on core 1
Doesn't run

Core 0 blocked, I2c on core 1, arduino on core 0
Doesn't run

Core 1 blocked, I2c on core 0, arduino on core 0
blocked 481us
unblocked 474us

Sketch - you will need an I2C device to reproduce. However, even without a device the transmission time is drastically different with and without the block on core 0.

#include <soc/timer_group_struct.h>
#include <soc/timer_group_reg.h>

#include <Wire.h>

void core0Loop(void *pvParameters){
  log_i("cor01Loop started on core: %u", xPortGetCoreID());
  
  for (;;){
    TIMERG0.wdt_wprotect = TIMG_WDT_WKEY_VALUE;
    TIMERG0.wdt_feed = 1;
    TIMERG0.wdt_wprotect = 0;
  }
}

void core1Loop(void *pvParameters){
  log_i("core1Loop started on core: %u", xPortGetCoreID());
  
  if (!Wire.begin())
  {
    log_e("Failed to start I2C");
  }

  for (;;){

    for (int brightness=0; brightness<256; brightness++){

    Wire.beginTransmission(0b00111110);
    Wire.write(0x56);
    Wire.write(brightness);
    int64_t t0 = esp_timer_get_time();
    if(Wire.endTransmission() != I2C_ERROR_OK){
      log_e("TRANSMISSION ERROR");
    }
    log_i("Transmission time %lldus", esp_timer_get_time() - t0);
    delay(2);
    }
    delay(500);
  }
}

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

  xTaskCreatePinnedToCore(
    core0Loop
    ,  "core0Loop"
    ,  5000
    ,  NULL
    ,  6
    ,  NULL 
    ,  0);

  xTaskCreatePinnedToCore(
    core1Loop
    ,  "core1Loop"
    ,  5000
    ,  NULL
    ,  6
    ,  NULL 
    ,  1);

    vTaskDelete(nullptr);
}

void loop()
{
  vTaskDelete(nullptr);
}

Metadata

Metadata

Assignees

Type

No type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions