From fa237002ab54222f18109be49dcb8368c253b107 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Tue, 30 Jul 2002 23:16:40 +0000 Subject: 2002-07-30 Jay Monkman * cpu.c, cpu_asm.S, rtems/score/arm.h, rtems/score/cpu.h, rtems/score/cpu_asm.h, rtems/score/types.h: ARM port works well enough to run all sptests, tmtests, and ttcp. In addition to general cleanup, there has been considerable optimization to interrupt disable/enable, endian swapping, and context switching. --- cpukit/score/cpu/arm/ChangeLog | 9 ++ cpukit/score/cpu/arm/cpu.c | 199 ++++++++++++++++++-------- cpukit/score/cpu/arm/cpu_asm.S | 112 ++++----------- cpukit/score/cpu/arm/rtems/score/arm.h | 49 +++++-- cpukit/score/cpu/arm/rtems/score/cpu.h | 215 ++++++++++++----------------- cpukit/score/cpu/arm/rtems/score/cpu_asm.h | 32 ++--- cpukit/score/cpu/arm/rtems/score/types.h | 29 ++-- 7 files changed, 325 insertions(+), 320 deletions(-) (limited to 'cpukit/score') diff --git a/cpukit/score/cpu/arm/ChangeLog b/cpukit/score/cpu/arm/ChangeLog index 14d22754d0..faab01473a 100644 --- a/cpukit/score/cpu/arm/ChangeLog +++ b/cpukit/score/cpu/arm/ChangeLog @@ -1,3 +1,12 @@ +2002-07-30 Jay Monkman + + * cpu.c, cpu_asm.S, rtems/score/arm.h, rtems/score/cpu.h, + rtems/score/cpu_asm.h, rtems/score/types.h: ARM port works + well enough to run all sptests, tmtests, and ttcp. + In addition to general cleanup, there has been considerable + optimization to interrupt disable/enable, endian swapping, + and context switching. + 2002-07-26 Ralf Corsepius * Makefile.am: Build libscorecpu.a instead of rtems-cpu.rel. diff --git a/cpukit/score/cpu/arm/cpu.c b/cpukit/score/cpu/arm/cpu.c index 3ae3f5828a..54a556bc9f 100644 --- a/cpukit/score/cpu/arm/cpu.c +++ b/cpukit/score/cpu/arm/cpu.c @@ -32,6 +32,9 @@ * */ +unsigned32 g_data_abort_cnt = 0; +unsigned32 g_data_abort_insn_list[1024]; + void _CPU_Initialize( rtems_cpu_table *cpu_table, void (*thread_dispatch) /* ignored on this CPU */ @@ -51,7 +54,8 @@ unsigned32 _CPU_ISR_Get_level( void ) asm volatile ("mrs %0, cpsr \n" \ "and %0, %0, #0xc0 \n" \ - : "=r" (reg)); + : "=r" (reg) \ + : "0" (reg) ); return reg; } @@ -101,80 +105,34 @@ void _CPU_Context_Initialize( boolean is_fp ) { - the_context->register_sp = ((unsigned32)(stack_base)) + (size) ; - the_context->register_pc = (entry_point); - the_context->register_cpsr = (new_level | 0x13); + the_context->register_sp = (unsigned32)stack_base + size ; + the_context->register_lr = (unsigned32)entry_point; + the_context->register_cpsr = new_level | 0x13; } -/*PAGE - * - * _CPU_Install_interrupt_stack - */ - -void _CPU_Install_interrupt_stack( void ) -{ -/* FIXME: do something here */ -#if 0 - extern unsigned long _fiq_stack; - extern unsigned long _fiq_stack_size; - extern unsigned long _irq_stack; - extern unsigned long _irq_stack_size; - extern unsigned long _abt_stack; - extern unsigned long _abt_stack_size; - unsigned long *ptr; - int i; - - ptr = &_fiq_stack; - for (i = 0; i < ((int)&_fiq_stack_size/4); i++) { - ptr[i] = 0x13131313; - } - - ptr = &_irq_stack; - for (i = 0; i < ((int)&_irq_stack_size/4); i++) { - ptr[i] = 0xf0f0f0f0; - } - - ptr = &_abt_stack; - for (i = 0; i < ((int)&_abt_stack_size/4); i++) { - ptr[i] = 0x55555555; - } -#endif -} -/*PAGE - * - * _CPU_Thread_Idle_body - * - * NOTES: - * - * 1. This is the same as the regular CPU independent algorithm. - * - * 2. If you implement this using a "halt", "idle", or "shutdown" - * instruction, then don't forget to put it in an infinite loop. - * - * 3. Be warned. Some processors with onboard DMA have been known - * to stop the DMA if the CPU were put in IDLE mode. This might - * also be a problem with other on-chip peripherals. So use this - * hook with caution. +/* + * _CPU_Install_interrupt_stack - this function is empty since the + * BSP must set up the interrupt stacks. */ -void _CPU_Thread_Idle_body( void ) +void _CPU_Install_interrupt_stack( void ) { - - while(1); /* FIXME: finish this */ - /* insert your "halt" instruction here */ ; } void _defaultExcHandler (CPU_Exception_frame *ctx) { printk("\n\r"); printk("----------------------------------------------------------\n\r"); +#if 0 printk("Exception 0x%x caught at PC 0x%x by thread %d\n", ctx->register_pc, 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); @@ -187,7 +145,7 @@ void _defaultExcHandler (CPU_Exception_frame *ctx) 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 @@ -207,6 +165,7 @@ cpuExcHandlerType _currentExcHandler = _defaultExcHandler; extern void _Exception_Handler_Undef_Swi(); extern void _Exception_Handler_Abort(); +extern void _exc_data_abort(); /* FIXME: put comments here */ void rtems_exception_init_mngt() { @@ -226,7 +185,7 @@ void rtems_exception_init_mngt() NULL); _CPU_ISR_install_vector(ARM_EXCEPTION_DATA_ABORT, - _Exception_Handler_Abort, + _exc_data_abort, NULL); _CPU_ISR_install_vector(ARM_EXCEPTION_FIQ, @@ -240,4 +199,126 @@ void rtems_exception_init_mngt() _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) (((unsigned32 *)ctx)[r]) +#define SET_REG(r, ctx, v) (((unsigned32 *)ctx)[r] = v) +#define GET_OFFSET(insn) (insn & 0xfff) + + +/* This function is supposed to figure out what caused the + * data abort, do that, then return. + * + * All unhandled instructions cause the system to hang. + */ + +void do_data_abort(unsigned32 insn, unsigned32 spsr, + CPU_Exception_frame *ctx) +{ + unsigned8 decode; + unsigned8 insn_type; + + unsigned32 rn; + unsigned32 rd; + unsigned8 *src_addr; + unsigned8 *dest_addr; + unsigned32 tmp; + + g_data_abort_insn_list[g_data_abort_cnt & 0x3ff] = ctx->register_lr - 8; + g_data_abort_cnt++; + + decode = ((insn >> 20) & 0xff); + + insn_type = decode & INSN_MASK; + switch(insn_type) { + case INSN_STM1: + printk("\n\nINSN_STM1\n"); + break; + case INSN_STM2: + printk("\n\nINSN_STM2\n"); + break; + case INSN_STR: + printk("\n\nINSN_STR\n"); + break; + case INSN_STRB: + printk("\n\nINSN_STRB\n"); + break; + case INSN_LDM1: + printk("\n\nINSN_LDM1\n"); + break; + case INSN_LDM23: + printk("\n\nINSN_LDM23\n"); + break; + case INSN_LDR: + printk("\n\nINSN_LDR\n"); + + rn = GET_RN(insn); + rd = GET_RD(insn); + + /* immediate offset/index */ + if (GET_I(insn) == 0) { + switch(decode & 0x12) { /* P and W bits */ + case 0x00: /* P=0, W=0 -> base is updated, post-indexed */ + printk("\tPost-indexed\n"); + break; + case 0x02: /* P=0, W=1 -> user mode access */ + printk("\tUser mode\n"); + break; + case 0x10: /* P=1, W=0 -> base not updated */ + src_addr = GET_REG(rn, ctx); + if (GET_U(insn) == 0) { + src_addr -= GET_OFFSET(insn); + } else { + src_addr += GET_OFFSET(insn); + } + tmp = (src_addr[0] | + (src_addr[1] << 8) | + (src_addr[2] << 16) | + (src_addr[3] << 24)); + SET_REG(rd, ctx, tmp); + return; + break; + case 0x12: /* P=1, W=1 -> base is updated, pre-indexed */ + printk("\tPre-indexed\n"); + break; + } + } + break; + case INSN_LDRB: + printk("\n\nINSN_LDRB\n"); + break; + default: + printk("\n\nUnrecognized instruction\n"); + break; + } + + printk("data_abort at address 0x%x, instruction: 0x%x, spsr = 0x%x\n", + ctx->register_lr - 8, insn, spsr); + + /* disable interrupts, wait forever */ + _CPU_ISR_Disable(tmp); + while(1) { + continue; + } + return; +} + + + diff --git a/cpukit/score/cpu/arm/cpu_asm.S b/cpukit/score/cpu/arm/cpu_asm.S index 60c638d80a..db0847ddce 100644 --- a/cpukit/score/cpu/arm/cpu_asm.S +++ b/cpukit/score/cpu/arm/cpu_asm.S @@ -31,57 +31,21 @@ * This function copies the current registers to where r0 points, then * restores the ones from where r1 points. * - * - * NOTE: The function should be able to only save/restore the registers - * that would be saved by a C function since the others have already - * been saved. - * - * It should also be able to use the stm/ldm instructions. + * Using the ldm/stm opcodes save 2-3 us on 100 MHz ARM9TDMI with + * a 16 bit data bus. * */ - .globl _CPU_Context_switch _CPU_Context_switch: -/* FIXME: This should use load and store multiple instructions */ /* Start saving context */ - str r2, [r0, #REG_R2] - str r3, [r0, #REG_R3] - str r4, [r0, #REG_R4] - str r5, [r0, #REG_R5] - str r6, [r0, #REG_R6] - str r7, [r0, #REG_R7] - str r8, [r0, #REG_R8] - str r9, [r0, #REG_R9] - str r10, [r0, #REG_R10] - - str r11, [r0, #REG_R11] - str r12, [r0, #REG_R12] - - str sp, [r0, #REG_SP] - str lr, [r0, #REG_PC] /* save LR at PC's location */ - mrs r2, cpsr - str r2, [r0, #REG_CPSR] + stmia r0, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14} + /* Start restoring context */ - - ldr r2, [r1, #REG_CPSR] +_restore: + ldmia r1, {r2, r4, r5, r6, r7, r8, r9, r10, r11, r13, r14} msr cpsr, r2 - - ldr r2, [r1, #REG_R2] - ldr r3, [r1, #REG_R3] - ldr r4, [r1, #REG_R4] - ldr r5, [r1, #REG_R5] - ldr r6, [r1, #REG_R6] - ldr r7, [r1, #REG_R7] - ldr r8, [r1, #REG_R8] - ldr r9, [r1, #REG_R9] - ldr r10, [r1, #REG_R10] - ldr r11, [r1, #REG_R11] - ldr r12, [r1, #REG_R12] - - ldr sp, [r1, #REG_SP] - ldr lr, [r1, #REG_PC] mov pc, lr /* @@ -90,34 +54,12 @@ _CPU_Context_switch: * This function copies the restores the registers from where r0 points. * It must match _CPU_Context_switch() * - * NOTE: The function should be able to only save/restore the registers - * that would be saved by a C function since the others have already - * been saved. - * - * It should also be able to use the stm/ldm instructions. - * */ .globl _CPU_Context_restore _CPU_Context_restore: -/* FIXME: This should use load and store multiple instructions */ - ldr r2, [r0, #REG_CPSR] - msr cpsr, r2 + mov r1, r0 + b _restore - ldr r2, [r0, #REG_R2] - ldr r3, [r0, #REG_R3] - ldr r4, [r0, #REG_R4] - ldr r5, [r0, #REG_R5] - ldr r6, [r0, #REG_R6] - ldr r7, [r0, #REG_R7] - ldr r8, [r0, #REG_R8] - ldr r9, [r0, #REG_R9] - ldr r10, [r0, #REG_R10] - ldr r11, [r1, #REG_R11] - ldr r12, [r1, #REG_R12] - - ldr sp, [r0, #REG_SP] - ldr lr, [r0, #REG_PC] - mov pc, lr /* FIXME: _Exception_Handler_Undef_Swi is untested */ @@ -125,10 +67,6 @@ _CPU_Context_restore: _Exception_Handler_Undef_Swi: /* FIXME: This should use load and store multiple instructions */ sub r13,r13,#SIZE_REGS - str r0, [r13, #REG_R0] - str r1, [r13, #REG_R1] - str r2, [r13, #REG_R2] - str r3, [r13, #REG_R3] str r4, [r13, #REG_R4] str r5, [r13, #REG_R5] str r6, [r13, #REG_R6] @@ -137,7 +75,6 @@ _Exception_Handler_Undef_Swi: str r9, [r13, #REG_R9] str r10, [r13, #REG_R10] str r11, [r13, #REG_R11] - str r12, [r13, #REG_R12] str sp, [r13, #REG_SP] str lr, [r13, #REG_LR] mrs r0, cpsr /* read the status */ @@ -149,10 +86,6 @@ _Exception_Handler_Undef_Swi: ldr lr, =_go_back_1 ldr pc,[r1] /* call handler */ _go_back_1: - ldr r0, [r13, #REG_R0] - ldr r1, [r13, #REG_R1] - ldr r2, [r13, #REG_R2] - ldr r3, [r13, #REG_R3] ldr r4, [r13, #REG_R4] ldr r5, [r13, #REG_R5] ldr r6, [r13, #REG_R6] @@ -161,7 +94,6 @@ _go_back_1: ldr r9, [r13, #REG_R9] ldr r10, [r13, #REG_R10] ldr r11, [r13, #REG_R11] - ldr r12, [r13, #REG_R12] ldr sp, [r13, #REG_SP] ldr lr, [r13, #REG_LR] add r13,r13,#SIZE_REGS @@ -172,19 +104,13 @@ _go_back_1: _Exception_Handler_Abort: /* FIXME: This should use load and store multiple instructions */ sub r13,r13,#SIZE_REGS - str r0, [r13, #REG_R0] - str r1, [r13, #REG_R1] - str r2, [r13, #REG_R2] - str r3, [r13, #REG_R3] str r4, [r13, #REG_R4] str r5, [r13, #REG_R5] str r6, [r13, #REG_R6] str r7, [r13, #REG_R7] str r8, [r13, #REG_R8] str r9, [r13, #REG_R9] - str r10, [r13, #REG_R10] str sp, [r13, #REG_R11] - str lr, [r13, #REG_R12] str lr, [r13, #REG_SP] str lr, [r13, #REG_LR] mrs r0, cpsr /* read the status */ @@ -196,10 +122,6 @@ _Exception_Handler_Abort: ldr lr, =_go_back_2 ldr pc,[r1] /* call handler */ _go_back_2: - ldr r0, [r13, #REG_R0] - ldr r1, [r13, #REG_R1] - ldr r2, [r13, #REG_R2] - ldr r3, [r13, #REG_R3] ldr r4, [r13, #REG_R4] ldr r5, [r13, #REG_R5] ldr r6, [r13, #REG_R6] @@ -208,9 +130,25 @@ _go_back_2: ldr r9, [r13, #REG_R9] ldr r10, [r13, #REG_R10] ldr sp, [r13, #REG_R11] - ldr lr, [r13, #REG_R12] ldr lr, [r13, #REG_SP] ldr lr, [r13, #REG_LR] add r13,r13,#SIZE_REGS subs pc,r14,#4 /* return */ + .globl _exc_data_abort +_exc_data_abort: + sub sp, sp, #SIZE_REGS /* reserve register frame */ + stmia sp, {r0-r12} + str lr, [sp, #REG_LR] + mov r1, lr + ldr r0, [r1, #-8] /* r0 = bad instruction */ + mrs r1, spsr /* r1 = spsr */ + mov r2, r13 /* r2 = exception frame */ + bl do_data_abort + + ldr lr, [sp, #REG_LR] + ldmia sp, {r0-r12} + add sp, sp, #SIZE_REGS + + subs pc, r14, #4 /* return to the instruction */ + /* _AFTER_ the aborted one */ diff --git a/cpukit/score/cpu/arm/rtems/score/arm.h b/cpukit/score/cpu/arm/rtems/score/arm.h index 05aed89892..7d8d135488 100644 --- a/cpukit/score/cpu/arm/rtems/score/arm.h +++ b/cpukit/score/cpu/arm/rtems/score/arm.h @@ -29,25 +29,44 @@ extern "C" { * dependent features are present in a particular member * of the family. */ -#if defined(__arm9__) -# define CPU_MODEL_NAME "arm9" -# define ARM_HAS_FPU 0 -#elif defined(__arm9tdmi__) -# define CPU_MODEL_NAME "arm9tdmi" -# define ARM_HAS_FPU 0 -#elif defined(__arm7__) -# define CPU_MODEL_NAME "arm7" -# define ARM_HAS_FPU 0 -#elif defined(__arm7tdmi__) -# define CPU_MODEL_NAME "arm7tdmi" -# define ARM_HAS_FPU 0 -#elif defined(__arm__) -# define CPU_MODEL_NAME "unknown ARM" -# define ARM_HAS_FPU 0 +#if defined(__ARM_ARCH_4__) +# define CPU_MODEL_NAME "ARMv4" +# define ARM_HAS_CLZ 0 +# define ARM_HAS_THUMB 0 + +#elif defined(__ARM_ARCH_4T__) +# define CPU_MODEL_NAME "ARMv4T" +# define ARM_HAS_CLZ 0 +# define ARM_HAS_THUMB 1 + +#elif defined(__ARM_ARCH_5__) +# define CPU_MODEL_NAME "ARMv5" +# define ARM_HAS_CLZ 1 +# define ARM_HAS_THUMB 0 + +#elif defined(__ARM_ARCH_5T__) +# define CPU_MODEL_NAME "ARMv5T" +# define ARM_HAS_CLZ 1 +# define ARM_HAS_THUMB 1 + +#elif defined(__ARM_ARCH_5E__) +# define CPU_MODEL_NAME "ARMv5E" +# define ARM_HAS_CLZ 1 +# define ARM_HAS_THUMB 0 + +#elif defined(__ARM_ARCH_5TE__) +# define CPU_MODEL_NAME "ARMv5TE" +# define ARM_HAS_CLZ 1 +# define ARM_HAS_THUMB 1 + #else # error "Unsupported CPU Model" + #endif +/* All ARM CPUs are assumed to not have floating point units */ +#define ARM_HAS_FPU 0 + /* * Define the name of the CPU family. */ diff --git a/cpukit/score/cpu/arm/rtems/score/cpu.h b/cpukit/score/cpu/arm/rtems/score/cpu.h index 7074d0022e..7468d998c5 100644 --- a/cpukit/score/cpu/arm/rtems/score/cpu.h +++ b/cpukit/score/cpu/arm/rtems/score/cpu.h @@ -1,8 +1,10 @@ /* + * $RCSfile$ + * * This include file contains information pertaining to the ARM * processor. * - * COPYRIGHT (c) 2002 Advent Networks, Inc. + * Copyright (c) 2002 Advent Networks, Inc. * Jay Monkman * * COPYRIGHT (c) 2000 Canon Research Centre France SA. @@ -12,7 +14,6 @@ * found in the file LICENSE in this distribution or at * http://www.OARcorp.com/rtems/license.html. * - * $Id$ */ /* FIXME: finish commenting/cleaning up this file */ @@ -25,7 +26,7 @@ extern "C" { #include /* pick up machine definitions */ #ifndef ASM -#include +#include #endif /* conditional compilation parameters */ @@ -103,7 +104,7 @@ extern "C" { * * If this is TRUE, CPU_ALLOCATE_INTERRUPT_STACK should also be TRUE. * - * Only one of CPU_HAS_SOFTWARE_INTERRU + * Only one of CPU_HAS_SOFTWARE_INTERRUPT_STACK and * CPU_HAS_HARDWARE_INTERRUPT_STACK should be set to TRUE. It is * possible that both are FALSE for a particular CPU. Although it * is unclear what that would imply about the interrupt processing @@ -122,7 +123,7 @@ extern "C" { * or CPU_INSTALL_HARDWARE_INTERRUPT_STACK is TRUE. */ -#define CPU_ALLOCATE_INTERRUPT_STACK TRUE +#define CPU_ALLOCATE_INTERRUPT_STACK FALSE /* * Does the RTEMS invoke the user's ISR with the vector number and @@ -141,7 +142,7 @@ extern "C" { * If there is a FP coprocessor such as the i387 or mc68881, then * the answer is TRUE. * - * The macro name "NO_CPU_HAS_FPU" should be made CPU specific. + * The macro name "ARM_HAS_FPU" should be made CPU specific. * It indicates whether or not this CPU model has FP support. For * example, it would be possible to have an i386_nofp CPU model * which set this to false to indicate that you have an i386 without @@ -331,12 +332,8 @@ extern "C" { * this is enough information for RTEMS, it is probably not enough for * a debugger such as gdb. But that is another problem. */ - typedef struct { - unsigned32 register_r0; - unsigned32 register_r1; - unsigned32 register_r2; - unsigned32 register_r3; + unsigned32 register_cpsr; unsigned32 register_r4; unsigned32 register_r5; unsigned32 register_r6; @@ -345,18 +342,23 @@ typedef struct { unsigned32 register_r9; unsigned32 register_r10; unsigned32 register_fp; - unsigned32 register_ip; unsigned32 register_sp; unsigned32 register_lr; unsigned32 register_pc; - unsigned32 register_cpsr; } Context_Control; typedef struct { double some_float_register; } Context_Control_fp; -typedef Context_Control CPU_Exception_frame; +typedef struct { + unsigned32 register_r0; + unsigned32 register_r1; + unsigned32 register_r2; + unsigned32 register_r3; + unsigned32 register_ip; + unsigned32 register_lr; +} CPU_Exception_frame; typedef void (*cpuExcHandlerType) (CPU_Exception_frame*); extern cpuExcHandlerType _currentExcHandler; @@ -372,7 +374,7 @@ typedef CPU_Exception_frame CPU_Interrupt_frame; /* * The following table contains the information required to configure - * the ARM processor specific parameters. + * the XXX processor specific parameters. */ typedef struct { @@ -396,7 +398,9 @@ typedef struct { */ /* - * Macros to access NO_CPU specific additions to the CPU Table + * Macros to access ARM specific additions to the CPU Table + * + * none required */ /* There are no CPU specific additions to the CPU Table for this port. */ @@ -410,40 +414,6 @@ typedef struct { SCORE_EXTERN Context_Control_fp _CPU_Null_fp_context; -/* - * On some CPUs, RTEMS supports a software managed interrupt stack. - * This stack is allocated by the Interrupt Manager and the switch - * is performed in _ISR_Handler. These variables contain pointers - * to the lowest and highest addresses in the chunk of memory allocated - * for the interrupt stack. Since it is unknown whether the stack - * grows up or down (in general), this give the CPU dependent - * code the option of picking the version it wants to use. - * - * NOTE: These two variables are required if the macro - * CPU_HAS_SOFTWARE_INTERRUPT_STACK is defined as TRUE. - */ - -SCORE_EXTERN void *_CPU_Interrupt_stack_low; -SCORE_EXTERN void *_CPU_Interrupt_stack_high; - -/* - * With some compilation systems, it is difficult if not impossible to - * call a high-level language routine from assembly language. This - * is especially true of commercial Ada compilers and name mangling - * C++ ones. This variable can be optionally defined by the CPU porter - * and contains the address of the routine _Thread_Dispatch. This - * can make it easier to invoke that routine at the end of the interrupt - * sequence (if a dispatch is necessary). - */ - -SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); - -/* - * Nothing prevents the porter from declaring more CPU specific variables. - */ - -/* XXX: if needed, put more variables here */ - /* * The size of the floating point context area. On some CPUs this * will not be a "sizeof" because the format of the floating point @@ -481,7 +451,7 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * that a "reasonable" small application should not have any problems. */ -#define CPU_STACK_MINIMUM_SIZE (1024*16) +#define CPU_STACK_MINIMUM_SIZE (1024*4) /* * CPU's worst alignment requirement for data types on a byte boundary. This @@ -535,7 +505,7 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * Support routine to initialize the RTEMS vector table after it is allocated. */ -#define _CPU_Initialize_vectors() +#define _CPU_Initialize_vectors() /* * Disable all interrupts for an RTEMS critical section. The previous @@ -543,15 +513,13 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); */ #define _CPU_ISR_Disable( _level ) \ - do { \ - int reg; \ - asm volatile ("MRS %0, cpsr \n" \ - "ORR %1, %0, #0xc0 \n" \ - "MSR cpsr, %1 \n" \ - "AND %0, %0, #0xc0 \n" \ - : "=r" (_level), "=r" (reg) \ - : "0" (_level), "1" (reg)); \ - } while (0) + { \ + int reg; \ + asm volatile ("MRS %0, cpsr \n" \ + "ORR %1, %0, #0xc0 \n" \ + "MSR cpsr, %1 \n" \ + : "=&r" (_level), "=&r" (reg)); \ + } /* * Enable interrupts to the previous level (returned by _CPU_ISR_Disable). @@ -560,15 +528,10 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); */ #define _CPU_ISR_Enable( _level ) \ - do { \ - int reg; \ - asm volatile ("MRS %0, cpsr \n" \ - "BIC %0, %0, #0xc0 \n" \ - "ORR %0, %0, %2 \n" \ - "MSR cpsr, %0 \n" \ - : "=r" (reg) \ - : "0" (reg), "r" (_level)); \ - } while (0) + { \ + asm volatile ("MSR cpsr, %0 \n" \ + : : "r" (_level)); \ + } /* * This temporarily restores the interrupt to _level before immediately @@ -579,15 +542,12 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); #define _CPU_ISR_Flash( _level ) \ { \ - int reg1; \ - int reg2; \ + int reg; \ asm volatile ("MRS %0, cpsr \n" \ - "BIC %1, %0, #0xc0 \n" \ - "ORR %1, %1, %4 \n" \ "MSR cpsr, %1 \n" \ "MSR cpsr, %0 \n" \ - : "=r" (reg1), "=r" (reg2) \ - : "0" (reg1), "1" (reg2), "r" (_level)); \ + : "=&r" (reg) \ + : "r" (_level)); \ } /* @@ -603,15 +563,15 @@ SCORE_EXTERN void (*_CPU_Thread_dispatch_pointer)(); * The get routine usually must be implemented as a subroutine. */ -#define _CPU_ISR_Set_level( new_level ) \ - { \ +#define _CPU_ISR_Set_level( new_level ) \ + { \ int reg; \ asm volatile ("MRS %0, cpsr \n" \ - "BIC %0, %0, #0xc0 \n" \ + "BIC %0, %0, #0xc0 \n" \ "ORR %0, %0, %2 \n" \ - "MSR cpsr_c, %0 \n" \ - : "=r" (reg) \ - : "0" (reg), "r" (new_level)); \ + "MSR cpsr_c, %0 \n" \ + : "=r" (reg) \ + : "r" (reg), "0" (reg)); \ } @@ -708,9 +668,17 @@ void _CPU_Context_Initialize( * halts/stops the CPU. */ -#define _CPU_Fatal_halt( _error ) \ - { \ - } +#define _CPU_Fatal_halt( _error ) \ + do { \ + int _level; \ + _CPU_ISR_Disable( _level ); \ + asm volatile ("mov r0, %0\n" \ + : "=r" (_error) \ + : "0" (_error) \ + : "r0" ); \ + while(1) ; \ + } while(0); + /* end of Fatal Error manager macros */ @@ -770,18 +738,17 @@ void _CPU_Context_Initialize( * where bit_set_table[ 16 ] has values which indicate the first * bit set */ +#if (ARM_HAS_CLZ == 0) +# define CPU_USE_GENERIC_BITFIELD_CODE TRUE +# define CPU_USE_GENERIC_BITFIELD_DATA TRUE +#else +# define CPU_USE_GENERIC_BITFIELD_CODE FALSE +# define CPU_USE_GENERIC_BITFIELD_DATA FALSE -#define CPU_USE_GENERIC_BITFIELD_CODE TRUE -#define CPU_USE_GENERIC_BITFIELD_DATA TRUE - -#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE) - -#define _CPU_Bitfield_Find_first_bit( _value, _output ) \ - { \ - (_output) = 0; /* do something to prevent warnings */ \ - } - -#endif +# define _CPU_Bitfield_Find_first_bit( _value, _output ) \ + { \ + (_output) = 0; /* do something to prevent warnings */ \ + } /* end of Bitfield handler macros */ @@ -791,12 +758,10 @@ void _CPU_Context_Initialize( * for that routine. */ -#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE) -#define _CPU_Priority_Mask( _bit_number ) \ - ( 1 << (_bit_number) ) +# define _CPU_Priority_Mask( _bit_number ) \ + ( 1 << (_bit_number) ) -#endif /* * This routine translates the bit numbers returned by @@ -805,11 +770,11 @@ void _CPU_Context_Initialize( * for that routine. */ -#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE) -#define _CPU_Priority_bits_index( _priority ) \ - (_priority) +# define _CPU_Priority_bits_index( _priority ) \ + (_priority) +# error "Implement CLZ verson of priority bit functions for ARMv5" #endif /* end of Priority handler macros */ @@ -862,17 +827,6 @@ void _CPU_ISR_install_vector( void _CPU_Install_interrupt_stack( void ); -/* - * _CPU_Thread_Idle_body - * - * This routine is the CPU dependent IDLE thread body. - * - * NOTE: It need only be provided if CPU_PROVIDES_IDLE_THREAD_BODY - * is TRUE. - */ - -void _CPU_Thread_Idle_body( void ); - /* * _CPU_Context_switch * @@ -897,6 +851,7 @@ void _CPU_Context_restore( Context_Control *new_context ); +#if (ARM_HAS_FPU == 1) /* * _CPU_Context_save_fp * @@ -916,6 +871,7 @@ void _CPU_Context_save_fp( void _CPU_Context_restore_fp( void **fp_context_ptr ); +#endif /* (ARM_HAS_FPU == 1) */ /* The following routine swaps the endian format of an unsigned int. * It must be static because it is referenced indirectly. @@ -941,19 +897,28 @@ static inline unsigned int CPU_swap_u32( unsigned int value ) { - unsigned32 byte1, byte2, byte3, byte4, swapped; - - byte4 = (value >> 24) & 0xff; - byte3 = (value >> 16) & 0xff; - byte2 = (value >> 8) & 0xff; - byte1 = value & 0xff; - - swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4; - return( swapped ); + unsigned32 tmp; + asm volatile ("EOR %1, %0, %0, ROR #16\n" \ + "BIC %1, %1, #0xff0000\n" \ + "MOV %0, %0, ROR #8\n" \ + "EOR %0, %0, %1, LSR #8\n" \ + : "=&r" (value), "=&r" (tmp) \ + : "0" (value)); + + return value; } -#define CPU_swap_u16( value ) \ - (((value&0xff) << 8) | ((value >> 8)&0xff)) +static inline unsigned16 CPU_swap_u16(unsigned16 value) +{ + unsigned32 tmp = value; /* make compiler warnings go away */ + asm volatile ("MOV %1, %0, LSR #8\n" \ + "BIC %0, %0, #0xff00\n" \ + "MOV %0, %0, LSL #8\n" \ + "ORR %0, %0, %1\n" \ + : "=&r" (value), "=&r" (tmp) \ + : "0" (value)); + return value; +} #ifdef __cplusplus } diff --git a/cpukit/score/cpu/arm/rtems/score/cpu_asm.h b/cpukit/score/cpu/arm/rtems/score/cpu_asm.h index 2c13347578..9cc5577a56 100644 --- a/cpukit/score/cpu/arm/rtems/score/cpu_asm.h +++ b/cpukit/score/cpu/arm/rtems/score/cpu_asm.h @@ -18,24 +18,18 @@ /* Registers saved in context switch: */ -.set REG_R0, 0 -.set REG_R1, 4 -.set REG_R2, 8 -.set REG_R3, 12 -.set REG_R4, 16 -.set REG_R5, 20 -.set REG_R6, 24 -.set REG_R7, 28 -.set REG_R8, 32 -.set REG_R9, 36 -.set REG_R10, 40 -.set REG_R11, 44 -.set REG_R12, 48 -.set REG_SP, 52 -.set REG_LR, 56 -.set REG_PC, 60 -.set REG_CPSR, 64 -.set SIZE_REGS, REG_CPSR + 4 - +.set REG_CPSR, 0 +.set REG_R4, 4 +.set REG_R5, 8 +.set REG_R6, 12 +.set REG_R7, 16 +.set REG_R8, 20 +.set REG_R9, 24 +.set REG_R10, 28 +.set REG_R11, 32 +.set REG_SP, 36 +.set REG_LR, 40 +.set REG_PC, 44 +.set SIZE_REGS, REG_PC + 4 #endif diff --git a/cpukit/score/cpu/arm/rtems/score/types.h b/cpukit/score/cpu/arm/rtems/score/types.h index 4408046d4e..dc790a2b0b 100644 --- a/cpukit/score/cpu/arm/rtems/score/types.h +++ b/cpukit/score/cpu/arm/rtems/score/types.h @@ -25,25 +25,24 @@ extern "C" { * This section defines the basic types for this processor. */ -typedef unsigned char unsigned8; /* unsigned 8-bit integer */ -typedef unsigned short unsigned16; /* unsigned 16-bit integer */ -typedef unsigned int unsigned32; /* unsigned 32-bit integer */ -typedef unsigned long long unsigned64; /* unsigned 64-bit integer */ +typedef unsigned char unsigned8; /* unsigned 8-bit integer */ +typedef unsigned short unsigned16; /* unsigned 16-bit integer */ +typedef unsigned int unsigned32; /* unsigned 32-bit integer */ +typedef unsigned long long unsigned64; /* unsigned 64-bit integer */ -typedef unsigned16 Priority_Bit_map_control; +typedef signed char signed8; /* 8-bit signed integer */ +typedef signed short signed16; /* 16-bit signed integer */ +typedef signed int signed32; /* 32-bit signed integer */ +typedef signed long long signed64; /* 64 bit signed integer */ -typedef signed char signed8; /* 8-bit signed integer */ -typedef signed short signed16; /* 16-bit signed integer */ -typedef signed int signed32; /* 32-bit signed integer */ -typedef signed long long signed64; /* 64 bit signed integer */ +typedef unsigned32 boolean; /* Boolean value */ +typedef unsigned16 Priority_Bit_map_control; -typedef unsigned32 boolean; /* Boolean value */ +typedef float single_precision; /* single precision float */ +typedef double double_precision; /* double precision float */ -typedef float single_precision; /* single precision float */ -typedef double double_precision; /* double precision float */ - -typedef void no_cpu_isr; -typedef void ( *no_cpu_isr_entry )( void ); +typedef void arm_cpu_isr; +typedef void ( *arm_cpu_isr_entry )( void ); #ifdef __cplusplus } -- cgit v1.2.3