Jump to content
Jakki

attachInterrupt() takes a long time

Recommended Posts

MSP Launchpad Exp430G2 with Exp430G2553 Rev 1.5

Energia 1.6.10E18

MacOS Sierra 10.12.6

Hello friends,

When I call attachInterrupt at the end of a service Routine after I detached it from a pin, I find that it takes a long time for that call to finish (two seconds).

Do you have any hint how I can make that faster? Thanks

Share this post


Link to post
Share on other sites
volatile int ledPin = 18;
volatile int espPin = 2;
volatile int switchPin = 3;

void ToggleFast(volatile int pinu)
{
    volatile unsigned long n = 100000;
    digitalWrite(pinu,HIGH);
    do{n--;}
    while(n>0);
    digitalWrite(pinu,LOW);
    n = 100000;
    do{n--;}
    while(n>0);
    digitalWrite(pinu,HIGH);
    n = 100000;
    do{n--;}
    while(n>0);
    digitalWrite(pinu,LOW);
    n = 100000;
    do{n--;}
    while(n>0);
  
}

void setup() 
{
    pinMode(ledPin, OUTPUT);
    attachInterrupt(switchPin, myISR, FALLING);
    attachInterrupt(espPin, myISR2, RISING);
}

void loop() {
//toggle slow
  digitalWrite(ledPin, LOW);
  delay(400);
  digitalWrite(ledPin, HIGH);
  delay(400);  
}

void myISR()
{
  detachInterrupt(espPin);
  //ToggleFast(ledPin); //see description below 
  attachInterrupt(espPin, myISR2, RISING);
}

void myISR2()
{
  ToggleFast(ledPin); 
  ToggleFast(ledPin); 
  ToggleFast(ledPin); 
}

 

There is two "issues":

1. When I enter "myISR()" it takes about two seconds until the call of "attachInterrupt(espPin, myISR2, RISING)" is finished. 

2. When I uncomment "ToggleFast(ledPin)" in "myISR" the program hangs for about 8-10 seconds while toggling the ledPin, when myISR is entered and the call to ToggleFast(ledPin) is executed. However, this call should not even take 1 second or so. And that is the case when I comment out  "attachInterrupt(espPin, myISR2, RISING)".

"switchPin" is externally configured with a pullup resistor and "espPin" is externally configured with a pulldown resistor.

Share this post


Link to post
Share on other sites

@Fmilburn is right, you should never do work that takes a long time in the ISR. This is because while in the ISR, all interrupts are disabled.

The below Sketch works as expected where detachInterrupt()/attachInterrupt() do not cause the 2 seconds delay as you observed.

The RED_LED initially turns on after reset. Pressing PUSH2 will turn it off after a 200 ms debounce. myISR will detach from myISR and attach to myISR2. Pressing PUSH2 one more time will fire myISR2 and turn the RED_LED off permanently.  Also note that I activated the PULLUP on PUSH2. Make sure that you have the correct PULLUP/PULLDOWN state on the pin depending on the desired RISING/FALLING edge of the interrupt.

volatile bool isr_flag = false;
volatile bool isr_flag2 = false;

void setup() {
  // put your setup code here, to run once:
  pinMode(RED_LED, OUTPUT);
  digitalWrite(RED_LED, HIGH);
  pinMode(PUSH2, INPUT_PULLUP);
  attachInterrupt(PUSH2, myISR, FALLING);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (isr_flag == true) {
    digitalWrite(RED_LED, LOW);
  }

  if (isr_flag2 == true) {
    digitalWrite(RED_LED, HIGH);
  }

}

void myISR()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();

  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    isr_flag = true;
    detachInterrupt(PUSH2);
    attachInterrupt(PUSH2, myISR2, FALLING);

  }
  
  last_interrupt_time = interrupt_time;
}

void myISR2()
{
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();
  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200)
  {
    isr_flag = false;
    isr_flag2 = true;
  }

  last_interrupt_time = interrupt_time;
}

 

Share this post


Link to post
Share on other sites
Quote
On 5.2.2018 at 6:28 PM, energia said:

Pressing PUSH2 one more time will fire myISR2 and turn the RED_LED off permanently

 

Thank you for your replies!! I think you meant "on" instead of "off" right?

For now I could successfully work around my issue with flags and I would like to proceed with the other components of my project. But when I have more time I will consider to integrate your solution into my Energia Code. 

Thanks again!! Jakob

Share this post


Link to post
Share on other sites
On 5.2.2018 at 6:28 PM, energia said:

This is because while in the ISR, all interrupts are disabled.

I experienced something different: Looking at my code example above, when myISR is executed and during that time "espPin" is pressed (which is attached to myISR2), then myISR2 is executed after the execution of "myISR" is finished. That is the reason why I wanted to use "detach" and "attach" in "myISR". I need to do this because in "myISR" I also need to listen to both switches "switchPin" and "espPin".

Share this post


Link to post
Share on other sites

When you are in an ISR interrupts are disabled and hence no other ISR's will be executed until the first ISR exits. This is also the reason why you should NOT do extensive work in the ISR that takes a long time as you will eventually miss interrupts. In the linux world this is called bottom an top half. The bottom half does minimal work like setting flags / clearing interrupts. The top half then uses the flags set by the ISR to determine what work needs to be done in mainline.

Robert

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×