summaryrefslogblamecommitdiff
path: root/nuttx/arch/arm/src/str71x/str71x_head.S
blob: 744e5865a789e5c654ff2b8d9b669c693a857de2 (plain) (tree)
1
2
3
4


                                                                              
                                                               




































                                                                               
 









                                                                               


                                                                    

   
                                                                              
















                                                                                   







































































































































































































































                                                                                          
                                                          












                                                                      



                                                                       







































                                                                               
                                                   
                                                                 

                                                          


                                         
                        
                                                                      


                                           









































                                                                               


                                                                              




















































































                                                                                 











                                                        
                                                                       



                                
                               

                               
                  
 




                                                                     
                       




                           






                                                 
                        


                                   
                       












                                    

                        












                                                 

                            

















                                                               
                                                                   





                                                              
                                                   
 


                                                                      











                                                                  
                                                 



                                        
/*****************************************************************************
 * arch/arm/src/str71x/str71x_head.S
 *
 *   Copyright (C) 2008-2009 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 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 CONFIG_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 CONFIG_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