How to add assembler function to Interrupt Jump Table

Dear all

I have two (native, not inline) assembly functions that I want to use as an Interrupt Service Routine (ISR) for interrupt vector TIMER1_COMPB and TIMER1_CAPT, respectively. I’m working with a Arduino Uno Rev3 / Atmega328.

I have spent many hours trying but I can’t figure out how to add these functions to the Interrupt Jump Table.

I’ve tried:

.org 0x0014
	jmp TIMER1_COMPB
.org 0x0018
	jmp TIMER1_COMPB

but the .org directives are ignored and the interrupts point at <__bad_interrupt> as a result.

ISR(TIMER1_COMPB_vect)
{
	TIMER1_COMPB();
}

works but adds a lot of overhead because the program first jumps to <__vector_12> before calling TIMER1_COMPB().

Any ideas how to get the interrupt jump table right?

Many thanks
Lukas

Use the ISR method as it is portable between different AVRs.

Mark

PS learn to like the overhead.

M

TIMER1_COMPB_vect is the address for "TIMER1_COMPB" in the interrupt vector table (vector not jump by the way).

Mark

The interrupt for timer1 COMPB is listed in the data sheet as vector no. 13. But the Arduino compiler appears to start numbering with 0 instead of 1 and so calls it vector 12. This vector lives at address 0x0018 according to the data sheet. But the address refers to 16-bit words, not bytes, so the physical address is twice that: 0x0030.

When the interrupt is serviced by the processor it loads the 4-byte instruction which is at that address. Typically that instruction is a JMP. I suppose it would be possible in principle to place your ISR at that location. Provided you weren't using any interrupts greater than no. 13 your code wouldn't interfere. But it would be pretty weird. If speed is that much of a concern you might consider other alternatives first.

How you would place your own JMP there with the Arduino compiler isn't clear to me. But even if you succeeded you wouldn't be getting to your ISR any faster.

I think the minimum would be to use the ISR_NAKED attribute. That produces an ISR without any overhead. You have to push/pop any used registers and supply a RETI instruction yourself. Maybe you can make the ISR a little tighter that way.

ISR(TIMER1_COMPB_vect, ISR_NAKED)
{
// your handler here
}

Or just copy the code from TIMER1_COMPB into TIMER1_COMPB_vect .

Google up "avr/interrupts"

Mark

ISR_ALIAS...
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#gade46eb4e42cc9d56c19b1f91448f1b76