| /***************************************************************************** | |
| * Copyright (c) 2009 Rowley Associates Limited. * | |
| * * | |
| * This file may be distributed under the terms of the License Agreement * | |
| * provided with this software. * | |
| * * | |
| * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE * | |
| * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * | |
| *****************************************************************************/ | |
| /***************************************************************************** | |
| * Preprocessor Definitions | |
| * ------------------------ | |
| * APP_ENTRY_POINT | |
| * | |
| * Defines the application entry point function, if undefined this setting | |
| * defaults to "main". | |
| * | |
| * USE_PROCESS_STACK | |
| * | |
| * If defined, thread mode will be configured to use the process stack if | |
| * the size of the process stack is greater than zero bytes in length. | |
| * | |
| * INITIALIZE_STACK | |
| * | |
| * If defined, the contents of the stack will be initialized to a the | |
| * value 0xCC. | |
| * | |
| * FULL_LIBRARY | |
| * | |
| * If defined then | |
| * - argc, argv are setup by the debug_getargs. | |
| * - the exit symbol is defined and executes on return from main. | |
| * - the exit symbol calls destructors, atexit functions and then debug_exit. | |
| * | |
| * If not defined then | |
| * - argc and argv are zero. | |
| * - no exit symbol, code loops on return from main. | |
| *****************************************************************************/ | |
| #ifndef APP_ENTRY_POINT | |
| #define APP_ENTRY_POINT main | |
| #endif | |
| #ifndef ARGSSPACE | |
| #define ARGSSPACE 128 | |
| #endif | |
| .global _start | |
| .syntax unified | |
| .extern APP_ENTRY_POINT | |
| #ifdef FULL_LIBRARY | |
| .global exit | |
| #endif | |
| .section .init, "ax" | |
| .code 16 | |
| .align 2 | |
| .thumb_func | |
| _start: | |
| #ifdef __RAM_BUILD | |
| ldr r1, =__stack_end__ | |
| mov sp, r1 | |
| #endif | |
| #ifdef INITIALIZE_STACK | |
| mov r2, #0xCC | |
| ldr r0, =__stack_start__ | |
| #ifndef __RAM_BUILD | |
| mov r1, sp | |
| #endif | |
| bl memory_set | |
| #endif | |
| #ifdef USE_PROCESS_STACK | |
| /* Set up process stack if size > 0 */ | |
| ldr r1, =__stack_process_end__ | |
| ldr r0, =__stack_process_start__ | |
| subs r2, r1, r0 | |
| beq 1f | |
| msr psp, r1 | |
| mov r2, #2 | |
| msr control, r2 | |
| #ifdef INITIALIZE_STACK | |
| mov r2, #0xCC | |
| bl memory_set | |
| #endif | |
| 1: | |
| #endif | |
| /* Copy initialised memory sections into RAM (if necessary). */ | |
| ldr r0, =__data_load_start__ | |
| ldr r1, =__data_start__ | |
| ldr r2, =__data_end__ | |
| bl memory_copy | |
| ldr r0, =__text_load_start__ | |
| ldr r1, =__text_start__ | |
| ldr r2, =__text_end__ | |
| bl memory_copy | |
| ldr r0, =__fast_load_start__ | |
| ldr r1, =__fast_start__ | |
| ldr r2, =__fast_end__ | |
| bl memory_copy | |
| ldr r0, =__ctors_load_start__ | |
| ldr r1, =__ctors_start__ | |
| ldr r2, =__ctors_end__ | |
| bl memory_copy | |
| ldr r0, =__dtors_load_start__ | |
| ldr r1, =__dtors_start__ | |
| ldr r2, =__dtors_end__ | |
| bl memory_copy | |
| ldr r0, =__rodata_load_start__ | |
| ldr r1, =__rodata_start__ | |
| ldr r2, =__rodata_end__ | |
| bl memory_copy | |
| /* Zero the bss. */ | |
| ldr r0, =__bss_start__ | |
| ldr r1, =__bss_end__ | |
| mov r2, #0 | |
| bl memory_set | |
| /* Initialise the heap */ | |
| ldr r0, = __heap_start__ | |
| ldr r1, = __heap_end__ | |
| sub r1, r1, r0 | |
| mov r2, #0 | |
| str r2, [r0] | |
| add r0, r0, #4 | |
| str r1, [r0] | |
| /* Call constructors */ | |
| ldr r0, =__ctors_start__ | |
| ldr r1, =__ctors_end__ | |
| ctor_loop: | |
| cmp r0, r1 | |
| beq ctor_end | |
| ldr r2, [r0] | |
| add r0, #4 | |
| push {r0-r1} | |
| blx r2 | |
| pop {r0-r1} | |
| b ctor_loop | |
| ctor_end: | |
| /* Setup initial call frame */ | |
| mov r0, #0 | |
| mov lr, r0 | |
| mov r12, sp | |
| start: | |
| /* Jump to application entry point */ | |
| #ifdef FULL_LIBRARY | |
| mov r0, #ARGSSPACE | |
| ldr r1, =args | |
| ldr r2, =debug_getargs | |
| blx r2 | |
| ldr r1, =args | |
| #else | |
| mov r0, #0 | |
| mov r1, #0 | |
| #endif | |
| ldr r2, =APP_ENTRY_POINT | |
| blx r2 | |
| #ifdef FULL_LIBRARY | |
| .thumb_func | |
| exit: | |
| mov r5, r0 // save the exit parameter/return result | |
| /* Call destructors */ | |
| ldr r0, =__dtors_start__ | |
| ldr r1, =__dtors_end__ | |
| dtor_loop: | |
| cmp r0, r1 | |
| beq dtor_end | |
| ldr r2, [r0] | |
| add r0, #4 | |
| push {r0-r1} | |
| blx r2 | |
| pop {r0-r1} | |
| b dtor_loop | |
| dtor_end: | |
| /* Call atexit functions */ | |
| ldr r2, =_execute_at_exit_fns | |
| blx r2 | |
| /* Call debug_exit with return result/exit parameter */ | |
| mov r0, r5 | |
| ldr r2, =debug_exit | |
| blx r2 | |
| #endif | |
| /* Returned from application entry point, loop forever. */ | |
| exit_loop: | |
| b exit_loop | |
| memory_copy: | |
| cmp r0, r1 | |
| beq 2f | |
| subs r2, r2, r1 | |
| beq 2f | |
| 1: | |
| ldrb r3, [r0] | |
| add r0, r0, #1 | |
| strb r3, [r1] | |
| add r1, r1, #1 | |
| subs r2, r2, #1 | |
| bne 1b | |
| 2: | |
| bx lr | |
| memory_set: | |
| cmp r0, r1 | |
| beq 1f | |
| strb r2, [r0] | |
| add r0, r0, #1 | |
| b memory_set | |
| 1: | |
| bx lr | |
| #ifdef FULL_LIBRARY | |
| .bss | |
| args: | |
| .space ARGSSPACE | |
| #endif | |