« Previous | Next»

Gettting rid of the interrupt table on the AVR

Posted by coldtobi | 20 Jul, 2007, 10:52

Sometimes, programm size is everthing. This is especially true, if you are coding for a very constraint system like the AVR or you are going to write a bootloader, which should be as small as possible.

Well, I actually hit both of the categories, as I program a bootloader for a customer's project for a 8k-flash Atmel. 

But as the numbers of features implemented grew, on the other side available space shrinked.

The AVRs have a dedicated bootloader section, which -- if properly used -- have useful features, like read/write protection, Read-While-Write (my error: RWW is not configurable)  and more. The size of the bootloader and the features section is user configurable by the so called Bootloader Fuses, but not modifiable by the AVR itself. In my case I have the options of 128, 256, 512 or 1024 flash words (flash is organized word-wide in the AVR) or from about 3% to 25%. 

So finally when I was (almost) done, I figured out that I gonna miss the magical size by some few dozens bytes. "Overlapping" to application space is not really an good idea, as not easily handled by the toolchain (would be possible through relocating with .org) and the bootloader would not be protected against accidental overwriting by the AVR flash controller, but waste almost 1k of precious flash?

The solution is to get rid of the intterupt vector table, which is -- of course -- only an option if you are not enabling interrupts in your program. My bootloader is not interrupt driven (interrupts take a LOT of flash for the context saving), so this would be an option. 

But how?  The answer to this question took some time, googling after it, but here's the procdeured:

 

1. Get rid of the ISR-Table. This done by telling the linker by the option "-nostartfiles", usually using a

LDFLAGS += -nostartfiles

 in the Makefiles

 

2. As this also discards some gcc-needed initialization, like the "Zero-Register" and the "Stack Pointer",  you'll need a custom entry function linked to the init9 section:

void __jMain(void) __attribute__ ((naked)) __attribute__ ((section (".init9")));
void __jMain(void)
{   
    asm volatile ( ".set __stack, %0" :: "i" (RAMEND) );
    asm volatile ( "clr __zero_reg__" );        // gcc expcets this to be zero.  
    asm volatile ( "rjmp main");                // start main()
}

 Just a note: In my case, the function has also be the very first linked to the hexfile. This can usally be accomplished by "coding" the function as the top function of e.g main.c, and to make sure, that the object file, main.o is also the very first object file linked into the project. If this is not this way, you might ending executing other code than you expect. In doubt, check the assembler code generated by the compiler, or just execute it in the AVRStudio simulator. 

Electronics and Atmel AVR | Comments (0) | Trackbacks (0)

Related Articles:

0 Comments | "Gettting rid of the interrupt table on the AVR" »