From 39c8fdb416327c5ec0c23807ae701798a5739cdf Mon Sep 17 00:00:00 2001 From: Thomas Doerfler Date: Tue, 12 Jan 2010 15:03:22 +0000 Subject: add support for lpc32xx --- cpukit/score/cpu/arm/ChangeLog | 9 ++ cpukit/score/cpu/arm/Makefile.am | 1 + cpukit/score/cpu/arm/arm_exc_abort.S | 123 ++++++++++++++++++++++ cpukit/score/cpu/arm/arm_exc_interrupt.S | 20 +--- cpukit/score/cpu/arm/cpu.c | 28 ++--- cpukit/score/cpu/arm/rtems/asm.h | 16 +++ cpukit/score/cpu/arm/rtems/score/cpu.h | 169 +++++++++++++++++++------------ 7 files changed, 272 insertions(+), 94 deletions(-) create mode 100644 cpukit/score/cpu/arm/arm_exc_abort.S (limited to 'cpukit/score/cpu/arm') diff --git a/cpukit/score/cpu/arm/ChangeLog b/cpukit/score/cpu/arm/ChangeLog index 4c81e5cb1a..a47947170f 100644 --- a/cpukit/score/cpu/arm/ChangeLog +++ b/cpukit/score/cpu/arm/ChangeLog @@ -1,3 +1,12 @@ +2010-01-12 Sebastian Huber + + * arm_exc_abort.S: New file. + * Makefile.am: Update for new file. + * arm_exc_interrupt.S, cpu.c, rtems/asm.h, rtems/score/cpu.h: Changed + macros which switch from and to THUMB mode. Added a default prefetch + and data abort handler which reports the complete processor context. + Added PSR defines. + 2009-12-15 Sebastian Huber * rtems/score/arm.h: Recognize ARMv5TEJ. diff --git a/cpukit/score/cpu/arm/Makefile.am b/cpukit/score/cpu/arm/Makefile.am index 4cab7ddcd9..57f2b70642 100644 --- a/cpukit/score/cpu/arm/Makefile.am +++ b/cpukit/score/cpu/arm/Makefile.am @@ -13,6 +13,7 @@ noinst_LIBRARIES = libscorecpu.a libscorecpu_a_CPPFLAGS = $(AM_CPPFLAGS) libscorecpu_a_SOURCES = cpu.c \ cpu_asm.S \ + arm_exc_abort.S \ arm_exc_interrupt.S \ arm_exc_handler_low.S \ arm_exc_handler_high.c diff --git a/cpukit/score/cpu/arm/arm_exc_abort.S b/cpukit/score/cpu/arm/arm_exc_abort.S new file mode 100644 index 0000000000..906dcbb9f1 --- /dev/null +++ b/cpukit/score/cpu/arm/arm_exc_abort.S @@ -0,0 +1,123 @@ +/** + * @file + * + * @ingroup arm + * + * @brief ARM data and prefetch abort exception prologue and epilogue. + */ + +/* + * Copyright (c) 2009 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include +#include + +.extern rtems_fatal_error_occurred + +.globl arm_exc_data_abort_set_handler +.globl arm_exc_data_abort + +.globl arm_exc_prefetch_abort_set_handler +.globl arm_exc_prefetch_abort + +.section ".bss" + +data_abort_handler: +.long 0 + +prefetch_abort_handler: +.long 0 + +.section ".text" + +#ifdef __thumb__ + .thumb_func +#endif + +arm_exc_data_abort_set_handler: + ldr r1, =data_abort_handler + str r0, [r1] + bx lr + +#ifdef __thumb__ + .thumb_func +#endif + +arm_exc_prefetch_abort_set_handler: + ldr r1, =prefetch_abort_handler + str r0, [r1] + bx lr + +.arm + +arm_exc_prefetch_abort: + + /* Save context and load handler */ + sub sp, #16 + stmdb sp!, {r0-r12} + ldr r6, =prefetch_abort_handler + + b save_more_context + +arm_exc_data_abort: + + /* Save context and load handler */ + sub sp, #16 + stmdb sp!, {r0-r12} + ldr r6, =data_abort_handler + +save_more_context: + + /* Save more context */ + mov r2, lr + mrs r3, spsr + mrs r4, cpsr + orr r5, r3, #ARM_PSR_I + bic r5, #ARM_PSR_T + msr cpsr, r5 + mov r0, sp + mov r1, lr + msr cpsr, r4 + add r5, sp, #68 + stmdb r5!, {r0-r3} + + /* Call high level handler */ + ldr r2, [r6] + cmp r2, #0 + ldreq r2, =rtems_fatal_error_occurred + movne r0, sp + moveq r0, #0xaa +#ifndef __thumb__ + mov lr, pc + bx r2 +#else /* __thumb__ */ + SWITCH_FROM_ARM_TO_THUMB r1 + bl call_handler + SWITCH_FROM_THUMB_TO_ARM +#endif /* __thumb__ */ + + /* Restore context */ + ldmia r5!, {r0-r3} + mov lr, r2 + msr spsr, r3 + ldmia sp!, {r0-r12} + add sp, #16 + + /* Return from interrupt */ + subs pc, lr, #8 + +#ifdef __thumb__ +.thumb +call_handler: + bx r2 +#endif /* __thumb__ */ diff --git a/cpukit/score/cpu/arm/arm_exc_interrupt.S b/cpukit/score/cpu/arm/arm_exc_interrupt.S index 738c248141..a260d9dda1 100644 --- a/cpukit/score/cpu/arm/arm_exc_interrupt.S +++ b/cpukit/score/cpu/arm/arm_exc_interrupt.S @@ -1,6 +1,8 @@ /** * @file * + * @ingroup arm + * * @brief ARM interrupt exception prologue and epilogue. */ @@ -23,6 +25,8 @@ * The exchange area is only accessed if INT is disabled. */ +#include + #define EXCHANGE_LR r4 #define EXCHANGE_SPSR r5 #define EXCHANGE_CPSR r6 @@ -41,22 +45,6 @@ .extern bsp_interrupt_dispatch -.macro SWITCH_FROM_THUMB_TO_ARM -#ifdef __thumb__ -.align 2 - bx pc -.arm -#endif /* __thumb__ */ -.endm - -.macro SWITCH_FROM_ARM_TO_THUMB REG -#ifdef __thumb__ - add \REG, pc, #1 - bx \REG -.thumb -#endif /* __thumb__ */ -.endm - .arm .globl arm_exc_interrupt arm_exc_interrupt: diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c index a44cff59bb..53b42c3748 100644 --- a/cpukit/score/cpu/arm/cpu.c +++ b/cpukit/score/cpu/arm/cpu.c @@ -56,31 +56,31 @@ void _CPU_Context_Initialize( void _CPU_ISR_Set_level( uint32_t level ) { - uint32_t reg; + uint32_t arm_switch_reg; asm volatile ( - THUMB_TO_ARM - "mrs %0, cpsr\n" - "bic %0, %0, #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n" - "orr %0, %0, %1\n" + ARM_SWITCH_TO_ARM + "mrs %[arm_switch_reg], cpsr\n" + "bic %[arm_switch_reg], #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n" + "orr %[arm_switch_reg], %[level]\n" "msr cpsr, %0\n" - ARM_TO_THUMB - : "=r" (reg) - : "r" (level) + ARM_SWITCH_BACK + : [arm_switch_reg] "=&r" (arm_switch_reg) + : [level] "r" (level) ); } uint32_t _CPU_ISR_Get_level( void ) { - uint32_t reg; + ARM_SWITCH_REGISTERS; uint32_t level; asm volatile ( - THUMB_TO_ARM - "mrs %0, cpsr\n" - "and %1, %0, #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n" - ARM_TO_THUMB - : "=r" (reg), "=r" (level) + ARM_SWITCH_TO_ARM + "mrs %[level], cpsr\n" + "and %[level], #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n" + ARM_SWITCH_BACK + : [level] "=&r" (level) ARM_SWITCH_ADDITIONAL_OUTPUT ); return level; diff --git a/cpukit/score/cpu/arm/rtems/asm.h b/cpukit/score/cpu/arm/rtems/asm.h index 04c5360790..f8b027cf1b 100644 --- a/cpukit/score/cpu/arm/rtems/asm.h +++ b/cpukit/score/cpu/arm/rtems/asm.h @@ -141,4 +141,20 @@ .globl name ; name: ; .globl name ## _arm ; name ## _arm: #endif +.macro SWITCH_FROM_THUMB_TO_ARM +#ifdef __thumb__ +.align 2 + bx pc +.arm +#endif /* __thumb__ */ +.endm + +.macro SWITCH_FROM_ARM_TO_THUMB REG +#ifdef __thumb__ + add \REG, pc, #1 + bx \REG +.thumb +#endif /* __thumb__ */ +.endm + #endif /* _RTEMS_ASM_H */ diff --git a/cpukit/score/cpu/arm/rtems/score/cpu.h b/cpukit/score/cpu/arm/rtems/score/cpu.h index d7eca1527c..de452e8cb4 100644 --- a/cpukit/score/cpu/arm/rtems/score/cpu.h +++ b/cpukit/score/cpu/arm/rtems/score/cpu.h @@ -8,6 +8,8 @@ * This include file contains information pertaining to the ARM * processor. * + * Copyright (c) 2009 embedded brains GmbH. + * * Copyright (c) 2007 Ray Xu * * Copyright (c) 2006 OAR Corporation @@ -44,13 +46,42 @@ #endif #ifdef __thumb__ - #define ARM_TO_THUMB "add %0, pc, #1\nbx %0\n.thumb\n" - #define THUMB_TO_ARM ".align 2\nbx pc\n.arm\n" + #define ARM_SWITCH_REGISTERS uint32_t arm_switch_reg + #define ARM_SWITCH_TO_ARM ".align 2\nbx pc\n.arm\n" + #define ARM_SWITCH_BACK "add %[arm_switch_reg], pc, #1\nbx %[arm_switch_reg]\n.thumb\n" + #define ARM_SWITCH_OUTPUT [arm_switch_reg] "=&r" (arm_switch_reg) + #define ARM_SWITCH_ADDITIONAL_OUTPUT , ARM_SWITCH_OUTPUT #else - #define ARM_TO_THUMB - #define THUMB_TO_ARM + #define ARM_SWITCH_REGISTERS + #define ARM_SWITCH_TO_ARM + #define ARM_SWITCH_BACK + #define ARM_SWITCH_OUTPUT + #define ARM_SWITCH_ADDITIONAL_OUTPUT #endif +#define ARM_PSR_N (1 << 31) +#define ARM_PSR_Z (1 << 30) +#define ARM_PSR_C (1 << 29) +#define ARM_PSR_V (1 << 28) +#define ARM_PSR_Q (1 << 27) +#define ARM_PSR_J (1 << 24) +#define ARM_PSR_GE_SHIFT 16 +#define ARM_PSR_GE_MASK (0xf << ARM_PSR_GE_SHIFT) +#define ARM_PSR_E (1 << 9) +#define ARM_PSR_A (1 << 8) +#define ARM_PSR_I (1 << 7) +#define ARM_PSR_F (1 << 6) +#define ARM_PSR_T (1 << 5) +#define ARM_PSR_M_SHIFT 0 +#define ARM_PSR_M_MASK (0x1f << ARM_PSR_M_SHIFT) +#define ARM_PSR_M_USR 0x10 +#define ARM_PSR_M_FIQ 0x11 +#define ARM_PSR_M_IRQ 0x12 +#define ARM_PSR_M_SVC 0x13 +#define ARM_PSR_M_ABT 0x17 +#define ARM_PSR_M_UND 0x1b +#define ARM_PSR_M_SYS 0x1f + /* If someone uses THUMB we assume she wants minimal code size */ #ifdef __thumb__ #define CPU_INLINE_ENABLE_DISPATCH FALSE @@ -205,16 +236,16 @@ SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context; static inline uint32_t arm_interrupt_disable( void ) { - uint32_t reg; + uint32_t arm_switch_reg; uint32_t level; asm volatile ( - THUMB_TO_ARM - "mrs %1, cpsr\n" - "orr %0, %1, #0x80\n" - "msr cpsr, %0\n" - ARM_TO_THUMB - : "=r" (reg), "=r" (level) + ARM_SWITCH_TO_ARM + "mrs %[level], cpsr\n" + "orr %[arm_switch_reg], %[level], #0x80\n" + "msr cpsr, %[arm_switch_reg]\n" + ARM_SWITCH_BACK + : [arm_switch_reg] "=&r" (arm_switch_reg), [level] "=&r" (level) ); return level; @@ -222,54 +253,46 @@ static inline uint32_t arm_interrupt_disable( void ) static inline void arm_interrupt_enable( uint32_t level ) { - #ifdef __thumb__ - uint32_t reg; - - asm volatile ( - THUMB_TO_ARM - "msr cpsr, %1\n" - ARM_TO_THUMB - : "=r" (reg) - : "r" (level) - ); - #else - asm volatile ( - "msr cpsr, %0" - : - : "r" (level) - ); - #endif + ARM_SWITCH_REGISTERS; + + asm volatile ( + ARM_SWITCH_TO_ARM + "msr cpsr, %[level]\n" + ARM_SWITCH_BACK + : ARM_SWITCH_OUTPUT + : [level] "r" (level) + ); } static inline void arm_interrupt_flash( uint32_t level ) { - uint32_t reg; + uint32_t arm_switch_reg; asm volatile ( - THUMB_TO_ARM - "mrs %0, cpsr\n" - "msr cpsr, %1\n" - "msr cpsr, %0\n" - ARM_TO_THUMB - : "=r" (reg) - : "r" (level) + ARM_SWITCH_TO_ARM + "mrs %[arm_switch_reg], cpsr\n" + "msr cpsr, %[level]\n" + "msr cpsr, %[arm_switch_reg]\n" + ARM_SWITCH_BACK + : [arm_switch_reg] "=&r" (arm_switch_reg) + : [level] "r" (level) ); } static inline uint32_t arm_status_irq_enable( void ) { - uint32_t reg; + uint32_t arm_switch_reg; uint32_t psr; RTEMS_COMPILER_MEMORY_BARRIER(); asm volatile ( - THUMB_TO_ARM - "mrs %1, cpsr\n" - "bic %0, %1, #0x80\n" - "msr cpsr, %0\n" - ARM_TO_THUMB - : "=r" (reg), "=r" (psr) + ARM_SWITCH_TO_ARM + "mrs %[psr], cpsr\n" + "bic %[arm_switch_reg], %[psr], #0x80\n" + "msr cpsr, %[arm_switch_reg]\n" + ARM_SWITCH_BACK + : [arm_switch_reg] "=&r" (arm_switch_reg), [psr] "=&r" (psr) ); return psr; @@ -277,23 +300,15 @@ static inline uint32_t arm_status_irq_enable( void ) static inline void arm_status_restore( uint32_t psr ) { - #ifdef __thumb__ - uint32_t reg; - - asm volatile ( - THUMB_TO_ARM - "msr cpsr, %1\n" - ARM_TO_THUMB - : "=r" (reg) - : "r" (psr) - ); - #else - asm volatile ( - "msr cpsr, %0" - : - : "r" (psr) - ); - #endif + ARM_SWITCH_REGISTERS; + + asm volatile ( + ARM_SWITCH_TO_ARM + "msr cpsr, %[psr]\n" + ARM_SWITCH_BACK + : ARM_SWITCH_OUTPUT + : [psr] "r" (psr) + ); RTEMS_COMPILER_MEMORY_BARRIER(); } @@ -402,16 +417,42 @@ static inline uint16_t CPU_swap_u16( uint16_t value ) extern uint32_t arm_cpu_mode; -void arm_exc_abort_data( void ); +typedef struct { + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t sp; + uint32_t lr; + uint32_t pc; + uint32_t cpsr; +} arm_cpu_context; + +typedef void arm_exc_abort_handler( arm_cpu_context *context ); + +void arm_exc_data_abort_set_handler( arm_exc_abort_handler handler ); + +void arm_exc_data_abort( void ); + +void arm_exc_prefetch_abort_set_handler( arm_exc_abort_handler handler ); + +void arm_exc_prefetch_abort( void ); -void arm_exc_abort_prefetch( void ); +void bsp_interrupt_dispatch( void ); void arm_exc_interrupt( void ); void arm_exc_undefined( void ); -void bsp_interrupt_dispatch( void ); - #ifdef __cplusplus } #endif -- cgit v1.2.3