;----------------------------------------------------------------------------- ; 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