Are all Vectors intialized to RETI by GCC?

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

Good morning, World.

Are all Vector addresses loaded with a return (RETI) command by Default?

Where would I find and/or manipulate this within GCC without resorting to Program Memory re-write ?

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

I think you may be misunderstanding some terminology.

All Interrupt Service Routines (ISR) end with reti. You could, in theory, mess with where it returns to by changing the return address on the stack.

The Interrupt Vector is the place that the MCU goes to, depending on the source of the interrupt. There, there is a jump to the interrupt service routine. So, no the "Vector Address" has no reti. The ISR does.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

No. Typically they are loaded with "jmp __bad_interrupt", and __bad_interrupt has a "jmp 0" (reset, sort of)

Note that a RETI would be an infinite loop; if you don't remove the cause of an interrupt, the interrupt will occur again 1 instruction after the reti instruction returns.

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

When I write asm I place RETI in the vector addresses that I don't care about, which causes a return to where I am at in the code, and the interrupt flag is cleared. I know this works, because I will enable timers that will be used, but I don't have the functions within the interrupt handler built. REM that vector addresses are only Flash locations like any other program location.

I don't prefer C, but I do use C when required. What I am seeking to find is where I am returning to. I set Timer 0 running and I've enabled the T0 interrupt. I sleep and wake. Where is the ISR located, so I can discover where I've gone to?
Thank you much

Chris

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

You could look at the stack return address after a weak interrupt, or use the code after HANG_ON_UNKNOWN_INTERRUPT at https://github.com/contiki/contiki-mirror/blob/d6dc216e02bb00a40411e6901f6af61d42366d17/cpu/avr/dev/clock.c

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

As this post is in GCC forum you could always give in and read the user manual:

http://www.nongnu.org/avr-libc/u...

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

In my humble opinion, this is a rather poor programming practice.

If, for no other reason, interrupts are going off (stealing processor cycles and blocking other interrupts). It can only slow things down.

Only enable interrupts that your code is actually using. Then, you have no problem.

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

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

Jim wrote:
The Interrupt Vector is the place that the MCU goes to, depending on the source of the interrupt. There, there is a jump to the interrupt service routine. So, no the "Vector Address" has no reti. The ISR does.

Technically, what is required after an interrupt has triggered is that a RETI is executed sooner or later. As far as I can see this could well be as early as the RETI actually being placed at the vector per se.

Useful? Perhaps not.

