//-----------------------------------------------------------------------------------------
// startup.c
//
//alternate
startup vector table/startup code to replace c runtime object file, and
//library
functions from libgcc.a
//
//purpose-
to
have all startup code in one file/one location that can be modified as
//needed
//
//there
are
symbols in c runtime object file that are not defined here
//
//linker
option --nostartfiles is needed to prevent linking in the crt*.o oject
file,
//which
is
what this replaces in part
//
//the
functions from libgcc.a for setting up ram, are prevented from being
linked in
//by
providing
the functions here, which are naked (empty, no code)
//-----------------------------------------------------------------------------------------
#include
<avr/io.h>
#include
<avr/pgmspace.h>
//-----------------------------------------------------------------------------------------
//defines
//-----------------------------------------------------------------------------------------
#define
NAKED
__attribute__((naked))
#define
VECTORS __attribute__((naked,noinline,section(".vectors")))
#define
V(num)
__attribute__((weak,alias("__bad_interrupt"))) void __vector_##num(void)
#define
NL
"\n\t"
#define
WDR()
asm("wdr")
//-----------------------------------------------------------------------------------------
//linker
symbols
//-----------------------------------------------------------------------------------------
extern void*
__bss_end;
extern void*
__data_load_start;
extern void*
__data_load_end;
extern void*
__data_start;
//-----------------------------------------------------------------------------------------
//prevent
these functions from being pulled in (libgcc.a) by creating empty
functions
//-----------------------------------------------------------------------------------------
NAKED void
__do_copy_data(){}
NAKED void
__do_clear_bss(){}
//-----------------------------------------------------------------------------------------
//function
prototypes, vectors are weak with alias to __bad_interrupt
//-----------------------------------------------------------------------------------------
int main(void);
V(1); V(2);
V(3); V(4); V(5); V(6); V(7); V(8);
V(9);
V(10);V(11);V(12);V(13);V(14);V(15);V(16);
V(17);V(18);V(19);V(20);V(21);V(22);V(23);V(24);
V(25);V(26);V(27);V(28);V(29);V(30);V(31);V(32);
V(33);V(34);V(35);V(36);V(37);V(38);V(39);V(40);
V(41);V(42);V(43);V(44);V(45);V(46);V(47);V(48);
V(49);V(50);V(51);V(52);V(53);V(54);V(55);V(56);
//-----------------------------------------------------------------------------------------
//vector
table
+ startup code + exit code
//-----------------------------------------------------------------------------------------
VECTORS void
__vectors(void){
asm(
".irp
d,,1,2,3,4,5"
NL
// tens
".irp c,0,1,2,3,4,5,6,7,8,9"
NL
// ones (dc=0-59, max set below)
".if \\d\\c <
%0"
NL
// if < max irq #
".if
%1"
NL
"jmp
__vector_\\d\\c"
NL
// jmp to __vector_dc
".else"
NL
"rjmp
__vector_\\d\\c"
NL
// rjmp to __vector_dc
".endif"
NL
".endif"
NL
".endr"
NL
".endr"
NL
"__vector_0:"
NL
"clr
__zero_reg__"
NL
// clear r1
"out __SREG__,__zero_reg__"
NL
// SREG=0 (cli)
:
: "M"(FLASHEND>8192?_VECTORS_SIZE/4:_VECTORS_SIZE/2),
"M"(FLASHEND>8192?1:0)
);
SP=RAMEND;
// set stack
uint8_t* r =
(uint8_t*)&__data_start;
// set start of data (ram)
uint16_t ef =
(uint16_t)&__data_load_end; //
set end of data (flash)
uint8_t* er =
(uint8_t*)&__bss_end;
// set end of bss (ram)
uint8_t data;
#ifdef RAMPZ
uint32_t f;
asm("ldi
%C0,hlo8(%1)" NL
"ldi
%B0,hi8(%1)"
NL
"ldi
%A0,lo8(%1)"
NL
: "=d" (f)
: "p" (&__data_load_start)
);
#define READ_FLASH
pgm_read_byte_far
#else
uint16_t f = (uint16_t)&__data_load_start;
#define READ_FLASH
pgm_read_byte
#endif
while(r!=er){
// while not at end of bss (ram)
data=0;
// assume bss, data = 0
if((uint16_t)f!=ef){ data = READ_FLASH(f++);
} // if flash, data = read flash
*r++=data;
// data-> ram
WDR();
// clear watchdog
}
main();
// call main
SREG=0;
// exit from main, cli
while(1);
// then stop
}
//-----------------------------------------------------------------------------------------
//bad
interrupts will call __vectors (reset vector), this can be changed as
needed
//-----------------------------------------------------------------------------------------
NAKED void
__bad_interrupt(void){ __vectors(); }