summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/arm
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2010-01-12 15:03:22 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2010-01-12 15:03:22 +0000
commit39c8fdb416327c5ec0c23807ae701798a5739cdf (patch)
tree0f2bb4acb60e60d74b7ef08e345a21d7896aba20 /cpukit/score/cpu/arm
parent2010-01-11 Marc Pignat <marc.pignat@hevs.ch> (diff)
downloadrtems-39c8fdb416327c5ec0c23807ae701798a5739cdf.tar.bz2
add support for lpc32xx
Diffstat (limited to 'cpukit/score/cpu/arm')
-rw-r--r--cpukit/score/cpu/arm/ChangeLog9
-rw-r--r--cpukit/score/cpu/arm/Makefile.am1
-rw-r--r--cpukit/score/cpu/arm/arm_exc_abort.S123
-rw-r--r--cpukit/score/cpu/arm/arm_exc_interrupt.S20
-rw-r--r--cpukit/score/cpu/arm/cpu.c28
-rw-r--r--cpukit/score/cpu/arm/rtems/asm.h16
-rw-r--r--cpukit/score/cpu/arm/rtems/score/cpu.h169
7 files changed, 272 insertions, 94 deletions
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 <sebastian.huber@embedded-brains.de>
+
+ * 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 <sebastian.huber@embedded-brains.de>
* 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
+ * <rtems@embedded-brains.de>
+ *
+ * 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 <rtems/asm.h>
+#include <rtems/score/cpu.h>
+
+.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 <rtems/asm.h>
+
#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 <Rayx.cn@gmail.com>
*
* 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