Code in ISR section

Hi,

I have a question involving code in ISR section.

Has the code in this section a timeout or something similar?

I’m trying this code:

long time1, time2 = 0;
long w = 0;

void setup()
{
  Serial.begin(115200);

  cli();

  TCCR2A = 0; //Set Timer to 0
  TCCR2B = 0; //Set Timer to 0

  TCCR2B = (1 << CS20); //Pre-scaler to 1 (0.5us)
  TIMSK2 = (1 << TOIE2); //Enable Ovf Interrupt

  sei();
}

ISR(TIMER2_OVF_vect)
{

  time1 = micros();

  for(long z = 0; z < 99999999; z++)
  {
    w = 10.0d * 9.378326432786427836482d / 293.34343d;
  }

  time2 = micros();
}

void loop()
{
  long diff = time2 - time1;

  Serial.print(time1);
  Serial.print("\t");
  Serial.print(time2);
  Serial.print("\t");
  Serial.println(diff);
  delay(100);
}

The output of diff is 4us, but if I modify the “for” code in ISR method to take more time (pe copy & paste for 50/500 times) the code just frezze or print the same diff value; 4us.

Has ISR method a special behaviour?

Thank you.

I don’t understand the purpose of this fragment:

  for(long z = 0; z < 99999999; z++)
  {
    w = 10.0d * 9.378326432786427836482d / 293.34343d;
  }

Nothing changes in the loop, so why bother? Also, the double data type is not supported in the IDE. Since these are all constants, why not just use:0.3197047. My guess is that it’s there just to bleed time. Also, it customary to make variables used by an ISR as volatile.

My guess is that it's there just to bleed time.

That was OP's intent, I'm reasonably confident. The compiler is smarter than OP, though, and threw out the whole useless loop.

OP, you need to make some variable used in the calculation volatile, so the compiler knows that it can't just throw out the otherwise useless code.

Yes, is for bleed time and yes, I forgot the volatile clause :roll_eyes:

That was OP's intent, I'm reasonably confident. The compiler is smarter than OP, though, and threw out the whole useless loop.

When the compiler detects useless code just "remove" it?

So now, I define "volatile long w = 0;" and dont get output on loop, why?

I suspect that the interrupt only arrives to a for, but why loop() function doesnt work?

Thank you for your time.

That very long for loop probably takes longer to run that it takes for the timer to roll over again. So before the ISR even exits the timer overflow has happened again. Serial reuires interrupts to send out the data, but the timer interrupt has precedence. So the serial stuff can never run because of this crazy long ISR.

I just compiled it and I'm getting output:

52 536 4 101588 102856 4 204596 205928 4 307588 308840 4 410580 411864 20 513812 515096 4 616820 618072 4 719828 721112 4 822804 824056 4

The volatile modifier for w does nothing, since it appears that the ISR for loop optimized away. Since time1 and time2 are in the ISR, you may want to make them volatile.

econjack, If I put the w volatile the println never occurs on me.

So… Ok guys, I’m sorry about that but I dont understand this.

Setting time1, time2 and w to volatile, and for() by this way

  for(long z = 0; z < 1; z++)
  {
    w = 10.0d * 9.378326432786427836482d / 293.34343d;
  }

I get this output

52	536	4
101604	102856	4
204612	205896	4
307588	308840	4
410612	411928	4
513588	514840	4
616596	617848	4

But modifying for() to 100 cicles, I get this:

1936	1852	-304
1948	1604	-308
1904	1220	716
1960	1616	-308
1684	1828	-304
1668	1440	-308
1652	1168	-308
1264	1976	-304
2016	1676	460
1620	2020	-308
1460	1120	-304
2016	1676	460

And the time between print is slower.

So my question arround this is: Is the code discarded when the ISR occurs from previously running code of ISR?

What I’m trying to get is the “maximum” time for operations that I can use inside ISR.

Thank you again.

EDIT: Ok, I’ve changed the “micros()” for TCNT2 and it seems more sense. Still investigating.

What I'm trying to get is the "maximum" time for operations that I can use inside ISR.

You are going about it wrong. When the mailman has a package for you that won't fit in the mailbox, he/she rings your doorbell. That is an interrupt. You go to the door and get the package, and the mailman is on his/her way. You don't stand around shooting the shit, seeing how long you can keep him/her from leaving.

Interrupts are suppose do be fast. Trying to figure how slow you can make them is a foolish idea.

You need to analyze your program differently. Say you have some control loop which is controlling a motor - take a reading, do some math, set some outputs. This needs to happen rapidly, like maybe 1000 times per second. If you write it anyway halfway sensible, you could probably get this loop to take less than 1/10,000th of second.

So to get this loop running at the desired speed, it only needs 10% of the processor time to do its work. You may have other interrupts coming in while this loop is running - interrupts for shaft encoders or button presses. Each time an interrupt is triggered, it should run for less than 1/1000th of a second, otherwise the main loop won’t get its opportunity to update its outputs. And then look at the total number of interrupts - do you get interrupted 1000 times per second? Then add up the amount of time that the interrupts are using - they might use 60% of the processor time if they are particularly bad.

So now we’ve used 70% of the processor. There are some other tasks like sending and receiving serial data or maybe writing to an LCD screen. You need to organise those functions so they take less than 30% of the processor and no individual delay is longer than the main loop can tolerate.

Don’t try to maximise the interrupts. Work out what is your main loop that has to run at high speed and maximise that. Then fit everything else into the gaps.