/************************************************************************/
/*                                                                      */
/*    Startup file for memory and basic controller initialisation       */
/*                                                                      */
/************************************************************************/

/************************************************************************/
/* 1  Disclaimer                                                        */
/************************************************************************/
/* __DISCLAIMER_START__                                                 */
/************************************************************************/
/******************************************************************************/
/* (c) 2014-2016, Cypress Semiconductor Corporation                           */
/* or a subsidiary of Cypress Semiconductor Corporation. All rights           */
/* reserved.                                                                  */
/*                                                                            */
/* This software, including source code, documentation and related            */
/* materials ( "Software" ), is owned by Cypress Semiconductor                */
/* Corporation or one of its subsidiaries ( "Cypress" ) and is protected by   */
/* and subject to worldwide patent protection (United States and foreign),    */
/* United States copyright laws and international treaty provisions.          */
/* Therefore, you may use this Software only as provided in the license       */
/* agreement accompanying the software package from which you                 */
/* obtained this Software ( "EULA" ).                                         */
/*                                                                            */
/* If no EULA applies, Cypress hereby grants you a personal, nonexclusive,    */
/* non-transferable license to copy, modify, and compile the                  */
/* Software source code solely for use in connection with Cypress' s          */
/* integrated circuit products. Any reproduction, modification, translation,  */
/* compilation, or representation of this Software except as specified        */
/* above is prohibited without the express written permission of Cypress.     */
/*                                                                            */
/* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO                       */
/* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,                       */
/* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED                               */
/* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A                            */
/* PARTICULAR PURPOSE. Cypress reserves the right to make                     */
/* changes to the Software without notice. Cypress does not assume any        */
/* liability arising out of the application or use of the Software or any     */
/* product or circuit described in the Software. Cypress does not             */
/* authorize its products for use in any products where a malfunction or      */
/* failure of the Cypress product may reasonably be expected to result in     */
/* significant property damage, injury or death ( "High Risk Product" ). By   */
/* including Cypress' s product in a High Risk Product, the manufacturer      */
/* of such system or application assumes all risk of such use and in doing    */
/* so agrees to indemnify Cypress against all liability.                      */
/******************************************************************************/
/************************************************************************/
/* __DISCLAIMER_END__                                                   */
/************************************************************************/
/************************************************************************/
/* 2  Contents                                                          */
/************************************************************************/
/*  1  Disclaimer                                                       */
/*  2  Contents                                                         */
/*  3  History                                                          */
/*  4  Settings                                                         */
/*  5  Declarations                                                     */
/*  5.1  Local definitions                                              */
/*  5.2  Import symbols                                                 */
/*  5.3  Export symbols                                                 */
/*  5.4  Declare sections                                               */
/*  6  Exception Vector table                                           */
/*  7  Start-up Code                                                    */
/*  7.1  Initialize stacks for start-up sequence                        */
/*  7.2  Call Start_PreInit                                             */
/*  7.3  Setup user defined stacks                                      */
/*  7.4  Call system library                                            */
/*  7.5  End loop                                                       */
/*  7.6  Literal pool                                                   */
/*  8  File end                                                         */

/************************************************************************/
/* 3  History                                                           */
/************************************************************************/
/*
/* Version      Date        Author  Description                         */
/* V0.01        2014-10-01   ST     Initial version for Traveo          */

/************************************************************************/
/* 4  Settings                                                          */
/************************************************************************/

/* Define start-up stack size which will be used during start-up. The   */
/* start-up stack is put at the beginning of the TCM RAM                */
/* (0x00000000 + STARTUP_STACK_SIZE_BYTE).                              */
/* The size must be a multiple of 128 byte. After Start_PreInit() is    */
/* executed, the user defined stacks will be set up.                    */

STARTUP_STACK_SIZE_BYTE DEFINE 128 /* <<< set size of start-up stack */

