Using .weak in custom vector table

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

I have a custom vector table (thanks AVR Bootloader FAQ). I have modified the linker script to throw out the original .vectors section and replace it with mine. Following the example in gcrt1.S, I tried to make the vectors weak link to __bad_interrupt. However, the vectors continue to point to __bad_interrupt even when I define an ISR. Here is the source code:

#define __SFR_OFFSET 0

#include 
#include "UsbDef.h"

.section .usb_vectors,"ax",@progbits

.global __vector_default

	.macro	vector name
	.if (. - __vector_default < _VECTORS_SIZE)
	.weak	\name
	.set	\name, __bad_interrupt
	rjmp	\name
	.endif
	.endm

__vector_default:
	rjmp	__init
	rjmp	__vector_1		; INT0 vector
; PCINT vector goes here
	in	r0, USB_TIMER_CNT	; PCINT0 vector
	st	Z+, r0			; TIMER1_COMPA vector
	reti				; TIMER1_OVF vector
	vector	__vector_5		; TIMER0_OVF vector
	vector	__vector_6
	vector	__vector_7
	vector	__vector_8
	vector	__vector_9
	vector	__vector_10
	vector	__vector_11
	vector	__vector_12
	vector	__vector_13
	vector	__vector_14
	vector	__vector_15

So __vector_1 works because I hardcoded the rjmp. All the rest go to __bad_interrupt whether I define an ISR or not. I can see the defined vectors showing up in the map file at their correct address.

Can someone help me get the weak linkage working?

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

Show us a minimal complete compilable example together with the way how you compiled (command-line used or makefile), and the version of the tools.

JW

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

We don't see the options. You use -nostartfiles, yes?

The default vectab is not weak.

avrfreaks does not support Opera. Profile inactive.

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

I have not changed/added any command line options, but I edited the linker script. I removed the standard vector table with:

/DISCARD/ : { *(.vectors); } 

I put the section name for my vector table (.usb_vectors) in place of the of .vectors. So I have kept the rest of the startup code, including the definition of __bad_interrupt. I got the instructions for this from the AVR Bootloader FAQ (Q18): http://blog.schicks.net/2009/avr-bootloader-faq/

The vector table replacement all seems to be working. Here is a snippet from the .lss file:

__vector_default:
	rjmp	__init
   0:	55 c0       	rjmp	.+170    	; 0xac <__ctors_end>
	rjmp	__vector_1		; INT0 vector
   2:	ba c2       	rjmp	.+1396   	; 0x578 <__vector_1>
; PCINT vector goes here
	in	r0, USB_TIMER_CNT	; PCINT0 vector
   4:	0f b4       	in	r0, 0x2f	; 47
	st	Z+, r0			; TIMER1_COMPA vector
   6:	01 92       	st	Z+, r0
	reti				; TIMER1_OVF vector
   8:	18 95       	reti
	vector	__vector_5		; TIMER0_OVF vector
   a:	6b c0       	rjmp	.+214    	; 0xe2 <__bad_interrupt>
	vector	__vector_6
   c:	6a c0       	rjmp	.+212    	; 0xe2 <__bad_interrupt>
	vector	__vector_7
   e:	69 c0       	rjmp	.+210    	; 0xe2 <__bad_interrupt>
	vector	__vector_8
  10:	68 c0       	rjmp	.+208    	; 0xe2 <__bad_interrupt>
	vector	__vector_9
  12:	67 c0       	rjmp	.+206    	; 0xe2 <__bad_interrupt>
	vector	__vector_10
  14:	66 c0       	rjmp	.+204    	; 0xe2 <__bad_interrupt>
	vector	__vector_11
  16:	65 c0       	rjmp	.+202    	; 0xe2 <__bad_interrupt>
	vector	__vector_12
  18:	64 c0       	rjmp	.+200    	; 0xe2 <__bad_interrupt>
	vector	__vector_13
  1a:	63 c0       	rjmp	.+198    	; 0xe2 <__bad_interrupt>
	vector	__vector_14
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A suggestion- use original linker script, and simply grab a copy of gcrt1.S, add it to your project, edit as needed, add '-nostartfiles' to the linker options.

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

curtvm wrote:
A suggestion- use original linker script, and simply grab a copy of gcrt1.S, add it to your project, edit as needed, add '-nostartfiles' to the linker options.
Wouldn't -nostartfiles wipe out also some of the needed stuff (global/static variables initialisation, constructors/destructors, whatever)?

I repeat, there's no point to continue without an example reproducing the problem, or a well-working crystal ball.

JW

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

I have been away from my avr's for a while, but I believe -nostartfiles just removes the crt object file. With gcrt1.S added to the project (with -nostartfiles), and left in 'stock' form, you would be at the same starting point.

