-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathxtruntime.h
184 lines (165 loc) · 7.84 KB
/
xtruntime.h
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
/*
* xtruntime.h -- general C definitions for single-threaded run-time
*
* Copyright (c) 2002-2008 Tensilica Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef XTRUNTIME_H
#define XTRUNTIME_H
#include <xtensa/config/core.h>
#include <xtensa/config/specreg.h>
#ifndef XTSTR
#define _XTSTR(x) # x
#define XTSTR(x) _XTSTR(x)
#endif
#define _xtos_set_execption_handler _xtos_set_exception_handler /* backward compatibility */
#define _xtos_set_saved_intenable _xtos_ints_on /* backward compatibility */
#define _xtos_clear_saved_intenable _xtos_ints_off /* backward compatibility */
#if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__)
#ifdef __cplusplus
extern "C" {
#endif
/*typedef void (_xtos_timerdelta_func)(int);*/
#ifdef __cplusplus
typedef void (_xtos_handler_func)(...);
#else
typedef void (_xtos_handler_func)();
#endif
typedef _xtos_handler_func *_xtos_handler;
/*
* unsigned XTOS_SET_INTLEVEL(int intlevel);
* This macro sets the current interrupt level.
* The 'intlevel' parameter must be a constant.
* This macro returns a 32-bit value that must be passed to
* XTOS_RESTORE_INTLEVEL() to restore the previous interrupt level.
* XTOS_RESTORE_JUST_INTLEVEL() also does this, but in XEA2 configs
* it restores only PS.INTLEVEL rather than the entire PS register
* and thus is slower.
*/
#if !XCHAL_HAVE_INTERRUPTS
# define XTOS_SET_INTLEVEL(intlevel) 0
# define XTOS_SET_MIN_INTLEVEL(intlevel) 0
# define XTOS_RESTORE_INTLEVEL(restoreval)
# define XTOS_RESTORE_JUST_INTLEVEL(restoreval)
#elif XCHAL_HAVE_XEA2
/* In XEA2, we can simply safely set PS.INTLEVEL directly: */
/* NOTE: these asm macros don't modify memory, but they are marked
* as such to act as memory access barriers to the compiler because
* these macros are sometimes used to delineate critical sections;
* function calls are natural barriers (the compiler does not know
* whether a function modifies memory) unless declared to be inlined. */
# define XTOS_SET_INTLEVEL(intlevel) ({ unsigned __tmp; \
__asm__ __volatile__( "rsil %0, " XTSTR(intlevel) "\n" \
: "=a" (__tmp) : : "memory" ); \
__tmp;})
# define XTOS_SET_MIN_INTLEVEL(intlevel) ({ unsigned __tmp, __tmp2, __tmp3; \
__asm__ __volatile__( "rsr %0, " XTSTR(PS) "\n" /* get old (current) PS.INTLEVEL */ \
"movi %2, " XTSTR(intlevel) "\n" \
"extui %1, %0, 0, 4\n" /* keep only INTLEVEL bits of parameter */ \
"blt %2, %1, 1f\n" \
"rsil %0, " XTSTR(intlevel) "\n" \
"1:\n" \
: "=a" (__tmp), "=&a" (__tmp2), "=&a" (__tmp3) : : "memory" ); \
__tmp;})
# define XTOS_RESTORE_INTLEVEL(restoreval) do{ unsigned __tmp = (restoreval); \
__asm__ __volatile__( "wsr %0, " XTSTR(PS) " ; rsync\n" \
: : "a" (__tmp) : "memory" ); \
}while(0)
# define XTOS_RESTORE_JUST_INTLEVEL(restoreval) _xtos_set_intlevel(restoreval)
#else
/* In XEA1, we have to rely on INTENABLE register virtualization: */
extern unsigned _xtos_set_vpri( unsigned vpri );
extern unsigned _xtos_vpri_enabled; /* current virtual priority */
# define XTOS_SET_INTLEVEL(intlevel) _xtos_set_vpri(~XCHAL_INTLEVEL_ANDBELOW_MASK(intlevel))
# define XTOS_SET_MIN_INTLEVEL(intlevel) _xtos_set_vpri(_xtos_vpri_enabled & ~XCHAL_INTLEVEL_ANDBELOW_MASK(intlevel))
# define XTOS_RESTORE_INTLEVEL(restoreval) _xtos_set_vpri(restoreval)
# define XTOS_RESTORE_JUST_INTLEVEL(restoreval) _xtos_set_vpri(restoreval)
#endif
/*
* The following macros build upon the above. They are generally used
* instead of invoking the SET_INTLEVEL and SET_MIN_INTLEVEL macros directly.
* They all return a value that can be used with XTOS_RESTORE_INTLEVEL()
* or _xtos_restore_intlevel() or _xtos_restore_just_intlevel() to restore
* the effective interrupt level to what it was before the macro was invoked.
* In XEA2, the DISABLE macros are much faster than the MASK macros
* (in all configs, DISABLE sets the effective interrupt level, whereas MASK
* makes ensures the effective interrupt level is at least the level given
* without lowering it; in XEA2 with INTENABLE virtualization, these macros
* affect PS.INTLEVEL only, not the virtual priority, so DISABLE has partial
* MASK semantics).
*
* A typical critical section sequence might be:
* unsigned rval = XTOS_DISABLE_EXCM_INTERRUPTS;
* ... critical section ...
* XTOS_RESTORE_INTLEVEL(rval);
*/
/* Enable all interrupts (those activated with _xtos_ints_on()): */
#define XTOS_ENABLE_INTERRUPTS XTOS_SET_INTLEVEL(0)
/* Disable low priority level interrupts (they can interact with the OS): */
#define XTOS_DISABLE_LOWPRI_INTERRUPTS XTOS_SET_INTLEVEL(XCHAL_NUM_LOWPRI_LEVELS)
#define XTOS_MASK_LOWPRI_INTERRUPTS XTOS_SET_MIN_INTLEVEL(XCHAL_NUM_LOWPRI_LEVELS)
/* Disable interrupts that can interact with the OS: */
#define XTOS_DISABLE_EXCM_INTERRUPTS XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL)
#define XTOS_MASK_EXCM_INTERRUPTS XTOS_SET_MIN_INTLEVEL(XCHAL_EXCM_LEVEL)
#if 0 /* XTOS_LOCK_LEVEL is not exported to applications */
/* Disable interrupts that can interact with the OS, or manipulate virtual INTENABLE: */
#define XTOS_DISABLE_LOCK_INTERRUPTS XTOS_SET_INTLEVEL(XTOS_LOCK_LEVEL)
#define XTOS_MASK_LOCK_INTERRUPTS XTOS_SET_MIN_INTLEVEL(XTOS_LOCK_LEVEL)
#endif
/* Disable ALL interrupts (not for common use, particularly if one's processor
* configuration has high-level interrupts and one cares about their latency): */
#define XTOS_DISABLE_ALL_INTERRUPTS XTOS_SET_INTLEVEL(15)
extern unsigned int _xtos_ints_off( unsigned int mask );
extern unsigned int _xtos_ints_on( unsigned int mask );
extern unsigned _xtos_set_intlevel( int intlevel );
extern unsigned _xtos_set_min_intlevel( int intlevel );
extern unsigned _xtos_restore_intlevel( unsigned restoreval );
extern unsigned _xtos_restore_just_intlevel( unsigned restoreval );
extern _xtos_handler _xtos_set_interrupt_handler( int n, _xtos_handler f );
extern _xtos_handler _xtos_set_interrupt_handler_arg( int n, _xtos_handler f, void *arg );
extern _xtos_handler _xtos_set_exception_handler( int n, _xtos_handler f );
extern void _xtos_memep_initrams( void );
extern void _xtos_memep_enable( int flags );
/* Deprecated (but kept because they were documented): */
extern unsigned int _xtos_read_ints( void ); /* use xthal_get_interrupt() instead */
extern void _xtos_clear_ints( unsigned int mask ); /* use xthal_set_intclear() instead */
#if XCHAL_NUM_CONTEXTS > 1
extern unsigned _xtos_init_context(int context_num, int stack_size,
_xtos_handler_func *start_func, int arg1);
#endif
/* Deprecated: */
#if XCHAL_NUM_TIMERS > 0
extern void _xtos_timer_0_delta( int cycles );
#endif
#if XCHAL_NUM_TIMERS > 1
extern void _xtos_timer_1_delta( int cycles );
#endif
#if XCHAL_NUM_TIMERS > 2
extern void _xtos_timer_2_delta( int cycles );
#endif
#if XCHAL_NUM_TIMERS > 3
extern void _xtos_timer_3_delta( int cycles );
#endif
#ifdef __cplusplus
}
#endif
#endif /* !_ASMLANGUAGE && !__ASSEMBLER__ */
#endif /* XTRUNTIME_H */