Jump to content
43oh

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

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.

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;
}

 

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

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".

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

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...