$CASE $DEBUG ; %'@(#)cstart.asm @(#)cstart.asm 1.22 01/13/95' ; Header file for 8051 type processors for C8051 ; ----------------------------------------------- ; ; When using the reentrant model, and interrupt protection of updating ; the virtual stackpointer is required. Define PROTECT as YES ; NAME _CSTART ; EXTRN CODE(_?main) ; start label user program PUBLIC __STKSTART ; start of stack (also used by CrossView51) PUBLIC __EXIT ; address to jump to on 'exit()' ; ----------------------------------------------- ; IMPORTANT ; ; Next values must be set correctly to get correct execution of programs ; ; 'HEAP' determines the maximum space that can be 'malloc()'ed, when the ; function 'malloc' is not used in a program, this value should be '0' ; When 'HEAP' has a size 0, No HEAP is allocated. When using 'malloc()' ; will result in a linker error ; ; 'STACKLENGTH' value will create the possibility to create a minimum ; stacklength. The stack is placed at the end of internal RAM. Filling ; 'STACKLENGTH' with a value will enable the linker to produce an error ; if the stack does not fit in RAM anymore next to all other variables. ; ; 'RAMSIZE' determines the amount of internal (on chip) RAM that should ; be cleared at startup ; 'XDATSTART' and 'XDATEND' determine the location and size of external ; RAM shat should be cleared at startup ; Clearance of the memory is done to give all non initialized 'static' ; variables the value '0' at startup (defined by ANSI) ; ; 'REGBANK' determines the registerbank used at startup (Normally '0'). ; This value should be equal to the registerbank used by the 'main()' ; routine. ; ; 'VSTACK' should be set to 'YES' when the C-51 program has some functions ; declared '_reentrant' while the program is not compiled in the reentrant ; model. This causes a virtual stack space to be allocated and the virtual ; stackpointer to be initialized. ; ; 'VIRT_STACK' is only used with the 'REENTRANT' model of C-51 or for ; C-functions declared '_reentrant'. This space is used to place all ; Function parameters, Function locals, etc. during program execution. ; ; 'PROTECT' should be set to 'YES' only when the C-51 Program is ; compiled with the 'REENTRANT' model, AND when interrupts may occur ; during program execution (only when the interrupt procedure needs to ; use the virtual stack in any way). Also set to 'YES' when there are ; functions declared '_reentrant' within the main program and within ; interrupt functions. ; ; 'FLOATMEM' should be set to the number of floats that should be ; allowed on the 'floating point stack'. When floating point is ; used within the application, this value MUST be set to at least ; '2'. Any action with a floating point variable will use this 'stack' ; The stack should be configured as large as needed to do the most ; complex expression used in the application (for routines from the ; 'math.h' library, the given size ('5') will do). ; ; 'MFLOAT' should be set to 'XDATA' when floating point is used and the library ; 'float.lib' is linked. 'MFLOAT' should be set to 'IDATA' when the small library ; 'floats.lib' is linked. Which library can be used in what circumstances is explained ; in the C-51 manual. ; ; When the program does not make use of these features, values as ; presented here do not have to be changed ; ----------------------------------------------- %DEFINE(HEAP) (0H) ; define a heap (room for malloc in ; xdat) of 0 bytes %DEFINE(STACKLENGTH) (20H) ; define a (minimum) stacklength of 32 bytes %DEFINE(RAMSIZE) (0H) ; size of IDAT memory (in the range ; from 128 to 256) %DEFINE(XDATSTART) (0H) ; start address of XDAT %DEFINE(XDATEND) (0H) ; end address of XDAT (size is 0 Bytes) %DEFINE(REGBANK) (0) ; default register bank %DEFINE(VSTACK) (NO) ; define if the virtual stack is needed when not in reentrant model %DEFINE(VIRT_STACK) (400H) ; define a virtual stack in xdat of ; 1Kbyte (Reentrant model or Used reentrant functions) %DEFINE(PROTECT) (NO) ; default no protection is done on ; updating the virtual stack pointer ; (reentrant model/reentrant functions only) %DEFINE(FLOATMEM) (0) ; define floating point stack members to allocate %DEFINE(MFLOAT) (XDATA) ; Floating point stack in XDATA (normal library 'float.lib' linked) ; When changed to 'IDATA', 'floats.lib' can be linked (See the manual). ; ; ; MODEL can have values (SMALL), (AUX), (LARGE) or (REENTRANT) ; it defines in which area the strings are located. ; .DEFINE(MODEL) (LARGE) ; The following include file must define this variable: $INCLUDE(MODEL) EXTRN CODE(%MODEL) ; So LINK51 gives an error when memory ; models are mixed up ; ; MON51 can have the value (YES) or (NO) ; When building an application for debugging with CrossView51-ROM ; (using the BSO/Tasking ROM monitor) include the following line ; in the MONITOR include file: ; .DEFINE(MON51) (YES) ; When using MON51, the following CSTART items are affected: ; - Interrupts are NOT disabled, before calling main() ; (keeping serial line interrupt of MON51 alive) ; - Internal RAM is NOT cleared (MON51 uses registerbank 3 ; and two bytes of bitaddressable RAM) ; - Port P2 is NOT cleared (P2 is used by MON51, to access ; its external data, allocated in one page of external RAM) ; - reset vector application at 100H, allowing reset vector ; ROM monitor at 0H, when COPYVECTORS of ROM monitor is on ; (i.e., RAM present in lower memory area of board). ; The following include file must define this variable: $INCLUDE(MONITOR) ; ; The following code is needed for initialization of static variables ; Definition of names needed for initialization of static variables ; PUBLIC __START_ROM_XD PUBLIC __START_ROM_ID PUBLIC __START_ROM_PD PUBLIC __START_ROM_BA PUBLIC __START_ROM_BI PUBLIC __START_ROM_DA PUBLIC __START_ROM_ST PUBLIC __START_RAM_XD PUBLIC __START_RAM_ID PUBLIC __START_RAM_PD PUBLIC __START_RAM_BA PUBLIC __START_RAM_BI PUBLIC __START_RAM_DA PUBLIC __START_RAM_ST CINIT_ROM_XD SEGMENT CODE ROMDATA ; define labels needed for ; initialization RSEG CINIT_ROM_XD __START_ROM_XD: CINIT_ROM_ID SEGMENT CODE ROMDATA RSEG CINIT_ROM_ID __START_ROM_ID: CINIT_ROM_PD SEGMENT CODE ROMDATA RSEG CINIT_ROM_PD __START_ROM_PD: CINIT_ROM_BA SEGMENT CODE ROMDATA RSEG CINIT_ROM_BA __START_ROM_BA: CINIT_ROM_BI SEGMENT CODE ROMDATA RSEG CINIT_ROM_BI __START_ROM_BI: CINIT_ROM_DA SEGMENT CODE ROMDATA RSEG CINIT_ROM_DA __START_ROM_DA: CINIT_ROM_ST SEGMENT CODE ROMDATA RSEG CINIT_ROM_ST __START_ROM_ST: CINIT_RAM_XD SEGMENT XDATA RSEG CINIT_RAM_XD __START_RAM_XD: CINIT_RAM_ID SEGMENT IDATA RSEG CINIT_RAM_ID __START_RAM_ID: CINIT_RAM_PD SEGMENT XDATA SHORT RSEG CINIT_RAM_PD __START_RAM_PD: CINIT_RAM_BA SEGMENT DATA BITADDRESSABLE RSEG CINIT_RAM_BA __START_RAM_BA: CINIT_RAM_BI SEGMENT BIT RSEG CINIT_RAM_BI __START_RAM_BI: CINIT_RAM_DA SEGMENT DATA RSEG CINIT_RAM_DA __START_RAM_DA: %IF(%EQS(%MODEL,SMALL)) THEN ( CINIT_RAM_ST SEGMENT IDATA ; This is the small memory model, so ; strings are allocated in idata )FI %IF(%EQS(%MODEL,AUX)) THEN ( CINIT_RAM_ST SEGMENT XDATA SHORT ; This is the auxiliary memory model, ; so strings are allocated in pdata )FI %IF(%EQS(%MODEL,LARGE)) THEN ( CINIT_RAM_ST SEGMENT XDATA ; This is the large memory model, so ; strings are allocated in xdata )FI %IF(%EQS(%MODEL,REENTRANT)) THEN ( CINIT_RAM_ST SEGMENT XDATA ; This is the reentrant memory model, ; so strings are allocated in xdata )FI RSEG CINIT_RAM_ST __START_RAM_ST: ; ?STACK SEGMENT IDATA RSEG ?STACK __STKSTLAB: DS %STACKLENGTH ; reserve space for the stack __STKSTART IDATA __STKSTLAB - 1 ; ; No 'HEAP' will result in linker error when using a 'malloc' routine ; %IF( %HEAP GT 00H ) THEN ( PUBLIC __HEAPSTART ; start of heap area PUBLIC __HEAPLENGTH ; length of heap area PUBLIC __HEAPEND ; end of heap area ?HEAP SEGMENT XDATA RSEG ?HEAP __HEAPSTART: DS %HEAP ; reserve space for the heap __HEAPEND: __HEAPLENGTH XDATA __HEAPEND - __HEAPSTART ; length of the heap )FI %IF( %EQS(%MODEL,REENTRANT) OR %EQS(%VSTACK,YES) ) THEN ( PUBLIC __TOP_OF_VIRT_STACK ?VIRT_STACK SEGMENT XDATA RSEG ?VIRT_STACK DS %VIRT_STACK ; reserve space for the virtual stack in ; external RAM __TOP_OF_VIRT_STACK: ) FI %IF( %FLOATMEM GT 00H ) THEN ( PUBLIC __FLOATSTART PUBLIC __FLOATEND FLOAT_STACK SEGMENT %MFLOAT RSEG FLOAT_STACK __FLOATSTART: DS 4 * %FLOATMEM ; reserve space for 'floating point stack' __FLOATEND: )FI ; %IF( %NES(%MON51,YES) ) THEN ( CSEG AT 0H ; Reset vector of the application )ELSE( CSEG AT 100H ; If MON51 uses COPYVECTORS (RAM area), allow run time ; RESET of monitor (e.g. Watchdog timer). So do NOT ; override the reset vector with ours. XVW 'rst' ; command assigns PC with startvalue from '-s option' ; specified with ieee51 conversion utility. )FI LCALL __START ; Do NOT change to 'LJMP', because a reference ; to the 'STARTUP' segment is needed. The return ; address will be removed from stack, because ; the stackpointer is initialized. STARTUP SEGMENT CODE RSEG STARTUP __START: ; First we have to do some initialisation. You may NOT disable ; the interrupts, when using a monitor as execution environment! ; Clear the memory and make sure register bank 0 is used. CLR A MOV PSW, A ; select register bank 0 %IF( %NES(%MON51,YES) ) THEN ( CLR EA ; disable interrupts ; First initialize all IDATA to '0' %IF( %RAMSIZE GT 08H ) THEN ( MOV R0, #08 ; one position after registerbank 0 __CLR_IDAT: MOV @R0, A INC R0 CJNE R0, #LOW (%RAMSIZE), __CLR_IDAT ; RAMSIZE must be 128 or 256 )FI %IF( %XDATEND GT %XDATSTART ) THEN ( MOV DPTR, #%XDATSTART ; Initialise all XDATA to '0' __CLR_XDAT: CLR A MOVX @DPTR, A INC DPTR MOV A, DPL CJNE A, #LOW(%XDATEND+1), __CLR_XDAT MOV A, DPH CJNE A, #HIGH(%XDATEND+1), __CLR_XDAT )FI MOV P2, #00 ; needed for models using pdat ; Do NOT execute when using MON51 !! )FI MOV SP, #LOW(__STKSTART) ; initialise stack pointer ; For reentrant model, initialise 'virtual stack' pointer %IF( %NES(%PROTECT,YES) AND (%EQS(%MODEL,REENTRANT) OR %EQS(%VSTACK,YES)) ) THEN ( EXTRN DATA( __SP ) MOV __SP, #HIGH( __TOP_OF_VIRT_STACK ) MOV __SP+1, #LOW( __TOP_OF_VIRT_STACK ) ) FI %IF( %EQS(%PROTECT,YES) AND (%EQS(%MODEL,REENTRANT) OR %EQS(%VSTACK,YES)) ) THEN ( EXTRN DATA( __SP ) PUSH 0A8H ; save interrupt flag (IE) CLR 0AFH ; No interrupts allowed MOV __SP, #HIGH( __TOP_OF_VIRT_STACK ) MOV __SP+1, #LOW( __TOP_OF_VIRT_STACK ) POP 0A8H ; restore interrupt flag ) FI %IF( %FLOATMEM GT 00H AND %EQS(%MFLOAT,XDATA) ) THEN ( EXTRN DATA( __FLOATSP ) MOV __FLOATSP, #HIGH( __FLOATSTART ) ; initialise floating point stackpointer MOV __FLOATSP+1, #LOW( __FLOATSTART ) ) FI %IF( %FLOATMEM GT 00H AND %EQS(%MFLOAT,IDATA) ) THEN ( EXTRN DATA( __FLOATSP ) MOV __FLOATSP, #__FLOATSTART ) FI LCALL __INITS ; initialise needed data segments MOV PSW, #(%REGBANK * 8) ; select correct registerbank USING %REGBANK LCALL _?main ; Jump to C-program __EXIT: ; exit() function jumps to this place. When it is required to restart ; the program, SP and __SP should be initialized again (if applicable). __STOP: ; DB 0A5H ; illegal instruction halts simulator ; (but will loop some emulators) SJMP __STOP __INITS: ; all neccessary initialisation code will ; automatically be linked here ; Do NOT remove these lines and do NOT place ; it somewhere else in the startup code ; (must be the last lines in the startup code) EXTRN CODE( __EINITS ) ; Leave this external here END