The data initialization comes from the gcc built library (the gcc guys, not the libc guys), which gets linked in by a couple symbols passed to the linker (I think that's who gets it). Things change a little for big avr's, but either using gcrt1.S with -nostartfiles, or using the crt object file (without -nostartfiles) will work.

(-nodefaultlibs removes the gcc default lib that contains the data initialization functions for <128k avrs. For large avr's, the crt does the data initialization)

Maybe things have changed, though.

Quote:
I have not changed/added any command line options, but I edited the linker script
I would rather add a linker option, than edit linker scripts. In either case you will have a .S file. Nothing wrong with changing linker scripts, but I would rather leave it alone if possible.

Last Edited: Tue. Sep 27, 2011 - 10:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I meant it as a question, not a provocation ;-)

Jan

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

was taken as a good question.

I think maybe the OP is experiencing some 'weirdness' with the combo of having the crt object file linked in (he said no command line options), along with removing the .vector section.

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

curtvm's suggestion of putting gcrt1.S in the project proved to be an excellent debugging tool. By stripping things out and/or moving code between files, I found the answer: .weak only works when the target is defined in the same file.

My custom vectors are trying to weak link with __bad_interrupt in gcrt1. So instead I linked them to __invalid_int, a symbol I defined in the same file as follows:

.weak	__invalid_int
.set	 __invalid_int, __vector_default

Everything works now.

I prefer to keep the rest of the CRT startup, rather than use a copy of gcrt1.S, so that I can upgrade compilers in the future and have less worry about compatibility (should CRT startup change).

For reference, here is the completed working code:

#define __SFR_OFFSET 0

#include 
#include "UsbDef.h"

.section .usb_vectors,"ax",@progbits

.global __vector_default

	.macro	vector name
	.if (. - __vector_default < _VECTORS_SIZE)
	.weak	\name
	.set	\name, __invalid_int
	rjmp	\name
	.endif
	.endm

__vector_default:
	rjmp	__init
	rjmp	__vector_1		; INT0 vector
; PCINT vector goes here
	in	r0, USB_TIMER_CNT	; PCINT0 vector
	st	Z+, r0			; TIMER1_COMPA vector
	reti				; TIMER1_OVF vector
	vector	__vector_5		; TIMER0_OVF vector
	vector	__vector_6
	vector	__vector_7
	vector	__vector_8
	vector	__vector_9
	vector	__vector_10
	vector	__vector_11
	vector	__vector_12
	vector	__vector_13
	vector	__vector_14
	vector	__vector_15
	
	.weak	__invalid_int
	.set	__invalid_int, __vector_default
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Wouldn't -nostartfiles wipe out also some of the needed stuff (global/static variables initialisation, constructors/destructors, whatever)?

But you put that back with your locally built copy of gctr1.S so there's no worries. (Actually the data and bss loops now come out of libc when required and are no longer located in gcrt1.S).

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

clawson wrote:
Quote:
Wouldn't -nostartfiles wipe out also some of the needed stuff (global/static variables initialisation, constructors/destructors, whatever)?
But you put that back with your locally built copy of gctr1.S so there's no worries. (Actually the data and bss loops now come out of libc when required and are no longer located in gcrt1.S).
These parts of startup live in libgcc, not in libc. avr-gcc's specs depend on -nostartfiles.

avrfreaks does not support Opera. Profile inactive.

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

Damn I tried to remember without checking and remembered wrong - that'll teach me to check next time :oops:

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

Whenever I contemplate a custom vector,
I always imagine removing the standard vector table with objcopy applied to gcrt1.o and somehow pointing the linker to the result.
Another possibility would be to
link as usual, possibly with -r, but without the custom vector table
strip the vector table with objcopy
link the result with the custom vector table.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?

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

Quote:
Actually the data and bss loops now come out of libc when required and are no longer located in gcrt1.S
It sounds like there's been some changes, which is pretty much my case in point. I have projects using the last WinAVR and some using the new AVR Studio 5 toolchain, and I don't want to think about getting the startup code right for each.

clawson, you're listed as a contributor to the AVR Bootloader FAQ. Do you disagree with its recipe to edit the linker script to replace the vector table?

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

Quote:

Do you disagree with its recipe to edit the linker script to replace the vector table?

I do - I know Brad asked me to proof read the bits he wrote but I fear I may have skated over his question 18 as it was something he'd proven to work for himself. I much prefer the idea of a locally copied gcrt1.S and -nostartfiles myself.

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

clawson wrote:
Quote:

Do you disagree with its recipe to edit the linker script to replace the vector table?

I do - I know Brad asked me to proof read the bits he wrote but I fear I may have skated over his question 18 as it was something he'd proven to work for himself. I much prefer the idea of a locally copied gcrt1.S and -nostartfiles myself.
What is your opinion of the link, objcopy, link method?
It seems to me that if it works it would be more resistant to changes in the tools.

Also, I just read the bootloader FAQ. Wow.
The jump table involves rather a lot of hand copying.
How about something like this:

grok:
grok(fred)
grok(greg)
grok(hank)

jumptable.S:
.section .jumptable
#define grok(target) jmp target $ align 4
#include grok

jumptable-fake.S:
.section .jumptable
#define grok(target) target: org .+4  $ .global target
#include grok

grok contains the list of shared functions.

jumptable.S can be assembled and linked separately using --just-symbols bootloader.elf --no-start-up-or-other-extras
The align 4 is in case jmp gets --relaxed to rjmp.

jumptable-fake.S is also assembled and linked with --no-start-up-or-other-extras

The application can be compiled and linked with --just-symbols jumptable-fake.elf

jumptable.S and jumptable-fake.S would be the same for all bootloaders for AVRs with four-byte jump instructions.

International Theophysical Year seems to have been forgotten..
Anyone remember the song Jukebox Band?