source: rtems/cpukit/score/cpu/arm/cpu.c @ f172fc8

4.104.114.84.95
Last change on this file since f172fc8 was ea1d598f, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 11, 2006 at 9:41:36 PM

2006-09-11 Joel Sherrill <joel@…>

  • cpu.c: Remove warning.
  • Property mode set to 100644
File size: 10.3 KB
Line 
1/*
2 *  ARM CPU Dependent Source
3 *
4 *
5 *  COPYRIGHT (c) 2000 Canon Research Centre France SA.
6 *  Emmanuel Raguet, mailto:raguet@crf.canon.fr
7 *
8 *  Copyright (c) 2002 Advent Networks, Inc
9 *      Jay Monkman <jmonkman@adventnetworks.com>
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.rtems.com/license/LICENSE.
14 *
15 */
16
17#include <rtems/system.h>
18#include <rtems.h>
19#include <rtems/bspIo.h>
20#include <rtems/score/isr.h>
21#include <rtems/score/wkspace.h>
22#include <rtems/score/thread.h>
23#include <rtems/score/cpu.h>
24
25/*  _CPU_Initialize
26 *
27 *  This routine performs processor dependent initialization.
28 *
29 *  INPUT PARAMETERS:
30 *    cpu_table       - CPU table to initialize
31 *    thread_dispatch - address of ISR disptaching routine (unused)
32 *   
33 */
34
35uint32_t   g_data_abort_cnt = 0;
36uint32_t   g_data_abort_insn_list[1024];
37
38void _CPU_Initialize(
39  rtems_cpu_table  *cpu_table,
40  void      (*thread_dispatch)      /* ignored on this CPU */
41)
42{
43    _CPU_Table = *cpu_table;
44}
45
46/*
47 *
48 *  _CPU_ISR_Get_level - returns the current interrupt level
49 */
50 
51uint32_t   _CPU_ISR_Get_level( void )
52{
53    uint32_t   reg = 0; /* to avoid warning */
54   
55    asm volatile ("mrs  %0, cpsr \n"           \
56                  "and  %0,  %0, #0xc0 \n"     \
57                  : "=r" (reg)                 \
58                  : "0" (reg) );
59   
60    return reg;
61}
62
63/*
64 *  _CPU_ISR_install_vector
65 *
66 *  This kernel routine installs the RTEMS handler for the
67 *  specified vector.
68 *
69 *  Input parameters:
70 *    vector      - interrupt vector number
71 *    new_handler - replacement ISR for this vector number
72 *    old_handler - pointer to store former ISR for this vector number
73 *
74 *  FIXME: This vector scheme should be changed to allow FIQ to be
75 *         handled better. I'd like to be able to put VectorTable
76 *         elsewhere - JTM
77 *
78 *
79 *  Output parameters:  NONE
80 *
81 */
82void _CPU_ISR_install_vector(
83  uint32_t    vector,
84  proc_ptr    new_handler,
85  proc_ptr   *old_handler
86)
87{
88    /* pointer on the redirection table in RAM */
89    long *VectorTable = (long *)(MAX_EXCEPTIONS * 4); 
90   
91    if (old_handler != NULL) {
92        old_handler = *(proc_ptr *)(VectorTable + vector);
93    }
94
95    *(VectorTable + vector) = (long)new_handler ;
96 
97}
98
99void _CPU_Context_Initialize(
100  Context_Control  *the_context,
101  uint32_t         *stack_base,
102  uint32_t          size,
103  uint32_t          new_level,
104  void             *entry_point,
105  boolean           is_fp
106)
107{
108    the_context->register_sp = (uint32_t  )stack_base + size ;
109    the_context->register_lr = (uint32_t  )entry_point;
110    the_context->register_cpsr = new_level | 0x13;
111}
112
113
114/*
115 *  _CPU_Install_interrupt_stack - this function is empty since the
116 *  BSP must set up the interrupt stacks.
117 */
118
119void _CPU_Install_interrupt_stack( void )
120{
121}
122
123void _defaultExcHandler (CPU_Exception_frame *ctx)
124{
125    printk("\n\r");
126    printk("----------------------------------------------------------\n\r");
127#if 1
128    printk("Exception 0x%x caught at PC 0x%x by thread %d\n",
129           ctx->register_ip, ctx->register_lr - 4,
130           _Thread_Executing->Object.id);
131#endif
132    printk("----------------------------------------------------------\n\r");
133    printk("Processor execution context at time of the fault was  :\n\r");
134    printk("----------------------------------------------------------\n\r");
135#if 0
136    printk(" r0  = %8x  r1  = %8x  r2  = %8x  r3  = %8x\n\r",
137           ctx->register_r0, ctx->register_r1,
138           ctx->register_r2, ctx->register_r3);
139    printk(" r4  = %8x  r5  = %8x  r6  = %8x  r7  = %8x\n\r",
140           ctx->register_r4, ctx->register_r5,
141           ctx->register_r6, ctx->register_r7);
142    printk(" r8  = %8x  r9  = %8x  r10 = %8x\n\r",
143           ctx->register_r8, ctx->register_r9, ctx->register_r10);
144    printk(" fp  = %8x  ip  = %8x  sp  = %8x  pc  = %8x\n\r",
145           ctx->register_fp, ctx->register_ip,
146           ctx->register_sp, ctx->register_lr - 4);
147    printk("----------------------------------------------------------\n\r");
148#endif   
149    if (_ISR_Nest_level > 0) {
150        /*
151         * In this case we shall not delete the task interrupted as
152         * it has nothing to do with the fault. We cannot return either
153         * because the eip points to the faulty instruction so...
154         */
155        printk("Exception while executing ISR!!!. System locked\n\r");
156        while(1);
157    }
158    else {
159        printk("*********** FAULTY THREAD WILL BE DELETED **************\n\r");
160        rtems_task_delete(_Thread_Executing->Object.id);
161    }
162}
163
164cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
165
166extern void _Exception_Handler_Undef_Swi(); 
167extern void _Exception_Handler_Abort(); 
168extern void _exc_data_abort(); 
169/* FIXME: put comments here */
170void rtems_exception_init_mngt()
171{
172        ISR_Level level;
173     
174      _CPU_ISR_Disable(level);
175      _CPU_ISR_install_vector(ARM_EXCEPTION_UNDEF,
176                              _Exception_Handler_Undef_Swi,
177                              NULL);
178 
179      _CPU_ISR_install_vector(ARM_EXCEPTION_SWI,
180                              _Exception_Handler_Undef_Swi,
181                              NULL);
182     
183      _CPU_ISR_install_vector(ARM_EXCEPTION_PREF_ABORT,
184                              _Exception_Handler_Abort,
185                              NULL);
186     
187      _CPU_ISR_install_vector(ARM_EXCEPTION_DATA_ABORT,
188                              _exc_data_abort,
189                              NULL);
190     
191      _CPU_ISR_install_vector(ARM_EXCEPTION_FIQ,       
192                              _Exception_Handler_Abort,
193                              NULL);
194     
195      _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, 
196                              _Exception_Handler_Abort,
197                              NULL);
198     
199      _CPU_ISR_Enable(level);
200}
201 
202#define INSN_MASK         0xc5
203
204#define INSN_STM1         0x80
205#define INSN_STM2         0x84
206#define INSN_STR          0x40
207#define INSN_STRB         0x44
208
209#define INSN_LDM1         0x81
210#define INSN_LDM23        0x85
211#define INSN_LDR          0x41
212#define INSN_LDRB         0x45
213
214#define GET_RD(x)         ((x & 0x0000f000) >> 12)
215#define GET_RN(x)         ((x & 0x000f0000) >> 16)
216
217#define GET_U(x)              ((x & 0x00800000) >> 23)
218#define GET_I(x)              ((x & 0x02000000) >> 25)
219
220#define GET_REG(r, ctx)      (((uint32_t   *)ctx)[r])
221#define SET_REG(r, ctx, v)   (((uint32_t   *)ctx)[r] = v)
222#define GET_OFFSET(insn)     (insn & 0xfff)
223
224char *_print_full_context_mode2txt[0x20]={
225        [0x10]="user",  /* User */
226        [0x11]="fiq",   /* FIQ - Fast Interrupt Request */
227        [0x12]="irq",   /* IRQ - Interrupt Request */
228        [0x13]="super", /* Supervisor */
229        [0x17]="abort", /* Abort */
230        [0x1b]="undef", /* Undefined */
231        [0x1f]="system" /* System */
232    };
233
234void _print_full_context(uint32_t spsr)
235{
236    char *mode;
237    uint32_t prev_sp,prev_lr,cpsr,tmp;
238    int i;
239
240    printk("active thread thread 0x%08x\n", _Thread_Executing->Object.id);
241
242    mode=_print_full_context_mode2txt[spsr&0x1f];
243    if(!mode) mode="unknown";
244
245    asm volatile ("     MRS  %[cpsr], cpsr \n"
246              " ORR  %[tmp], %[spsr], #0xc0 \n"
247              " MSR  cpsr_c, %[tmp] \n"
248              " MOV  %[prev_sp], sp \n"
249              " MOV  %[prev_lr], lr \n"
250              " MSR  cpsr_c, %[cpsr] \n"
251              : [prev_sp] "=&r" (prev_sp), [prev_lr] "=&r" (prev_lr),
252                [cpsr] "=&r" (cpsr), [tmp] "=&r" (tmp)
253              : [spsr] "r" (spsr)
254              : "cc");
255
256    printk("Previous sp=0x%08x lr=0x%08x and actual cpsr=%08x\n", prev_sp, prev_lr, cpsr);
257
258    for(i=0;i<48;){
259        printk(" 0x%08x",((uint32_t*)prev_sp)[i++]);
260        if((i%6) == 0)
261            printk("\n");
262    }
263
264}
265
266/* This function is supposed to figure out what caused the
267 * data abort, do that, then return.
268 *
269 * All unhandled instructions cause the system to hang.
270 */
271
272void do_data_abort(uint32_t   insn, uint32_t   spsr, 
273                    Context_Control *ctx)
274{
275    /* Clarify, which type is correct, CPU_Exception_frame or Context_Control */
276
277    uint8_t    decode;
278    uint8_t    insn_type;
279
280#if 0
281    uint32_t   rn;
282    uint32_t   rd;
283
284    uint8_t    *src_addr;
285#endif
286    uint32_t    tmp;
287
288    g_data_abort_insn_list[g_data_abort_cnt & 0x3ff] = ctx->register_lr - 8;
289    g_data_abort_cnt++;
290   
291    decode = ((insn >> 20) & 0xff);
292
293    insn_type = decode & INSN_MASK;
294    switch(insn_type) {
295    case INSN_STM1:
296        printk("\n\nINSN_STM1\n");
297        break;
298    case INSN_STM2:
299        printk("\n\nINSN_STM2\n");
300        break;
301    case INSN_STR:
302        printk("\n\nINSN_STR\n");
303        break;
304    case INSN_STRB:
305        printk("\n\nINSN_STRB\n");
306        break;
307    case INSN_LDM1:
308        printk("\n\nINSN_LDM1\n");
309        break;
310    case INSN_LDM23:
311        printk("\n\nINSN_LDM23\n");
312        break;
313    case INSN_LDR:
314        printk("\n\nINSN_LDR\n");
315
316#if 0
317        rn = GET_RN(insn);
318        rd = GET_RD(insn);
319
320        /* immediate offset/index */
321        if (GET_I(insn) == 0) {
322            switch(decode & 0x12) {  /* P and W bits */
323            case 0x00:  /* P=0, W=0 -> base is updated, post-indexed */
324                printk("\tPost-indexed\n");
325                break;
326            case 0x02:  /* P=0, W=1 -> user mode access */
327                printk("\tUser mode\n");
328                break;
329            case 0x10:  /* P=1, W=0 -> base not updated */
330                src_addr = (uint8_t   *)GET_REG(rn, ctx);
331                if (GET_U(insn) == 0) {
332                    src_addr -= GET_OFFSET(insn);
333                } else {
334                    src_addr += GET_OFFSET(insn);
335                }
336                tmp = (src_addr[0] |
337                       (src_addr[1] << 8) |
338                       (src_addr[2] << 16) |
339                       (src_addr[3] << 24));
340                SET_REG(rd, ctx, tmp);
341                return;
342                break;
343            case 0x12:  /* P=1, W=1 -> base is updated, pre-indexed */
344                printk("\tPre-indexed\n");
345                break;
346            }
347        }
348#endif
349
350        break;
351    case INSN_LDRB:
352        printk("\n\nINSN_LDRB\n");
353        break;
354    default:
355        printk("\n\nUnrecognized instruction\n");
356        break;
357    }
358   
359    printk("data_abort at address 0x%x, instruction: 0x%x,   spsr = 0x%x\n",
360           ctx->register_lr - 8, insn, spsr);
361
362    _print_full_context(spsr);
363
364    /* disable interrupts, wait forever */
365    _CPU_ISR_Disable(tmp);
366    while(1) {
367        continue;
368    }
369    return;
370}
Note: See TracBrowser for help on using the repository browser.