📄 crt.s
字号:
;*;* File: crt.s;*;* uC/OS Real-time multitasking kernel for the ARM processor.;*;* C run-time support.;*;* Copyright (C) 1993 Advanced RISC Machines Ltd. All rights reserved.;* Copyright (C) 1993 VLSI Technology Inc. All rights reserved.;*;* VLSI Technology Inc. does not assume any liability arising out of;* this program or use thereof.;*;*;----------------------------------------------------------------------------;; The following constant is the Top Of Memory - Adjust this for your system ;;----------------------------------------------------------------------------;TopOfMemory EQU 0x100000 ; 1MB is the minimum amount of ; memory on a PID board. ; If you have 4MB change this.;----------------------------------------------------------------------------;; Things you may wish to tune, but which you don't need to alter, follow. ;;----------------------------------------------------------------------------;DefaultStackSize EQU 4*1024 ; The stack starts of this big unless ; over-ridden by __root_stack_size.DefaultStackIncrement EQU 1*1024 ; At each overflow it grows by at ; at least this many bytes.StackSlop EQU 512 ; sl is kept this far above the real ; stack low-water mark. NOTE: MUST be ; >= 256 or the compiled limit checks ; will be invalidated.MinHeapIncrement EQU 256 ; Min number of WORDS to extend the ; heap by on calling __rt_alloc. GBLL EnsureNoFPSupportEnsureNoFPSupport SETL {TRUE} ; If {TRUE} then the availability of ; Floating Point Support is ignored. ; If {FALSE} then FP availability is ; checked for. ; Setting to {TRUE} saves a little ; space.;----------------------------------------------------------------------------;; Symbols defined in other, separately-assembled modules, must be IMPORTed. ;; We import them WEAKly so that they need not be defined. ;;----------------------------------------------------------------------------; IF EnsureNoFPSupport = {TRUE} IMPORT |__fp_initialise|, WEAK IMPORT |__fp_finalise|, WEAK ENDIF;----------------------------------------------------------------------------;; The existence of __fp_initialise (imported WEAKly) indicates that floating ;; point support code (or the access stub thereof) has been linked with this ;; application. If you wish to load the FP support code separately, you may ;; want to define some other mechanism for detecting the presence/absence of ;; floating point support. Note that setjmp and longjmp must know whether the ;; floating-point instruction set is supported. ;; __fp_initialise is called by __main and __fp_finalise is called by _exit. ;;----------------------------------------------------------------------------; IMPORT |__root_stack_size|, WEAK;----------------------------------------------------------------------------;; If __root_stack_size, also imported WEAKly, exists, the value it addresses ;; is used as the initial size of the stack. It can be defined in your C ;; program as, e.g. int __root_stack_size = 10000; /* 10KB initial stack */ ;;----------------------------------------------------------------------------; IMPORT |__err_handler|, WEAK;----------------------------------------------------------------------------;; If __err_handler exists, errors are passed to it; otherwise, we print a ;; simple diagnostic message and exit. ;;----------------------------------------------------------------------------; IMPORT |Image$$RW$$Limit|;----------------------------------------------------------------------------;; Image$$RW$$Limit is a linker-created symbol marking the end of the image. ;; Its value is used as the heap base. ;;----------------------------------------------------------------------------; IMPORT main;----------------------------------------------------------------------------;; The symbol main identifies the C function entered from this code. ;;----------------------------------------------------------------------------;;----------------------------------------------------------------------------;; THE MEMORY MODEL ASSUMED BY THIS IMPLEMENTATION ;; ;; +----------------+ <--- top of memory (high address) ;; | Stack space | ;; |................| <--- stack pointer (sp) ;; | Free stack | ;; |................| <--- stack limit pointer (sl) ;; +----------------+ <--- stack low-water mark (sl - StackSlop) ;; | | ;; | Unused memory | ; ; | | ;; +----------------+ <--- top of heap (HeapLimit) ;; | | ;; | Heap space | ;; | | ;; +----------------+ <--- top of application (Image$$RW$$Limit) ;; | Static data | } ;; |................| } the application's memory image ;; | Code | } ;; +----------------+ <--- application load address ;;----------------------------------------------------------------------------;;----------------------------------------------------------------------------;; Now the symbols we define and EXPORT from this this module. ;;----------------------------------------------------------------------------;; First, symbols identifying the four functions you have to implement to ;; make this run-time kernel work on your hardware. ;;----------------------------------------------------------------------------; EXPORT |__main| EXPORT |__rt_exit| EXPORT |__rt_fpavailable| EXPORT |__rt_trap|;----------------------------------------------------------------------------;; Then some simple support for C heap management. It interacts with stack- ;; limit checking but should require no attention in a first re-targetting. ;;----------------------------------------------------------------------------; EXPORT |__rt_alloc|;----------------------------------------------------------------------------;; Next, optional support for C stack-limit checking. This code should need ;; no attention in a first re-targetting. ;;----------------------------------------------------------------------------; EXPORT |__rt_stkovf_split_small| ; veneer EXPORT |__rt_stkovf_split_big|;----------------------------------------------------------------------------;; And, finally, generic ARM functions, referred to by the C compiler. ;; You should not need to alter any of these unless you wish to incorporate ;; them in your operating system kernel. See also later comments. ;;----------------------------------------------------------------------------; EXPORT |__rt_udiv| EXPORT |__rt_udiv10| EXPORT |__rt_sdiv| EXPORT |__rt_sdiv10| EXPORT |__rt_divtest|;----------------------------------------------------------------------------; AREA |C$$data| ; This module's data area ;;----------------------------------------------------------------------------;HeapLimit DCD |Image$$RW$$Limit| ; initialised by the linker.;----------------------------------------------------------------------------;; This code has to run in but 26-bit ARM modes and 32-bit modes. To allow ;; for this, the code is carefully written so that all PSR restoration in ;; 26-bit mode is via the following macro. ;;----------------------------------------------------------------------------; MACRO RET $cond IF {CONFIG} = 26 MOV$cond.S pc, lr ELSE MOV$cond pc, lr ENDIF MEND;----------------------------------------------------------------------------;; The following four SWI definitions are specific to ARMulator/RISC OS. ;; However, you will need to replace the whole of this following section... ;; and all uses of these SWIs should also be replaced. ;;----------------------------------------------------------------------------;; NOTE: not such luxury with uC/OS (yet).WriteC EQU 0 ; Write r0 to error/debug stream.Write0 EQU 2 ; Write 0-terminated string pointed ; to by r0 to error/debug stream.Exit EQU 17 ; Terminate program execution.;----------------------------------------------------------------------------; AREA |C$$code$$__main|, CODE, READONLY; The code area containing __main, __rt_exit ;;----------------------------------------------------------------------------; ENTRY ; Define the image entry point.|__main|;; This is the initial entry point to the image.; Have to establish a stack for C; No arguments are passed to main from an embedded application,; so argc and argv are set up to 0 MOV sp, #TopOfMemory ; Initial stack pointer... MOV fp, #0 ; No previous frame, so fp=0 LDR a3, RootStackSize CMP a3, #0 ; Is RootStackSize defined? LDRNE a3, [a3] ; Yes: use value... CMPNE a3, #DefaultStackSize ; but check caller not being silly. MOVLE a3, #DefaultStackSize ; No/silly: use default size. SUB sl, sp, a3 ; stack low-water mark ADD sl, sl, #StackSlop ; sl = LWM + StackSlop IF EnsureNoFPSupport = {FALSE} LDR a1, fp_initialise ; initialise FP code if present CMP a1, #0 MOVNE lr, pc MOVNE pc, a1 ENDIF MOV a1, #0 ; set argc to 0 MOV a2, #0 ; and argv to NUL BL main ; Call main, falling through to ; exit on return.|__rt_exit| ; exit;; void __rt_exit(int code);; Terminate execution, optionally setting return code (ignored here).; MUST NOT RETURN. IF EnsureNoFPSupport = {FALSE} LDR a2, fp_finalise ; finalise FP code if present CMP a2, #0 MOVNE lr, pc MOVNE pc, a2 ENDIF ; in uC/OS we get here only because stack overflow ; divide by zero, a call to exit() or by mistake. B . ; SWI Exit ; suicide...RootStackSize DCD |__root_stack_size| IF EnsureNoFPSupport = {FALSE}fp_initialise DCD |__fp_initialise|fp_finalise DCD |__fp_finalise| ENDIF;----------------------------------------------------------------------------; AREA |C$$code$$__rt_fpavailable|, CODE, READONLY; The code area containing __rt_fpavailable ;;----------------------------------------------------------------------------;|__rt_fpavailable|;; int __rt_fpavailable(); return non-0 if FP support code linked. IF EnsureNoFPSupport = {FALSE} LDR a1, fp_initialise ELSE MOV a1, #0 ENDIF RET;----------------------------------------------------------------------------; AREA |C$$code$$__rt_trap|, CODE, READONLY; The code area containing __rt_trap ;;----------------------------------------------------------------------------;; Support for low-level failures - currently stack overflow, divide by 0 and ;; floating-point exceptions. If there is a higher level handler, call it; ;; otherwise, print a message and exit gracefully. ;; ;; NOTES ;; ;; typedef struct { unsigned code; char message[252];} __rt_error; ;; typedef struct { unsigned r[16];} __rt_registers; ;; ;;----------------------------------------------------------------------------;|__rt_trap|;; void __rt_trap(__rt_error *e, __rt_registers *r); STMFD sp!, {a1} ; save e in case handler returns... LDR ip, err_handler CMP ip, #0 MOVNE lr, pc IF {CONFIG} = 26 MOVNES pc, ip ; if got a handler, use it and ELSE MOVNE pc, ip ; if got a handler, use it and ENDIF LDMFD sp!, {v1} ; hope not to return...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -