Interrup Vector jumps to Reset (program address zero !!!)

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

I've been pulling my hair out trying to figure out why my code just isn't working. ATMEGA2560

Finally I think I've tracked it down to the following issue.

 

It all goes wrong when I set an interrupt in the code:      

UCSR0B |= (1<<UDRIE0);        // Enable USART data register empty interrupt

 

In the simulator I have a breakpoint set in the associated ISR but the code never got there. Instead the code went right back to the beginning (I mean the very beginning).

 

Single stepping through the disassembly I was shocked to find what happened. After the above instruction that sets the interrupt, the code jumped to this:

00000034  JMP  0x00000000

00000034 is the correct vector address for the interrupt but then it's redirecting the program counter to RESET. 

 

Any idea what could be causing this. The code was compiled with Codevision in Atmel Studio 7.

 

EDIT:

 

I found something interesting when I looked in on of the generated files. The next interrupt vector (00000036) has the jump address for my ISR:

00000034  JMP 0x00000000		Jump 
00000036  JMP 0x0000024E		Jump 

My ISR is located at address 0x0000024E which is jumped to by vector 36, but that is the vector for Tx Complete, not UDR empty.

 

OK, sorted my own problem. I had something wrong in the ISR name. Made a little change and vector 0x34 now jumps to my ISR.

 

Keith.

Last Edited: Mon. Apr 15, 2019 - 02:04 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Very likely your Interrupt Routine is

named incorrectly.  It should be called

USART0_UDRE_vect which has a zero

in it, not a capital letter O.  Any slight

difference and the compiler won't link

it up to the jump table.  The default is

to jump to address zero, a kind of soft

reset, which you are experiencing.

 

--Mike

 

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

Most likely you haven't named the interrupt vector correctly for your ISR. The compiler should complain. Or simply you have not defined the ISR for the usart0 data ready interrupt.

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

Odds are, you used the wrong vector name from what you think it is.

 

There is an exhaustive table in AVR LibC documentation.

 

This is exactly the behavior of hitting an undefined interrupt. Undefined ones are filled with 0x0000 to force a jump to reset. So, the actual interrupt is going to a different place than the place you have defined.

 

Jim

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

Last Edited: Mon. Apr 15, 2019 - 01:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


I'm going to disagree with the others and say that the code looks like it is unlinked.

 

If I first get a vector name wrong then:

 

 

Sure I get a warning, but because this vector is unknown how could it possibly know to put a 0x0000 destination into one of the vectors ? In fact you just find:

00000000 <__vectors>:
   0:	0c 94 72 00 	jmp	0xe4	; 0xe4 <__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 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  20:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  24:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  28:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  2c:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  30:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  34:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  38:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  3c:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  40:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  44:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
etc

They ALL link to __bad_interrupt. You can't get one to have a 0x0000 destination this way.

 

As far as I know the only way to get unwanted 0x0000 destinations for CALL/JMP is to generate code with a non-resolved linker fixup.

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

Thanks everyone, a wrongly named ISR is indeed what the problem was.

 

Codevision ISR names have had me a bit confused but now I think I know how the naming works.

 

Initially I had the ISR named as follows:

interrupt [USART0_TXC] void usart0_dre_isr(void)

 

and I thought the usart0_dre_isr was the important bit. However I now think that bit can be called whatever you want and the important bit is in the square brackets.

So I changed the name to:

interrupt [USART0_UDRE] void usart0_dre_isr(void) 

 

and the correct interrupt vector was jumped to and the interrupt vector jumped to my ISR.

 

Looking in the Codevision mega2560.h include file, I found the interrupt vectors listed exactly as in the square brackets in my ISR names.

 

Keith

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

As my example showed - misspelling a vector can't make one 0x0000

 

The way GCC vectors work is that each of INT0_vect, ADC_vect, TMER_COMPA_vect and so on simply maps to _VECTOR(3) or _VECTOR(13) or whatever and that macro in turn simply creates a function that is:
 

__attribute__((used, externally_visible, signal)) void __vector_13(void) {
   //stuff
}

or whatever. Then when __vector_N is implemented the strong link over-rides the previous weak link in the JMP to the code.

 

So when you use ISR(DOES_NOT_EXIST_vect) then, because DOES_NOT_EXIST does not map to any _VECTOR(N) and in turn to any __vector_n() then nothing troubles the IVT. In fact in my previous example you can see what was created in the .i file:

void 
# 4 ".././main.c"
TOTALLY_MADE_UP_vect 
# 4 ".././main.c" 3
(void) __attribute__ ((signal,used, externally_visible)) ; void 
# 4 ".././main.c"
TOTALLY_MADE_UP_vect 
# 4 ".././main.c" 3
(void) 
# 4 ".././main.c"
                         {
 
# 5 ".././main.c" 3
(*(volatile uint8_t *)((0x05) + 0x20)) 
# 5 ".././main.c"
      = 0x55;
}

So tat has created a routine called TOTALLY_MADE_UP_vect().

 

it's because it has the signal attribute that the compiler expects it to have a name that is __vector_n() and because it does not have this is why the compiler emits the "may be misspelled" warning.

 

Bottom line I don't believe a mis named vector can create a 0x0000 as there'd be no __vector_N() implementation to over-ride a weak link to __bad_interrupt.

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

Yes, all unimplemented vectors do a

jump to __bad_interrupt, but all the

__bad_interrupt does is jump to zero:

 

  5c:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  60:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
  64:   0c 94 3e 00     jmp 0x7c    ; 0x7c <__bad_interrupt>
...
0000007c <__bad_interrupt>:
  7c:   0c 94 00 00     jmp 0   ; 0x0 <__vectors>

 

--Mike

 

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

Yes but OP was seeing:

00000034  JMP 0x00000000		Jump 
00000036  JMP 0x0000024E		Jump 

That is a direct jump to 0. Yet it should be indirect via bad interrupt. That is:

   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>

with that address (0x00FC in this case) then having the JMP 0. To actually get a "JMP 0" into the vector table itself requires some other mechanism.

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

clawson wrote:
. Yet it should be indirect via bad interrupt

Cliff, you are correct for the operation of GCC, but OP is using CV for his compiler, perhaps it behaves differently WRT interrupt vectors...

Artandsparks wrote:
The code was compiled with Codevision in Atmel Studio 7.

 

Jim

 

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

Last Edited: Mon. Apr 15, 2019 - 03:50 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh right - I need to learn to read ;-)

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

clawson wrote:
Oh right - I need to learn to read ;-)

Me too, I've been staring all morning at a piece of code that would not compile, the compiler keep insisting the number of params did not match function in the call....

I had done a copy/paste of the function line into the call so it should have the same # of params, of course the copied line included the defs of the params, ie. function(uint8_t data1, uint8_t data2)....

I just could not see the error, until I called another programmer to come look at my code and help me find my error!   He did right away!  Duh (head slap) .....

 

Oh well , back to work.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274