summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/str71x/str71x_head.S
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-10-30 23:35:19 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2008-10-30 23:35:19 +0000
commit6bd496502fdb4e1c651ed07b627ac7159b727d25 (patch)
treee15020d8cd9cbdd6ab306d5005e1cd022d796469 /nuttx/arch/arm/src/str71x/str71x_head.S
parent3e32a2d288d69de5fe9c3138b1b516e3f9b16d76 (diff)
downloadpx4-nuttx-6bd496502fdb4e1c651ed07b627ac7159b727d25.tar.gz
px4-nuttx-6bd496502fdb4e1c651ed07b627ac7159b727d25.tar.bz2
px4-nuttx-6bd496502fdb4e1c651ed07b627ac7159b727d25.zip
Adding more STR71x logic
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1105 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/arm/src/str71x/str71x_head.S')
-rw-r--r--nuttx/arch/arm/src/str71x/str71x_head.S667
1 files changed, 667 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/str71x/str71x_head.S b/nuttx/arch/arm/src/str71x/str71x_head.S
new file mode 100644
index 000000000..6f2b2892e
--- /dev/null
+++ b/nuttx/arch/arm/src/str71x/str71x_head.S
@@ -0,0 +1,667 @@
+/*****************************************************************************
+ * arch/arm/src/str71x/str71x_head.S
+ *
+ * Copyright (C) 2008 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included Files
+ *****************************************************************************/
+
+#include <nuttx/config.h> /* NuttX configuration settings */
+#include <arch/board/board.h> /* Board-specific settings */
+#include "arm.h" /* ARM-specific settings */
+#include "chip.h" /* Chip-specific settings */
+#include "up_internal.h"
+#include "up_arch.h"
+
+/*****************************************************************************
+ * Definitions
+ *****************************************************************************/
+
+/* This file holds the NuttX start logic that runs when the STR711
+ * is reset. This logic must be located at address 0x0000:0000 in
+ * flash but may be linked to run at different locations based on
+ * the selected mode:
+ *
+ * default: Executes from 0x0000:0000. In non-default modes, the
+ * MEMAP register is set override the settings of the CPU configuration
+ * pins.
+ *
+ * CONFIG_EXTMEM_MODE: Code executes from external memory starting at
+ * address 0x6000:0000.
+ *
+ * CONFIG_RAM_MODE: Code executes from on-chip RAM at address
+ * 0x2000:0000.
+ *
+ * Starupt Code must be linked to run at the correct address
+ * corresponding to the selected mode.
+ */
+
+#if defined(CONFIG_EXTMEM_MODE)
+# if CONFIG_CODE_BASE != STR71X_EXTMEM_BASE
+# error "CONFIG_CODE_BASE must be 0x60000000 in EXTMEM mode"
+# endif
+#elif defined(CONFIG_RAM_MODE)
+# if CONFIG_CODE_BASE != STR71X_ONCHIP_RAM_BASE
+# error "CONFIG_CODE_BASE must be 0x20000000 in EXTMEM mode"
+# endif
+#else
+# if CONFIG_CODE_BASE != STR71X_FLASH_BASE
+# error "CONFIG_CODE_BASE must be 0x00000000 in default mode"
+# endif
+#endif
+
+/*****************************************************************************
+ * Macros
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Name: showprogress
+ *
+ * Description:
+ * Print a character on the UART to show boot status. This macro will
+ * modify r0, r1, r2 and r14
+ *
+ *****************************************************************************/
+
+ .macro showprogress, code
+#ifdef CONFIG_DEBUG
+ mov r0, #\code
+ bl up_lowputc
+#endif
+ .endm
+
+/*****************************************************************************
+ * Name: emiinit
+ *
+ * Description:
+ * Initialize external memory banks 0-3 as configured
+ *
+ *****************************************************************************/
+
+ .macro emiinit, base, value
+#if defined(CONFIG_STR71X_BANK0) || defined(CONFIG_STR71X_BANK1) || \
+ defined(CONFIG_STR71X_BANK2) || defined(CONFIG_STR71X_BANK3)
+
+ /* In order to use the external memory, certain GPIO pins must be
+ * configured in the alternate function:
+ *
+ * GPIO ALT Description
+ * P2.0-3 CS.0-3 External memory chip select for banks 0,1,3,4
+ * P2.4-7 A.20-23 External memory extended address bus (needed for
+ * address space > 1Mb)
+ */
+
+#ifdef CONFIG_STR71X_BIGEXTMEM
+# define EXTMEM_GPIO_BITSET 0x000000ff /* P2.0-7 */
+#else
+# define EXTMEM_GPIO_BITSET 0x0000000f /* P2.0-3 */
+#endif
+
+ ldr \base, =STR71X_GPIO_BASE ; Configure P2.0 to P2.3/7 in AF_PP mode
+ ldr \value, [\base, #STR71X_GPIO_PC0_OFFSET]
+ orr \value, \value, #EXTMEM_GPIO_BITSET
+ str \value, [\base, #STR71X_GPIO_PC0_OFFSET]
+ ldr \value, [\base, #STR71X_GPIO_PC1_OFFSET]
+ orr \value, \value, #EXTMEM_GPIO_BITSET
+ str \value, [\base, #STR71X_GPIO_PC1_OFFSET]
+ ldr \value, [\base, #STR71X_GPIO_PC2_OFFSET]
+ orr \value, \value, #EXTMEM_GPIO_BITSET
+ str \value, [\base, #STR71X_GPIO_PC2_OFFSET]
+
+ /* Enable bank 0 */
+
+ ldr \base, =STR71X_EMI_BASE
+
+#ifdef CONFIG_STR71X_BANK0
+
+ /* Get the bank 0 size */
+
+# if CONFIG_STR71X_BANK0_SIZE == 8
+# define EXTMEM_BANK0_SIZE STR71X_EMIBCON_BSIZE8
+# elif CONFIG_STR71X_BANK0_SIZE == 16
+# define EXTMEM_BANK0_SIZE STR71X_EMIBCON_BSIZE16
+# else
+# error "CONFIG_STR71X_BANK0_SIZE invalid"
+# endif
+
+ /* Get the bank 0 waitstates */
+
+# if !defined(CONFIG_STR71X_BANK0_WAITSTATES) || \
+ CONFIG_STR71X_BANK0_WAITSTATES < 0 || CONFIG_STR71X_BANK0_WAITSTATES > 15
+# error "CONFIG_STR71X_BANK0_WAITSTATES invalid"
+# else
+ /* Bits 2-5: wait states */
+# define EXTMEM_BANK0_WAITSTATES (CONFIG_STR71X_BANK0_WAITSTATES << 2)
+# endif
+
+ ldr \value, =(STR71X_EMIBCON_ENABLE|EXTMEM_BANK0_WAITSTATES|EXTMEM_BANK0_SIZE)
+#else
+ mov \value, #0
+#endif
+ str \value, [\base, #STR71X_EMI_BCON0_OFFSET]
+
+ /* Enable bank 1 */
+
+#ifdef CONFIG_STR71X_BANK1
+
+ /* Get the bank 1 size */
+
+# if CONFIG_STR71X_BANK1_SIZE == 8
+# define EXTMEM_BANK1_SIZE STR71X_EMIBCON_BSIZE8
+# elif CONFIG_STR71X_BANK1_SIZE == 16
+# define EXTMEM_BANK1_SIZE STR71X_EMIBCON_BSIZE16
+# else
+# error "CONFIG_STR71X_BANK1_SIZE invalid"
+# endif
+
+ /* Get the bank 1 waitstates */
+
+# if !defined(CONFIG_STR71X_BANK1_WAITSTATES) || \
+ CONFIG_STR71X_BANK1_WAITSTATES < 0 || CONFIG_STR71X_BANK1_WAITSTATES > 15
+# error "CONFIG_STR71X_BANK1_WAITSTATES invalid"
+# else
+ /* Bits 2-5: wait states */
+# define EXTMEM_BANK1_WAITSTATES (CONFIG_STR71X_BANK1_WAITSTATES << 2)
+# endif
+
+ ldr \value, =(STR71X_EMIBCON_ENABLE|EXTMEM_BANK1_WAITSTATES|EXTMEM_BANK1_SIZE)
+#else
+ mov \value, #0
+#endif
+ str \value, [\base, #STR71X_EMI_BCON1_OFFSET]
+
+ /* Enable bank 2 */
+
+#ifdef CONFIG_STR71X_BANK2
+
+ /* Get the bank 2 size */
+
+# if CONFIG_STR71X_BANK2_SIZE == 8
+# define EXTMEM_BANK2_SIZE STR71X_EMIBCON_BSIZE8
+# elif CONFIG_STR71X_BANK2_SIZE == 16
+# define EXTMEM_BANK2_SIZE STR71X_EMIBCON_BSIZE16
+# else
+# error "CONFIG_STR71X_BANK2_SIZE invalid"
+# endif
+
+ /* Get the bank 2 waitstates */
+
+# if !defined(CONFIG_STR71X_BANK2_WAITSTATES) || \
+ CONFIG_STR71X_BANK2_WAITSTATES < 2 || CONFIG_STR71X_BANK2_WAITSTATES > 15
+# error "CONFIG_STR71X_BANK2_WAITSTATES invalid"
+# else
+ /* Bits 2-5: wait states */
+# define EXTMEM_BANK2_WAITSTATES (CONFIG_STR71X_BANK2_WAITSTATES << 2)
+# endif
+
+ ldr \value, =(STR71X_EMIBCON_ENABLE|EXTMEM_BANK2_WAITSTATES|EXTMEM_BANK2_SIZE)
+#else
+ mov \value, #0
+#endif
+ str \value, [\base, #STR71X_EMI_BCON2_OFFSET]
+
+ /* Enable bank 3 */
+
+#ifdef CONFIG_STR71X_BANK3
+
+ /* Get the bank 3 size */
+
+# if CONFIG_STR71X_BANK3_SIZE == 8
+# define EXTMEM_BANK3_SIZE STR71X_EMIBCON_BSIZE8
+# elif CONFIG_STR71X_BANK3_SIZE == 16
+# define EXTMEM_BANK3_SIZE STR71X_EMIBCON_BSIZE16
+# else
+# error "CONFIG_STR71X_BANK3_SIZE invalid"
+# endif
+
+ /* Get the bank 3 waitstates */
+
+# if !defined(CONFIG_STR71X_BANK3_WAITSTATES) || \
+ CONFIG_STR71X_BANK3_WAITSTATES < 3 || CONFIG_STR71X_BANK3_WAITSTATES > 15
+# error "CONFIG_STR71X_BANK3_WAITSTATES invalid"
+# else
+ /* Bits 2-5: wait states */
+# define EXTMEM_BANK3_WAITSTATES (CONFIG_STR71X_BANK3_WAITSTATES << 2)
+# endif
+
+ ldr \value, =(STR71X_EMIBCON_ENABLE|EXTMEM_BANK3_WAITSTATES|EXTMEM_BANK3_SIZE)
+#else
+ mov \value, #0
+#endif
+ str \value, [\base, #STR71X_EMI_BCON3_OFFSET]
+#endif
+ .endm
+
+/*****************************************************************************
+ * Name: eicinit
+ *
+ * Description:
+ * The EIC is initialized for use with NuttX. This initialization does not
+ * take advantage of the high performance capabilities of the EIC. Instead,
+ * The EIC is only used to to provide NuttX IRQ numbers. Here is what is
+ * done:
+ *
+ * IRQs and FIQs are disabled
+ * IVR set to zero
+ * All channels are disabled
+ * Channels set to priority 0
+ * All SIR[n] registers contain the NuttX IRQ number in the MS 16-bits
+ *
+ * At the time of IRQ processing, the IVR will contain the decoded IRQ
+ * number needed by NuttX.
+ *
+ *****************************************************************************/
+
+ .macro eicinit, eicbase, value, irqno, offset
+ /* Disable and clear all interrupts */
+
+ ldr \eicbase, =STR71X_EIC_BASE
+
+ /* Disable FIQ and IRQ */
+
+ mov \value, #0
+ str \value, [\eicbase, #STR71X_EIC_ICR_OFFSET]
+
+ /* Disable all channel interrupts */
+
+ str \value, [\eicbase, #STR71X_EIC_IER_OFFSET]
+
+ /* Clear all pending IRQs */
+
+ ldr \value, =0xffffffff
+ str \value, [\eicbase, #STR71X_EIC_IPR_OFFSET]
+
+ /* Disable FIQ channels/clear pending FIQs */
+
+ mov \value, #0x0c
+ str \value, [\eicbase, #STR71X_EIC_FIR_OFFSET]
+
+ /* Reset the current priority register */
+
+ mov \value, #0
+ str \value, [\eicbase, #STR71X_EIC_CIPR_OFFSET]
+
+ /* Zero IVR 31:16 */
+
+ str \value, [\eicbase, STR71X_EIC_IVR_OFFSET]
+
+ /* Set up the loop to initialize each SIR register. Start
+ * with IRQ number 0 and SIR0
+ */
+
+ mov \irqno, #0
+ ldr \offset, =STR71X_EIC_SIR_OFFSET
+
+ /* Then loop for each EIC channel */
+eicloop:
+ /* Shift the IRQ number to bits 16-31 and save the shifted IRQ
+ * number as SIR[irqno]. This will appear as bits 0:15 in the
+ * IVR during IRQ processing.
+ */
+
+ mov \value, \irqno, lsl #16
+ str \value, [\eicbase, \offset]
+
+ /* Increment the offset to the next SIR register and inrement
+ * the IRQ number.
+ */
+
+ add \offset, \offset, #4
+ add \irqno, \irqno, #1
+
+ /* Continue to loop until all of the SIR registers have been
+ * intialized.
+ */
+
+ cmp \irqno, #STR71X_EIC_NCHANNELS
+ blt eicloop
+ .endm
+
+/*****************************************************************************
+ * Name: periphinit
+ *
+ * Description"
+ * Disable all perfipherals (except EIC)
+ *
+ *****************************************************************************/
+
+ .macro periphinit, value, base1, base2
+#ifndef CONFIG_STR71X_DISABLE_PERIPHINIT
+ /* Set up APB1 and APB2 addresses */
+
+ ldr \base1, =STR71X_APB1_BASE
+ ldr \base2, =STR71X_APB2_BASE
+
+ /* Disable all APB1 peripherals */
+
+ ldr \value, =STR71X_APB1_APB1ALL
+ strh \value, [\base1, #STR71X_APB_CKDIS_OFFSET]
+
+ /* Disable all(or most) APB1 peripherals */
+#if 1 /* See below */
+ ldr \value, =(STR71X_APB2_APB2ALL & ~STR71X_APB2_EIC)
+#else
+ ldr \value, =STR71X_APB2_APB2ALL
+#endif
+ strh \value, [\base2, #STR71X_APB_CKDIS_OFFSET]
+
+ /* Reset and enable peripherals */
+#if 0
+ /* Hold all APB1 and APB2 peripherals under reset */
+
+ ldr \value, =STR71X_APB1_APB1ALL
+ strh \value, [\base1, #STR71X_APB_SWRES_OFFSET]
+ ldr \value, =STR71X_APB2_APB2ALL
+ strh \value, [\base2, #STR71X_APB_SWRES_OFFSET]
+
+ /* Wait that the selected macrocells exit from reset */
+
+ mov \value, #10
+loop1: subs \value, \value, #1
+ bne loop1
+
+ /* Release APB1 and APB2 peripherals from reset */
+
+ mov \value, #0
+ strh \value, [\base1, #STR71X_APB_SWRES_OFFSET]
+ strh \value, [\base2, #STR71X_APB_SWRES_OFFSET]
+
+ /* Enable clocking for all APB1 and APB2 peripherals */
+
+ strh \value, [\base1, #STR71X_APB_CKDIS_OFFSET]
+ strh \value, [\base2, #STR71X_APB_CKDIS_OFFSET];
+
+ /* Wait that the selected macrocells exit from reset */
+
+ mov \value, #10
+loop2: subs \value, \value, #1
+ bne loop2
+#endif
+
+ /* Allow EMI and USB */
+
+ ldr \base1, =STR71X_RCCU_BASE
+ ldr \value, =(STR71X_RCCUPER_EMI|STR71X_RCCUPER_USBKERNEL)
+ strh \value, [\base1, #STR71X_RCCU_PER_OFFSET]
+#endif
+ .endm
+
+/*****************************************************************************
+ * Name: remap
+ *
+ * Description:
+ * Remap memory at address 0x0000000 to either FLASH. The system always
+ * boots at Bank0, sector 0 of FLASH. Part of the initial setup will be to
+ * map the memory appropriately for the execution configuration. Various
+ * options are possible, but only boot from FLASH is currently supported.
+ *
+ *****************************************************************************/
+
+ .macro remap, base, value
+ /* Read the PCU BOOTCR register */
+
+ ldr \base, =STR71X_PCU_BASE
+ ldrh \value, [\base, #STR71X_PCU_BOOTCR_OFFSET]
+
+ /* Mask out the old boot mode bits and set the boot mode to FLASH */
+
+ bic \value, \value, #STR71X_PCUBOOTCR_BOOTMASK
+ orr \value, \value, #STR71X_PCUBOOTCR_BMFLASH
+
+ /* Save the modified BOOTCR register */
+
+ strh \value, [\base, #STR71X_PCU_BOOTCR_OFFSET]
+ .endm
+
+/*****************************************************************************
+ * Text
+ *****************************************************************************/
+
+ .text
+
+/*****************************************************************************
+ * Name: _vector_table
+ *
+ * Description:
+ * Interrrupt vector table. This must be located at the beginning
+ * of the memory space (at CONFIG_CODE_BASE). The first entry in
+ * the vector table is the reset vector and this is the code that
+ * will execute whn the processor is reset.
+ *
+ *****************************************************************************/
+
+ .globl _vector_table
+ .type _vector_table, %function
+_vector_table:
+ ldr pc, .Lresethandler /* 0x00: Reset */
+ ldr pc, .Lundefinedhandler /* 0x04: Undefined instruction */
+ ldr pc, .Lswihandler /* 0x08: Software interrupt */
+ ldr pc, .Lprefetchaborthandler /* 0x0c: Prefetch abort */
+ ldr pc, .Ldataaborthandler /* 0x10: Data abort */
+ .long 0 /* 0x14: Reserved vector */
+ ldr pc, .Lirqhandler /* 0x18: IRQ */
+ ldr pc, .Lfiqhandler /* 0x1c: FIQ */
+
+ .globl __start
+ .globl up_vectorundefinsn
+ .globl up_vectorswi
+ .globl up_vectorprefetch
+ .globl up_vectordata
+ .globl up_vectorirq
+ .globl up_vectorfiq
+
+.Lresethandler:
+ .long __start
+.Lundefinedhandler:
+ .long up_vectorundefinsn
+.Lswihandler:
+ .long up_vectorswi
+.Lprefetchaborthandler:
+ .long up_vectorprefetch
+.Ldataaborthandler:
+ .long up_vectordata
+.Lirqhandler:
+ .long up_vectorirq
+.Lfiqhandler:
+ .long up_vectorfiq
+ .size _vector_table, . - _vector_table
+
+/*****************************************************************************
+ * Name: __start
+ *
+ * Description:
+ * Reset entry point. This is the first function to execute when
+ * the processor is reset. It initializes hardware and then gives
+ * control to NuttX.
+ *
+ *****************************************************************************/
+
+ .global __start
+ .type __start, #function
+
+__start:
+ /* On reset, an aliased copy of FLASH is mapped to address 0x00000000.
+ * Continue execution in the 'real' FLASH address space rather than
+ * the aliased copy
+ */
+
+ ldr pc, =__flashstart
+__flashstart:
+ .rept 9
+ nop /* Wait for OSC stabilization*/
+ .endr
+
+ /* Setup the initial processor mode */
+
+ mov r0, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT )
+ msr cpsr, r0
+
+ /* Initialize the external memory interface (EMI) */
+
+ emiinit r0, r1
+
+ /* Initialize the enhanced interrupt controller (EIC) */
+
+ eicinit r0, r1, r2, r3
+
+ /* Disable all peripherals except EIC */
+
+ periphinit r0, r1, r2
+
+ /* Map memory appropriately for configuration */
+
+ remap r0, r1
+
+ /* Configure the uart so that we can get debug output as soon
+ * as possible. Modifies r0, r1, r2, and r14.
+ */
+
+ bl up_lowsetup
+ showprogress 'A'
+
+ /* Setup system stack (and get the BSS range) */
+
+ adr r0, LC0
+ ldmia r0, {r4, r5, sp}
+
+ /* Clear system BSS section */
+
+ mov r0, #0
+1: cmp r4, r5
+ strcc r0, [r4], #4
+ bcc 1b
+
+ showprogress 'B'
+
+ /* Copy system .data sections to new home in RAM. */
+
+#ifdef CONFIG_BOOT_FROM_FLASH
+
+ adr r3, LC2
+ ldmia r3, {r0, r1, r2}
+
+1: ldmia r0!, {r3 - r10}
+ stmia r1!, {r3 - r10}
+ cmp r1, r2
+ blt 1b
+
+#endif
+ /* Perform early serial initialization */
+
+ mov fp, #0
+#ifdef CONFIG_USE_EARLYSERIALINIT
+ bl up_earlyserialinit
+#endif
+
+ showprogress 'C'
+
+ /* Call C++ constructors */
+
+ ldr r0, =__ctors_start__
+ ldr r1, =__ctors_end__
+ctor_loop:
+ cmp r0, r1
+ beq ctor_end
+ ldr r2, [r0], #4
+ stmfd sp!, {r0-r1}
+ mov lr, pc
+ mov pc, r2
+ ldmfd sp!, {r0-r1}
+ b ctor_loop
+ctor_end:
+
+ showprogress 'D'
+ showprogress '\n'
+
+ /* Initialize onboard LEDs */
+
+#ifdef CONFIG_ARCH_LEDS
+ bl up_ledinit
+#endif
+
+ /* Then jump to OS entry */
+
+ b os_start
+
+ /* Call destructors -- never get here */
+#if 0
+ ldr r0, =__dtors_start__
+ ldr r1, =__dtors_end__
+dtor_loop:
+ cmp r0, r1
+ beq dtor_end
+ ldr r2, [r0], #4
+ stmfd sp!, {r0-r1}
+ mov lr, pc
+ mov pc, r2
+ ldmfd sp!, {r0-r1}
+ b dtor_loop
+dtor_end:
+#endif
+
+ /* Variables:
+ * _sbss is the start of the BSS region (see ld.script)
+ * _ebss is the end of the BSS regsion (see ld.script)
+ * The idle task stack starts at the end of BSS and is
+ * of size CONFIG_PROC_STACK_SIZE. The heap continues
+ * from there until the end of memory. See g_heapbase
+ * below.
+ */
+
+LC0: .long _sbss
+ .long _ebss
+ .long _ebss+CONFIG_PROC_STACK_SIZE-4
+
+#ifdef CONFIG_BOOT_FROM_FLASH
+LC2: .long _eronly /* Where .data defaults are stored in FLASH */
+ .long _sdata /* Where .data needs to reside in SDRAM */
+ .long _edata
+#endif
+ .size __start, .-__start
+
+ /* This global variable is unsigned long g_heapbase and is
+ * exported from here only because of its coupling to LCO
+ * above.
+ */
+
+ .data
+ .align 4
+ .globl g_heapbase
+ .type g_heapbase, object
+g_heapbase:
+ .long _ebss+CONFIG_PROC_STACK_SIZE
+ .size g_heapbase, .-g_heapbase
+
+ .end
+