9
0
Fork 0
nuttx-bb/nuttx/arch/arm/src/str71x/str71x_head.S

630 lines
17 KiB
ArmAsm

/*****************************************************************************
* arch/arm/src/str71x/str71x_head.S
*
* Copyright (C) 2008-2009, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 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 up_earlyserialinit /* Early initialization of serial driver */
#endif
#ifdef CONFIG_ARCH_LEDS
.globl up_ledinit /* Boot LED setup */
#endif
#ifdef CONFIG_DEBUG
.globl up_lowputc /* Low-level debug output */
#endif
.globl os_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
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.
*
* 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
* 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) 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:
* Interrrupt 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 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
/* 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 up_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 up_ledinit
#endif
/* Then jump to OS entry */
b os_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 regsion (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_heapbase
* below.
*/
LC0: .long _sbss
.long _ebss
.long _ebss+CONFIG_IDLETHREAD_STACKSIZE-4
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_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_IDLETHREAD_STACKSIZE
.size g_heapbase, .-g_heapbase
.end