ESP32 - FreeRTOS conflict with tasks and interrupt

alexvazquez
Posts: 2
Joined: Wed Jan 12, 2022 12:04 am

ESP32 - FreeRTOS conflict with tasks and interrupt

Postby alexvazquez » Sun May 22, 2022 3:33 pm

I have an ESP32 using an 8 bit I2C multiplexer TCA9548 IC. TCA9548 IC is connected to my ESP32 SCL and SCA pins.

I have the following I2C devices connected to the I2C TCA9548 exapander so I can choose on code what device to access and control (in the future I will have other 6 I2C devices):
  • I2C I/O 16 bit expander TCA6416 --- Connected to SC0/SD0 of TCA9548
  • MAX31875 I2C Temp Sensor --- Connected to SC1/SD1 of TCA9548
The TCA6416 I/O expander IC has its interrupt output pin connected to my ESP32 35 pin.

In order to get any event that happens in the TCA6416 I/O expander I created a FreeRTOS task that handles the interrupt. Here is the code:

Code: Select all


// function for selecting the I2C Device
void TCA9548A(uint8_t bus)
{

  if (xSemaphoreTake(I2CMutexSemaphore, 100) == pdTRUE)
  {
    Wire.beginTransmission(0x70); // TCA9548A address
    Wire.write(1 << bus);         // send byte to select bus
    Wire.endTransmission();
    xSemaphoreGive(I2CMutexSemaphore);
  }
}

void setup()
{
   ... some code here
     
     // create task that will get any interrupt event on ESP32 35 pin.
      xTaskCreatePinnedToCore(&readInterruptEventTask, "interrupt taskr", 2048, NULL, 20, &TaskHandle_InterruptEvent, 0);
      
      // attach the interrupt with the initCallBack function
     attachInterrupt(35, intCallBack, FALLING);
   
}

void IRAM_ATTR intCallBack()
{
  xSemaphoreGiveFromISR(interruptISRSemaphore, &xHigherPriorityTaskWoken);
  if (xHigherPriorityTaskWoken)
  {
     portYIELD_FROM_ISR();
  }
  
}

void readInterruptEventTask(void *pArgs)
{
  (void)pArgs;
  
  while (true)
  {
    if (xSemaphoreTake(interruptISRSemaphore, portMAX_DELAY) == pdPASS)
    {
      handleInterrupt();
    }
  }
}

void handleInterrupt()
{
    TCA9548A(0); // select I2C Device 0, in this case the TCA6416 
    
    uint16_t gpioAB = mcp.readINTCAPAB(); // mcp is my TCA6416 I/O expander 
    
    ... some code here to process the result.
}


The above code works fine because when I push any button connected to my TCA6416 I/O expander I get into the handleInterrupt function and I can get the button that was pressed from other logic that reads the bytes of the TCA6416 I/O expander.

The problem comes here:

I have another task that every 500ms it gets the temperature from my MAX Temp Sensor.

Insise my setup() function I have this:

Code: Select all

 xTaskCreate(
      requestTemp,
      "Temp Reading",
      4096,
      NULL,
      3,
      &TaskHandle_Temp);
Then my task does this:

Code: Select all

void requestTemp(void *params)
{
    (void)params;

     for (;;)
    {
       TCA9548A(1); // Selects the MAX31875 I2C device
        tmp.getReading(); // gets the reading from the device.
        vTaskDelay(500 / portTICK_PERIOD_MS);
    }
     
}
If you see my requestTemp task is always running accessing on every loop the TCA9548A I2C device, at the same time my interrupt task could get an event from my TCA6416 I/O and then will also communicate to my TCA9548A I2C device in order to get the bytes and see which button was pressed. This is the reason of my reboot and problem.

What could I do? My interrupt method has of course a higher priority because I don't want to lose any event from my TCA6416 I/O IC.

Ideally what should happen is that when I get any interrupt action I should stop the requestTemp task before communication to the TCA9548A I2C device and when finish the interrupt code then I resume the requestTemp task so no conflict on communication at the same time to the TCA9548A I2C device but I already did that I get reboots randomly.

Appreciate any help please!!

panilsunil
Posts: 2
Joined: Mon May 23, 2022 11:21 am

Re: ESP32 - FreeRTOS conflict with tasks and interrupt

Postby panilsunil » Mon May 23, 2022 12:08 pm

hello alexvazquez,
it seems that you have semaphore management (I2CMutexSemaphore) for TCA9548A but not for TCA9548A.
it may happen that the communication is going on with TCA9548A and interrupt strucks.
The solution may be take I2CMutexSemaphore in interrupt handler also and give after executing the code.
As it is not directly run in interrupt handler (it is another task) there will not be any problem.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 105 guests