xref: /nrf52832-nimble/rt-thread/libcpu/avr32/uc3/exception_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero/* This file is part of the ATMEL AVR32-UC3-SoftwareFramework-1.6.0 Release */
2*10465441SEvalZero
3*10465441SEvalZero/*This file is prepared for Doxygen automatic documentation generation.*/
4*10465441SEvalZero/*! \file *********************************************************************
5*10465441SEvalZero *
6*10465441SEvalZero * \brief Exception and interrupt vectors.
7*10465441SEvalZero *
8*10465441SEvalZero * This file maps all events supported by an AVR32.
9*10465441SEvalZero *
10*10465441SEvalZero * - Compiler:           GNU GCC for AVR32
11*10465441SEvalZero * - Supported devices:  All AVR32 devices with an INTC module can be used.
12*10465441SEvalZero * - AppNote:
13*10465441SEvalZero *
14*10465441SEvalZero * \author               Atmel Corporation: http://www.atmel.com \n
15*10465441SEvalZero *                       Support and FAQ: http://support.atmel.no/
16*10465441SEvalZero *
17*10465441SEvalZero ******************************************************************************/
18*10465441SEvalZero
19*10465441SEvalZero/* Copyright (c) 2009 Atmel Corporation. All rights reserved.
20*10465441SEvalZero *
21*10465441SEvalZero * Redistribution and use in source and binary forms, with or without
22*10465441SEvalZero * modification, are permitted provided that the following conditions are met:
23*10465441SEvalZero *
24*10465441SEvalZero * 1. Redistributions of source code must retain the above copyright notice, this
25*10465441SEvalZero * list of conditions and the following disclaimer.
26*10465441SEvalZero *
27*10465441SEvalZero * 2. Redistributions in binary form must reproduce the above copyright notice,
28*10465441SEvalZero * this list of conditions and the following disclaimer in the documentation
29*10465441SEvalZero * and/or other materials provided with the distribution.
30*10465441SEvalZero *
31*10465441SEvalZero * 3. The name of Atmel may not be used to endorse or promote products derived
32*10465441SEvalZero * from this software without specific prior written permission.
33*10465441SEvalZero *
34*10465441SEvalZero * 4. This software may only be redistributed and used in connection with an Atmel
35*10465441SEvalZero * AVR product.
36*10465441SEvalZero *
37*10465441SEvalZero * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
38*10465441SEvalZero * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
39*10465441SEvalZero * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
40*10465441SEvalZero * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
41*10465441SEvalZero * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42*10465441SEvalZero * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43*10465441SEvalZero * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44*10465441SEvalZero * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45*10465441SEvalZero * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46*10465441SEvalZero * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
47*10465441SEvalZero *
48*10465441SEvalZero */
49*10465441SEvalZero
50*10465441SEvalZero#if !__AVR32_UC__ && !__AVR32_AP__
51*10465441SEvalZero  #error Implementation of the AVR32 architecture not supported by the INTC driver.
52*10465441SEvalZero#endif
53*10465441SEvalZero
54*10465441SEvalZero
55*10465441SEvalZero#include <avr32/io.h>
56*10465441SEvalZero
57*10465441SEvalZero
58*10465441SEvalZero//! @{
59*10465441SEvalZero//! \verbatim
60*10465441SEvalZero
61*10465441SEvalZero
62*10465441SEvalZero  .section  .exception, "ax", @progbits
63*10465441SEvalZero
64*10465441SEvalZero
65*10465441SEvalZero// Start of Exception Vector Table.
66*10465441SEvalZero
67*10465441SEvalZero  // EVBA must be aligned with a power of two strictly greater than the EVBA-
68*10465441SEvalZero  // relative offset of the last vector.
69*10465441SEvalZero  .balign 0x200
70*10465441SEvalZero
71*10465441SEvalZero  // Export symbol.
72*10465441SEvalZero  .global _evba
73*10465441SEvalZero  .type _evba, @function
74*10465441SEvalZero_evba:
75*10465441SEvalZero
76*10465441SEvalZero        .org  0x000
77*10465441SEvalZero        // Unrecoverable Exception.
78*10465441SEvalZero_handle_Unrecoverable_Exception:
79*10465441SEvalZero        rjmp $
80*10465441SEvalZero
81*10465441SEvalZero        .org  0x004
82*10465441SEvalZero        // TLB Multiple Hit.
83*10465441SEvalZero_handle_TLB_Multiple_Hit:
84*10465441SEvalZero        rjmp $
85*10465441SEvalZero
86*10465441SEvalZero        .org  0x008
87*10465441SEvalZero        // Bus Error Data Fetch.
88*10465441SEvalZero_handle_Bus_Error_Data_Fetch:
89*10465441SEvalZero        rjmp $
90*10465441SEvalZero
91*10465441SEvalZero        .org  0x00C
92*10465441SEvalZero         // Bus Error Instruction Fetch.
93*10465441SEvalZero_handle_Bus_Error_Instruction_Fetch:
94*10465441SEvalZero        rjmp $
95*10465441SEvalZero
96*10465441SEvalZero        .org  0x010
97*10465441SEvalZero        // NMI.
98*10465441SEvalZero_handle_NMI:
99*10465441SEvalZero        rjmp $
100*10465441SEvalZero
101*10465441SEvalZero        .org  0x014
102*10465441SEvalZero        // Instruction Address.
103*10465441SEvalZero_handle_Instruction_Address:
104*10465441SEvalZero        rjmp $
105*10465441SEvalZero
106*10465441SEvalZero        .org  0x018
107*10465441SEvalZero        // ITLB Protection.
108*10465441SEvalZero_handle_ITLB_Protection:
109*10465441SEvalZero        rjmp $
110*10465441SEvalZero
111*10465441SEvalZero        .org  0x01C
112*10465441SEvalZero        // Breakpoint.
113*10465441SEvalZero_handle_Breakpoint:
114*10465441SEvalZero        rjmp $
115*10465441SEvalZero
116*10465441SEvalZero        .org  0x020
117*10465441SEvalZero        // Illegal Opcode.
118*10465441SEvalZero_handle_Illegal_Opcode:
119*10465441SEvalZero        rjmp $
120*10465441SEvalZero
121*10465441SEvalZero        .org  0x024
122*10465441SEvalZero        // Unimplemented Instruction.
123*10465441SEvalZero_handle_Unimplemented_Instruction:
124*10465441SEvalZero        rjmp $
125*10465441SEvalZero
126*10465441SEvalZero        .org  0x028
127*10465441SEvalZero        // Privilege Violation.
128*10465441SEvalZero_handle_Privilege_Violation:
129*10465441SEvalZero        rjmp $
130*10465441SEvalZero
131*10465441SEvalZero        .org  0x02C
132*10465441SEvalZero        // Floating-Point: UNUSED IN AVR32UC and AVR32AP.
133*10465441SEvalZero_handle_Floating_Point:
134*10465441SEvalZero        rjmp $
135*10465441SEvalZero
136*10465441SEvalZero        .org  0x030
137*10465441SEvalZero        // Coprocessor Absent: UNUSED IN AVR32UC.
138*10465441SEvalZero_handle_Coprocessor_Absent:
139*10465441SEvalZero        rjmp $
140*10465441SEvalZero
141*10465441SEvalZero        .org  0x034
142*10465441SEvalZero        // Data Address (Read).
143*10465441SEvalZero_handle_Data_Address_Read:
144*10465441SEvalZero        rjmp $
145*10465441SEvalZero
146*10465441SEvalZero        .org  0x038
147*10465441SEvalZero        // Data Address (Write).
148*10465441SEvalZero_handle_Data_Address_Write:
149*10465441SEvalZero        rjmp $
150*10465441SEvalZero
151*10465441SEvalZero        .org  0x03C
152*10465441SEvalZero        // DTLB Protection (Read).
153*10465441SEvalZero_handle_DTLB_Protection_Read:
154*10465441SEvalZero        rjmp $
155*10465441SEvalZero
156*10465441SEvalZero        .org  0x040
157*10465441SEvalZero        // DTLB Protection (Write).
158*10465441SEvalZero_handle_DTLB_Protection_Write:
159*10465441SEvalZero        rjmp $
160*10465441SEvalZero
161*10465441SEvalZero        .org  0x044
162*10465441SEvalZero        // DTLB Modified: UNUSED IN AVR32UC.
163*10465441SEvalZero_handle_DTLB_Modified:
164*10465441SEvalZero        rjmp $
165*10465441SEvalZero
166*10465441SEvalZero        .org  0x050
167*10465441SEvalZero        // ITLB Miss.
168*10465441SEvalZero_handle_ITLB_Miss:
169*10465441SEvalZero        rjmp $
170*10465441SEvalZero
171*10465441SEvalZero        .org  0x060
172*10465441SEvalZero        // DTLB Miss (Read).
173*10465441SEvalZero_handle_DTLB_Miss_Read:
174*10465441SEvalZero        rjmp $
175*10465441SEvalZero
176*10465441SEvalZero        .org  0x070
177*10465441SEvalZero        // DTLB Miss (Write).
178*10465441SEvalZero_handle_DTLB_Miss_Write:
179*10465441SEvalZero        rjmp $
180*10465441SEvalZero
181*10465441SEvalZero        .org  0x100
182*10465441SEvalZero        // Supervisor Call.
183*10465441SEvalZero_handle_Supervisor_Call:
184*10465441SEvalZero        rjmp $
185*10465441SEvalZero
186*10465441SEvalZero
187*10465441SEvalZero// Interrupt support.
188*10465441SEvalZero// The interrupt controller must provide the offset address relative to EVBA.
189*10465441SEvalZero// Important note:
190*10465441SEvalZero//   All interrupts call a C function named _get_interrupt_handler.
191*10465441SEvalZero//   This function will read group and interrupt line number to then return in
192*10465441SEvalZero//   R12 a pointer to a user-provided interrupt handler.
193*10465441SEvalZero
194*10465441SEvalZero  .balign 4
195*10465441SEvalZero
196*10465441SEvalZero_int0:
197*10465441SEvalZero  mov     r12, 0          // Pass the int_level parameter to the _get_interrupt_handler function.
198*10465441SEvalZero  call    _get_interrupt_handler
199*10465441SEvalZero  cp.w    r12, 0          // Get the pointer to the interrupt handler returned by the function.
200*10465441SEvalZero  breq    _spint0         // If this was not a spurious interrupt (R12 != NULL), jump to the handler.
201*10465441SEvalZero  call    rt_interrupt_enter
202*10465441SEvalZero  icall   r12
203*10465441SEvalZero  call    rt_interrupt_leave
204*10465441SEvalZero  ssrf    AVR32_SR_GM_OFFSET			/* Disable global interrupt */
205*10465441SEvalZero  lda.w   r12, rt_interrupt_nest		/* Is nested interrupt? */
206*10465441SEvalZero  ld.w    r11, r12[0]
207*10465441SEvalZero  cp.w    r11, 0
208*10465441SEvalZero  brne    _spint0
209*10465441SEvalZero  lda.w   r12, rt_thread_switch_interrupt_flag	/* Is thread switch required? */
210*10465441SEvalZero  ld.w    r11, r12[0]
211*10465441SEvalZero  cp.w    r11, 1
212*10465441SEvalZero  breq    rt_hw_context_switch_interrupt_do
213*10465441SEvalZero_spint0:
214*10465441SEvalZero  csrf    AVR32_SR_GM_OFFSET			/* Enable global interrupt */
215*10465441SEvalZero  rete                    // If this was a spurious interrupt (R12 == NULL), return from event handler.
216*10465441SEvalZero
217*10465441SEvalZero
218*10465441SEvalZero_int1:
219*10465441SEvalZero  mov     r12, 1          // Pass the int_level parameter to the _get_interrupt_handler function.
220*10465441SEvalZero  call    _get_interrupt_handler
221*10465441SEvalZero  cp.w    r12, 0          // Get the pointer to the interrupt handler returned by the function.
222*10465441SEvalZero  breq    _spint1         // If this was not a spurious interrupt (R12 != NULL), jump to the handler.
223*10465441SEvalZero  call    rt_interrupt_enter
224*10465441SEvalZero  icall   r12
225*10465441SEvalZero  call    rt_interrupt_leave
226*10465441SEvalZero  ssrf    AVR32_SR_GM_OFFSET			/* Disable global interrupt */
227*10465441SEvalZero  lda.w   r12, rt_interrupt_nest		/* Is nested interrupt? */
228*10465441SEvalZero  ld.w    r11, r12[0]
229*10465441SEvalZero  cp.w    r11, 0
230*10465441SEvalZero  brne    _spint1
231*10465441SEvalZero  lda.w   r12, rt_thread_switch_interrupt_flag	/* Is thread switch required? */
232*10465441SEvalZero  ld.w    r11, r12[0]
233*10465441SEvalZero  cp.w    r11, 1
234*10465441SEvalZero  breq    rt_hw_context_switch_interrupt_do
235*10465441SEvalZero_spint1:
236*10465441SEvalZero  csrf    AVR32_SR_GM_OFFSET			/* Enable global interrupt */
237*10465441SEvalZero  rete                    // If this was a spurious interrupt (R12 == NULL), return from event handler.
238*10465441SEvalZero
239*10465441SEvalZero
240*10465441SEvalZero_int2:
241*10465441SEvalZero  mov     r12, 2          // Pass the int_level parameter to the _get_interrupt_handler function.
242*10465441SEvalZero  call    _get_interrupt_handler
243*10465441SEvalZero  cp.w    r12, 0          // Get the pointer to the interrupt handler returned by the function.
244*10465441SEvalZero  breq    _spint2         // If this was not a spurious interrupt (R12 != NULL), jump to the handler.
245*10465441SEvalZero  call    rt_interrupt_enter
246*10465441SEvalZero  icall   r12
247*10465441SEvalZero  call    rt_interrupt_leave
248*10465441SEvalZero  ssrf    AVR32_SR_GM_OFFSET			/* Disable global interrupt */
249*10465441SEvalZero  lda.w   r12, rt_interrupt_nest		/* Is nested interrupt? */
250*10465441SEvalZero  ld.w    r11, r12[0]
251*10465441SEvalZero  cp.w    r11, 0
252*10465441SEvalZero  brne    _spint2
253*10465441SEvalZero  lda.w   r12, rt_thread_switch_interrupt_flag	/* Is thread switch required? */
254*10465441SEvalZero  ld.w    r11, r12[0]
255*10465441SEvalZero  cp.w    r11, 1
256*10465441SEvalZero  breq    rt_hw_context_switch_interrupt_do
257*10465441SEvalZero_spint2:
258*10465441SEvalZero  csrf    AVR32_SR_GM_OFFSET			/* Enable global interrupt */
259*10465441SEvalZero  rete                    // If this was a spurious interrupt (R12 == NULL), return from event handler.
260*10465441SEvalZero
261*10465441SEvalZero
262*10465441SEvalZero_int3:
263*10465441SEvalZero  mov     r12, 3          // Pass the int_level parameter to the _get_interrupt_handler function.
264*10465441SEvalZero  call    _get_interrupt_handler
265*10465441SEvalZero  cp.w    r12, 0          // Get the pointer to the interrupt handler returned by the function.
266*10465441SEvalZero  breq    _spint3         // If this was not a spurious interrupt (R12 != NULL), jump to the handler.
267*10465441SEvalZero  call    rt_interrupt_enter
268*10465441SEvalZero  icall   r12
269*10465441SEvalZero  call    rt_interrupt_leave
270*10465441SEvalZero  ssrf    AVR32_SR_GM_OFFSET			/* Disable global interrupt */
271*10465441SEvalZero  lda.w   r12, rt_interrupt_nest		/* Is nested interrupt? */
272*10465441SEvalZero  ld.w    r11, r12[0]
273*10465441SEvalZero  cp.w    r11, 0
274*10465441SEvalZero  brne    _spint3
275*10465441SEvalZero  lda.w   r12, rt_thread_switch_interrupt_flag	/* Is thread switch required? */
276*10465441SEvalZero  ld.w    r11, r12[0]
277*10465441SEvalZero  cp.w    r11, 1
278*10465441SEvalZero  breq    rt_hw_context_switch_interrupt_do
279*10465441SEvalZero_spint3:
280*10465441SEvalZero  csrf    AVR32_SR_GM_OFFSET			/* Enable global interrupt */
281*10465441SEvalZero  rete                    // If this was a spurious interrupt (R12 == NULL), return from event handler.
282*10465441SEvalZero
283*10465441SEvalZero
284*10465441SEvalZerort_hw_context_switch_interrupt_do:
285*10465441SEvalZero  mov     r11, 0
286*10465441SEvalZero  st.w    r12[0], r11					/* Clear rt_thread_switch_interrupt_flag */
287*10465441SEvalZero  stm     --sp, r0-r7					/* Push R0-R7 */
288*10465441SEvalZero  lda.w   r12, rt_interrupt_from_thread	/* Get old thread SP */
289*10465441SEvalZero  ld.w    r12, r12[0]
290*10465441SEvalZero  lda.w   r11, rt_interrupt_to_thread	/* Get new thread SP */
291*10465441SEvalZero  ld.w    r11, r11[0]
292*10465441SEvalZero  st.w    r12[0], sp					/* Store old thead SP */
293*10465441SEvalZero  ld.w    sp, r11[0]					/* Load new thread SP */
294*10465441SEvalZero  ldm     sp++, r0-r7					/* Pop R0-R7 (new thread) */
295*10465441SEvalZero  rete									/* RETE pops R8-R12, LR, PC, SR automatically */
296*10465441SEvalZero
297*10465441SEvalZero
298*10465441SEvalZero// Constant data area.
299*10465441SEvalZero
300*10465441SEvalZero  .balign 4
301*10465441SEvalZero
302*10465441SEvalZero  // Values to store in the interrupt priority registers for the various interrupt priority levels.
303*10465441SEvalZero  // The interrupt priority registers contain the interrupt priority level and
304*10465441SEvalZero  // the EVBA-relative interrupt vector offset.
305*10465441SEvalZero  .global ipr_val
306*10465441SEvalZero  .type ipr_val, @object
307*10465441SEvalZeroipr_val:
308*10465441SEvalZero  .word (AVR32_INTC_INT0 << AVR32_INTC_IPR_INTLEVEL_OFFSET) | (_int0 - _evba),\
309*10465441SEvalZero        (AVR32_INTC_INT1 << AVR32_INTC_IPR_INTLEVEL_OFFSET) | (_int1 - _evba),\
310*10465441SEvalZero        (AVR32_INTC_INT2 << AVR32_INTC_IPR_INTLEVEL_OFFSET) | (_int2 - _evba),\
311*10465441SEvalZero        (AVR32_INTC_INT3 << AVR32_INTC_IPR_INTLEVEL_OFFSET) | (_int3 - _evba)
312*10465441SEvalZero
313*10465441SEvalZero
314*10465441SEvalZero//! \endverbatim
315*10465441SEvalZero//! @}
316