summaryrefslogtreecommitdiffstats
path: root/cpukit/score/cpu/arm/cpu.c
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2009-07-17 13:50:31 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2009-07-17 13:50:31 +0000
commit632e4306dcb9bada638e35e7cd5f1de0fcf66902 (patch)
tree859cba08c62c464bed3da9305c15015ddd82e422 /cpukit/score/cpu/arm/cpu.c
parentUpdate. (diff)
downloadrtems-632e4306dcb9bada638e35e7cd5f1de0fcf66902.tar.bz2
exception handler maintenance
Diffstat (limited to 'cpukit/score/cpu/arm/cpu.c')
-rw-r--r--cpukit/score/cpu/arm/cpu.c283
1 files changed, 69 insertions, 214 deletions
diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c
index a717923b82..3c4d96da48 100644
--- a/cpukit/score/cpu/arm/cpu.c
+++ b/cpukit/score/cpu/arm/cpu.c
@@ -1,7 +1,10 @@
-/*
- * ARM CPU Dependent Source
- *
+/**
+ * @file
*
+ * ARM support code.
+ */
+
+/*
* COPYRIGHT (c) 2000 Canon Research Centre France SA.
* Emmanuel Raguet, mailto:raguet@crf.canon.fr
*
@@ -10,6 +13,8 @@
*
* Copyright (c) 2007 Ray xu <rayx.cn@gmail.com>
*
+ * Copyright (c) 2009 embedded brains GmbH
+ *
* 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.
@@ -29,236 +34,86 @@
* This variable can be used to change the running mode of the execution
* contexts.
*/
+uint32_t arm_cpu_mode = 0x13;
-unsigned int arm_cpu_mode = 0x13;
-
-/* _CPU_Initialize
- *
- * INPUT PARAMETERS: NONE
- *
- * This routine performs processor dependent initialization.
- */
-
-void _CPU_Initialize(void)
+void _CPU_Context_Initialize(
+ Context_Control *the_context,
+ uint32_t *stack_base,
+ uint32_t size,
+ uint32_t new_level,
+ void *entry_point,
+ bool is_fp
+)
{
+ the_context->register_sp = (uint32_t) stack_base + size ;
+ the_context->register_lr = (uint32_t) entry_point;
+ the_context->register_cpsr = new_level | arm_cpu_mode;
}
-/*
- *
- * _CPU_ISR_Get_level - returns the current interrupt level
- */
-#define str(x) #x
-#define xstr(x) str(x)
-#define L(x) #x "_" xstr(__LINE__)
-
-#define TO_ARM_MODE(x) \
- asm volatile ( \
- ".code 16 \n" \
- L(x) "_thumb: \n" \
- ".align 2 \n" \
- "push {lr} \n" \
- "adr %0, "L(x) "_arm \n" \
- "bl " L(x)" \n" \
- "pop {pc} \n" \
- ".balign 4 \n" \
- L(x) ": \n" \
- "bx %0 \n" \
- "nop \n" \
- ".pool \n" \
- ".code 32 \n" \
- L(x) "_arm: \n" \
- :"=&r" (reg))
-
-
-/*
- * Switch to Thumb mode Veneer,ugly but safe
- */
-
-#define TO_THUMB_MODE(x) \
- asm volatile ( \
- ".code 32 \n"\
- "adr %0, "L(x) "_thumb +1 \n"\
- "bx %0 \n"\
- ".pool \n"\
- ".thumb_func \n"\
- L(x) "_thumb: \n"\
- : "=&r" (reg))
+/* Preprocessor magic for stringification of x */
+#define _CPU_ISR_LEVEL_DO_STRINGOF( x) #x
+#define _CPU_ISR_LEVEL_STRINGOF( x) _CPU_ISR_LEVEL_DO_STRINGOF( x)
-#if (!defined(__THUMB_INTERWORK__) && !defined(__thumb__))
-uint32_t _CPU_ISR_Get_level( void )
+void _CPU_ISR_Set_level( uint32_t level )
{
- uint32_t reg = 0; /* to avoid warning */
- asm volatile ("mrs %0, cpsr \n" \
- "and %0, %0, #0xc0 \n" \
- : "=r" (reg) \
- : "0" (reg) );
- return reg;
+ uint32_t 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"
+ "msr cpsr, %0\n"
+ ARM_TO_THUMB
+ : "=r" (reg)
+ : "r" (level)
+ );
}
-#endif
-
+uint32_t _CPU_ISR_Get_level( void )
+{
+ uint32_t reg;
+ 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)
+ );
+
+ return level;
+}
-/*
- * _CPU_ISR_install_vector
- *
- * This kernel routine installs the RTEMS handler for the
- * specified vector.
- *
- * Input parameters:
- * vector - interrupt vector number
- * new_handler - replacement ISR for this vector number
- * old_handler - pointer to store former ISR for this vector number
- *
- * FIXME: This vector scheme should be changed to allow FIQ to be
- * handled better. I'd like to be able to put VectorTable
- * elsewhere - JTM
- *
- *
- * Output parameters: NONE
- *
- */
void _CPU_ISR_install_vector(
- uint32_t vector,
- proc_ptr new_handler,
- proc_ptr *old_handler
+ uint32_t vector,
+ proc_ptr new_handler,
+ proc_ptr *old_handler
)
{
- /* pointer on the redirection table in RAM */
- long *VectorTable = (long *)(MAX_EXCEPTIONS * 4);
-
- if (old_handler != NULL) {
- old_handler = *(proc_ptr *)(VectorTable + vector);
- }
+ /* Redirection table starts at the end of the vector table */
+ volatile uint32_t *table = (volatile uint32_t *) (MAX_EXCEPTIONS * 4);
- *(VectorTable + vector) = (long)new_handler ;
+ uint32_t current_handler = table [vector];
+ /* The current handler is now the old one */
+ if (old_handler != NULL) {
+ *old_handler = (proc_ptr) current_handler;
+ }
+
+ /* Write only if necessary to avoid writes to a maybe read-only memory */
+ if (current_handler != (uint32_t) new_handler) {
+ table [vector] = (uint32_t) new_handler;
+ }
}
-void _CPU_Context_Initialize(
- Context_Control *the_context,
- uint32_t *stack_base,
- uint32_t size,
- uint32_t new_level,
- void *entry_point,
- bool is_fp
-)
-{
- the_context->register_sp = (uint32_t)stack_base + size ;
- the_context->register_lr = (uint32_t)entry_point;
- the_context->register_cpsr = new_level | arm_cpu_mode;
-}
-
-
-/*
- * _CPU_Install_interrupt_stack - this function is empty since the
- * BSP must set up the interrupt stacks.
- */
-
void _CPU_Install_interrupt_stack( void )
{
+ /* This function is empty since the BSP must set up the interrupt stacks */
}
-void _defaultExcHandler (CPU_Exception_frame *ctx)
+void _CPU_Initialize( void )
{
- printk("\n\r");
- printk("----------------------------------------------------------\n\r");
-#if 1
- printk("Exception 0x%x caught at PC 0x%x by thread %d\n",
- ctx->register_ip, ctx->register_lr - 4,
- _Thread_Executing->Object.id);
-#endif
- printk("----------------------------------------------------------\n\r");
- printk("Processor execution context at time of the fault was :\n\r");
- printk("----------------------------------------------------------\n\r");
-#if 0
- printk(" r0 = %8x r1 = %8x r2 = %8x r3 = %8x\n\r",
- ctx->register_r0, ctx->register_r1,
- ctx->register_r2, ctx->register_r3);
- printk(" r4 = %8x r5 = %8x r6 = %8x r7 = %8x\n\r",
- ctx->register_r4, ctx->register_r5,
- ctx->register_r6, ctx->register_r7);
- printk(" r8 = %8x r9 = %8x r10 = %8x\n\r",
- ctx->register_r8, ctx->register_r9, ctx->register_r10);
- printk(" fp = %8x ip = %8x sp = %8x pc = %8x\n\r",
- ctx->register_fp, ctx->register_ip,
- ctx->register_sp, ctx->register_lr - 4);
- printk("----------------------------------------------------------\n\r");
-#endif
- if (_ISR_Nest_level > 0) {
- /*
- * In this case we shall not delete the task interrupted as
- * it has nothing to do with the fault. We cannot return either
- * because the eip points to the faulty instruction so...
- */
- printk("Exception while executing ISR!!!. System locked\n\r");
- while(1);
- }
- else {
- printk("*********** FAULTY THREAD WILL BE DELETED **************\n\r");
- rtems_task_delete(_Thread_Executing->Object.id);
- }
+ /* Do nothing */
}
-
-cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
-
-extern void _Exception_Handler_Undef_Swi(void);
-extern void _Exception_Handler_Abort(void);
-extern void _exc_data_abort(void);
-
-
-
-/* FIXME: put comments here */
-void rtems_exception_init_mngt(void)
-{
- ISR_Level level;
-
- _CPU_ISR_Disable(level);
- _CPU_ISR_install_vector(ARM_EXCEPTION_UNDEF,
- _Exception_Handler_Undef_Swi,
- NULL);
-
- _CPU_ISR_install_vector(ARM_EXCEPTION_SWI,
- _Exception_Handler_Undef_Swi,
- NULL);
-
- _CPU_ISR_install_vector(ARM_EXCEPTION_PREF_ABORT,
- _Exception_Handler_Abort,
- NULL);
-
- _CPU_ISR_install_vector(ARM_EXCEPTION_DATA_ABORT,
- _exc_data_abort,
- NULL);
-
- _CPU_ISR_install_vector(ARM_EXCEPTION_FIQ,
- _Exception_Handler_Abort,
- NULL);
-
- _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ,
- _Exception_Handler_Abort,
- NULL);
-
- _CPU_ISR_Enable(level);
-}
-
-#define INSN_MASK 0xc5
-
-#define INSN_STM1 0x80
-#define INSN_STM2 0x84
-#define INSN_STR 0x40
-#define INSN_STRB 0x44
-
-#define INSN_LDM1 0x81
-#define INSN_LDM23 0x85
-#define INSN_LDR 0x41
-#define INSN_LDRB 0x45
-
-#define GET_RD(x) ((x & 0x0000f000) >> 12)
-#define GET_RN(x) ((x & 0x000f0000) >> 16)
-
-#define GET_U(x) ((x & 0x00800000) >> 23)
-#define GET_I(x) ((x & 0x02000000) >> 25)
-
-#define GET_REG(r, ctx) (((uint32_t *)ctx)[r])
-#define SET_REG(r, ctx, v) (((uint32_t *)ctx)[r] = v)
-#define GET_OFFSET(insn) (insn & 0xfff)
-