Interesting interrupt behavior of an unclocked periphery :-)

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

Hi
I have a new problem with my Ap7000 for you :-)
It seems that a software-problem aka bug triggers an interrupt.
Concrete situation:
All autovectored interrupts are handled by one function that correspondents to its priority. Then the

Interruptline is looked up and an array of functionadresses is indexed and the function is called.
It basically the same like the interrupthandling that can be found in the Framework..
But self written :-) Its a prooven system and it works perfectly.

Now: accidently comletely randomly interrupt line 96 is triggering an interrupt. It mostly happens when cpu-load is high.
This IRQ line seems to be the connection to the PBA-depnendend periphery SPI0.

SPI0 is never used! Better: SPI0 clock is deactivated! (corresponding PBAmask-bit zeroed)

How this interrupt happens? :-)
If someone has any idea how an unclocked periphery can trigger an interrupt.. please shoot.
My understanding is that already enabling this interrupt should cause the cpu to a deadlock. since pba-acces should hang. at loeast every following pba access should hang.

Code for extracting the Index for the normal interrupt priority:

unsigned int icr = AVR32_INTC.icr[2];
unsigned int irr = AVR32_INTC.irr[icr];
unsigned int Index = icr*32+__builtin_ctz(irr);
//... 
HandlerList
(); //call

CPU-Exceptions are handled. this is not an exception that randomly jumps into a interrupt handler.

hmmh. Idea?

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

Good to see no one posting. :-D It at least confirms that its weird :-)

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

News: Its definitivly an real Interrupt. Mode-Bits are {M0 M1 M2} = 110 indicating execution on Interrupt-Level 1. Therefor the AP7000 stors the return adress in AVR32_RAR_INT1. This register points to an instruction directly after a "sleep 0".
Here is the complete disasm:

nop
   225d6:	d7 03       	nop
   225d8:	eb b0 00 00 	sync	0x0
   225dc:	e9 b0 00 00 	sleep	0x0
   225e0:	d7 03       	nop <<<<<<<<

So someting goes wrong when waking up.

Could this be a problem of this errata:

Quote:
35. Unreliable branch folding
In certain situations, branch folding does not work as expected.
Fix/Workaround
Write 0 to CPUCR.FE before executing any branch instructions after reset.
Btw: this is rediculous. This is a major feature of the AVR32.. :-/

The error is not predictable... so trying something is hard.

Muhaaaa: invalidating the return stack (frs) before going to sleep mode _seems_ to solve the issue.
I'll keep posintg if interrupt 96 bothers me again.

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

The errata number 35 is only affective if you have a multi-cycle instruction before a branch.

Hans-Christian

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

This could have been the error.
First version was only a "sleep 0" at the end of a loop. Then the return adress of the interrupt handler points to the rjmp after the sleep-instruction.
Then i put some nops and frs after the sleep-instruction. the frs last. also frs should be a longer lasting instruction. So the error was still there.
Now i have used some random nops:

asm volatile ("frs");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("sync 0");
asm volatile ("nop");
asm volatile ("nop");
asm volatile ("sleep 0");
asm volatile ("nop");
asm volatile ("frs");
asm volatile ("nop");
asm volatile ("nop");
..end of loop -> compiler generated "rjmp" here

This runs without problems.
Is my conclusion right that this was indeed errata #35?

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

...And it happens again. As stated before..
the instruction RAR_INT1 points to is the nop directly after the sleep instruction.

   229ac:	d5 03       	csrf	0x10
   229ae:	d7 03       	nop
   229b0:	d7 03       	nop
   229b2:	d7 43       	frs
   229b4:	d7 03       	nop
   229b6:	d7 03       	nop
   229b8:	eb b0 00 00 	sync	0x0
   229bc:	d7 03       	nop
   229be:	d7 03       	nop
   229c0:	e9 b0 00 00 	sleep	0x0
   229c4:	d7 03       	nop   <<<<<<<<<<<<
   229c6:	d7 43       	frs
   229c8:	d7 03       	nop
   229ca:	d7 03       	nop
   229cc:	ce ea       	rjmp	227a8 <_Z15ProcessMessagesSs+0x108>

hmmh. So far i got an idea. What if this is unrelated to the instruction. Any interrupt that occurs has the instruction after sleep as its return adress stored.

Soo i go back to the original question: how Interrupt line 96 can trigger this interrupt :-) Its source is unclocked.

