4.1.4 MCS51/DS390 Startup Code
Keywords: sdccman

##
4.1.4 MCS51/DS390 Startup Code

The compiler triggers the linker to link certain initialization modules from the runtime library called crt<something>. Only the necessary ones are linked, for instance crtxstack.asm (GSINIT1, GSINIT5) is not linked unless the --xstack option is used. These modules are highly entangled by the use of special segments/areas, but a common layout is shown below:

> (main.asm)

> .area HOME (CODE)
> __interrupt_vect:
> ljmp __sdcc_gsinit_startup

> (crtstart.asm)

> .area GSINIT0 (CODE)
> __sdcc_gsinit_startup::
> mov sp,#__start__stack - 1

> (crtxstack.asm)

> .area GSINIT1 (CODE)
> __sdcc_init_xstack::
> ; Need to initialize in GSINIT1 in case the user's __sdcc_external_startup uses the xstack.
> mov __XPAGE,#(__start__xstack » 8)
> mov _spx,#__start__xstack

> (crtstart.asm)

> .area GSINIT2 (CODE)
> lcall ___sdcc_external_startup
> mov a,dpl
> jz __sdcc_init_data
> ljmp __sdcc_program_startup
> __sdcc_init_data:

> (crtxinit.asm)

> .area GSINIT3 (CODE)
> __mcs51_genXINIT::
> mov r1,#l_XINIT
> mov a,r1
> orl a,#(l_XINIT » 8)
> jz 00003$
> mov r2,#((l_XINIT+255) » 8)
> mov dptr,#s_XINIT
> mov r0,#s_XISEG
> mov __XPAGE,#(s_XISEG » 8)
> 00001$: clr a
> movc a,@a+dptr
> movx @r0,a
> inc dptr
> inc r0
> cjne r0,#0,00002$
> inc __XPAGE
> 00002$: djnz r1,00001$
> djnz r2,00001$
> mov __XPAGE,#0xFF
> 00003$:

> (crtclear.asm)

> .area GSINIT4 (CODE)
> __mcs51_genRAMCLEAR::
> clr a
> mov r0,#(l_IRAM-1)
> 00004$: mov @r0,a
> djnz r0,00004$
> ; _mcs51_genRAMCLEAR() end

> (crtxclear.asm)

> .area GSINIT4 (CODE)
> __mcs51_genXRAMCLEAR::
> mov r0,#l_PSEG
> mov a,r0
> orl a,#(l_PSEG » 8)
> jz 00006$
> mov r1,#s_PSEG
> mov __XPAGE,#(s_PSEG » 8)
> clr a
> 00005$: movx @r1,a
> inc r1
> djnz r0,00005$
> 00006$:
> mov r0,#l_XSEG
> mov a,r0
> orl a,#(l_XSEG » 8)
> jz 00008$
> mov r1,#((l_XSEG + 255) » 8)
> mov dptr,#s_XSEG
> clr a
> 00007$: movx @dptr,a
> inc dptr
> djnz r0,00007$
> djnz r1,00007$
> 00008$:

> (crtxstack.asm)

> .area GSINIT5 (CODE)
> ; Need to initialize in GSINIT5 because __mcs51_genXINIT modifies __XPAGE
> ; and __mcs51_genRAMCLEAR modifies _spx.
> mov __XPAGE,#(__start__xstack » 8)
> mov _spx,#__start__xstack

> (application modules)

> .area GSINIT (CODE)

> (main.asm)

> .area GSFINAL (CODE)
> ljmp __sdcc_program_startup
> ;--------------------------------------------------------
> ; Home
> ;--------------------------------------------------------
> .area HOME (CODE)
> .area CSEG (CODE)
> __sdcc_program_startup:
> lcall _main
> ; return from main will lock up
> sjmp .

On some mcs51 variants __xdata memory has to be explicitly enabled before it can be accessed or if the watchdog needs to be disabled, this is the place to do it. The startup code clears all internal data memory, 256 bytes by default, but from 0 to n-1 if —iram-size <n> is used. (recommended for Chipcon CC1010).

See also the compiler option —no-xinit-opt and section 4.1 about MCS51-variants.

While these initialization modules are meant as generic startup code there might be the need for customization. Let's assume the return value of __sdcc_external_startup() in crtstart.asm should not be checked (or __sdcc_external_startup() should not be called at all). The recommended way would be to copy crtstart.asm (f.e. from `http://svn.code.sf.net/p/sdcc/code/trunk/sdcc/device/lib/mcs51/crtstart.asm`) into the source directory, adapt it there, then assemble it with sdas8051 -plosgff4.1 crtstart.asm and when linking your project explicitly specify crtstart.rel. As a bonus a listing of the relocated object file crtstart.rst is generated.