/************************************************************************/
/* 5  Declarations                                                      */
/************************************************************************/

        MODULE ?CSTARTUP
/************************************************************************/
/* 5.1  Local definitions                                               */
/************************************************************************/

MODE_MSK DEFINE 0x1F
MODE_USR DEFINE 0x10
MODE_FIQ DEFINE 0x11
MODE_IRQ DEFINE 0x12
MODE_SVC DEFINE 0x13
MODE_ABT DEFINE 0x17
MODE_UND DEFINE 0x1B
MODE_SYS DEFINE 0x1F /* shares stack with USR mode */

ADDRESS_TCRAM_START EQU 0x00000000

/************************************************************************/
/* 5.2  Import symbols                                                  */
/************************************************************************/

        EXTERN Start_PreInit
        EXTERN __cmain

/************************************************************************/
/* 5.3  Export symbols                                                  */
/************************************************************************/

        PUBLIC __iar_program_start

        PUBLIC ADDRESS_BOOT_USR_STACK_END

/************************************************************************/
/* 5.4  Declare sections                                                */
/************************************************************************/

        SECTION USR_STACK:DATA:NOROOT(3)
        SECTION FIQ_STACK:DATA:NOROOT(3)
        SECTION IRQ_STACK:DATA:NOROOT(3)
        SECTION SVC_STACK:DATA:NOROOT(3)
        SECTION ABT_STACK:DATA:NOROOT(3)
        SECTION UND_STACK:DATA:NOROOT(3)
        SECTION HEAP:DATA:NOROOT(3)
/************************************************************************/
/* 6  Exception Vector table                                            */
/************************************************************************/

/* The exception vector table is provided by BootROM                    */
/* (see hardware manual).                                               */

/************************************************************************/
/* 7  Start-up Code                                                     */
/************************************************************************/

        SECTION .BOOTSTART:CODE:ROOT(2)
        ARM
_def_appl_start: /* Default application entry (in case BDR_ABV is not used) */
        LDR PC,ADDRESS_START_LABEL /* Jump to AXI start of flash */

ADDRESS_START_LABEL:
        DCD __iar_program_start

        SECTION .text:CODE:ROOT(2)
        ARM
__iar_program_start:

/************************************************************************/
/* 7.1  Initialize stacks for start-up sequence                         */
/*      (fixed stack addresses to support ECC RAM initialization)       */
/************************************************************************/

/* Clear 'A' flag of CPSR to enable Imprecise Data Aborts */
        CPSID A

/* Enter each mode in turn and set up the stack pointer */
        MRS r0, cpsr /* Original PSR value */

/* Setup fast interrupt stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_FIQ /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_BOOT_FIQ_STACK_END /* Top of FIQ stack */

/* Setup normal interrupt stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_IRQ /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_BOOT_IRQ_STACK_END /* Top of IRQ stack */

/* Setup data abort stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_ABT /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_BOOT_ABT_STACK_END /* Top of ABT stack */

/* Setup undefined instruction stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_UND /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_BOOT_UND_STACK_END /* Top of UND stack */

/* Setup supervisor stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_SVC /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_BOOT_SVC_STACK_END /* Top of SVC stack */

/* Setup system/user stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_SYS /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_BOOT_USR_STACK_END /* Top of USR stack */

/* Initialize start stack area and exception vector table to force       */
/* initial calculation of ECC bits. (Remaining RAM ECC initialization    */
/* will be done by DMA in Start_PreInit())                               */
        LDR r0, ADDRESS_BOOT_USR_STACK_END /* End of start stack area */
        MOV r12, #0 /* Begin of TCM RAM i.e. start stack area */
init_start_clearing_loop:
        SUB r0, r0, #4 /* calculate next address */
        STR r12, [r0] /* write 32-bit value to force ECC bits calculation */
        CMP r0, r12 /* check if begin of TCM RAM is reached */
        BNE init_start_clearing_loop

