ESP32 - FreeRTOS conflict with tasks and interrupt
Posted: 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):
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:
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:
Then my task does this:
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!!
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
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);
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);
}
}
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!!