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!!