mirror of
				https://github.com/FreeRTOS/FreeRTOS-Kernel.git
				synced 2025-10-29 00:36:16 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			342 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			342 lines
		
	
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*****************************************************
 | |
|       start12.c - standard startup code
 | |
|    The startup code may be optimized to special user requests
 | |
|  ----------------------------------------------------
 | |
|    Copyright (c) Metrowerks, Basel, Switzerland
 | |
|                All rights reserved
 | |
|                   Do not modify!
 | |
| 
 | |
| Note: ROM libraries are not implemented in this startup code
 | |
| Note: C++ destructors of global objects are NOT yet supported in the HIWARE Object File Format.
 | |
|       To use this feature, please build your application with the ELF object file format.
 | |
|  *****************************************************/
 | |
| 
 | |
| #include "hidef.h"
 | |
| #include "start12.h"
 | |
| 
 | |
| /* Macros to control how the startup code handles the COP: */
 | |
| /* #define _DO_FEED_COP_  : do feed the COP  */
 | |
| /* #define _DO_ENABLE_COP_: do enable the COP  */
 | |
| /* #define _DO_DISABLE_COP_: disable the COP */
 | |
| /* Without defining any of these, the startup code does NOT handle the COP */
 | |
| 
 | |
| #pragma DATA_SEG __NEAR_SEG STARTUP_DATA /* _startupData can be accessed using 16 bit accesses. This is needed because it contains the stack top, and without stack, far data cannot be accessed */
 | |
| struct _tagStartup _startupData;  /*   read-only: */
 | |
|                                   /*   _startupData is allocated in ROM and */
 | |
|                                   /*   initialized by the linker */
 | |
| #pragma DATA_SEG DEFAULT
 | |
| #if defined(FAR_DATA)
 | |
| #include "non_bank.sgm"
 | |
| /* the init function must be in non banked memory if banked variables are used */
 | |
| /* because _SET_PAGE is called, which may change any page register. */
 | |
| 
 | |
| #ifdef __cplusplus
 | |
|   extern "C"
 | |
| #endif
 | |
| void _SET_PAGE(void);             /* the inline assembler needs a prototype */
 | |
|                                   /* this is a runtime routine with a special */
 | |
|                                   /* calling convention, dont use it in c code! */
 | |
| static void Init(void);
 | |
| static void Fini(void);
 | |
| #else
 | |
| #include "default.sgm"
 | |
| #if defined( __BANKED__) || defined(__LARGE__)
 | |
| static void __far Init(void);
 | |
| static void __far Fini(void);
 | |
| #endif /* defined( __BANKED__) || defined(__LARGE__) */
 | |
| #endif /* FAR_DATA */
 | |
| 
 | |
| 
 | |
| /* define value and bits for Windef Register */
 | |
| #ifdef HC812A4
 | |
| #define WINDEF (*(volatile unsigned char*) 0x37)
 | |
| #if defined( __BANKED__) || defined(__LARGE__) || defined(__PPAGE__)
 | |
| #define __ENABLE_PPAGE__ 0x40
 | |
| #else
 | |
| #define __ENABLE_PPAGE__ 0x0
 | |
| #endif
 | |
| #if defined(__DPAGE__)
 | |
| #define __ENABLE_DPAGE__ 0x80
 | |
| #else
 | |
| #define __ENABLE_DPAGE__ 0x0
 | |
| #endif
 | |
| #if defined(__EPAGE__)
 | |
| #define __ENABLE_EPAGE__ 0x20
 | |
| #else
 | |
| #define __ENABLE_EPAGE__ 0x0
 | |
| #endif
 | |
| #endif  /* HC812A4 */
 | |
| 
 | |
| #ifdef _HCS12_SERIALMON
 | |
|       /* for Monitor based software remap the RAM & EEPROM to adhere
 | |
|          to EB386. Edit RAM and EEPROM sections in PRM file to match these. */
 | |
| #define ___INITRM      (*(volatile unsigned char *) 0x0010)
 | |
| #define ___INITRG      (*(volatile unsigned char *) 0x0011)
 | |
| #define ___INITEE      (*(volatile unsigned char *) 0x0012)
 | |
| #endif
 | |
| 
 | |
| #if defined(_DO_FEED_COP_)
 | |
| #define __FEED_COP_IN_HLI()  } __asm movb #0x55, _COP_RST_ADR; __asm movb #0xAA, _COP_RST_ADR; __asm {
 | |
| #else
 | |
| #define __FEED_COP_IN_HLI() /* do nothing */
 | |
| #endif
 | |
| 
 | |
| #if !defined(FAR_DATA) && (defined( __BANKED__) || defined(__LARGE__))
 | |
| static void __far Init(void)
 | |
| #else
 | |
| static void Init(void)
 | |
| #endif
 | |
