[632e4306] | 1 | /** |
---|
| 2 | * @file |
---|
[08330bf] | 3 | * |
---|
[78623bce] | 4 | * @ingroup ScoreCPU |
---|
| 5 | * |
---|
| 6 | * @brief ARM architecture support implementation. |
---|
[632e4306] | 7 | */ |
---|
| 8 | |
---|
| 9 | /* |
---|
[08330bf] | 10 | * COPYRIGHT (c) 2000 Canon Research Centre France SA. |
---|
| 11 | * Emmanuel Raguet, mailto:raguet@crf.canon.fr |
---|
| 12 | * |
---|
[4f0b287] | 13 | * Copyright (c) 2002 Advent Networks, Inc |
---|
| 14 | * Jay Monkman <jmonkman@adventnetworks.com> |
---|
| 15 | * |
---|
[a3ff693] | 16 | * Copyright (c) 2007 Ray xu <rayx.cn@gmail.com> |
---|
| 17 | * |
---|
[632e4306] | 18 | * Copyright (c) 2009 embedded brains GmbH |
---|
| 19 | * |
---|
[08330bf] | 20 | * The license and distribution terms for this file may be |
---|
| 21 | * found in the file LICENSE in this distribution or at |
---|
[57b8a7b6] | 22 | * http://www.rtems.com/license/LICENSE. |
---|
[08330bf] | 23 | * |
---|
[bf0a3b2] | 24 | * $Id$ |
---|
[08330bf] | 25 | */ |
---|
| 26 | |
---|
[0acc9af3] | 27 | #ifdef HAVE_CONFIG_H |
---|
| 28 | #include "config.h" |
---|
| 29 | #endif |
---|
| 30 | |
---|
[08330bf] | 31 | #include <rtems/system.h> |
---|
| 32 | #include <rtems.h> |
---|
[d56918c9] | 33 | #include <rtems/bspIo.h> |
---|
[08330bf] | 34 | #include <rtems/score/isr.h> |
---|
| 35 | #include <rtems/score/wkspace.h> |
---|
| 36 | #include <rtems/score/thread.h> |
---|
| 37 | #include <rtems/score/cpu.h> |
---|
| 38 | |
---|
[547af38] | 39 | /* |
---|
| 40 | * This variable can be used to change the running mode of the execution |
---|
| 41 | * contexts. |
---|
| 42 | */ |
---|
[632e4306] | 43 | uint32_t arm_cpu_mode = 0x13; |
---|
[547af38] | 44 | |
---|
[632e4306] | 45 | void _CPU_Context_Initialize( |
---|
| 46 | Context_Control *the_context, |
---|
| 47 | uint32_t *stack_base, |
---|
| 48 | uint32_t size, |
---|
| 49 | uint32_t new_level, |
---|
| 50 | void *entry_point, |
---|
| 51 | bool is_fp |
---|
| 52 | ) |
---|
[08330bf] | 53 | { |
---|
[632e4306] | 54 | the_context->register_sp = (uint32_t) stack_base + size ; |
---|
| 55 | the_context->register_lr = (uint32_t) entry_point; |
---|
| 56 | the_context->register_cpsr = new_level | arm_cpu_mode; |
---|
[08330bf] | 57 | } |
---|
| 58 | |
---|
[632e4306] | 59 | /* Preprocessor magic for stringification of x */ |
---|
| 60 | #define _CPU_ISR_LEVEL_DO_STRINGOF( x) #x |
---|
| 61 | #define _CPU_ISR_LEVEL_STRINGOF( x) _CPU_ISR_LEVEL_DO_STRINGOF( x) |
---|
[661e5de4] | 62 | |
---|
[632e4306] | 63 | void _CPU_ISR_Set_level( uint32_t level ) |
---|
[08330bf] | 64 | { |
---|
[39c8fdb] | 65 | uint32_t arm_switch_reg; |
---|
[632e4306] | 66 | |
---|
| 67 | asm volatile ( |
---|
[39c8fdb] | 68 | ARM_SWITCH_TO_ARM |
---|
| 69 | "mrs %[arm_switch_reg], cpsr\n" |
---|
| 70 | "bic %[arm_switch_reg], #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n" |
---|
| 71 | "orr %[arm_switch_reg], %[level]\n" |
---|
[632e4306] | 72 | "msr cpsr, %0\n" |
---|
[39c8fdb] | 73 | ARM_SWITCH_BACK |
---|
| 74 | : [arm_switch_reg] "=&r" (arm_switch_reg) |
---|
| 75 | : [level] "r" (level) |
---|
[632e4306] | 76 | ); |
---|
[08330bf] | 77 | } |
---|
[661e5de4] | 78 | |
---|
[632e4306] | 79 | uint32_t _CPU_ISR_Get_level( void ) |
---|
| 80 | { |
---|
[39c8fdb] | 81 | ARM_SWITCH_REGISTERS; |
---|
[632e4306] | 82 | uint32_t level; |
---|
| 83 | |
---|
| 84 | asm volatile ( |
---|
[39c8fdb] | 85 | ARM_SWITCH_TO_ARM |
---|
| 86 | "mrs %[level], cpsr\n" |
---|
| 87 | "and %[level], #" _CPU_ISR_LEVEL_STRINGOF( CPU_MODES_INTERRUPT_MASK ) "\n" |
---|
| 88 | ARM_SWITCH_BACK |
---|
| 89 | : [level] "=&r" (level) ARM_SWITCH_ADDITIONAL_OUTPUT |
---|
[632e4306] | 90 | ); |
---|
| 91 | |
---|
| 92 | return level; |
---|
| 93 | } |
---|
[08330bf] | 94 | |
---|
| 95 | void _CPU_ISR_install_vector( |
---|
[632e4306] | 96 | uint32_t vector, |
---|
| 97 | proc_ptr new_handler, |
---|
| 98 | proc_ptr *old_handler |
---|
[08330bf] | 99 | ) |
---|
| 100 | { |
---|
[632e4306] | 101 | /* Redirection table starts at the end of the vector table */ |
---|
[5bb38e15] | 102 | volatile uint32_t *table = (volatile uint32_t *) (MAX_EXCEPTIONS * 4); |
---|
[4f0b287] | 103 | |
---|
[632e4306] | 104 | uint32_t current_handler = table [vector]; |
---|
[5bb38e15] | 105 | |
---|
[632e4306] | 106 | /* The current handler is now the old one */ |
---|
| 107 | if (old_handler != NULL) { |
---|
| 108 | *old_handler = (proc_ptr) current_handler; |
---|
| 109 | } |
---|
| 110 | |
---|
| 111 | /* Write only if necessary to avoid writes to a maybe read-only memory */ |
---|
| 112 | if (current_handler != (uint32_t) new_handler) { |
---|
| 113 | table [vector] = (uint32_t) new_handler; |
---|
| 114 | } |
---|
[08330bf] | 115 | } |
---|
| 116 | |
---|
[fa237002] | 117 | void _CPU_Install_interrupt_stack( void ) |
---|
[08330bf] | 118 | { |
---|
[632e4306] | 119 | /* This function is empty since the BSP must set up the interrupt stacks */ |
---|
[08330bf] | 120 | } |
---|
| 121 | |
---|
[632e4306] | 122 | void _CPU_Initialize( void ) |
---|
[08330bf] | 123 | { |
---|
[632e4306] | 124 | /* Do nothing */ |
---|
[08330bf] | 125 | } |
---|