Edit: it also happens if the SPI is clocked.
Edit2: if i return from the interrupt handler if the InterruptLine is 96, the interrupt does not occur again!
This tells me that the interrupt is not a one. Because normally at least the interrupt source must clean the request. In this case i would need to read the SPI.sr register or something like that. I dont - and i do not stuck in the ISR.

:-/

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

Interrupt line is generated by the SPI0 instance. Do you use the SPI0 to anything? Could you double check to see if anything is enabled, by accident, in the SPI0 peripheral?

What interrupt do you expect to get the device out of sleep?

How is your clocks masked? Are you very conservative, or do you run with all clocks enabled?

AFAICT all your instructions are single cycle instructions, hence you are not affected by the branch prediction errata.

Hans-Christian

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

As stated before SPI is never used and its additionally not clocked. But the error happend also if the SPI is clocked. AND the interrupt line doesnt have to be cleaned to leave the interrupt.

The wakening interrupt can be TWI-transmit-finish, USART-dma-buffer-full, gpio-pin-change or Timer0-RC-compare.
Last one is the highest reason.

The clocks of periperhy i dont need are disabled at programm start.
The Mask-Bits are not changed during the normal programm operation.

I now ignore the misgenerated interrupt by explicitly filtering line 96 out with a direct if Line == 96) return;.

NEXT:
Now i am hanging around and i tried to use the USBA.dma channels. They dont work so far (cant get the linked list to work) :-( But if i (try to) use it a moment later the high priority interrupt handler receives an interrupt from line 1024!!
This is the SDRAMC :-/ I didnt even know that it can generate interrupts so far. I never enable the interrupt.

This seems to have a system THAT an interrupt occurs. but so far there is no system WHEN an interrupt occurs.

I would love to have any solution or reason for that.
I thought about having an databreakpoint on the SPI0-relating register. But
1) its not clocked - any acces should crash
2) the interrupt line does not need to be cleaned - this is not the behavior of a normal interrupt.
3) i dont know wich register
4) how to do it in AVR32 Studio
5) SDRAMC also triggers interrupt of this kind with other priority.

My software is really big. Every details will not help concretely without its context.

I need a solution that tells me "when you do xyz you will get misgerated interrupt abc".

Then i can look where i do xyz. :-)

If more details needed, please ask.

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

How much did you align the various interrupt and exception tables? At what addresses did you put your various interrupt and exception tables?

Hans-Christian

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

Exceptionhandling and Interrupt handling works normally.
A misaligned adress or comaparable problem would show more frequent effects.

To answer your question anyway:
The interrupt section is currently on 0x9e000. As you see its well aligned.

ALL autovectored interrupts are initialiszed to jump to a special routine named "unhandled_interrupt". Initialized interrupts jump into the handlers according to their priority (low (reserved), normal, high and highest) and then they are redirectd with the help of the interruptline-number to their desitnation function.
Nothing special so far.

Ha. Interesting that you asked this. This answer shows a new miss-behavoir i have ignored before:
If all interrupts are initialized to got to unhandled_interrupt.. why an unitialized interrupt triggers the handler of the normal-priotity interrupts? (And according to the new behavior also to the highest-priority interrupt handler)
:-o

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

Are you just working on one unit of hardware?

Maybe you have a faulty/broken CPU?

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

This behavior is random, but present at at least 2 boards :-) (Every board) But thanks for that idea. I missed to report this.

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

Just to ask some things:
I have Self-Modifying-Code executed.
1) Because right now i have got an Illegal Opcode Exception - what is the right way to flush the instruction cache.
currently: "cache adr_reg[0], 0x01" should invalidate the cacheline. This is executed for every adress that is self-modefied. It can also be a Ram-failure.

2) When enabling interrupts of a periphery.. is it a MUST DO to disable interrupts during this time? Also if the handler is registered before?

I know 1) can cause erroneous behavior. With 2) i am unsure.

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

Quote:
2) When enabling interrupts of a periphery.. is it a MUST DO to disable interrupts during this time? Also if the handler is registered before?
Make sure the status flag is cleared before enabling the interrupt, or else you would get an immediate interrupt.

Hans-Christian

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

An immediate interrupt doesnt matter. An interrupt of an different line would be bad :-D e.g. if i enable te TWI interrupt and interrupt line 96 (just an example :-D) is triggered.