;-----------------------------------------------------------------------------
; This file contains the startup code used by the ICCARM C compiler.
;
; The modules in this file are included in the libraries, and may be replaced
; by any user-defined modules that define the PUBLIC symbol _program_start or
; a user defined start symbol.
; To override the cstartup defined in the library, simply add your modified
; version to the workbench project.
;
; All code in the modules (except ?RESET) will be placed in the ICODE segment.
;
; $Revision: 1.1 $
;
;-----------------------------------------------------------------------------
	
;
; Naming covention of labels in this file:
;
;  ?xxx	  - External labels only accessed from assembler.
;  __xxx  - External labels accessed from or defined in C.
;  xxx	  - Labels local to one module (note: this file contains
;           several modules).
;  main	  - The starting point of the user program.
;

;---------------------------------------------------------------
; Macros and definitions for the whole file
;---------------------------------------------------------------


; --- Standard definitions of mode bits and interrupt (I & F) flags in PSRs



Mode_USR           DEFINE     0x10
Mode_FIQ           DEFINE     0x11
Mode_IRQ           DEFINE     0x12
Mode_SVC           DEFINE     0x13
Mode_ABT           DEFINE     0x17
Mode_UNDEF         DEFINE     0x1B
Mode_SYS           DEFINE     0x1F ; available on ARM Arch 4 and later

I_Bit              DEFINE     0x80 ; when I bit is set, IRQ is disabled
F_Bit              DEFINE     0x40 ; when F bit is set, FIQ is disabled


; --- System memory locations

RAM_Base            DEFINE    0x20000000
RAM_Limit           DEFINE    0x20010000
SRAM_Base           DEFINE    0x60000000

SVC_Stack           DEFINE     RAM_Limit         ; 512 byte SVC stack at
	                                             ; top of memory - used by kernel.
IRQ_Stack           DEFINE     SVC_Stack-512     ; followed by IRQ stack
USR_Stack           DEFINE     IRQ_Stack-512   	 ; followed by USR stack.  Tasks run in
                                                 ; system mode but task stacks are allocated
                                                 ; when the task is created.
FIQ_Stack           DEFINE     USR_Stack-8       ; followed by FIQ stack
ABT_Stack           DEFINE     FIQ_Stack-8       ; followed by ABT stack
UNDEF_Stack         DEFINE     ABT_Stack-8       ; followed by UNDEF stack

EIC_Base_addr       DEFINE    0xFFFFF800         ; EIC base address
ICR_off_addr        DEFINE    0x00               ; Interrupt Control register offset
CIPR_off_addr       DEFINE    0x08               ; Current Interrupt Priority Register offset
IVR_off_addr        DEFINE    0x18               ; Interrupt Vector Register offset
FIR_off_addr        DEFINE    0x1C               ; Fast Interrupt Register offset
IER_off_addr        DEFINE    0x20               ; Interrupt Enable Register offset
IPR_off_addr        DEFINE    0x40               ; Interrupt Pending Bit Register offset
SIR0_off_addr       DEFINE    0x60               ; Source Interrupt Register 0

EMI_Base_addr       DEFINE    0x6C000000         ; EMI base address
BCON0_off_addr      DEFINE    0x00               ; Bank 0 configuration register offset
BCON1_off_addr      DEFINE    0x04               ; Bank 1 configuration register offset
BCON2_off_addr      DEFINE    0x08               ; Bank 2 configuration register offset
BCON3_off_addr      DEFINE    0x0C               ; Bank 3 configuration register offset

GPIO2_Base_addr     DEFINE    0xE0005000         ; GPIO2 base address
PC0_off_addr        DEFINE    0x00               ; Port Configuration Register 0 offset
PC1_off_addr        DEFINE    0x04               ; Port Configuration Register 1 offset
PC2_off_addr        DEFINE    0x08               ; Port Configuration Register 2 offset
PD_off_addr         DEFINE    0x0C               ; Port Data Register offset

CPM_Base_addr       DEFINE    0xA0000040         ; CPM Base Address
BOOTCONF_off_addr   DEFINE    0x10               ; CPM - Boot Configuration Register
FLASH_mask          DEFINE    0x0000             ; to remap FLASH at 0x0
RAM_mask            DEFINE    0x0002             ; to remap RAM at 0x0
EXTMEM_mask         DEFINE    0x0003             ; to remap EXTMEM at 0x0

