AVR32DA48 bad interrupt

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

TCA0 interrupt is not vectored to my ISR-function.

 

I have a Start-atmel generated project with only one software component, a TCA0 counter set up in normal mode to yield a periodic overflow interrupt. However, TCA0 overflow interrupts never hit my vector7 function and are instead catched by a bad vector interrupt function.

 

What I know:

 

A __vector_default function catches  the interrupts. In this function I clear the TCA0 OVF flag bit and toggle an LED. The LED then flips as expected at the programmed timer interval.

 

If the __vector_default function only  has en endless loop the background program stops.

 

To find the interrupt source I set the CPUINT.LVL1VEC  for vector 1 and upwards and checked the CPUINT.STATUS register. In all cases only the LVL0EX bit was set. Until I reached vector 7 which set the LVL1EX bit. This indicates that it is actually vector 7 which is in action. It also shows that I have not activated the compact vector table option.

 

So I'm confident that the bad interrupt is caused by TCA0 overflow..

Here is the beginning of the disassembled code, looks like the vector_7 is at the location stated in the data sheet (word address 0x0e).

00000000 <__vectors>:
   0:   0c 94 74 00     jmp     0xe8    ; 0xe8 <__ctors_end>
   4:   0c 94 7e 00     jmp     0xfc    ; 0xfc <__bad_interrupt>
   8:   0c 94 7e 00     jmp     0xfc    ; 0xfc <__bad_interrupt>
   c:   0c 94 7e 00     jmp     0xfc    ; 0xfc <__bad_interrupt>
  10:   0c 94 7e 00     jmp     0xfc    ; 0xfc <__bad_interrupt>
  14:   0c 94 7e 00     jmp     0xfc    ; 0xfc <__bad_interrupt>
  18:   0c 94 7e 00     jmp     0xfc    ; 0xfc <__bad_interrupt>
  1c:   0c 94 f3 00     jmp     0x1e6   ; 0x1e6 <__vector_7>
  20:   0c 94 7e 00     jmp     0xfc    ; 0xfc <__bad_interrupt>
  24:   0c 94 7e 00     jmp     0xfc    ; 0xfc <__bad_interrupt>
 

 

and 0x1e6 is actually the address of my vectror7 handler:

000001e6 <__vector_7>:
 1e6:   1f 92           push    r1
 (...)

Any idea about what I'm doing wrong?

 

 

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

Create a minimal example-

 

#include <avr/io.h>
#include <avr/interrupt.h>

ISR(TCA0_OVF_vect){
    asm("nop"); //breakpoint here

    //if ovf flag not cleared, we will be back here 1 instruction after return
}
int main(void) {
    TCA0.SINGLE.CNT--; //now matches PER
    TCA0.SINGLE.INTCTRL = 1; //OVF irq on
    TCA0.SINGLE.CTRLA = 1; //enable
    sei(); //irq's on
    while(1){
        asm("nop"); //provide a place to stop
    }
}

 

Run it in the simulator (works for me), run it on hardware.  You sure you enabled the correct irq in TCA0?

 

You can enable LVLRR to figure out which vector you are in. With round robin enabled, LVL0PRI will contain the current vector you are in.

Last Edited: Sat. Nov 28, 2020 - 08:22 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The answer to your question is here:

https://www.avrfreaks.net/forum/...

Seems that the chip has a silicon bug.

 

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

If it is a silicon bug, and not just enabling the wrong interrupt then one could still make it work without much effort-

 

 

    ; copy avrxmega3.xn to project folder, modify-
    ; add a .vectors_stub section before .vectors
    ;  .text   :
    ; {
    ; *(.vectors_stub)
    ; KEEP(*(.vectors_stub))
    ; *(.vectors)
    ; KEEP(*(.vectors))
    ; ...

 

    ; vectors_stub.s

    ; create the vector stub
    .section .vectors_stub
    .global __vectors_stub
    __vectors_stub:
    .set ofs,0
    .rept 58
    rjmp .+57*2+ofs
    .set ofs,ofs+2
    .endr

 

    ; add vectors_stub.s to project
    ; gcc ld options- add
    ; -Xlinker -script=avrxmega3.xn
    ; (various methods available, the above is the end result)

 

It looks like it is correct (stub vectors rjmp's to real vectors), but the simulator does not like it. Maybe I'm forgetting something, but I think its correct and looks to be the simplest fix.

 

Last Edited: Sun. Nov 29, 2020 - 02:28 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, thank you. I use the compact vector option now. Works for the timer, but USART interrupts seem to be a bit fishy. Looks like I get sporadic interrupts form the serial transmitter while both transmitter and receiver are disabled. I have never had such problems with an Atmel chip. 

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

> I use the compact vector option now

 

Explain what that means.

 

You would still need to get the 4 vectors that normally are 4 bytes wide in the vector table to now be 2 bytes wide (due to silicon bug).

 

word addr

0x0000 reset: jmp __init

0x0002 nmi:   jmp __bad_interrupt

0x0004 lvl1:  jmp __bad_interrupt

0x0006 lvl0:  jmp __bad_interrupt

 

So unless something is done about the vector table itself, your LVL0 irq's are going to word address 0x0003, which means you are at the second half of of the nmi jmp instruction, then get to the LVL1 jmp. Seems harmless except for what is going on in the second half of that nmi jmp, which could be doing some instruction that is changing a register (and flags) and that would be something that could cause strange problems.

 

Have you tried solution #4? That would end up with a little rjmp table to the original jmp table and you could then proceed as if there was no problem.

 

Of course, the best solution is to contact mchp and get a replacement part if it is the buggered version, but use #4 in the meantime.