xref: /nrf52832-nimble/rt-thread/libcpu/arm/cortex-a/trap.c (revision 167494296f0543431a51b6b1b83e957045294e05)
1 /*
2  * Copyright (c) 2006-2018, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2013-07-20     Bernard      first version
9  */
10 
11 #include <rtthread.h>
12 #include <rthw.h>
13 #include <board.h>
14 
15 #include "armv7.h"
16 
17 #include "gic.h"
18 
19 extern struct rt_thread *rt_current_thread;
20 #ifdef RT_USING_FINSH
21 extern long list_thread(void);
22 #endif
23 
24 /**
25  * this function will show registers of CPU
26  *
27  * @param regs the registers point
28  */
29 void rt_hw_show_register(struct rt_hw_exp_stack *regs)
30 {
31     rt_kprintf("Execption:\n");
32     rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3);
33     rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7);
34     rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10);
35     rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip);
36     rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc);
37     rt_kprintf("cpsr:0x%08x\n", regs->cpsr);
38 }
39 
40 /**
41  * When comes across an instruction which it cannot handle,
42  * it takes the undefined instruction trap.
43  *
44  * @param regs system registers
45  *
46  * @note never invoke this function in application
47  */
48 void rt_hw_trap_undef(struct rt_hw_exp_stack *regs)
49 {
50     rt_kprintf("undefined instruction:\n");
51     rt_hw_show_register(regs);
52 #ifdef RT_USING_FINSH
53     list_thread();
54 #endif
55     rt_hw_cpu_shutdown();
56 }
57 
58 /**
59  * The software interrupt instruction (SWI) is used for entering
60  * Supervisor mode, usually to request a particular supervisor
61  * function.
62  *
63  * @param regs system registers
64  *
65  * @note never invoke this function in application
66  */
67 void rt_hw_trap_swi(struct rt_hw_exp_stack *regs)
68 {
69     rt_kprintf("software interrupt:\n");
70     rt_hw_show_register(regs);
71 #ifdef RT_USING_FINSH
72     list_thread();
73 #endif
74     rt_hw_cpu_shutdown();
75 }
76 
77 /**
78  * An abort indicates that the current memory access cannot be completed,
79  * which occurs during an instruction prefetch.
80  *
81  * @param regs system registers
82  *
83  * @note never invoke this function in application
84  */
85 void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs)
86 {
87     rt_kprintf("prefetch abort:\n");
88     rt_hw_show_register(regs);
89 #ifdef RT_USING_FINSH
90     list_thread();
91 #endif
92     rt_hw_cpu_shutdown();
93 }
94 
95 /**
96  * An abort indicates that the current memory access cannot be completed,
97  * which occurs during a data access.
98  *
99  * @param regs system registers
100  *
101  * @note never invoke this function in application
102  */
103 void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs)
104 {
105     rt_kprintf("data abort:");
106     rt_hw_show_register(regs);
107 #ifdef RT_USING_FINSH
108     list_thread();
109 #endif
110     rt_hw_cpu_shutdown();
111 }
112 
113 /**
114  * Normally, system will never reach here
115  *
116  * @param regs system registers
117  *
118  * @note never invoke this function in application
119  */
120 void rt_hw_trap_resv(struct rt_hw_exp_stack *regs)
121 {
122     rt_kprintf("reserved trap:\n");
123     rt_hw_show_register(regs);
124 #ifdef RT_USING_FINSH
125     list_thread();
126 #endif
127     rt_hw_cpu_shutdown();
128 }
129 
130 void rt_hw_trap_irq(void)
131 {
132     void *param;
133     rt_isr_handler_t isr_func;
134     extern struct rt_irq_desc isr_table[];
135 
136     // vectNum = RESERVED[31:13] | CPUID[12:10] | INTERRUPT_ID[9:0]
137     // send ack and get ID source
138     uint32_t vectNum = gic_read_irq_ack();
139 
140     // Check that INT_ID isn't 1023 or 1022 (spurious interrupt)
141     if (vectNum & 0x0200)
142     {
143         gic_write_end_of_irq(vectNum);  // send end of irq
144     }
145     else
146     {
147         // copy the local value to the global image of CPUID
148         unsigned cpu = (vectNum >> 10) & 0x7;
149         unsigned irq = vectNum & 0x1FF;
150 
151         /* skip warning */
152         cpu = cpu;
153 
154         // Call the service routine stored in the handlers array. If there isn't
155         // one for this IRQ, then call the default handler.
156         /* get interrupt service routine */
157         isr_func = isr_table[irq].handler;
158 #ifdef RT_USING_INTERRUPT_INFO
159         isr_table[irq].counter++;
160 #endif
161         if (isr_func)
162         {
163             /* Interrupt for myself. */
164             param = isr_table[irq].param;
165             /* turn to interrupt service routine */
166             isr_func(irq, param);
167         }
168 
169         // Signal the end of the irq.
170         gic_write_end_of_irq(vectNum);
171     }
172 }
173 
174 void rt_hw_trap_fiq(void)
175 {
176     /* TODO */
177 }
178