ISR killing a divide routine?

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,

I am having a strange problem with a divide routine. I am using the ATMega128 and GCC.

I am accumulating a total of, say 10 readings from the ADC in the ADC interrupts. In the main program, I then divide the accumulated sum by the number of element, as shown below.

The problem occurs when the ISR for int 7 is carried out during the divide routines. The problem is that the result of the divide routine is zero. I have checked that the all of the array elements are okay and that the accumulated sums are definately not zero before the division.

The problem does not happen with any of the other interrupt routines, only this one.

The zero result does not always occur when interrupted by ISR 7, however it does only occur when interupted by ISR 7.

During the ISR, I basically write a byte to the clock, via I2C and set a flag that the interrupt has occurred.

if (minuteInterval) printROM("\nStart"); //Indicates if interrupt has occurred yet
	position1 = posn1Accum/(ARRAY_SIZE_1); //A divide routine	
	position2 = posn1Accum/(ARRAY_SIZE_2);
if (minuteInterval) printROM("\nFinish");  //Indicates if interrupt has occurred yet

.....

ISR(INT7_vect)		//Clock interrupt occurs every minute.
{
printROM("\nInt vector 7");	
....
....
  //write a byte to the clock.	
	minuteInterval=1;
}

So in the case of an error, I will see that the 'Finish' but not the 'Start' is printed, that the "Int vector 7" is printed and that the result of one of the divides is zero.
(the problem also occurrs when the print-outs are omitted).

I am a bit new to this so if anyone has any ideas why this simple interrupt might have the capacity to ruin my divide routine, or where I could start to look for an answer,I would most appreciate it.

thanks in advance, back in the morning.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm afraid you nave not given nearly enough information, but my guess is that something is trashing registers/memory somewhere. What is this printROM routine, for example, and is it re-entrant? You really need to show all the code that makes up the ISR. GCC should stack any registers that are going to get trashed, but GCC doesn't protect you from such things as buffer overruns. Suppose that your I2C routine has a local array of size 3, and, because of a typo, you end up writing to buf[3], the 4th element, that will trash either a stacked register or part of a return address. I've been caught like this before, and it can be very hard to find.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There was a version of WinAVR around mid-Summer last year that had a fault in the ISR code generation that was not preserving sufficient registers. This problem sounds a lot like that.

Which version of WinAVR / avr-gcc are you using?

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you both for your answers,

I tried moving the RTC write on I2C to outside the interrupt (which I probably should have done earlier). Result: no more divide result = 0 problems, even when the interrupt occurred during the divide.

I then fired up a windows machine, installed the latest WinAVR and re-compiled everything how it was before (the RTC write in the ISR). Result: no more divide result = 0 problems.

So the problem appears to be a combination of my RTC write routine and the avr-gcc version.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

BTW,

I am using Kontrollerlab on Linux and appear to be using libc version 1.6.2-1 and gcc 4.3.1