/************************************************************************/
/* 7.2  Call Start_PreInit                                              */
/************************************************************************/

        LDR r12, ADDRESS_START_PREINIT
        BLX r12

/************************************************************************/
/* 7.3  Setup user defined stacks                                       */
/************************************************************************/
/* Clear start stack area to ensure all memory cells are 0              */
/* allowing to skip 0-initialization by system library.                 */
        LDR r0, ADDRESS_BOOT_USR_STACK_END /* End of start stack area */
        MOV r12, #0 /* Clear value and re-used start address of TCMRAM */
clear_start_stack_loop:
        SUB r0, r0, #4 /* calculate next address in start stack */
        STR r12, [r0] /* write 32-bit value to force ECC bits calculation */
        CMP r0, r12 /* check if begin of TCM RAM is reached */
        BNE clear_start_stack_loop

/* Enter each mode in turn and set up the stack pointer */
        MRS r0, cpsr /* Original PSR value */

/* Setup fast interrupt stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_FIQ /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_FIQ_STACK_END /* End of Section */

/* Setup normal interrupt stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_IRQ /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_IRQ_STACK_END /* End of Section */

/* Setup data abort stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_ABT /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_ABT_STACK_END /* End of Section */

/* Setup undefined instruction stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_UND /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_UND_STACK_END /* End of Section */

/* Setup supervisor stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_SVC /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_SVC_STACK_END /* End of Section */

/* Setup system/user stack */
        BIC r0 ,r0, #MODE_MSK /* Clear the mode bits */
        ORR r0 ,r0, #MODE_SYS /* Set specific mode bits */
        MSR cpsr_c, r0 /* Change the mode */
        LDR sp, ADDRESS_USR_STACK_END /* End of Section */

/************************************************************************/
/* 7.4  Call system library                                             */
/************************************************************************/
        LDR r12, ADDRESS_SYSTEM_LIBRARY
        BX r12

/************************************************************************/
/* 7.5  End loop                                                        */
/************************************************************************/

/* Note: Control flow does not necessarily return here. */
/* On some tool-chains (e.g. IAR) control flow will never return from */
/* the system library. */
end:
        B end

/************************************************************************/
/* 7.6  Literal pool                                                    */
/************************************************************************/
ADDRESS_START_PREINIT:
        DCD Start_PreInit
ADDRESS_SYSTEM_LIBRARY:
        DCD __cmain

ADDRESS_BOOT_USR_STACK_END:
        DCD (ADDRESS_TCRAM_START + STARTUP_STACK_SIZE_BYTE)
ADDRESS_BOOT_FIQ_STACK_END:
        DCD (ADDRESS_TCRAM_START + 40)
ADDRESS_BOOT_IRQ_STACK_END:
        DCD (ADDRESS_TCRAM_START + 32)
ADDRESS_BOOT_SVC_STACK_END:
        DCD (ADDRESS_TCRAM_START + 24)
ADDRESS_BOOT_ABT_STACK_END:
        DCD (ADDRESS_TCRAM_START + 16)
ADDRESS_BOOT_UND_STACK_END:
        DCD (ADDRESS_TCRAM_START + 8)

ADDRESS_USR_STACK_END:
        DCD SFE(USR_STACK)
ADDRESS_FIQ_STACK_END:
        DCD SFE(FIQ_STACK)
ADDRESS_IRQ_STACK_END:
        DCD SFE(IRQ_STACK)
ADDRESS_SVC_STACK_END:
        DCD SFE(SVC_STACK)
ADDRESS_ABT_STACK_END:
        DCD SFE(ABT_STACK)
ADDRESS_UND_STACK_END:
        DCD SFE(UND_STACK)

ADDRESS_HEAP:
        DCD SFB(HEAP)
ADDRESS_HEAP_END:
        DCD SFE(HEAP)

/************************************************************************/
/* 8  File end                                                          */
/************************************************************************/

        END
