In SVC mode, the banked register will be inconsistent with the user mode register: arch/arm/src/armv7-a/arm_vectors.S 276 .globl arm_syscall 277 .globl arm_vectorsvc 278 .type arm_vectorsvc, %function 279 280 arm_vectorsvc: ... 286 sub sp, sp, #XCPTCONTEXT_SIZE // < SVC mode SP ... 308 stmia r0, {r13, r14}^ // < USR mode SP/LR ... [ 2.200000] [ 4] [ ALERT] SYSCALL Entry: regs: 0x80202708 cmd: 4 [ 2.200000] [ 4] [ ALERT] R0: 00000004 80001229 00000001 80202018 00000000 00000000 00000000 802027d0 [ 2.200000] [ 4] [ ALERT] R8: 00000000 00000000 00000000 00000000 00000000 802027d0 1080f710 1080f710 [ 2.200000] [ 4] [ ALERT] CPSR: 00000073 [ 2.200000] [ 4] [ ALERT] SYSCALL Exit: regs: 0x80202708 [ 2.200000] [ 4] [ ALERT] R0: 1 80202018 1 80202018 0 0 0 802027d0 [ 2.200000] [ 4] [ ALERT] R8: 0 0 0 0 0 802027d0 1080f710 80001229 [ 2.200000] [ 4] [ ALERT] CPSR: 00000070 SVC SP is 0x80202708 USR SP is 0x802027d0 0x802027d0 - 0x80202708 should be XCPTCONTEXT_SIZE [ 2.200000] [ 4] [ ALERT] SYSCALL Entry: regs: 0x80202708 cmd: 51 [ 2.200000] [ 4] [ ALERT] R0: 00000033 00000000 80202780 00000000 00000000 00000000 00000000 80202710 [ 2.200000] [ 4] [ ALERT] R8: 00000000 00000000 00000000 00000000 00000000 80202710 800039d5 800039b2 [ 2.200000] [ 4] [ ALERT] CPSR: 00000070 [ 2.200000] [ 4] [ ALERT] SYSCALL Exit: regs: 0x80202708 [ 2.200000] [ 4] [ ALERT] R0: 2b 0 80202780 0 0 0 0 80202710 [ 2.200000] [ 4] [ ALERT] R8: 0 0 0 0 0 10843d80 800039d5 10801425 [ 2.200000] [ 4] [ ALERT] CPSR: 00000073 SVC SP is 0x80202708 USR SP is 0x80202710 SP overlap in SVC and USR mode This commit change the default CPU mode to System and ensure the consistency of SP/LR in USR/SYS mode during syscall. Signed-off-by: chao.an <anchao@xiaomi.com>
613 lines
16 KiB
ArmAsm
613 lines
16 KiB
ArmAsm
/****************************************************************************
|
|
* arch/arm/src/str71x/str71x_head.S
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h> /* NuttX configuration settings */
|
|
|
|
#include "arm.h" /* ARM-specific settings */
|
|
#include "chip.h" /* Chip-specific settings */
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/* This file holds the NuttX start logic that runs when the STR711
|
|
* is reset. This logic must be located at address 0x4000:0000 in
|
|
* flash. It will also be mapped to address zero when the STR711 is
|
|
* reset.
|
|
*/
|
|
|
|
/****************************************************************************
|
|
* External references
|
|
****************************************************************************/
|
|
|
|
.globl str71x_prccuinit /* Clock initialization */
|
|
.globl up_lowsetup /* Early initialization of UART */
|
|
#ifdef USE_EARLYSERIALINIT
|
|
.globl arm_earlyserialinit /* Early initialization of serial driver */
|
|
#endif
|
|
#ifdef CONFIG_ARCH_LEDS
|
|
.globl board_autoled_initialize /* Boot LED setup */
|
|
#endif
|
|
#ifdef CONFIG_DEBUG_FEATURES
|
|
.globl arm_lowputc /* Low-level debug output */
|
|
#endif
|
|
.globl nx_start /* NuttX entry point */
|
|
|
|
/****************************************************************************
|
|
* 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_FEATURES
|
|
mov r0, #\code
|
|
bl arm_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 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.
|
|
*
|
|
* NOTE that the initial priority is set to zero -- the current
|
|
* interrupt priority (CIP) is always zero, so these interrupts
|
|
* are all disabled.
|
|
*/
|
|
|
|
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
|
|
* initializeed.
|
|
*/
|
|
|
|
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) APB2 peripherals */
|
|
|
|
ldr \value, =(STR71X_APB2_APB2ALL & ~STR71X_APB2_EIC)
|
|
strh \value, [\base2, #STR71X_APB_CKDIS_OFFSET]
|
|
|
|
/* Allow EMI and USB */
|
|
|
|
ldr \base1, =STR71X_RCCU_BASE
|
|
#ifdef CONFIG_STR71X_USB
|
|
ldr \value, =(STR71X_RCCUPER_EMI|STR71X_RCCUPER_USBKERNEL)
|
|
#else
|
|
ldr \value, =STR71X_RCCUPER_EMI
|
|
#endif
|
|
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:
|
|
* Interrupt vector table. This must be located at the beginning
|
|
* of the memory space (at the beginning FLASH which will be mapped to
|
|
* address 0x00000000). The first entry in the vector table is the reset
|
|
* vector and this is the code that will execute when 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 arm_vectorundefinsn
|
|
.globl arm_vectorsvc
|
|
.globl arm_vectorprefetch
|
|
.globl arm_vectordata
|
|
.globl arm_vectorirq
|
|
.globl arm_vectorfiq
|
|
|
|
.Lresethandler:
|
|
.long __start
|
|
.Lundefinedhandler:
|
|
.long arm_vectorundefinsn
|
|
.Lswihandler:
|
|
.long arm_vectorsvc
|
|
.Lprefetchaborthandler:
|
|
.long arm_vectorprefetch
|
|
.Ldataaborthandler:
|
|
.long arm_vectordata
|
|
.Lirqhandler:
|
|
.long arm_vectorirq
|
|
.Lfiqhandler:
|
|
.long arm_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, #(PSR_MODE_SYS | 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
|
|
|
|
/* 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
|
|
|
|
/* Copy system .data sections from FLASH to new home in RAM. */
|
|
|
|
adr r3, LC2
|
|
ldmia r3, {r0, r1, r2}
|
|
|
|
2: ldmia r0!, {r3 - r10}
|
|
stmia r1!, {r3 - r10}
|
|
cmp r1, r2
|
|
blt 2b
|
|
|
|
/* Initialize clocking */
|
|
|
|
bl str71x_prccuinit
|
|
|
|
/* Configure the uart so that we can get debug output as soon
|
|
* as possible.
|
|
*/
|
|
|
|
bl up_lowsetup
|
|
showprogress 'A'
|
|
|
|
/* Perform early serial initialization */
|
|
|
|
mov fp, #0
|
|
#ifdef USE_EARLYSERIALINIT
|
|
bl arm_earlyserialinit
|
|
#endif
|
|
|
|
showprogress 'B'
|
|
|
|
/* Call C++ constructors */
|
|
|
|
#ifdef CONFIG_CPLUSPLUS
|
|
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 'C'
|
|
#endif
|
|
showprogress '\n'
|
|
|
|
/* Initialize onboard LEDs */
|
|
|
|
#ifdef CONFIG_ARCH_LEDS
|
|
bl board_autoled_initialize
|
|
#endif
|
|
|
|
/* Then jump to OS entry */
|
|
|
|
b nx_start
|
|
|
|
/* Call destructors -- never get here */
|
|
|
|
#if 0 /* CONFIG_CPLUSPLUS */
|
|
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 region (see ld.script)
|
|
* The idle task stack starts at the end of BSS and is
|
|
* of size CONFIG_IDLETHREAD_STACKSIZE. The heap continues
|
|
* from there until the end of memory. See g_idle_topstack
|
|
* below.
|
|
*/
|
|
|
|
LC0: .long _sbss
|
|
.long _ebss
|
|
.long _ebss+CONFIG_IDLETHREAD_STACKSIZE
|
|
|
|
LC2: .long _eronly /* Where .data defaults are stored in FLASH */
|
|
.long _sdata /* Where .data needs to reside in SDRAM */
|
|
.long _edata
|
|
.size __start, .-__start
|
|
|
|
/* This global variable is unsigned long g_idle_topstack and is
|
|
* exported from here only because of its coupling to LCO
|
|
* above.
|
|
*/
|
|
|
|
.data
|
|
.align 4
|
|
.globl g_idle_topstack
|
|
.type g_idle_topstack, object
|
|
g_idle_topstack:
|
|
.long _ebss+CONFIG_IDLETHREAD_STACKSIZE
|
|
.size g_idle_topstack, .-g_idle_topstack
|
|
|
|
.end
|