;---------------------------------------------------------------
; ?RESET
; Reset Vector.
; Normally, segment INTVEC is linked at address 0.
; For debugging purposes, INTVEC may be placed at other
; addresses.
; A debugger that honors the entry point will start the
; program in a normal way even if INTVEC is not at address 0.
;---------------------------------------------------------------

		MODULE	?RESET
		COMMON	INTVEC:CODE:NOROOT(2)
		PUBLIC  __program_start
		EXTERN	?cstartup		
		CODE32	; Always ARM mode after reset	
		
__program_start
		ldr	pc,=?cstartup  ; Absolute jump can reach 4 GByte
		b	?cstartup    ; Relative branch allows remap, limited to 32 MByte
		
		LTORG
                ENDMOD


;---------------------------------------------------------------
; ?CSTARTUP
;---------------------------------------------------------------
		MODULE	?CSTARTUP

;		RSEG	IRQ_STACK:DATA(2)
;		RSEG	SVC_STACK:DATA:NOROOT(2)
;		RSEG	CSTACK:DATA(2)
		RSEG	ICODE:CODE:NOROOT(2)
		PUBLIC	?cstartup
		EXTERN	?main




		CODE32
?cstartup


                NOP		; Wait for OSC stabilization
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		NOP
		

	/* Setup a stack for each mode - note that this only sets up a usable stack
	for system/user, SWI and IRQ modes.   Also each mode is setup with
	interrupts initially disabled. */
    msr   CPSR_c, #Mode_UNDEF|I_Bit|F_Bit /* Undefined Instruction Mode */
    LDR     SP, =UNDEF_Stack

	msr   CPSR_c, #Mode_ABT|I_Bit|F_Bit /* Abort Mode */
    LDR     SP, =ABT_Stack

	msr   CPSR_c, #Mode_FIQ|I_Bit|F_Bit /* FIQ Mode */
    LDR     SP, =FIQ_Stack

    msr   CPSR_c, #Mode_IRQ|I_Bit|F_Bit /* IRQ Mode */
    LDR     SP, =IRQ_Stack

	msr   CPSR_c, #Mode_SVC|I_Bit|F_Bit /* Supervisor Mode */
    LDR     SP, =SVC_Stack

    msr   CPSR_c, #Mode_SYS|I_Bit|F_Bit /* System Mode */
    LDR     SP, =USR_Stack

	/* We want to start in supervisor mode.  Operation will switch to system
	mode when the first task starts. */
	msr   CPSR_c, #Mode_SVC|I_Bit|F_Bit


         IMPORT  T0TIMI_Addr

EIC_INIT
        LDR     r3, =EIC_Base_addr
        LDR     r4, =0x00000000
        STR     r4, [r3, #ICR_off_addr]   ; Disable FIQ and IRQ
        STR     r4, [r3, #IER_off_addr]   ; Disable all channels interrupts
        LDR     r4, =0xFFFFFFFF
        STR     r4, [r3, #IPR_off_addr]   ; Clear all IRQ pending bits
        LDR     r4, =0x0C
        STR     r4, [r3, #FIR_off_addr]   ; Disable FIQ channels and clear FIQ pending bits
        LDR     r4, =0x00000000
        STR     r4, [r3, #CIPR_off_addr]  ; Reset the current priority register
        LDR     r4, =0xE59F0000
        STR     r4, [r3, #IVR_off_addr]   ; Write the LDR pc,pc,#offset instruction code in IVR[31:16]
        LDR     r2, =32                   ; 32 Channel to initialize
        LDR     r0, =T0TIMI_Addr          ; Read the address of the IRQs address table
        LDR     r1, =0x00000FFF
        AND     r0,r0,r1
        LDR     r5, =SIR0_off_addr        ; Read SIR0 address
        SUB     r4,r0,#8                  ; subtract 8 for prefetch
        LDR     r1, =0xF7E8               ; add the offset to the 0x00000000 address(IVR address + 7E8 = 0x00000000)
                                          ; 0xF7E8 used to complete the LDR pc,pc,#offset opcode
        ADD     r1,r4,r1                  ; compute the jump offset
EIC_INI MOV     r4, r1, LSL #16           ; Left shift the result
        STR     r4, [r3, r5]              ; Store the result in SIRx register
        ADD     r1, r1, #4                ; Next IRQ address
        ADD     r5, r5, #4                ; Next SIR
        SUBS    r2, r2, #1                ; Decrement the number of SIR registers to initialize
        BNE     EIC_INI                   ; If more then continue


        ldr     r0,=?main
        bx      r0

        LTORG

        ENDMOD


        END