Possible? I think so, but am gladly proven wrong. (It's been a while since I left the cave and stopped using assembler for anything but playful experiments... :wink:)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

I like caves. Anyway, I design new boards for most projects, and I'd be changing my function and define terminology too much in my efforts to make it read well against the schematic. Besides, I began my career debugging machine language generated from Fortran, so assembly is a step up!

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

The most reasonable way to ensure that the undefined interrupts do nothing is to provide empty ISR functions for each one that might occur. That would be MUCH more portable than (for example) replacing the startup crtxxx.o file with one that has reti instructions directly in the vector table.

With gcc (4.3.2), this takes 10 instructions (20 bytes) per ISR. If that's a problem, then you can look at the next solution (which is more compiler specific.)

You're wrong about reti clearing the interrupt flag. It'll reset the global IE flag, but not the individual peripherals' ISR status...

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

westfw wrote:
The most reasonable way to ensure that the undefined interrupts do nothing is to provide empty ISR functions for each one that might occur.
...
With gcc (4.3.2), this takes 10 instructions (20 bytes) per ISR.
No, it takes 2 instructions. A jump to the ISR in the table and a reti in the ISR.
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#ga751c22101f7e8f2fbe792c64a81f8dba

Stefan Ernst

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

It's one intermediate jump:

#include 

EMPTY_INTERRUPT (BADISR_vect);

int main (void)
{
    return 0;
}

yields:

00000000 <__vectors>:
   0:	0c 94 34 00 	jmp	0x68	; 0x68 <__init>
   4:	0c 94 3e 00 	jmp	0x7c	; 0x7c <__bad_interrupt>
   8:	0c 94 3e 00 	jmp	0x7c	; 0x7c <__bad_interrupt>
   c:	0c 94 3e 00 	jmp	0x7c	; 0x7c <__bad_interrupt>
   ...

00000068 <__init>:
  68:	11 24       eor	r1, r1
  ...

0000007c <__bad_interrupt>:
  7c:	0c 94 40 00 jmp	0x80	; 0x80 <__vector_default>

00000080 <__vector_default>:
  80:	18 95       reti

...

If this it too komplex, you may want to write own startup code and implement a vector layout that better fits your needs.

avrfreaks does not support Opera. Profile inactive.

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

I think the OP needs to be aware of the fact that different CPU architectures do treat the contents of an Interrupt vector table conceptually different. While some do view an entry of such a table as being the next instruction to execute (i.e. AVR, that's why you see a JMP instruction within the vector table), other processors take an int vector table entry simpla as the *address* where to continue exceution (via an implicit jump). So, if you simply put a RETI into the vector table of an AVR, it would properly execute it (of course all the comments above about removing the source of the interrupt are still valid). But, in contrast, if you put a RETI instruction into a vector table where the processor expects an address (i.e. Z80), it will take the hex bytes of the RETI instruction coding and treat this as an address, which of course will *not* work at all.

Einstein was right: "Two things are unlimited: the universe and the human stupidity. But i'm not quite sure about the former..."

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

westfw wrote:
The most reasonable way to ensure that the undefined interrupts do nothing is to provide empty ISR functions for each one that might occur. That would be MUCH more portable than (for example) replacing the startup crtxxx.o file with one that has reti instructions directly in the vector table.

With gcc (4.3.2), this takes 10 instructions (20 bytes) per ISR. If that's a problem, then you can look at the next solution (which is more compiler specific.)

You're wrong about reti clearing the interrupt flag. It'll reset the global IE flag, but not the individual peripherals' ISR status...

Most of the 8-bit AVR peripherals' individual ISR status bits are automatically cleared long before the RETI.

Most of them clear themselves the instant the CPU recognizes the opportunity to begin servicing the interrupt. As part of the same atomic operation in which the CPU halts normal program flow, stores the return address on the stack, and and vectors to the entry point of the ISR. Automatically. Before any code pointed to by the interrupt vector has even started to execute.

There are, or course, exceptions to this rule. Level-triggered (rather then edge) external pin interrupts do not clear themselves automatically. Neither does the UDRE interrupt flag in an 8-bit AVR U(S)ART. The EEPROM Ready interrupt also constantly fires. There may be others in some peripherals I haven't yet needed to use in an interrupt driven mechanism.

But the vast majority of other interrupt sources in an 8-bit AVR do clear themselves automatically, without the need for any deliberate code to trigger the clearing.

Of course, if the event which triggered the errant interrupt in the first place happens again later on, then the interrupt will obviously fire again.

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

Off-Earth wrote:
When I write asm I place RETI in the vector addresses that I don't care about

A good programmer should never hide programming faults. :!:
He should fix it.

If you have a leaky roof, your approach was putting a bucket under the leak.
But the professional solution was fixing the roof.

Peter

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

Quote:

A good programmer should never hide programming faults.

Which is the exact intention of avr-gcc's "catch all" mechanism - it's kind of hard to miss a "JMP 0" when you are not expecting it.

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

clawson wrote:
Quote:

A good programmer should never hide programming faults.

Which is the exact intention of avr-gcc's "catch all" mechanism - it's kind of hard to miss a "JMP 0" when you are not expecting it.
But it can be hard to realize what is going on,
hence all the "why is my processor resetting?" posts.
For debugging, a better default might be RJMP .-2 or CALL turn_off_watch_dog_and_loop_forever".
Neither would be confused with a reset and the particular
interrupt could be determined from the stack or from the PC.

For production, a watchdog reset would be better.
It will clear registers that might need clearing.

"SCSI is NOT magic. There are *fundamental technical
reasons* why it is necessary to sacrifice a young
goat to your SCSI chain now and then." -- John Woods