Hi, We are experiencing some issues with external interrupts resetting an Analog Devices ADuC842 controller (8051 family). The system we are working on analyses sensorial data from a rotary encoder connected to EX0. The interrupt is configured to be level-triggering. In our current set-up, the controller spontaneously resets when the rate with which the sensor interrupts occur exceeds certain level. We know from counting the number of CPU instructions in our ISR and estimating the number of interrupts, that the problem is likely to stem from the controller not being able to process the interrupts quick enough. What we fail to understand, though, is why this would reset the controller as we would expect the interrupt system to either queue interrupts occurring too soon to be processed, or to ignore them altogether. Can someone help us understand what is / might be going on? To set up the interrupt we've got the following code: IT0 = 0; /* Configure interrupt to be level triggering. */ EX0 = 1; /* Enable external interrupt 0. */ EA = 1; /* Global interrupt enable. */ Our ISR: static void encoder_isr(void) interrupt 0 { unsigned int new_AB; unsigned int old_and_new; /* Get the new A and B values by masking the entire port byte to avoid interference from pending interrupts: */ new_AB = (P1 & 0x18) >> 3; /* Combine the old and new A and B values. The resulting bit pattern indicates the direction of movement. eg: old = 0000 0011 --------- << 2x 0000 1100 new = 0000 0001 --------- OR 0000 1101 = 13d = negative movement. */ old_and_new = (old_AB << 2) | new_AB; /* Determine direction: */ if ((old_and_new == 0x02) || (old_and_new == 0x0B) || (old_and_new == 0x0D) || (old_and_new == 0x04)) position--; else position++; old_AB = new_AB; /* The interrupt is high-level triggered. The output of the pin corresponding to TOGGLE is XOR'ed with the pin being monitored by the interrupt to clear the interrupt. */ TOGGLE ^= 1; } Thanks in advance. Walter

Interrupts and Analog Devices ADuC842
Started by ●October 4, 2004
Reply by ●October 5, 20042004-10-05
Walter Smits wrote:> Hi, > > We are experiencing some issues with external interrupts resetting an > Analog Devices ADuC842 controller (8051 family). The system we are > working on analyses sensorial data from a rotary encoder connected to > EX0. The interrupt is configured to be level-triggering. In our > current set-up, the controller spontaneously resets when the rate with > which the sensor interrupts occur exceeds certain level. We know from > counting the number of CPU instructions in our ISR and estimating the > number of interrupts, that the problem is likely to stem from the > controller not being able to process the interrupts quick enough. What > we fail to understand, though, is why this would reset the controller > as we would expect the interrupt system to either queue interrupts > occurring too soon to be processed, or to ignore them altogether. > > Can someone help us understand what is / might be going on? > > To set up the interrupt we've got the following code: > > IT0 = 0; /* Configure interrupt to be level triggering. */ > EX0 = 1; /* Enable external interrupt 0. */ > EA = 1; /* Global interrupt enable. */ > > Our ISR: > > static void > encoder_isr(void) interrupt 0 { > unsigned int new_AB; > unsigned int old_and_new; > > /* Get the new A and B values by masking the entire port > byte to avoid interference from pending interrupts: */ > new_AB = (P1 & 0x18) >> 3; > > /* Combine the old and new A and B values. The resulting > bit pattern indicates the direction of movement. > eg: old = 0000 0011 > --------- << 2x > 0000 1100 > new = 0000 0001 > --------- OR > 0000 1101 = 13d = negative movement. */ > old_and_new = (old_AB << 2) | new_AB; > > /* Determine direction: */ > if ((old_and_new == 0x02) || > (old_and_new == 0x0B) || > (old_and_new == 0x0D) || > (old_and_new == 0x04)) position--; > else > position++; > > old_AB = new_AB; > > /* The interrupt is high-level triggered. The output > of the pin corresponding to TOGGLE is XOR'ed with > the pin being monitored by the interrupt to clear > the interrupt. */ > TOGGLE ^= 1; > } > > Thanks in advance. > WalterFirst you should use the "using" statement so you do not have to push everything on to the stack (like encoder_isr(void) interrupt 0 using 1) you could be over flowing the stack. You could be spending so much time in the interrupt that your watchdog resets. the 8051 does not queue interrupts. But since you are level sensing you could go right back to the int on the next instruction.
Reply by ●October 5, 20042004-10-05
On 2004-10-05 05:50:47 +0200, Neil Kurzman <nsk@mail.asb.com> said:> > > Walter Smits wrote: > >> Hi, >> >> We are experiencing some issues with external interrupts resetting an >> Analog Devices ADuC842 controller (8051 family). The system we are >> working on analyses sensorial data from a rotary encoder connected to >> EX0. The interrupt is configured to be level-triggering. In our >> current set-up, the controller spontaneously resets when the rate with >> which the sensor interrupts occur exceeds certain level. We know from >> counting the number of CPU instructions in our ISR and estimating the >> number of interrupts, that the problem is likely to stem from the >> controller not being able to process the interrupts quick enough. What >> we fail to understand, though, is why this would reset the controller >> as we would expect the interrupt system to either queue interrupts >> occurring too soon to be processed, or to ignore them altogether. >> >> Can someone help us understand what is / might be going on? >> >> To set up the interrupt we've got the following code: >> >> IT0 = 0; /* Configure interrupt to be level triggering. */ >> EX0 = 1; /* Enable external interrupt 0. */ >> EA = 1; /* Global interrupt enable. */ >> >> Our ISR: >> >> static void >> encoder_isr(void) interrupt 0 { >> unsigned int new_AB; >> unsigned int old_and_new; >> >> /* Get the new A and B values by masking the entire port >> byte to avoid interference from pending interrupts: */ >> new_AB = (P1 & 0x18) >> 3; >> >> /* Combine the old and new A and B values. The resulting >> bit pattern indicates the direction of movement. >> eg: old = 0000 0011 >> --------- << 2x >> 0000 1100 >> new = 0000 0001 >> --------- OR >> 0000 1101 = 13d = negative movement. */ >> old_and_new = (old_AB << 2) | new_AB; >> >> /* Determine direction: */ >> if ((old_and_new == 0x02) || >> (old_and_new == 0x0B) || >> (old_and_new == 0x0D) || >> (old_and_new == 0x04)) position--; >> else >> position++; >> >> old_AB = new_AB; >> >> /* The interrupt is high-level triggered. The output >> of the pin corresponding to TOGGLE is XOR'ed with >> the pin being monitored by the interrupt to clear >> the interrupt. */ >> TOGGLE ^= 1; >> } >> >> Thanks in advance. >> Walter > > First you should use the "using" statement so you do not have to push > everything on to the stack (like encoder_isr(void) interrupt 0 using 1) > you could be over flowing the stack. You could be spending so much time in > the interrupt that your watchdog resets. the 8051 does not queue > interrupts. But since you are level sensing you could go right back to the > int on the next instruction.Thanks for your reply. We solved the problem after we got in touch with Analog's tech support: the ADuC842 has a bug that resets the instruction pointer to 0 if a level-triggering interrupt is cleared too early (within 9 core clock cycles). In case someone else runs into the same kind of problem: see anomaly er10, http://www.analog.com/en/prodRes/0,2889,ADUC842%5F876,00.html. Fortunately for us we could easily adopt our design to be edge triggering. Walter
