1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
/*
* File : cpuport.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date Author Notes
* 2011-10-21 Bernard the first version.
* 2011-10-27 aozima update for cortex-M4 FPU.
* 2011-12-31 aozima fixed stack align issues.
* 2012-01-01 aozima support context switch load/store FPU register.
* 2012-12-11 lgnq fixed the coding style.
* 2012-12-23 aozima stack addr align to 8byte.
* 2012-12-29 Bernard Add exception hook.
* 2013-06-23 aozima support lazy stack optimized.
*/
#include <rtthread.h>
#define USE_FPU /* ARMCC */ ( (defined ( __CC_ARM ) && defined ( __TARGET_FPU_VFP )) \
/* IAR */ || (defined ( __ICCARM__ ) && defined ( __ARMVFP__ )) \
/* GNU */ || (defined ( __GNUC__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) )
/* exception and interrupt handler table */
rt_uint32_t rt_interrupt_from_thread;
rt_uint32_t rt_interrupt_to_thread;
rt_uint32_t rt_thread_switch_interrupt_flag;
/* exception hook */
static rt_err_t (*rt_exception_hook)(void *context) = RT_NULL;
struct exception_stack_frame
{
rt_uint32_t r0;
rt_uint32_t r1;
rt_uint32_t r2;
rt_uint32_t r3;
rt_uint32_t r12;
rt_uint32_t lr;
rt_uint32_t pc;
rt_uint32_t psr;
};
struct stack_frame
{
#if USE_FPU
rt_uint32_t flag;
#endif /* USE_FPU */
/* r4 ~ r11 register */
rt_uint32_t r4;
rt_uint32_t r5;
rt_uint32_t r6;
rt_uint32_t r7;
rt_uint32_t r8;
rt_uint32_t r9;
rt_uint32_t r10;
rt_uint32_t r11;
struct exception_stack_frame exception_stack_frame;
};
struct exception_stack_frame_fpu
{
rt_uint32_t r0;
rt_uint32_t r1;
rt_uint32_t r2;
rt_uint32_t r3;
rt_uint32_t r12;
rt_uint32_t lr;
rt_uint32_t pc;
rt_uint32_t psr;
#if USE_FPU
/* FPU register */
rt_uint32_t S0;
rt_uint32_t S1;
rt_uint32_t S2;
rt_uint32_t S3;
rt_uint32_t S4;
rt_uint32_t S5;
rt_uint32_t S6;
rt_uint32_t S7;
rt_uint32_t S8;
rt_uint32_t S9;
rt_uint32_t S10;
rt_uint32_t S11;
rt_uint32_t S12;
rt_uint32_t S13;
rt_uint32_t S14;
rt_uint32_t S15;
rt_uint32_t FPSCR;
rt_uint32_t NO_NAME;
#endif
};
struct stack_frame_fpu
{
rt_uint32_t flag;
/* r4 ~ r11 register */
rt_uint32_t r4;
rt_uint32_t r5;
rt_uint32_t r6;
rt_uint32_t r7;
rt_uint32_t r8;
rt_uint32_t r9;
rt_uint32_t r10;
rt_uint32_t r11;
#if USE_FPU
/* FPU register s16 ~ s31 */
rt_uint32_t s16;
rt_uint32_t s17;
rt_uint32_t s18;
rt_uint32_t s19;
rt_uint32_t s20;
rt_uint32_t s21;
rt_uint32_t s22;
rt_uint32_t s23;
rt_uint32_t s24;
rt_uint32_t s25;
rt_uint32_t s26;
rt_uint32_t s27;
rt_uint32_t s28;
rt_uint32_t s29;
rt_uint32_t s30;
rt_uint32_t s31;
#endif
struct exception_stack_frame_fpu exception_stack_frame;
};
rt_uint8_t *rt_hw_stack_init(void *tentry,
void *parameter,
rt_uint8_t *stack_addr,
void *texit)
{
struct stack_frame *stack_frame;
rt_uint8_t *stk;
unsigned long i;
stk = stack_addr + sizeof(rt_uint32_t);
stk = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stk, 8);
stk -= sizeof(struct stack_frame);
stack_frame = (struct stack_frame *)stk;
/* init all register */
for (i = 0; i < sizeof(struct stack_frame) / sizeof(rt_uint32_t); i ++)
{
((rt_uint32_t *)stack_frame)[i] = 0xdeadbeef;
}
stack_frame->exception_stack_frame.r0 = (unsigned long)parameter; /* r0 : argument */
stack_frame->exception_stack_frame.r1 = 0; /* r1 */
stack_frame->exception_stack_frame.r2 = 0; /* r2 */
stack_frame->exception_stack_frame.r3 = 0; /* r3 */
stack_frame->exception_stack_frame.r12 = 0; /* r12 */
stack_frame->exception_stack_frame.lr = (unsigned long)texit; /* lr */
stack_frame->exception_stack_frame.pc = (unsigned long)tentry; /* entry point, pc */
stack_frame->exception_stack_frame.psr = 0x01000000L; /* PSR */
#if USE_FPU
stack_frame->flag = 0;
#endif /* USE_FPU */
/* return task's current stack address */
return stk;
}
/**
* This function set the hook, which is invoked on fault exception handling.
*
* @param exception_handle the exception handling hook function.
*/
void rt_hw_exception_install(rt_err_t (*exception_handle)(void* context))
{
rt_exception_hook = exception_handle;
}
void rt_hw_hard_fault_exception(struct exception_stack_frame *exception_stack)
{
extern long list_thread(void);
if (rt_exception_hook != RT_NULL)
{
rt_err_t result;
result = rt_exception_hook(exception_stack);
if (result == RT_EOK) return;
}
rt_kprintf("psr: 0x%08x\n", exception_stack->psr);
rt_kprintf(" pc: 0x%08x\n", exception_stack->pc);
rt_kprintf(" lr: 0x%08x\n", exception_stack->lr);
rt_kprintf("r12: 0x%08x\n", exception_stack->r12);
rt_kprintf("r03: 0x%08x\n", exception_stack->r3);
rt_kprintf("r02: 0x%08x\n", exception_stack->r2);
rt_kprintf("r01: 0x%08x\n", exception_stack->r1);
rt_kprintf("r00: 0x%08x\n", exception_stack->r0);
rt_kprintf("hard fault on thread: %s\n", rt_thread_self()->name);
#ifdef RT_USING_FINSH
list_thread();
#endif
while (1);
}
void rt_hw_cpu_shutdown(void)
{
rt_kprintf("shutdown...\n");
RT_ASSERT(0);
}
|