diff options
Diffstat (limited to 'libcpu')
| -rw-r--r-- | libcpu/arm/cortex-r4/context_gcc.S | 255 | ||||
| -rw-r--r-- | libcpu/arm/cortex-r4/start_ccs.asm | 515 | ||||
| -rw-r--r-- | libcpu/arm/cortex-r4/start_gcc.S | 452 | ||||
| -rw-r--r-- | libcpu/arm/cortex-r4/vector_ccs.asm | 36 | ||||
| -rw-r--r-- | libcpu/arm/cortex-r4/vector_gcc.S | 31 |
5 files changed, 1289 insertions, 0 deletions
diff --git a/libcpu/arm/cortex-r4/context_gcc.S b/libcpu/arm/cortex-r4/context_gcc.S new file mode 100644 index 0000000000..5256645ab8 --- /dev/null +++ b/libcpu/arm/cortex-r4/context_gcc.S @@ -0,0 +1,255 @@ +/* + * File : context_ccs.asm + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2009-01-20 Bernard first version + * 2011-07-22 Bernard added thumb mode porting + * 2013-05-24 Grissiom port to CCS + * 2013-05-26 Grissiom optimize for ARMv7 + * 2013-10-20 Grissiom port to GCC + */ + +#include <rtconfig.h> + + .text + .arm + .globl rt_thread_switch_interrupt_flag + .globl rt_interrupt_from_thread + .globl rt_interrupt_to_thread + .globl rt_interrupt_enter + .globl rt_interrupt_leave + .globl rt_hw_trap_irq + +/* + * rt_base_t rt_hw_interrupt_disable() + */ + .globl rt_hw_interrupt_disable +rt_hw_interrupt_disable: + MRS r0, cpsr + CPSID IF + BX lr + +/* + * void rt_hw_interrupt_enable(rt_base_t level) + */ + .globl rt_hw_interrupt_enable +rt_hw_interrupt_enable: + MSR cpsr_c, r0 + BX lr + +/* + * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to) + * r0 --> from + * r1 --> to + */ + .globl rt_hw_context_switch +rt_hw_context_switch: + STMDB sp!, {lr} @ push pc (lr should be pushed in place of PC) + STMDB sp!, {r0-r12, lr} @ push lr & register file + + MRS r4, cpsr + TST lr, #0x01 + ORRNE r4, r4, #0x20 @ it's thumb code + + STMDB sp!, {r4} @ push cpsr + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) + VMRS r4, fpexc + TST r4, #0x40000000 + BEQ __no_vfp_frame1 + VSTMDB sp!, {d0-d15} + VMRS r5, fpscr + @ TODO: add support for Common VFPv3. + @ Save registers like FPINST, FPINST2 + STMDB sp!, {r5} +__no_vfp_frame1: + STMDB sp!, {r4} +#endif + + STR sp, [r0] @ store sp in preempted tasks TCB + LDR sp, [r1] @ get new task stack pointer + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) + LDMIA sp!, {r0} @ get fpexc + VMSR fpexc, r0 @ restore fpexc + TST r0, #0x40000000 + BEQ __no_vfp_frame2 + LDMIA sp!, {r1} @ get fpscr + VMSR fpscr, r1 + VLDMIA sp!, {d0-d15} +__no_vfp_frame2: + #endif + + LDMIA sp!, {r4} @ pop new task cpsr to spsr + MSR spsr_cxsf, r4 + + LDMIA sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr + +/* + * void rt_hw_context_switch_to(rt_uint32 to) + * r0 --> to + */ + .globl rt_hw_context_switch_to +rt_hw_context_switch_to: + LDR sp, [r0] @ get new task stack pointer + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) + LDMIA sp!, {r0} @ get fpexc + VMSR fpexc, r0 + TST r0, #0x40000000 + BEQ __no_vfp_frame_to + LDMIA sp!, {r1} @ get fpscr + VMSR fpscr, r1 + VLDMIA sp!, {d0-d15} +__no_vfp_frame_to: +#endif + + LDMIA sp!, {r4} @ pop new task cpsr to spsr + MSR spsr_cxsf, r4 + + LDMIA sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr + +/* + * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)@ + */ + + .globl rt_hw_context_switch_interrupt +rt_hw_context_switch_interrupt: + LDR r2, =rt_thread_switch_interrupt_flag + LDR r3, [r2] + CMP r3, #1 + BEQ _reswitch + MOV r3, #1 @ set rt_thread_switch_interrupt_flag to 1 + STR r3, [r2] + LDR r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread + + STR r0, [r2] +_reswitch: + LDR r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread + STR r1, [r2] + BX lr + + .globl IRQ_Handler +IRQ_Handler: + STMDB sp!, {r0-r12,lr} + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) + VMRS r0, fpexc + TST r0, #0x40000000 + BEQ __no_vfp_frame_str_irq + VSTMDB sp!, {d0-d15} + VMRS r1, fpscr + @ TODO: add support for Common VFPv3. + @ Save registers like FPINST, FPINST2 + STMDB sp!, {r1} +__no_vfp_frame_str_irq: + STMDB sp!, {r0} +#endif + + BL rt_interrupt_enter + BL rt_hw_trap_irq + BL rt_interrupt_leave + + @ if rt_thread_switch_interrupt_flag set, jump to + @ rt_hw_context_switch_interrupt_do and don't return + LDR r0, =rt_thread_switch_interrupt_flag + LDR r1, [r0] + CMP r1, #1 + BEQ rt_hw_context_switch_interrupt_do + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) + LDMIA sp!, {r0} @ get fpexc + VMSR fpexc, r0 + TST r0, #0x40000000 + BEQ __no_vfp_frame_ldr_irq + LDMIA sp!, {r1} @ get fpscr + VMSR fpscr, r1 + VLDMIA sp!, {d0-d15} +__no_vfp_frame_ldr_irq: +#endif + + LDMIA sp!, {r0-r12,lr} + SUBS pc, lr, #4 + +/* + * void rt_hw_context_switch_interrupt_do(rt_base_t flag) + */ + .globl rt_hw_context_switch_interrupt_do +rt_hw_context_switch_interrupt_do: + MOV r1, #0 @ clear flag + STR r1, [r0] + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) + LDMIA sp!, {r0} @ get fpexc + VMSR fpexc, r0 + TST r0, #0x40000000 + BEQ __no_vfp_frame_do1 + LDMIA sp!, {r1} @ get fpscr + VMSR fpscr, r1 + VLDMIA sp!, {d0-d15} +__no_vfp_frame_do1: +#endif + + LDMIA sp!, {r0-r12,lr} @ reload saved registers + STMDB sp, {r0-r3} @ save r0-r3. We will restore r0-r3 in the SVC + @ mode so there is no need to update SP. + SUB r1, sp, #16 @ save the right SP value in r1, so we could restore r0-r3. + SUB r2, lr, #4 @ save old task's pc to r2 + + MRS r3, spsr @ get cpsr of interrupt thread + + @ switch to SVC mode and no interrupt + CPSID IF, #0x13 + + STMDB sp!, {r2} @ push old task's pc + STMDB sp!, {r4-r12,lr} @ push old task's lr,r12-r4 + LDMIA r1!, {r4-r7} @ restore r0-r3 of the interrupted thread + STMDB sp!, {r4-r7} @ push old task's r3-r0. We don't need to push/pop them to + @ r0-r3 because we just want to transfer the data and don't + @ use them here. + STMDB sp!, {r3} @ push old task's cpsr + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) + VMRS r0, fpexc + TST r0, #0x40000000 + BEQ __no_vfp_frame_do2 + VSTMDB sp!, {d0-d15} + VMRS r1, fpscr + @ TODO: add support for Common VFPv3. + @ Save registers like FPINST, FPINST2 + STMDB sp!, {r1} +__no_vfp_frame_do2: + STMDB sp!, {r0} +#endif + + LDR r4, =rt_interrupt_from_thread + LDR r5, [r4] + STR sp, [r5] @ store sp in preempted tasks's TCB + + LDR r6, =rt_interrupt_to_thread + LDR r6, [r6] + LDR sp, [r6] @ get new task's stack pointer + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) + LDMIA sp!, {r0} @ get fpexc + VMSR fpexc, r0 + TST r0, #0x40000000 + BEQ __no_vfp_frame_do3 + LDMIA sp!, {r1} @ get fpscr + VMSR fpscr, r1 + VLDMIA sp!, {d0-d15} +__no_vfp_frame_do3: +#endif + + LDMIA sp!, {r4} @ pop new task's cpsr to spsr + MSR spsr_cxsf, r4 + + LDMIA sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr + diff --git a/libcpu/arm/cortex-r4/start_ccs.asm b/libcpu/arm/cortex-r4/start_ccs.asm new file mode 100644 index 0000000000..186d4f28ab --- /dev/null +++ b/libcpu/arm/cortex-r4/start_ccs.asm @@ -0,0 +1,515 @@ +;------------------------------------------------------------------------------- +; sys_core.asm +; +; (c) Texas Instruments 2009-2013, All rights reserved. +; + + .text + .arm + + .ref _c_int00 + + .def _reset + .asmfunc +_reset +;------------------------------------------------------------------------------- +; Initialize CPU Registers +; After reset, the CPU is in the Supervisor mode (M = 10011) + mov r0, lr + mov r1, #0x0000 + mov r2, #0x0000 + mov r3, #0x0000 + mov r4, #0x0000 + mov r5, #0x0000 + mov r6, #0x0000 + mov r7, #0x0000 + mov r8, #0x0000 + mov r9, #0x0000 + mov r10, #0x0000 + mov r11, #0x0000 + mov r12, #0x0000 + mov r13, #0x0000 + mrs r1, cpsr + msr spsr_cxsf, r1 + ; Switch to FIQ mode (M = 10001) + cps #17 + mov lr, r0 + mov r8, #0x0000 + mov r9, #0x0000 + mov r10, #0x0000 + mov r11, #0x0000 + mov r12, #0x0000 + mrs r1, cpsr + msr spsr_cxsf, r1 + ; Switch to IRQ mode (M = 10010) + cps #18 + mov lr, r0 + mrs r1,cpsr + msr spsr_cxsf, r1 + ; Switch to Abort mode (M = 10111) + cps #23 + mov lr, r0 + mrs r1,cpsr + msr spsr_cxsf, r1 + ; Switch to Undefined Instruction Mode (M = 11011) + cps #27 + mov lr, r0 + mrs r1,cpsr + msr spsr_cxsf, r1 + ; Switch to System Mode ( Shares User Mode registers ) (M = 11111) + cps #31 + mov lr, r0 + mrs r1,cpsr + msr spsr_cxsf, r1 + ; Switch back to Supervisor Mode (M = 10011) + cps #19 + + ; Turn on FPV coprocessor + mrc p15, #0x00, r2, c1, c0, #0x02 + orr r2, r2, #0xF00000 + mcr p15, #0x00, r2, c1, c0, #0x02 + + .if (RT_VFP_LAZY_STACKING) = 0 + fmrx r2, fpexc + orr r2, r2, #0x40000000 + fmxr fpexc, r2 + + fmdrr d0, r1, r1 + fmdrr d1, r1, r1 + fmdrr d2, r1, r1 + fmdrr d3, r1, r1 + fmdrr d4, r1, r1 + fmdrr d5, r1, r1 + fmdrr d6, r1, r1 + fmdrr d7, r1, r1 + fmdrr d8, r1, r1 + fmdrr d9, r1, r1 + fmdrr d10, r1, r1 + fmdrr d11, r1, r1 + fmdrr d12, r1, r1 + fmdrr d13, r1, r1 + fmdrr d14, r1, r1 + fmdrr d15, r1, r1 + .endif + +;------------------------------------------------------------------------------- +; Initialize Stack Pointers + cps #17 + ldr sp, fiqSp + cps #18 + ldr sp, irqSp + cps #23 + ldr sp, abortSp + cps #27 + ldr sp, undefSp + cps #31 + ldr sp, userSp + cps #19 + ldr sp, svcSp + + bl next1 +next1 + bl next2 +next2 + bl next3 +next3 + bl next4 +next4 + ldr lr, int00ad + bx lr + +int00ad .word _c_int00 +userSp .word 0x08000000+0x00001000 +svcSp .word 0x08000000+0x00001000+0x00000100 +fiqSp .word 0x08000000+0x00001000+0x00000100+0x00000100 +irqSp .word 0x08000000+0x00001000+0x00000100+0x00000100+0x00000100 +abortSp .word 0x08000000+0x00001000+0x00000100+0x00000100+0x00000100+0x00000100 +undefSp .word 0x08000000+0x00001000+0x00000100+0x00000100+0x00000100+0x00000100+0x00000100 + + .endasmfunc + +;------------------------------------------------------------------------------- +; Enable RAM ECC Support + + .def _coreEnableRamEcc_ + .asmfunc + +_coreEnableRamEcc_ + + stmfd sp!, {r0} + mrc p15, #0x00, r0, c1, c0, #0x01 + orr r0, r0, #0x0C000000 + mcr p15, #0x00, r0, c1, c0, #0x01 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Disable RAM ECC Support + + .def _coreDisableRamEcc_ + .asmfunc + +_coreDisableRamEcc_ + + stmfd sp!, {r0} + mrc p15, #0x00, r0, c1, c0, #0x01 + bic r0, r0, #0x0C000000 + mcr p15, #0x00, r0, c1, c0, #0x01 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Enable Flash ECC Support + + .def _coreEnableFlashEcc_ + .asmfunc + +_coreEnableFlashEcc_ + + stmfd sp!, {r0} + mrc p15, #0x00, r0, c1, c0, #0x01 + orr r0, r0, #0x02000000 + dmb + mcr p15, #0x00, r0, c1, c0, #0x01 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Disable Flash ECC Support + + .def _coreDisableFlashEcc_ + .asmfunc + +_coreDisableFlashEcc_ + + stmfd sp!, {r0} + mrc p15, #0x00, r0, c1, c0, #0x01 + bic r0, r0, #0x02000000 + mcr p15, #0x00, r0, c1, c0, #0x01 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + +;------------------------------------------------------------------------------- +; Get data fault status register + + .def _coreGetDataFault_ + .asmfunc + +_coreGetDataFault_ + + mrc p15, #0, r0, c5, c0, #0 + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Clear data fault status register + + .def _coreClearDataFault_ + .asmfunc + +_coreClearDataFault_ + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c5, c0, #0 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Get instruction fault status register + + .def _coreGetInstructionFault_ + .asmfunc + +_coreGetInstructionFault_ + + mrc p15, #0, r0, c5, c0, #1 + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Clear instruction fault status register + + .def _coreClearInstructionFault_ + .asmfunc + +_coreClearInstructionFault_ + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c5, c0, #1 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Get data fault address register + + .def _coreGetDataFaultAddress_ + .asmfunc + +_coreGetDataFaultAddress_ + + mrc p15, #0, r0, c6, c0, #0 + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Clear data fault address register + + .def _coreClearDataFaultAddress_ + .asmfunc + +_coreClearDataFaultAddress_ + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c6, c0, #0 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Get instruction fault address register + + .def _coreGetInstructionFaultAddress_ + .asmfunc + +_coreGetInstructionFaultAddress_ + + mrc p15, #0, r0, c6, c0, #2 + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Clear instruction fault address register + + .def _coreClearInstructionFaultAddress_ + .asmfunc + +_coreClearInstructionFaultAddress_ + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c6, c0, #2 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Get auxiliary data fault status register + + .def _coreGetAuxiliaryDataFault_ + .asmfunc + +_coreGetAuxiliaryDataFault_ + + mrc p15, #0, r0, c5, c1, #0 + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Clear auxiliary data fault status register + + .def _coreClearAuxiliaryDataFault_ + .asmfunc + +_coreClearAuxiliaryDataFault_ + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c5, c1, #0 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + + +;------------------------------------------------------------------------------- +; Get auxiliary instruction fault status register + + .def _coreGetAuxiliaryInstructionFault_ + .asmfunc + +_coreGetAuxiliaryInstructionFault_ + + mrc p15, #0, r0, c5, c1, #1 + bx lr + + .endasmfunc + +;------------------------------------------------------------------------------- +; Clear auxiliary instruction fault status register + + .def _coreClearAuxiliaryInstructionFault_ + .asmfunc + +_coreClearAuxiliaryInstructionFault_ + + stmfd sp!, {r0} + mov r0, #0 + mrc p15, #0, r0, c5, c1, #1 + ldmfd sp!, {r0} + bx lr + + .endasmfunc + +;------------------------------------------------------------------------------- +; Clear ESM CCM errorss + + .def _esmCcmErrorsClear_ + .asmfunc + +_esmCcmErrorsClear_ + + stmfd sp!, {r0-r2} + ldr r0, ESMSR1_REG ; load the ESMSR1 status register address + ldr r2, ESMSR1_ERR_CLR + str r2, [r0] ; clear the ESMSR1 register + + ldr r0, ESMSR2_REG ; load the ESMSR2 status register address + ldr r2, ESMSR2_ERR_CLR + str r2, [r0] ; clear the ESMSR2 register + + ldr r0, ESMSSR2_REG ; load the ESMSSR2 status register address + ldr r2, ESMSSR2_ERR_CLR + str r2, [r0] ; clear the ESMSSR2 register + + ldr r0, ESMKEY_REG ; load the ESMKEY register address + mov r2, #0x5 ; load R2 with 0x5 + str r2, [r0] ; clear the ESMKEY register + + ldr r0, VIM_INTREQ ; load the INTREQ register address + ldr r2, VIM_INT_CLR + str r2, [r0] ; clear the INTREQ register + ldr r0, CCMR4_STAT_REG ; load the CCMR4 status register address + ldr r2, CCMR4_ERR_CLR + str r2, [r0] ; clear the CCMR4 status register + ldmfd sp!, {r0-r2} + bx lr + +ESMSR1_REG .word 0xFFFFF518 +ESMSR2_REG .word 0xFFFFF51C +ESMSR3_REG .word 0xFFFFF520 +ESMKEY_REG .word 0xFFFFF538 +ESMSSR2_REG .word 0xFFFFF53C +CCMR4_STAT_REG .word 0xFFFFF600 +ERR_CLR_WRD .word 0xFFFFFFFF +CCMR4_ERR_CLR .word 0x00010000 +ESMSR1_ERR_CLR .word 0x80000000 +ESMSR2_ERR_CLR .word 0x00000004 +ESMSSR2_ERR_CLR .word 0x00000004 +VIM_INT_CLR .word 0x00000001 +VIM_INTREQ .word 0xFFFFFE20 + + .endasmfunc + +;------------------------------------------------------------------------------- +; Work Around for Errata CORTEX-R4#57: +; +; Errata Description: +; Conditional VMRS APSR_Nzcv, FPSCR May Evaluate With Incorrect Flags +; Workaround: +; Disable out-of-order single-precision floating point +; multiply-accumulate instruction completion + + .def _errata_CORTEXR4_57_ + .asmfunc + +_errata_CORTEXR4_57_ + + push {r0} + mrc p15, #0, r0, c15, c0, #0 ; Read Secondary Auxiliary Control Register + orr r0, r0, #0x10000 ; Set BIT 16 (Set DOOFMACS) + mcr p15, #0, r0, c15, c0, #0 ; Write Secondary Auxiliary Control Register + pop {r0} + bx lr + .endasmfunc + +;------------------------------------------------------------------------------- +; Work Around for Errata CORTEX-R4#66: +; +; Errata Description: +; Register Corruption During A Load-Multiple Instruction At +; an Exception Vector +; Workaround: +; Disable out-of-order completion for divide instructions in +; Auxiliary Control register + + .def _errata_CORTEXR4_66_ + .asmfunc + +_errata_CORTEXR4_66_ + + push {r0} + mrc p15, #0, r0, c1, c0, #1 ; Read Auxiliary Control register + orr r0, r0, #0x80 ; Set BIT 7 (Disable out-of-order completion + ; for divide instructions.) + mcr p15, #0, r0, c1, c0, #1 ; Write Auxiliary Control register + pop {r0} + bx lr + .endasmfunc + + .def turnon_VFP + .asmfunc +turnon_VFP + ; Enable FPV + STMDB sp!, {r0} + fmrx r0, fpexc + orr r0, r0, #0x40000000 + fmxr fpexc, r0 + LDMIA sp!, {r0} + subs pc, lr, #4 + .endasmfunc + + .def _dabort + .asmfunc + +_dabort + stmfd r13!, {r0 - r12, lr} + ldmfd r13!, {r0 - r12, lr} + subs pc, lr, #8 + .endasmfunc +;------------------------------------------------------------------------------- +; C++ construct table pointers + + .def __TI_PINIT_Base, __TI_PINIT_Limit + .weak SHT$$INIT_ARRAY$$Base, SHT$$INIT_ARRAY$$Limit + +__TI_PINIT_Base .long SHT$$INIT_ARRAY$$Base +__TI_PINIT_Limit .long SHT$$INIT_ARRAY$$Limit + + + +;------------------------------------------------------------------------------- + diff --git a/libcpu/arm/cortex-r4/start_gcc.S b/libcpu/arm/cortex-r4/start_gcc.S new file mode 100644 index 0000000000..00d459dd34 --- /dev/null +++ b/libcpu/arm/cortex-r4/start_gcc.S @@ -0,0 +1,452 @@ +@------------------------------------------------------------------------------- +@ sys_core.asm +@ +@ (c) Texas Instruments 2009-2013, All rights reserved. +@ + +#include <rtconfig.h> + +.equ Mode_USR, 0x10 +.equ Mode_FIQ, 0x11 +.equ Mode_IRQ, 0x12 +.equ Mode_SVC, 0x13 +.equ Mode_ABT, 0x17 +.equ Mode_UND, 0x1B +.equ Mode_SYS, 0x1F + +.equ I_Bit, 0x80 @ when I bit is set, IRQ is disabled +.equ F_Bit, 0x40 @ when F bit is set, FIQ is disabled + +.equ UND_Stack_Size, 0x00000000 +.equ SVC_Stack_Size, 0x00000100 +.equ ABT_Stack_Size, 0x00000000 +.equ FIQ_Stack_Size, 0x00000000 +.equ IRQ_Stack_Size, 0x00000100 +.equ USR_Stack_Size, 0x00000100 + +.section .bss.noinit +/* stack */ +.globl stack_start +.globl stack_top + +stack_start: +.rept (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + FIQ_Stack_Size + IRQ_Stack_Size) +.long 0 +.endr +stack_top: + +.section .text, "ax" + .text + .arm + + .globl _c_int00 + +.globl _reset +_reset: +@------------------------------------------------------------------------------- +@ Initialize CPU Registers +@ After reset, the CPU is in the Supervisor mode (M = 10011) + cpsid if, #19 + +#if defined (__VFP_FP__) && !defined(__SOFTFP__) && defined(RT_VFP_LAZY_STACKING) + @ Turn on FPV coprocessor + mrc p15, #0x00, r2, c1, c0, #0x02 + orr r2, r2, #0xF00000 + mcr p15, #0x00, r2, c1, c0, #0x02 + + fmrx r2, fpexc + orr r2, r2, #0x40000000 + fmxr fpexc, r2 +#endif + +@------------------------------------------------------------------------------- +@ Initialize Stack Pointers + ldr r0, =stack_top + + @ Enter Undefined Instruction Mode and set its Stack Pointer + msr cpsr_c, #Mode_UND|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #UND_Stack_Size + + @ Enter Abort Mode and set its Stack Pointer + msr cpsr_c, #Mode_ABT|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #ABT_Stack_Size + + @ Enter FIQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_FIQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #FIQ_Stack_Size + + @ Enter IRQ Mode and set its Stack Pointer + msr cpsr_c, #Mode_IRQ|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #IRQ_Stack_Size + + @ Enter Supervisor Mode and set its Stack Pointer + msr cpsr_c, #Mode_SVC|I_Bit|F_Bit + mov sp, r0 + sub r0, r0, #SVC_Stack_Size + + @ Enter User Mode and set its Stack Pointer + mov sp, r0 + sub sl, sp, #USR_Stack_Size + + bl next1 +next1: + bl next2 +next2: + bl next3 +next3: + bl next4 +next4: + ldr lr, =_c_int00 + bx lr + +.globl data_init +data_init: + /* copy .data to SRAM */ + ldr r1, =_sidata /* .data start in image */ + ldr r2, =_edata /* .data end in image */ + ldr r3, =_sdata /* sram data start */ +data_loop: + ldr r0, [r1, #0] + str r0, [r3] + + add r1, r1, #4 + add r3, r3, #4 + + cmp r3, r2 /* check if data to clear */ + blo data_loop /* loop until done */ + + /* clear .bss */ + mov r0,#0 /* get a zero */ + ldr r1,=__bss_start /* bss start */ + ldr r2,=__bss_end /* bss end */ + +bss_loop: + cmp r1,r2 /* check if data to clear */ + strlo r0,[r1],#4 /* clear 4 bytes */ + blo bss_loop /* loop until done */ + + /* call C++ constructors of global objects */ + ldr r0, =__ctors_start__ + ldr r1, =__ctors_end__ + +ctor_loop: + cmp r0, r1 + beq ctor_end + ldr r2, [r0], #4 + stmfd sp!, {r0-r3, ip, lr} + mov lr, pc + bx r2 + ldmfd sp!, {r0-r3, ip, lr} + b ctor_loop +ctor_end: + bx lr + +@------------------------------------------------------------------------------- +@ Enable RAM ECC Support + + .globl _coreEnableRamEcc_ +_coreEnableRamEcc_: + + stmfd sp!, {r0} + mrc p15, #0x00, r0, c1, c0, #0x01 + orr r0, r0, #0x0C000000 + mcr p15, #0x00, r0, c1, c0, #0x01 + ldmfd sp!, {r0} + bx lr + +@------------------------------------------------------------------------------- +@ Disable RAM ECC Support + + .globl _coreDisableRamEcc_ +_coreDisableRamEcc_: + + stmfd sp!, {r0} + mrc p15, #0x00, r0, c1, c0, #0x01 + bic r0, r0, #0x0C000000 + mcr p15, #0x00, r0, c1, c0, #0x01 + ldmfd sp!, {r0} + bx lr + + +@------------------------------------------------------------------------------- +@ Enable Flash ECC Support + + .globl _coreEnableFlashEcc_ +_coreEnableFlashEcc_: + + stmfd sp!, {r0} + mrc p15, #0x00, r0, c1, c0, #0x01 + orr r0, r0, #0x02000000 + dmb + mcr p15, #0x00, r0, c1, c0, #0x01 + ldmfd sp!, {r0} + bx lr + +@------------------------------------------------------------------------------- +@ Disable Flash ECC Support + + .globl _coreDisableFlashEcc_ +_coreDisableFlashEcc_: + + stmfd sp!, {r0} + mrc p15, #0x00, r0, c1, c0, #0x01 + bic r0, r0, #0x02000000 + mcr p15, #0x00, r0, c1, c0, #0x01 + ldmfd sp!, {r0} + bx lr + + +@------------------------------------------------------------------------------- +@ Get data fault status register + + .globl _coreGetDataFault_ +_coreGetDataFault_: + + mrc p15, #0, r0, c5, c0, #0 + bx lr + + + +@------------------------------------------------------------------------------- +@ Clear data fault status register + + .globl _coreClearDataFault_ +_coreClearDataFault_: + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c5, c0, #0 + ldmfd sp!, {r0} + bx lr + + + +@------------------------------------------------------------------------------- +@ Get instruction fault status register + + .globl _coreGetInstructionFault_ +_coreGetInstructionFault_: + + mrc p15, #0, r0, c5, c0, #1 + bx lr + + + +@------------------------------------------------------------------------------- +@ Clear instruction fault status register + + .globl _coreClearInstructionFault_ +_coreClearInstructionFault_: + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c5, c0, #1 + ldmfd sp!, {r0} + bx lr + + + +@------------------------------------------------------------------------------- +@ Get data fault address register + + .globl _coreGetDataFaultAddress_ +_coreGetDataFaultAddress_: + + mrc p15, #0, r0, c6, c0, #0 + bx lr + + + +@------------------------------------------------------------------------------- +@ Clear data fault address register + + .globl _coreClearDataFaultAddress_ +_coreClearDataFaultAddress_: + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c6, c0, #0 + ldmfd sp!, {r0} + bx lr + + + +@------------------------------------------------------------------------------- +@ Get instruction fault address register + + .globl _coreGetInstructionFaultAddress_ +_coreGetInstructionFaultAddress_: + + mrc p15, #0, r0, c6, c0, #2 + bx lr + + + +@------------------------------------------------------------------------------- +@ Clear instruction fault address register + + .globl _coreClearInstructionFaultAddress_ +_coreClearInstructionFaultAddress_: + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c6, c0, #2 + ldmfd sp!, {r0} + bx lr + + + +@------------------------------------------------------------------------------- +@ Get auxiliary data fault status register + + .globl _coreGetAuxiliaryDataFault_ +_coreGetAuxiliaryDataFault_: + + mrc p15, #0, r0, c5, c1, #0 + bx lr + + + +@------------------------------------------------------------------------------- +@ Clear auxiliary data fault status register + + .globl _coreClearAuxiliaryDataFault_ +_coreClearAuxiliaryDataFault_: + + stmfd sp!, {r0} + mov r0, #0 + mcr p15, #0, r0, c5, c1, #0 + ldmfd sp!, {r0} + bx lr + + + +@------------------------------------------------------------------------------- +@ Get auxiliary instruction fault status register + + .globl _coreGetAuxiliaryInstructionFault_ +_coreGetAuxiliaryInstructionFault_: + + mrc p15, #0, r0, c5, c1, #1 + bx lr + + +@------------------------------------------------------------------------------- +@ Clear auxiliary instruction fault status register + + .globl _coreClearAuxiliaryInstructionFault_ +_coreClearAuxiliaryInstructionFault_: + + stmfd sp!, {r0} + mov r0, #0 + mrc p15, #0, r0, c5, c1, #1 + ldmfd sp!, {r0} + bx lr + + +@------------------------------------------------------------------------------- +@ Clear ESM CCM errorss + + .globl _esmCcmErrorsClear_ +_esmCcmErrorsClear_: + + stmfd sp!, {r0-r2} + ldr r0, ESMSR1_REG @ load the ESMSR1 status register address + ldr r2, ESMSR1_ERR_CLR + str r2, [r0] @ clear the ESMSR1 register + + ldr r0, ESMSR2_REG @ load the ESMSR2 status register address + ldr r2, ESMSR2_ERR_CLR + str r2, [r0] @ clear the ESMSR2 register + + ldr r0, ESMSSR2_REG @ load the ESMSSR2 status register address + ldr r2, ESMSSR2_ERR_CLR + str r2, [r0] @ clear the ESMSSR2 register + + ldr r0, ESMKEY_REG @ load the ESMKEY register address + mov r2, #0x5 @ load R2 with 0x5 + str r2, [r0] @ clear the ESMKEY register + + ldr r0, VIM_INTREQ @ load the INTREQ register address + ldr r2, VIM_INT_CLR + str r2, [r0] @ clear the INTREQ register + ldr r0, CCMR4_STAT_REG @ load the CCMR4 status register address + ldr r2, CCMR4_ERR_CLR + str r2, [r0] @ clear the CCMR4 status register + ldmfd sp!, {r0-r2} + bx lr + +ESMSR1_REG: .word 0xFFFFF518 +ESMSR2_REG: .word 0xFFFFF51C +ESMSR3_REG: .word 0xFFFFF520 +ESMKEY_REG: .word 0xFFFFF538 +ESMSSR2_REG: .word 0xFFFFF53C +CCMR4_STAT_REG: .word 0xFFFFF600 +ERR_CLR_WRD: .word 0xFFFFFFFF +CCMR4_ERR_CLR: .word 0x00010000 +ESMSR1_ERR_CLR: .word 0x80000000 +ESMSR2_ERR_CLR: .word 0x00000004 +ESMSSR2_ERR_CLR: .word 0x00000004 +VIM_INT_CLR: .word 0x00000001 +VIM_INTREQ: .word 0xFFFFFE20 + + +@------------------------------------------------------------------------------- +@ Work Around for Errata CORTEX-R4#57: +@ +@ Errata Description: +@ Conditional VMRS APSR_Nzcv, FPSCR May Evaluate With Incorrect Flags +@ Workaround: +@ Disable out-of-order single-precision floating point +@ multiply-accumulate instruction completion + + .globl _errata_CORTEXR4_57_ +_errata_CORTEXR4_57_: + + push {r0} + mrc p15, #0, r0, c15, c0, #0 @ Read Secondary Auxiliary Control Register + orr r0, r0, #0x10000 @ Set BIT 16 (Set DOOFMACS) + mcr p15, #0, r0, c15, c0, #0 @ Write Secondary Auxiliary Control Register + pop {r0} + bx lr + +@------------------------------------------------------------------------------- +@ Work Around for Errata CORTEX-R4#66: +@ +@ Errata Description: +@ Register Corruption During A Load-Multiple Instruction At +@ an Exception Vector +@ Workaround: +@ Disable out-of-order completion for divide instructions in +@ Auxiliary Control register + + .globl _errata_CORTEXR4_66_ +_errata_CORTEXR4_66_: + + push {r0} + mrc p15, #0, r0, c1, c0, #1 @ Read Auxiliary Control register + orr r0, r0, #0x80 @ Set BIT 7 (Disable out-of-order completion + @ for divide instructions.) + mcr p15, #0, r0, c1, c0, #1 @ Write Auxiliary Control register + pop {r0} + bx lr + + .globl turnon_VFP +turnon_VFP: + @ Enable FPV + STMDB sp!, {r0} + fmrx r0, fpexc + orr r0, r0, #0x40000000 + fmxr fpexc, r0 + LDMIA sp!, {r0} + subs pc, lr, #4 + + .globl _dabort +_dabort: + stmfd r13!, {r0 - r12, lr} + ldmfd r13!, {r0 - r12, lr} + subs pc, lr, #8 diff --git a/libcpu/arm/cortex-r4/vector_ccs.asm b/libcpu/arm/cortex-r4/vector_ccs.asm new file mode 100644 index 0000000000..0ac6647266 --- /dev/null +++ b/libcpu/arm/cortex-r4/vector_ccs.asm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------- +; sys_intvecs.asm +; +; (c) Texas Instruments 2009-2013, All rights reserved. +; + + .sect ".intvecs" + .arm + +;------------------------------------------------------------------------------- +; import reference for interrupt routines + + .ref _reset + .ref _dabort + .ref turnon_VFP + .ref IRQ_Handler + + .def resetEntry + +;------------------------------------------------------------------------------- +; interrupt vectors + +resetEntry + b _reset + b turnon_VFP +svcEntry + b svcEntry +prefetchEntry + b prefetchEntry + b _dabort +reservedEntry + b reservedEntry + b IRQ_Handler + ldr pc,[pc,#-0x1b0] + +;------------------------------------------------------------------------------- diff --git a/libcpu/arm/cortex-r4/vector_gcc.S b/libcpu/arm/cortex-r4/vector_gcc.S new file mode 100644 index 0000000000..b21d5d4910 --- /dev/null +++ b/libcpu/arm/cortex-r4/vector_gcc.S @@ -0,0 +1,31 @@ +@------------------------------------------------------------------------------- +@ sys_intvecs.asm +@ +@ (c) Texas Instruments 2009-2013, All rights reserved. +@ + +.section .vectors, "ax" +.code 32 + +@------------------------------------------------------------------------------- +@ import reference for interrupt routines + + .globl _reset + .globl _dabort + .globl turnon_VFP + .globl IRQ_Handler + + +.globl system_vectors +system_vectors: + b _reset + b turnon_VFP +svcEntry: + b svcEntry +prefetchEntry: + b prefetchEntry + b _dabort +reservedEntry: + b reservedEntry + b IRQ_Handler + ldr pc,[pc,#-0x1b0] |
