How to use attachinterrupt() in specific core? | ESP32

Greatings, i have a question about to use attachinterrupt(), i didn't have any problems when I only used 1 core (without xTaskCreatePinnedToCore()) here is an example:

const byte interruptPin = 25;
volatile int interruptCounter = 0;
int numberOfInterrupts = 0;
 
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
 
void IRAM_ATTR handleInterrupt() {
  portENTER_CRITICAL_ISR(&mux);
  interruptCounter++;
  portEXIT_CRITICAL_ISR(&mux);
}
 
void setup() {
 
  Serial.begin(115200);
  Serial.println("Monitoring interrupts: ");
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
 
}
 
void loop() {
 
  if(interruptCounter>0){
 
      portENTER_CRITICAL(&mux);
      interruptCounter--;
      portEXIT_CRITICAL(&mux);
 
      numberOfInterrupts++;
      Serial.print("An interrupt has occurred. Total: ");
      Serial.println(numberOfInterrupts);
  }
}

In the previous code the interrupt works well, but when i create some task in the cores i can't attach the interrupt, here is my code:

const byte interruptPin = 25;
volatile int interruptCounter = 0;
int numberOfInterrupts = 0;
 
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
 
void IRAM_ATTR handleInterrupt() {
  portENTER_CRITICAL_ISR(&mux);
  interruptCounter++;
  portEXIT_CRITICAL_ISR(&mux);
}

void sensor_measure(void * parameter){
	Serial.print("Task 1 running");
	//Also, i tried to attach the interrupt inside task 1
	// attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
	
	
}

void alarm_system(void * parameter){
	Serial.print("Task 2 running");
	/*  if(interruptCounter>0){
 
      portENTER_CRITICAL(&mux);
      interruptCounter--;
      portEXIT_CRITICAL(&mux);
 
      numberOfInterrupts++;
      Serial.print("An interrupt has occurred. Total: ");
      Serial.println(numberOfInterrupts);
  } */
}

 
void setup() {
 
  Serial.begin(115200);
  Serial.println("Monitoring interrupts: ");
  pinMode(interruptPin, INPUT_PULLUP);
  
    //I tried to attach the interrupt before inicialice the task but doesn't work  
 // attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING);
  
  //Create task 1 in core 0
  xTaskCreatePinnedToCore(    sensor_measure,    "measure",    5000,    NULL,    2,    &Task1,    0);
  delay(500);  
  //Create task 2 in core 1
  xTaskCreatePinnedToCore(    alarm_system,    "alarm",    50000,    NULL,    2,    &Task2,    1);
  delay(500);
 
}
 
void loop() {
 

}

Bassically my question is: How can i attachinterrupt in specific core? I read the documention about interruptions (Interrupt allocation - ESP32 - — ESP-IDF Programming Guide latest documentation) but i couldn't solve my problem, if anyone can give me a example how to use it I really will apreciate.

Thank you.

1 Like

The interrupt gets attached to a pin, GPIO, not a core. The interrupt handler should be put into IRAM.

This ISR,

void IRAM_ATTR onTimer()
{
  BaseType_t xHigherPriorityTaskWoken;
  xEventGroupSetBitsFromISR(eg, OneMinuteGroup, &xHigherPriorityTaskWoken);
} // void IRAM_ATTR onTimer()

uses freeRTOS to trigger several tasks upon execution, event triggers work well in a ISR.

This volatile int interruptCounter = 0; would be better protected with a Semaphore.

are GPIOs accessible to both cores? if so, which core handles the interrupt?

I think they tell it best,

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/intr_alloc.html

The same core as the code that called attachInterrupt() was running in.

Typically, if using the Arduino AttachInterrupt thingy in setup() the interrupt will be attached to core1.

If assigning the interrupt in a task
common task congifuration

void taskthingy( void *pvparemeters )
{
//assign interrupt here and interrupt will go onto the core the task has been assigned to.
 for (;;)
{

}

}

GPIO's are accessible by Core0, Core1, and the ULP.

Do you have an example assign interrupt inside in a task ussing AttachInterrupt()? Like your code

void taskthingy( void *pvparemeters )
{
//assign interrupt here and interrupt will go onto the core the task has been assigned to.
 for (;;)
{

}

}

No.

Something like this. Compiles but untested.

void attachInterruptTask(void *pvParameters);
void isr();
const uint8_t interruptPin = 25;

const uint8_t core = 0; // ISR Will run on Core 0

void setup() {
  xTaskCreatePinnedToCore(attachInterruptTask, "Attach Interrupt Task", 2000, NULL, 6, NULL, core);
}

void loop() {
}

void attachInterruptTask(void *pvParameters) {
  attachInterrupt(digitalPinToInterrupt(interruptPin), isr, FALLING);
  vTaskDelete(NULL);
}

void IRAM_ATTR isr() {
}

Thank you so much, your code works great! I made little changes and this is my finally code and the solution of my question:

//Connection
//Button pin 1 -> GND
//Button pin 2 -> GPIO13

void attachInterruptTask(void *pvParameters);
void isr();
const uint8_t interruptPin = 13;

const uint8_t core = 0; // ISR Will run on Core 0

void setup() {
  delay(500);
  Serial.begin(115200);
  //Create Task running in core 0
  xTaskCreatePinnedToCore(attachInterruptTask, "Attach Interrupt Task", 2000, NULL, 6, NULL, 0);
  delay(500);
  //Create Task Running un core 1
  xTaskCreatePinnedToCore(        alarm_system,    "alarm",             2000, NULL, 2, NULL,    1);
  delay(500);
}

void loop() {
}

void attachInterruptTask(void *pvParameters) {
    //Set BTN as input pull-up
    pinMode(interruptPin, INPUT_PULLUP);
    //Attach Interrupt in core 0
    attachInterrupt(digitalPinToInterrupt(interruptPin), isr, FALLING);
    while(true){
        Serial.println("Task 1 Running");
        delay(500);
      }
    vTaskDelete(NULL);
}

void alarm_system(void *pvParameters) {
  while(true){
    Serial.println("Task 2 running");
    delay(500);
    }
  vTaskDelete(NULL);
}


void IRAM_ATTR isr() {
  Serial.println("BTN pressed");
}

Output:

I hope this code helps another people since I saw a lot of questions about this issue

3 Likes

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.