|  {
 | |
| /* purpose:     1) zero out RAM-areas where data is allocated   */
 | |
| /*              2) copy initialization data from ROM to RAM     */
 | |
| /*              3) call global constructors in C++              */
 | |
| /*   called from: _Startup, LibInits                            */
 | |
|    __asm {
 | |
| ZeroOut:
 | |
| #if defined(__HIWARE_OBJECT_FILE_FORMAT__) && defined(__LARGE__)
 | |
|              LDX   _startupData.pZeroOut:1  ; in the large memory model in the HIWARE format, pZeroOut is a 24 bit pointer
 | |
| #else
 | |
|              LDX   _startupData.pZeroOut    ; *pZeroOut
 | |
| #endif
 | |
|              LDY   _startupData.nofZeroOuts ; nofZeroOuts
 | |
|              BEQ   CopyDown                 ; if nothing to zero out
 | |
| 
 | |
| NextZeroOut: PSHY                           ; save nofZeroOuts
 | |
| #ifdef FAR_DATA
 | |
|              LDAB  1,X+                     ; load page of destination address
 | |
|              LDY   2,X+                     ; load offset of destination address
 | |
|              __PIC_JSR(_SET_PAGE)           ; sets the page in the correct page register
 | |
| #else   /* FAR_DATA */
 | |
|              LDY   2,X+                     ; start address and advance *pZeroOut (X = X+4)
 | |
| #endif  /* FAR_DATA */
 | |
|              LDD   2,X+                     ; byte count
 | |
| #ifdef  __OPTIMIZE_FOR_SIZE__               /* -os, default */
 | |
| NextWord:    CLR   1,Y+                     ; clear memory byte
 | |
|              __FEED_COP_IN_HLI()            ; feed the COP if necessary /*lint !e505 !e522 asm code */
 | |
|              DBNE  D, NextWord              ; dec byte count
 | |
| #else
 | |
|              LSRD                           ; /2 and save bit 0 in the carry
 | |
|              PSHX
 | |
|              LDX   #0
 | |
| LoopClrW:    STX   2,Y+                     ; Word-Clear
 | |
|              __FEED_COP_IN_HLI()            ; feed the COP if necessary /*lint !e505 !e522 asm code */
 | |
|              DBNE  D, LoopClrW
 | |
|              PULX
 | |
|              BCC   LastClr                  ; handle last byte
 | |
|              CLR   1,Y+
 | |
| LastClr:
 | |
| #endif
 | |
|              PULY                           ; restore nofZeroOuts
 | |
|              DEY                            ; dec nofZeroOuts
 | |
|              BNE  NextZeroOut
 | |
| CopyDown:
 | |
| #ifdef __ELF_OBJECT_FILE_FORMAT__
 | |
|              LDX   _startupData.toCopyDownBeg ; load address of copy down desc.
 | |
| #else
 | |
|              LDX   _startupData.toCopyDownBeg:2 ; load address of copy down desc.
 | |
| #endif
 | |
| NextBlock:
 | |
|              LDD   2,X+                     ; size of init-data -> D
 | |
|              BEQ   funcInits                ; end of copy down desc.
 | |
| #ifdef FAR_DATA
 | |
|              PSHD                           ; save counter
 | |
|              LDAB  1,X+                     ; load destination page
 | |
|              LDY   2,X+                     ; destination address
 | |
|              __PIC_JSR(_SET_PAGE)           ; sets the destinations page register
 | |
|              PULD                           ; restore counter
 | |
| #else  /* FAR_DATA */
 | |
|              LDY   2,X+                     ; load destination address
 | |
| #endif /* FAR_DATA */
 | |
| 
 | |
| #ifdef  __OPTIMIZE_FOR_SIZE__               /* -os, default */
 | |
| Copy:        MOVB  1,X+,1,Y+                ; move a byte from ROM to the data area
 | |
|              __FEED_COP_IN_HLI()            ; feed the COP if necessary /*lint !e505 !e522 asm code */
 | |
|              DBNE  D,Copy                   ; copy-byte loop
 | |
| #else
 | |
|              LSRD                           ; /2 and save bit 0 in the carry
 | |
| Copy:        MOVW  2,X+,2,Y+                ; move a word from ROM to the data area
 | |
|              __FEED_COP_IN_HLI()            ; feed the COP if necessary /*lint !e505 !e522 asm code */
 | |
|              DBNE  D,Copy                   ; copy-word loop
 | |
|              BCC   NextBlock                ; handle last byte?
 | |
|              MOVB  1,X+,1,Y+                ; copy the last byte
 | |
| #endif
 | |
|              BRA   NextBlock
 | |
| funcInits:                                  ; call of global construtors is only in c++ necessary
 | |
| #if defined(__cplusplus)
 | |
| #if defined(__ELF_OBJECT_FILE_FORMAT__)
 | |
| #if defined( __BANKED__) || defined(__LARGE__)
 | |
|              LDY   _startupData.nofInitBodies; load number of cpp.
 | |
|              BEQ   done                     ; if cppcount == 0, goto done
 | |
|              LDX   _startupData.initBodies  ; load address of first module to initialize
 | |
| nextInit:
 | |
|              LEAX   3,X                     ; increment to next init
 | |
|              PSHX                           ; save address of next function to initialize
 | |
|              PSHY                           ; save cpp counter
 | |
|              CALL  [-3,X]                   ; use double indirect call to load the page register also
 | |
|              PULY                           ; restore cpp counter
 | |
|              PULX                           ; restore actual address
 | |
|              DEY                            ; decrement cpp counter
 | |
|              BNE    nextInit
 | |
| #else  /* defined( __BANKED__) || defined(__LARGE__) */
 | |
| 
 | |
|              LDD   _startupData.nofInitBodies; load number of cpp.
 | |
|              BEQ   done                     ; if cppcount == 0, goto done
 | |
|              LDX   _startupData.initBodies  ; load address of first module to initialize
 | |
| nextInit:
 | |
|              LDY   2,X+                     ; load address of first module to initialize
 | |
|              PSHD
 | |
|              PSHX                           ; save actual address
 | |
|              JSR   0,Y                      ; call initialization function
 | |
|              PULX                           ; restore actual address
 | |
|              PULD                           ; restore cpp counter
 | |
|              DBNE D, nextInit
 | |
| #endif /* defined( __BANKED__) || defined(__LARGE__) */
 | |
| #else /* __ELF_OBJECT_FILE_FORMAT__  */
 | |
|              LDX   _startupData.mInits      ; load address of first module to initialize
 | |
| #if defined( __BANKED__) || defined(__LARGE__)
 | |
| nextInit:    LDY   3,X+                     ; load address of initialization function
 | |
|              BEQ   done                     ; stop when address  == 0
 | |
|                                             ; in common environments the offset of a function is never 0, so this test could be avoided
 | |
| #ifdef __InitFunctionsMayHaveOffset0__
 | |
|              BRCLR -1,X, done, 0xff         ; stop when address  == 0
 | |
| #endif  /* __InitFunctionsMayHaveOffset0__ */
 | |
|              PSHX                           ; save address of next function to initialize
 | |
|              CALL  [-3,X]                   ; use double indirect call to load the page register also
 | |
| #else  /* defined( __BANKED__) || defined(__LARGE__) */
 | |
| nextInit:
 | |
|              LDY   2,X+                     ; load address of first module to initialize
 | |
|              BEQ   done                     ; stop when address of function == 0
 | |
|              PSHX                           ; save actual address
 | |
|              JSR   0,Y                      ; call initialization function
 | |
| #endif /* defined( __BANKED__) || defined(__LARGE__) */
 | |
|              PULX                           ; restore actual address
 | |
|              BRA   nextInit
 | |
| #endif  /* __ELF_OBJECT_FILE_FORMAT__  */
 | |
| done:
 | |
| #endif /* __cplusplus */
 | |
|    }
 | |
| }
 | |
