[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-libc-dev] vector section disable, vector redirection
From: |
Jörg Diederich |
Subject: |
[avr-libc-dev] vector section disable, vector redirection |
Date: |
Tue, 14 Aug 2007 23:16:23 +0100 |
hello,
i've been working on a part of software which bases on another, already
installed part of software at the avr. in order to use interrupt vectors in the
part mentioned first, two steps were necessary. for both i'd like to discuss an
improvement in the current avr-libc.
first, it was necessary to prevent any vectors are included. this could easily
done by including '*(.vectors)' in the DISCARD-section in the linker script.
Unfortunatly, the '__bad_interrupt' func of the gcrt references section
.vectors. it can't easily discarded too because it is placed in the
.text-section.
as an easy workaround i would suggest to use another, special named section for
this. one simple name would be .bad_vectors. this would enable to discard this
in a simple way. the only neccessary changes in avr-libc would be to include
.bad_vectors right after .vectors in any linker script. the advantage would be
in a simple way to remove any vectors from a linked applicaton. if i remember
correctly, it is possible to use vector space as normal program space, btw.
second, a redirection of all interrupts is performed. on every interrupt a
table in SRAM is asked for the function pointer to jump to. a naive approach
results in very much program space, as the avr-gcc pushed and pops all
registers in an ISR with an call inside (3,2kB on the at90can128). using naked
ISR's is not the smallest thinkable way, as in every ISR the same instructions
are included. that's why my supervisor and me developed the redirection scheme
attached below (ca. 500byte). for me it's unknown if there is any place in the
avr-libc for vector redirections, but any hints are very welcome *g*. (i'm
sorry for long posting, but attachment are often ignored, 'cause of more effort)
the weakness of the redirection table is the set of a vector name in the
following procedure:
extern inthandler redir_tab[];
uint8_t
set_int_handler( inthandler handler, uint8_t idx )
{
[..]
if( idx-- && idx < ((_VECTORS_SIZE / 4) - 1 ) ) {
/*
* first, we are one ahead
* 4 for size of each jump instructions, 1 cause of ignored reset
* vector
*/
redir_tab[idx] = handler;
ret = 0;
}
[..]
}
i would like to use the vector names defined by the avr-libc as an index into
the redirection table (as the second argument in a call). at the moment, i'm
forced to use self-written definitions, because unfortunatly again, the
avr-libc-names are symbols and therefore addresses in program space. the
suggestion is to change the vector definition in avr/interrupt.h:
#define ISR(vector) \
void _VECTOR(vector) (void) __attribute__ ((signal)); \
void _VECTOR(vector) (void)
#endif
(and the others too, of course)
the original macro just uses
#define ISR(vector) \
void vector (void) __attribute__ ((signal)); \
void vector (void)
#endif
instead of defining each vector with _VECTOR(N) in each io.h-instance, it could
easily be defined in interrupt.h.
each io.h-instance therefore could only define interrupt names like this:
/* External Interrupt Request 0 */
#define INT0_vect 1
#define SIG_INTERRUPT0 1
instead of now
/* External Interrupt Request 0 */
#define INT0_vect _VECTOR(1)
#define SIG_INTERRUPT0 _VECTOR(1)
the benefit is, that each vector name is simply the number the interrupt was
given once by atmel. so any redirection or usage of an interrupt could use the
name as an index. the necessary changes in avr-libc are 12 changed function
macros in interrupt.h, plus the change in each io.h-instance. the latter could
be done by an sed-script, i can think about it, if necessary.
i would like the read your opinion. and any hints as well :)
bye jörg
asm-code of redirection procedure:
#include <avr/io.h>
; set size of a single vector
#define VECTOR_SIZE 4
; size of redirection vector
#define REDIRVEC_SIZE 8
; size of redirection table entry
#define REDIRTAB_SIZE 2
; macro for initializing interrupt vectors. see gcrt for prototype
.macro redir name
.if (. - redirs < (_VECTORS_SIZE / VECTOR_SIZE * REDIRVEC_SIZE))
.global \name
\name:
push r18 ; save call-used
; register
ldi r18, (. - redirs)/REDIRVEC_SIZE * 2 ; index into redir_tab
jmp redir_func ; jump to redir function
; TODO: MEGA-arch
; dependent
.endif
.endm
; macro for initializing redirection table. see gcrt for prototype
.macro redir_default cnt
.if (. - redir_tab < ((_VECTORS_SIZE / VECTOR_SIZE - 1) * \
REDIRTAB_SIZE))
; ignore one entry (the one for the reset vector)
.word redir_default
.endif
.endm
; all the following belongs into text
.text
.global redirs
.func redirs
; redir macro calls
redirs:
redir _VECTOR(1)
[...]
redir _VECTOR(56)
.endfunc
; default redirection symbol. similar to the bad_interrupt of avr-libc
; performs nothing more than a return
.global redir_default
.set redir_default, 0
; global redirection routine
; saves registers as needed and redirect to the address specified in
; redirection table
.global redir_func
.func redir_func
redir_func:
redir_func_store: ; save used registers. Saves all
; call-used registers. Called routines
; SHOULD do this by default. But
; ignored for the sake of clarity and
; in case of naked routines
push r1 ; save zero register
eor r1, r1 ; clear zero register, as assumed to
; always be zero
push r0 ; save temporary register
; long names (__zero_reg__)
; first avaiable in macros.inc
in r0, _SFR_IO_ADDR(SREG) ; load status. SREG is a SFR macro
push r0 ; save loaded status. Assumes irqs are
; disabled
push r19 ; save other call-used registers
push r20 ;
push r21 ;
push r22 ;
push r23 ;
push r24 ;
push r25 ;
push XL ;
push XH ;
push ZL ; save lower Z pointer
push ZH ; save upper Z pointer
redir_func_jmp: ; compute jump address
ldi XH, hi8(redir_tab) ; load upper part of vector table
; address
ldi XL, lo8(redir_tab) ; load lower part of vector table
; address
add XL, r18 ; add offset to vector table address.
; Was set with index by caller. Assumes
; less or equal 0x80 vector table
; entries
adc XH, r1 ; add carry now
ld ZL, X+ ; load content of address, which is
; the (lower) jump address
ld ZH, X ; load upper jump address
sbiw ZL, 0 ; test for zero
breq redir_func_restore ; skip next call, if zero
icall ; jump to address pointed by Z pointer
redir_func_restore: ; back from vector routine. restore
; used registers
pop ZH ; restore higher Z pointer
pop ZL ; restore lower Z pointer
pop XH ; restore call-used registers
pop XL ;
pop r25 ;
pop r24 ;
pop r23 ;
pop r22 ;
pop r21 ;
pop r20 ;
pop r19 ;
pop r0 ; restore status register into temporary
out _SFR_IO_ADDR(SREG), r0 ; load status register
pop r0 ; restore temporary register
pop r1 ; restore zero register
pop r18 ; resore first saved and used
reti ; return from redirection and so return
; from interrupt
.endfunc ; end of redirection routine
; all the following belongs to data
.data
.global redir_tab
.func redir_tab
redir_tab:
redir_default 1
[...]
redir_default 56
.endfunc
.end
=
--
Powered By Outblaze
- [avr-libc-dev] vector section disable, vector redirection,
Jörg Diederich <=