From 91c66742882c9eb33f7bef2775935b1c9190c78b Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Wed, 11 Mar 2015 14:23:49 +0000 Subject: Enhanced startups for ARMCMx. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@7757 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/common/ports/ARM/devices/LPC214x/armparams.h | 2 +- os/common/ports/ARMCMx/compilers/GCC/crt0.c | 304 +-------------------- os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s | 49 +--- os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s | 346 +++++++++++++++++------- 4 files changed, 260 insertions(+), 441 deletions(-) (limited to 'os/common') diff --git a/os/common/ports/ARM/devices/LPC214x/armparams.h b/os/common/ports/ARM/devices/LPC214x/armparams.h index 05ce875ec..9033e9e38 100644 --- a/os/common/ports/ARM/devices/LPC214x/armparams.h +++ b/os/common/ports/ARM/devices/LPC214x/armparams.h @@ -51,7 +51,7 @@ */ #define ARM_WFI_IMPL (PCON = 1) -#if !defined(__FROM_ASM__) || defined(__DOXYGEN__) +#if !defined(_FROM_ASM_) || defined(__DOXYGEN__) /** * @brief Address of the IRQ vector register in the interrupt controller. */ diff --git a/os/common/ports/ARMCMx/compilers/GCC/crt0.c b/os/common/ports/ARMCMx/compilers/GCC/crt0.c index daa6a63aa..c3bb3fd79 100644 --- a/os/common/ports/ARMCMx/compilers/GCC/crt0.c +++ b/os/common/ports/ARMCMx/compilers/GCC/crt0.c @@ -18,205 +18,15 @@ */ /** - * @file ARMCMx/GCC/crt0.c - * @brief Generic GCC Cortex-Mx startup file. + * @file ARMCMx/compilers/GCC/crt0.c + * @brief Startup stub functions. * * @addtogroup ARMCMx_GCC_STARTUP * @{ */ -#include #include -#if !defined(FALSE) -#define FALSE 0 -#endif - -#if !defined(TRUE) -#define TRUE 1 -#endif - -#define SCB_CPACR *((uint32_t *)0xE000ED88U) -#define SCB_FPCCR *((uint32_t *)0xE000EF34U) -#define SCB_FPDSCR *((uint32_t *)0xE000EF3CU) -#define FPCCR_ASPEN (uint32_t)((uint32_t)0x1U << (uint32_t)31U) -#define FPCCR_LSPEN (uint32_t)((uint32_t)0x1U << (uint32_t)30U) - -typedef void (*funcp_t)(void); -typedef funcp_t * funcpp_t; - -#define SYMVAL(sym) (uint32_t)&(sym) - -/* - * Area fill code, it is a macro because here functions cannot be called - * until stacks are initialized. - */ -#define fill32(start, end, filler) do { \ - uint32_t *p1 = (start); \ - uint32_t *p2 = (end); \ - /*lint -save -e681 [2.1] Lint cannot see the scatter file symbols.*/ \ - while (p1 < p2) { \ - /*lint -restore*/ \ - *p1++ = (filler); \ - } \ -} while (false) - -/*===========================================================================*/ -/** - * @name Startup settings - * @{ - */ -/*===========================================================================*/ - -/** - * @brief Control special register initialization value. - * @details The system is setup to run in privileged mode using the PSP - * stack (dual stack mode). - */ -#if !defined(CRT0_CONTROL_INIT) || defined(__DOXYGEN__) -#define CRT0_CONTROL_INIT 0x00000002 -#endif - -/** - * @brief Stack segments initialization switch. - */ -#if !defined(CRT0_STACKS_FILL_PATTERN) || defined(__DOXYGEN__) -#define CRT0_STACKS_FILL_PATTERN 0x55555555 -#endif - -/** - * @brief Stack segments initialization switch. - */ -#if !defined(CRT0_INIT_STACKS) || defined(__DOXYGEN__) -#define CRT0_INIT_STACKS TRUE -#endif - -/** - * @brief DATA segment initialization switch. - */ -#if !defined(CRT0_INIT_DATA) || defined(__DOXYGEN__) -#define CRT0_INIT_DATA TRUE -#endif - -/** - * @brief BSS segment initialization switch. - */ -#if !defined(CRT0_INIT_BSS) || defined(__DOXYGEN__) -#define CRT0_INIT_BSS TRUE -#endif - -/** - * @brief Constructors invocation switch. - */ -#if !defined(CRT0_CALL_CONSTRUCTORS) || defined(__DOXYGEN__) -#define CRT0_CALL_CONSTRUCTORS TRUE -#endif - -/** - * @brief Destructors invocation switch. - */ -#if !defined(CRT0_CALL_DESTRUCTORS) || defined(__DOXYGEN__) -#define CRT0_CALL_DESTRUCTORS TRUE -#endif - -/** @} */ - -/*===========================================================================*/ -/** - * @name Symbols from the scatter file - */ -/*===========================================================================*/ - -/** - * @brief Main stack lower boundary. - * @details This symbol must be exported by the linker script and represents - * the main stack lower boundary. - */ -extern uint32_t __main_stack_base__; - -/** - * - * @brief Main stack initial position. - * @details This symbol must be exported by the linker script and represents - * the main stack initial position. - */ -extern uint32_t __main_stack_end__; - -/** - * @brief Process stack lower boundary. - * @details This symbol must be exported by the linker script and represents - * the process stack lower boundary. - */ -extern uint32_t __process_stack_base__; - -/** - * @brief Process stack initial position. - * @details This symbol must be exported by the linker script and represents - * the process stack initial position. - */ -extern uint32_t __process_stack_end__; - -/** - * @brief ROM image of the data segment start. - * @pre The symbol must be aligned to a 32 bits boundary. - */ -extern uint32_t _textdata; - -/** - * @brief Data segment start. - * @pre The symbol must be aligned to a 32 bits boundary. - */ -extern uint32_t _data; - -/** - * @brief Data segment end. - * @pre The symbol must be aligned to a 32 bits boundary. - */ -extern uint32_t _edata; - -/** - * @brief BSS segment start. - * @pre The symbol must be aligned to a 32 bits boundary. - */ -extern uint32_t _bss_start; - -/** - * @brief BSS segment end. - * @pre The symbol must be aligned to a 32 bits boundary. - */ -extern uint32_t _bss_end; - -/** - * @brief Constructors table start. - * @pre The symbol must be aligned to a 32 bits boundary. - */ -extern funcp_t __init_array_start; - -/** - * @brief Constructors table end. - * @pre The symbol must be aligned to a 32 bits boundary. - */ -extern funcp_t __init_array_end; - -/** - * @brief Destructors table start. - * @pre The symbol must be aligned to a 32 bits boundary. - */ -extern funcp_t __fini_array_start; - -/** - * @brief Destructors table end. - * @pre The symbol must be aligned to a 32 bits boundary. - */ -extern funcp_t __fini_array_end; - -/** @} */ - -/** - * @brief Application @p main() function. - */ -extern void main(void); - /** * @brief Early initialization. * @details This hook is invoked immediately after the stack initialization @@ -255,119 +65,11 @@ void __late_init(void) {} __attribute__((noreturn, weak)) #endif /*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ -void _default_exit(void) { +void __default_exit(void) { /*lint -restore*/ while (true) { } } -/** - * @brief Reset vector. - */ -#if !defined(__DOXYGEN__) -__attribute__((naked)) -#endif -/*lint -save -e9075 [8.4] All symbols are invoked from asm context.*/ -void Reset_Handler(void) { -/*lint -restore*/ - uint32_t psp, reg; - - /* Process Stack initialization, it is allocated starting from the - symbol __process_stack_end__ and its lower limit is the symbol - __process_stack_base__.*/ - __asm volatile ("cpsid i"); - psp = SYMVAL(__process_stack_end__); - __asm volatile ("msr PSP, %0" : : "r" (psp)); - -#if CORTEX_USE_FPU == TRUE - /* Initializing the FPU context save in lazy mode.*/ - SCB_FPCCR = FPCCR_ASPEN | FPCCR_LSPEN; - - /* CP10 and CP11 set to full access.*/ - SCB_CPACR |= 0x00F00000U; - - /* FPSCR and FPDSCR initially zero.*/ - reg = 0; - __asm volatile ("vmsr FPSCR, %0" : : "r" (reg) : "memory"); - SCB_FPDSCR = reg; - - /* CPU mode initialization, enforced FPCA bit.*/ - reg = (uint32_t)CRT0_CONTROL_INIT | 4U; -#else - /* CPU mode initialization.*/ - reg = CRT0_CONTROL_INIT; -#endif - __asm volatile ("msr CONTROL, %0" : : "r" (reg)); - __asm volatile ("isb"); - - /* Early initialization hook invocation.*/ - __early_init(); - -#if CRT0_INIT_STACKS == TRUE - /* Main and Process stacks initialization.*/ - fill32(&__main_stack_base__, - &__main_stack_end__, - (uint32_t)CRT0_STACKS_FILL_PATTERN); - fill32(&__process_stack_base__, - &__process_stack_end__, - (uint32_t)CRT0_STACKS_FILL_PATTERN); -#endif - -#if CRT0_INIT_DATA == TRUE - /* DATA segment initialization.*/ - { - uint32_t *tp, *dp; - - tp = &_textdata; - dp = &_data; - /*lint -save -e681 [2.1] Lint cannot see the scatter file symbols.*/ - while (dp < &_edata) { - /*lint -restore*/ - *dp++ = *tp++; - } - } -#endif - -#if CRT0_INIT_BSS == TRUE - /* BSS segment initialization.*/ - fill32(&_bss_start, &_bss_end, 0); -#endif - - /* Late initialization hook invocation.*/ - __late_init(); - -#if CRT0_CALL_CONSTRUCTORS - /* Constructors invocation.*/ - { - funcpp_t fpp = &__init_array_start; - /*lint -save -e681 [2.1] Lint cannot see the scatter file symbols.*/ - while (fpp < &__init_array_end) { - /*lint -restore*/ - (*fpp)(); - fpp++; - } - } -#endif - - /* Invoking application main() function.*/ - main(); - -#if CRT0_CALL_DESTRUCTORS == TRUE - /* Destructors invocation.*/ - { - funcpp_t fpp = &__fini_array_start; - /*lint -save -e681 [2.1] Lint cannot see the scatter file symbols.*/ - while (fpp < &__fini_array_end) { - /*lint -restore*/ - (*fpp)(); - fpp++; - } - } -#endif - - /* Invoking the exit handler.*/ - _default_exit(); -} - /** @} */ diff --git a/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s b/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s index 962321cb2..38b4513b7 100644 --- a/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s +++ b/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s @@ -1,15 +1,14 @@ /* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012 Giovanni Di Sirio. + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - This file is part of ChibiOS/RT. + This file is part of ChibiOS. - ChibiOS/RT is free software; you can redistribute it and/or modify + ChibiOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - ChibiOS/RT is distributed in the hope that it will be useful, + ChibiOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -22,7 +21,7 @@ * @file crt0_v6m.s * @brief Generic ARMv6-M (Cortex-M0/M1) startup file for ChibiOS. * - * @addtogroup ARMCMx_GCC_STARTUP + * @addtogroup ARMCMx_GCC_STARTUP_V6M * @{ */ @@ -114,9 +113,9 @@ /* * Reset handler. */ + .align 2 .thumb_func .global Reset_Handler - .weak Reset_Handler Reset_Handler: /* Interrupts are globally masked initially.*/ cpsid i @@ -228,40 +227,8 @@ endfiniloop: #endif /* Branching to the defined exit handler.*/ - b __default_exit - -/*--------------------------------------------------------------------------* - * Default main exit code, the system is halted. - * It is a weak symbol, the application code can redefine the behavior. - * R0 contains the value returned by the main function. - *--------------------------------------------------------------------------*/ - .thumb_func - .weak __default_exit -__default_exit: - cpsid i -.loop: b .loop - -/*--------------------------------------------------------------------------* - * Default early initialization code. It is declared weak in order to be - * replaced by the real initialization code. - * The early initialization is performed just after stacks setup RAM areas - * initialization. - *--------------------------------------------------------------------------*/ - .thumb_func - .weak __early_init -__early_init: - bx lr - -/*--------------------------------------------------------------------------* - * Default late initialization code. It is declared weak in order to be - * replaced by the real initialization code. - * The late initialization is performed just after RAM areas initialization - * and before invoking the static constructors. - *--------------------------------------------------------------------------*/ - .thumb_func - .weak __late_init -__late_init: - bx lr + ldr r1, =__default_exit + bx r1 #endif diff --git a/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s b/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s index 5aebe0e23..fcfa4decd 100644 --- a/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s +++ b/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s @@ -1,55 +1,151 @@ /* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012 Giovanni Di Sirio. + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio. - This file is part of ChibiOS/RT. + This file is part of ChibiOS. - ChibiOS/RT is free software; you can redistribute it and/or modify + ChibiOS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - ChibiOS/RT is distributed in the hope that it will be useful, + ChibiOS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . - - --- - - A special exception to the GPL can be applied should you wish to distribute - a combined work that includes ChibiOS/RT, without being obliged to provide - the source code for any proprietary components. See the file exception.txt - for full details of how and when the exception can be applied. */ /** * @file crt0_v7m.s * @brief Generic ARMv7-M (Cortex-M3/M4/M7) startup file for ChibiOS. * - * @addtogroup ARMCMx_GCC_STARTUP + * @addtogroup ARMCMx_GCC_STARTUP_V7M * @{ */ +/*===========================================================================*/ +/* Module constants. */ +/*===========================================================================*/ + #if !defined(FALSE) || defined(__DOXYGEN__) -#define FALSE 0 +#define FALSE 0 #endif #if !defined(TRUE) || defined(__DOXYGEN__) -#define TRUE 1 +#define TRUE 1 #endif -#if !defined(__DOXYGEN__) +#define CONTROL_MODE_PRIVILEGED 0 +#define CONTROL_MODE_UNPRIVILEGED 1 +#define CONTROL_USE_MSP 0 +#define CONTROL_USE_PSP 2 +#define CONTROL_FPCA 4 + +#define FPCCR_ASPEN (1 << 31) +#define FPCCR_LSPEN (1 << 30) + +#define SCB_CPACR 0xE000ED88 +#define SCB_FPCCR 0xE000EF34 +#define SCB_FPDSCR 0xE000EF3C + +/*===========================================================================*/ +/* Module pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Control special register initialization value. + * @details The system is setup to run in privileged mode using the PSP + * stack (dual stack mode). + */ +#if !defined(CRT0_CONTROL_INIT) || defined(__DOXYGEN__) +#define CRT0_CONTROL_INIT (CONTROL_USE_PSP | \ + CONTROL_MODE_PRIVILEGED) +#endif + +/** + * @brief Stack segments initialization switch. + */ +#if !defined(CRT0_STACKS_FILL_PATTERN) || defined(__DOXYGEN__) +#define CRT0_STACKS_FILL_PATTERN 0x55555555 +#endif + +/** + * @brief Stack segments initialization switch. + */ +#if !defined(CRT0_INIT_STACKS) || defined(__DOXYGEN__) +#define CRT0_INIT_STACKS TRUE +#endif + +/** + * @brief DATA segment initialization switch. + */ +#if !defined(CRT0_INIT_DATA) || defined(__DOXYGEN__) +#define CRT0_INIT_DATA TRUE +#endif + +/** + * @brief BSS segment initialization switch. + */ +#if !defined(CRT0_INIT_BSS) || defined(__DOXYGEN__) +#define CRT0_INIT_BSS TRUE +#endif + +/** + * @brief Constructors invocation switch. + */ +#if !defined(CRT0_CALL_CONSTRUCTORS) || defined(__DOXYGEN__) +#define CRT0_CALL_CONSTRUCTORS TRUE +#endif + +/** + * @brief Destructors invocation switch. + */ +#if !defined(CRT0_CALL_DESTRUCTORS) || defined(__DOXYGEN__) +#define CRT0_CALL_DESTRUCTORS TRUE +#endif + +/** + * @brief FPU initialization switch. + */ +#if !defined(CRT0_INIT_FPU) || defined(__DOXYGEN__) +#if defined(CORTEX_USE_FPU) || defined(__DOXYGEN__) +#define CRT0_INIT_FPU CORTEX_USE_FPU +#else +#define CRT0_INIT_FPU FALSE +#endif +#endif + +/** + * @brief FPU FPCCR register initialization value. + * @note Only used if @p CRT0_INIT_FPU is equal to @p TRUE. + */ +#if !defined(CRT0_FPCCR_INIT) || defined(__DOXYGEN__) +#define CRT0_FPCCR_INIT (FPCCR_ASPEN | FPCCR_LSPEN) +#endif + +/** + * @brief CPACR register initialization value. + * @note Only used if @p CRT0_INIT_FPU is equal to @p TRUE. + */ +#if !defined(CRT0_CPACR_INIT) || defined(__DOXYGEN__) +#define CRT0_CPACR_INIT 0x00F00000 +#endif - .set CONTROL_MODE_PRIVILEGED, 0 - .set CONTROL_MODE_UNPRIVILEGED, 1 - .set CONTROL_USE_MSP, 0 - .set CONTROL_USE_PSP, 2 +/*===========================================================================*/ +/* Code section. */ +/*===========================================================================*/ - .cpu cortex-m0 +#if !defined(__DOXYGEN__) + + .syntax unified + .cpu cortex-m3 +#if CRT0_INIT_FPU == TRUE + .fpu fpv4-sp-d16 +#else .fpu softvfp +#endif .thumb .text @@ -57,88 +153,142 @@ /* * Reset handler. */ - .thumb_func - .global ResetHandler - .weak ResetHandler -ResetHandler: - /* - * Interrupts are globally masked initially. - */ - cpsid i - /* - * Stack pointers initialization. - */ - ldr r0, =__ram_end__ - ldr r1, =__main_stack_size__ - subs r0, r0, r1 - /* - * Note that r0 is the main stack low boundary address and process - * stack initial top address. - */ - msr PSP, r0 - /* - * Early initialization phase, it is empty by default. - */ - bl __early_init - /* - * Data initialization. - * NOTE: It assumes that the DATA size is a multiple of 4. - */ - ldr r1, =_textdata - ldr r2, =_data - ldr r3, =_edata + .align 2 + .thumb_func + .global Reset_Handler +Reset_Handler: + /* Interrupts are globally masked initially.*/ + cpsid i + + /* PSP stack pointers initialization.*/ + ldr r0, =__process_stack_end__ + msr PSP, r0 + +#if CRT0_INIT_FPU == TRUE + /* FPU FPCCR initialization.*/ + movw r0, #CRT0_FPCCR_INIT & 0xFFFF + movt r0, #CRT0_FPCCR_INIT >> 16 + movw r1, #SCB_FPCCR & 0xFFFF + movt r1, #SCB_FPCCR >> 16 + str r0, [r1] + + /* CPACR initialization.*/ + movw r0, #CRT0_CPACR_INIT & 0xFFFF + movt r0, #CRT0_CPACR_INIT >> 16 + movw r1, #SCB_CPACR & 0xFFFF + movt r1, #SCB_CPACR >> 16 + str r0, [r1] + + /* FPU FPSCR initially cleared.*/ + mov r0, #0 + vmsr FPSCR, r0 + + /* FPU FPDSCR initially cleared.*/ + movw r1, #SCB_FPDSCR & 0xFFFF + movt r1, #SCB_FPDSCR >> 16 + str r0, [r1] + + /* Enforcing FPCA bit in the CONTROL register.*/ + movs r0, #CRT0_CONTROL_INIT | CONTROL_FPCA + +#else + movs r0, #CRT0_CONTROL_INIT +#endif + + /* CONTROL register initialization as configured.*/ + msr CONTROL, r0 + isb + + /* Early initialization..*/ + bl __early_init + +#if CRT0_INIT_STACKS == TRUE + ldr r0, =CRT0_STACKS_FILL_PATTERN + /* Main Stack initialization. Note, it assumes that the + stack size is a multiple of 4 so the linker file must + ensure this.*/ + ldr r1, =__main_stack_base__ + ldr r2, =__main_stack_end__ +msloop: + cmp r1, r2 + itt lo + strlo r0, [r1], #4 + blo msloop + + /* Process Stack initialization. Note, it assumes that the + stack size is a multiple of 4 so the linker file must + ensure this.*/ + ldr r1, =__process_stack_base__ + ldr r2, =__process_stack_end__ +psloop: + cmp r1, r2 + itt lo + strlo r0, [r1], #4 + blo psloop +#endif + +#if CRT0_INIT_DATA == TRUE + /* Data initialization. Note, it assumes that the DATA size + is a multiple of 4 so the linker file must ensure this.*/ + ldr r1, =_textdata + ldr r2, =_data + ldr r3, =_edata dloop: - cmp r2, r3 - ittt lo - ldrlo r0, [r1], #4 - strlo r0, [r2], #4 - blo dloop - /* - * BSS initialization. - * NOTE: It assumes that the BSS size is a multiple of 4. - */ - movs r0, #0 - ldr r1, =_bss_start - ldr r2, =_bss_end + cmp r2, r3 + ittt lo + ldrlo r0, [r1], #4 + strlo r0, [r2], #4 + blo dloop +#endif + +#if CRT0_INIT_BSS == TRUE + /* BSS initialization. Note, it assumes that the DATA size + is a multiple of 4 so the linker file must ensure this.*/ + movs r0, #0 + ldr r1, =_bss_start + ldr r2, =_bss_end bloop: - cmp r1, r2 - itt lo - strlo r0, [r1], #4 - blo bloop - /* - * Switches to the Process Stack and uses a barrier just to be safe. - */ - movs r0, #CONTROL_MODE_PRIVILEGED | CONTROL_USE_PSP - msr CONTROL, r0 - isb - /* - * Main program invocation. - */ - bl main - b _main_exit_handler + cmp r1, r2 + itt lo + strlo r0, [r1], #4 + blo bloop +#endif -/* - * Default main exit code, just a loop. - * It is a weak symbol, the application code can redefine the behavior. - */ - .thumb_func - .global _main_exit_handler - .weak _main_exit_handler -_main_exit_handler: -.loop: b .loop + /* Late initialization..*/ + bl __late_init -/* - * Default early initialization code. It is declared weak in order to be - * replaced by the real initialization code. - * The arly initialization is performed just after stacks setup and before BSS - * and DATA segments initialization. - */ - .thumb_func - .global __early_init - .weak __early_init -__early_init: - bx lr +#if CRT0_CALL_CONSTRUCTORS == TRUE + /* Constructors invocation.*/ + ldr r4, =__init_array_start + ldr r5, =__init_array_end +initloop: + cmp r4, r5 + bge endinitloop + ldr r1, [r4], #4 + blx r1 + b initloop +endinitloop: +#endif + + /* Main program invocation, r0 contains the returned value.*/ + bl main +#if CRT0_CALL_CONSTRUCTORS == TRUE + /* Destructors invocation.*/ + ldr r4, =__fini_array_start + ldr r5, =__fini_array_end +finiloop: + cmp r4, r5 + bge endfiniloop + ldr r1, [r4], #4 + blx r1 + b finiloop +endfiniloop: #endif + /* Branching to the defined exit handler.*/ + b __default_exit + +#endif /* !defined(__DOXYGEN__) */ + /** @} */ -- cgit v1.2.3