| 
 | |
| #if defined( __ELF_OBJECT_FILE_FORMAT__) && defined(__cplusplus )
 | |
| 
 | |
| #if !defined(FAR_DATA) && (defined( __BANKED__) || defined(__LARGE__))
 | |
| static void __far Fini(void)
 | |
| #else
 | |
| static void Fini(void)
 | |
| #endif
 | |
| {
 | |
| /* purpose:     1) call global destructors in C++ */
 | |
|    __asm {
 | |
| #if defined( __BANKED__) || defined(__LARGE__)
 | |
| 
 | |
|              LDY   _startupData.nofFiniBodies; load number of cpp.
 | |
|              BEQ   done                     ; if cppcount == 0, goto done
 | |
|              LDX   _startupData.finiBodies  ; load address of first module to finalize
 | |
| nextInit2:
 | |
|              LEAX   3,X                     ; increment to next init
 | |
|              PSHX                           ; save address of next function to finalize
 | |
|              PSHY                           ; save cpp counter
 | |
|              CALL  [-3,X]                   ; use double indirect call to load the page register also
 | |
|              PULY                           ; restore cpp counter
 | |
|              PULX                           ; restore actual address
 | |
|              DEY                            ; decrement cpp counter
 | |
|              BNE    nextInit2
 | |
| #else  /* defined( __BANKED__) || defined(__LARGE__) */
 | |
| 
 | |
|              LDD   _startupData.nofFiniBodies; load number of cpp.
 | |
|              BEQ   done                     ; if cppcount == 0, goto done
 | |
|              LDX   _startupData.finiBodies  ; load address of first module to finalize
 | |
| nextInit2:
 | |
|              LDY   2,X+                     ; load address of first module to finalize
 | |
|              PSHD
 | |
|              PSHX                           ; save actual address
 | |
|              JSR   0,Y                      ; call finalize function
 | |
|              PULX                           ; restore actual address
 | |
|              PULD                           ; restore cpp counter
 | |
|              DBNE D, nextInit2
 | |
| #endif /* defined( __BANKED__) || defined(__LARGE__) */
 | |
| done:;
 | |
|    }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| 
 | |
| #include "non_bank.sgm"
 | |
| 
 | |
| #pragma MESSAGE DISABLE C12053 /* Stack-pointer change not in debugging-information */
 | |
| #pragma NO_FRAME
 | |
| #pragma NO_ENTRY
 | |
| #pragma NO_EXIT
 | |
| 
 | |
| #ifdef __cplusplus
 | |
|   extern "C"
 | |
| #endif
 | |
| 
 | |
| /* The function _Startup must be called in order to initialize global variables and to call main */
 | |
| /* You can adapt this function or call it from your startup code to implement a different startup */
 | |
| /* functionality. */
 | |
| 
 | |
| /* You should also setup the needed IO registers as WINDEF (HC12A4 only) or the COP registers to run */
 | |
| /* on hardware */
 | |
| 
 | |
| /* to set the reset vector several ways are possible : */
 | |
| /* 1. define the function with "interrupt 0" as done below in the first case */
 | |
| /* 2. add the following line to your prm file : VECTOR ADDRESS 0xfffe _Startup */
 | |
| /* of course, even more posibilities exists */
 | |
| /* the reset vector must be set so that the application has a defined entry point */
 | |
| 
 | |
| #define STARTUP_FLAGS_NOT_INIT_SP   (1<<1)
 | |
| 
 | |
| #if defined(__SET_RESET_VECTOR__)
 | |
| void __interrupt 0 _Startup(void) {
 | |
| #else
 | |
| void _Startup(void) {
 | |
| #endif
 | |
| /*  purpose:    1)  initialize the stack
 | |
|                 2)  initialize the RAM, copy down init data etc (Init)
 | |
|                 3)  call main;
 | |
|     parameters: NONE
 | |
|     called from: _PRESTART-code generated by the Linker 
 | |
|                  or directly referenced by the reset vector */
 | |
|   for(;;) { /* forever: initialize the program; call the root-procedure */
 | |
|       if (!(_startupData.flags&STARTUP_FLAGS_NOT_INIT_SP)) {
 | |
|         /* initialize the stack pointer */
 | |
|         INIT_SP_FROM_STARTUP_DESC(); /*lint !e522 asm code */ /* HLI macro definition in hidef.h */
 | |
|       }
 | |
| 
 | |
| #ifdef _HCS12_SERIALMON
 | |
|       /* for Monitor based software remap the RAM & EEPROM to adhere
 | |
|          to EB386. Edit RAM and EEPROM sections in PRM file to match these. */
 | |
|       ___INITRG = 0x00;  /* lock registers block to 0x0000 */
 | |
|       ___INITRM = 0x39;  /* lock Ram to end at 0x3FFF */
 | |
|       ___INITEE = 0x09;  /* lock EEPROM block to end at 0x0fff */
 | |
| #endif
 | |
|       
 | |
|       /* Here user defined code could be inserted, the stack could be used */
 | |
| #if defined(_DO_DISABLE_COP_)
 | |
|       _DISABLE_COP();
 | |
| #endif 
 | |
| 
 | |
|       /* Example : Set up WinDef Register to allow Paging */
 | |
| #ifdef HC812A4 /* HC12 A4 derivative needs WINDEF to configure which pages are available */
 | |
| #if  (__ENABLE_EPAGE__ != 0 ||  __ENABLE_DPAGE__ != 0 || __ENABLE_PPAGE__ != 0)
 | |
|       WINDEF= __ENABLE_EPAGE__ | __ENABLE_DPAGE__  | __ENABLE_PPAGE__;
 | |
| #endif
 | |
| #endif
 | |
|       Init(); /* zero out, copy down, call constructors */
 | |
|       /* Here user defined code could be inserted, all global variables are initilized */
 | |
| #if defined(_DO_ENABLE_COP_)
 | |
|       _ENABLE_COP(1);
 | |
| #endif
 | |
| 
 | |
|       /* call main() */
 | |
|       (*_startupData.main)();
 | |
| 
 | |
|       /* call destructors. Only done when this file is compiled as C++ and for the ELF object file format */
 | |
|       /* the HIWARE object file format does not support this */
 | |
| #if defined( __ELF_OBJECT_FILE_FORMAT__) && defined(__cplusplus )
 | |
|       Fini();
 | |
| #endif
 | |
| 
 | |
|    } /* end loop forever */
 | |
| }
 |