1 /*
2  * FreeRTOS Kernel V11.0.1
3  * Copyright (C) 2015-2019 Cadence Design Systems, Inc.
4  * Copyright (C) 2021 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
5  *
6  * SPDX-License-Identifier: MIT
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy of
9  * this software and associated documentation files (the "Software"), to deal in
10  * the Software without restriction, including without limitation the rights to
11  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
12  * the Software, and to permit persons to whom the Software is furnished to do so,
13  * subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in all
16  * copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
20  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
21  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  * https://www.FreeRTOS.org
26  * https://github.com/FreeRTOS
27  *
28  */
29 
30 /*
31  * Xtensa-specific interrupt and exception functions for RTOS ports.
32  * Also see xtensa_intr_asm.S.
33  */
34 
35 #include <stdlib.h>
36 
37 #include <xtensa/config/core.h>
38 
39 #include "xtensa_api.h"
40 
41 
42 #if XCHAL_HAVE_EXCEPTIONS
43 
44 /* Handler table is in xtensa_intr_asm.S */
45 
46     extern xt_exc_handler _xt_exception_table[ XCHAL_EXCCAUSE_NUM ];
47 
48 
49 /*
50  * Default handler for unhandled exceptions.
51  */
xt_unhandled_exception(XtExcFrame * frame)52     void xt_unhandled_exception( XtExcFrame * frame )
53     {
54         exit( -1 );
55     }
56 
57 
58 /*
59  * This function registers a handler for the specified exception.
60  * The function returns the address of the previous handler.
61  * On error, it returns 0.
62  */
xt_set_exception_handler(int n,xt_exc_handler f)63     xt_exc_handler xt_set_exception_handler( int n,
64                                              xt_exc_handler f )
65     {
66         xt_exc_handler old;
67 
68         if( ( n < 0 ) || ( n >= XCHAL_EXCCAUSE_NUM ) )
69         {
70             return 0; /* invalid exception number */
71         }
72 
73         old = _xt_exception_table[ n ];
74 
75         if( f )
76         {
77             _xt_exception_table[ n ] = f;
78         }
79         else
80         {
81             _xt_exception_table[ n ] = &xt_unhandled_exception;
82         }
83 
84         return( ( old == &xt_unhandled_exception ) ? 0 : old );
85     }
86 
87 #endif /* if XCHAL_HAVE_EXCEPTIONS */
88 
89 #if XCHAL_HAVE_INTERRUPTS
90 
91 /* Handler table is in xtensa_intr_asm.S */
92 
93     typedef struct xt_handler_table_entry
94     {
95         void * handler;
96         void * arg;
97     } xt_handler_table_entry;
98 
99     extern xt_handler_table_entry _xt_interrupt_table[ XCHAL_NUM_INTERRUPTS ];
100 
101 
102 /*
103  * Default handler for unhandled interrupts.
104  */
xt_unhandled_interrupt(void * arg)105     void xt_unhandled_interrupt( void * arg )
106     {
107         exit( -1 );
108     }
109 
110 
111 /*
112  * This function registers a handler for the specified interrupt. The "arg"
113  * parameter specifies the argument to be passed to the handler when it is
114  * invoked. The function returns the address of the previous handler.
115  * On error, it returns 0.
116  */
xt_set_interrupt_handler(int n,xt_handler f,void * arg)117     xt_handler xt_set_interrupt_handler( int n,
118                                          xt_handler f,
119                                          void * arg )
120     {
121         xt_handler_table_entry * entry;
122         xt_handler old;
123 
124         if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) )
125         {
126             return 0; /* invalid interrupt number */
127         }
128 
129         if( Xthal_intlevel[ n ] > XCHAL_EXCM_LEVEL )
130         {
131             return 0; /* priority level too high to safely handle in C */
132         }
133 
134         entry = _xt_interrupt_table + n;
135         old = entry->handler;
136 
137         if( f )
138         {
139             entry->handler = f;
140             entry->arg = arg;
141         }
142         else
143         {
144             entry->handler = &xt_unhandled_interrupt;
145             entry->arg = ( void * ) n;
146         }
147 
148         return( ( old == &xt_unhandled_interrupt ) ? 0 : old );
149     }
150 
151 
152 #endif /* XCHAL_HAVE_INTERRUPTS */
153