From 632e4306dcb9bada638e35e7cd5f1de0fcf66902 Mon Sep 17 00:00:00 2001 From: Thomas Doerfler Date: Fri, 17 Jul 2009 13:50:31 +0000 Subject: exception handler maintenance --- cpukit/score/cpu/arm/cpu.c | 283 +++++++++++---------------------------------- 1 file changed, 69 insertions(+), 214 deletions(-) (limited to 'cpukit/score/cpu/arm/cpu.c') 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 * + * 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) - -- cgit v1.2.3