|
0
|
1 #ifndef CYGONCE_HAL_HAL_ARCH_H |
|
|
2 #define CYGONCE_HAL_HAL_ARCH_H |
|
|
3 |
|
2
|
4 //========================================================================== |
|
0
|
5 // |
|
2
|
6 // hal_arch.h |
|
0
|
7 // |
|
2
|
8 // Architecture specific abstractions |
|
0
|
9 // |
|
2
|
10 //========================================================================== |
|
0
|
11 //####COPYRIGHTBEGIN#### |
|
|
12 // |
|
|
13 // ------------------------------------------- |
|
|
14 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
15 // Version 1.0 (the "License"); you may not use this file except in |
|
|
16 // compliance with the License. You may obtain a copy of the License at |
|
|
17 // http://sourceware.cygnus.com/ecos |
|
|
18 // |
|
|
19 // Software distributed under the License is distributed on an "AS IS" |
|
|
20 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
21 // License for the specific language governing rights and limitations under |
|
|
22 // the License. |
|
|
23 // |
|
|
24 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
25 // September 30, 1998. |
|
|
26 // |
|
|
27 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
2
|
28 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. |
|
0
|
29 // ------------------------------------------- |
|
|
30 // |
|
|
31 //####COPYRIGHTEND#### |
|
2
|
32 //========================================================================== |
|
0
|
33 //#####DESCRIPTIONBEGIN#### |
|
|
34 // |
|
2
|
35 // Author(s): nickg |
|
|
36 // Contributors: nickg |
|
|
37 // Date: 1999-02-17 |
|
|
38 // Purpose: Define architecture abstractions |
|
|
39 // Usage: #include <cyg/hal/hal_arch.h> |
|
|
40 // |
|
0
|
41 //####DESCRIPTIONEND#### |
|
|
42 // |
|
2
|
43 //========================================================================== |
|
0
|
44 |
|
2
|
45 #include <pkgconf/hal.h> |
|
0
|
46 #include <cyg/infra/cyg_type.h> |
|
|
47 |
|
2
|
48 //-------------------------------------------------------------------------- |
|
0
|
49 // Processor saved states: |
|
|
50 // The layout of this structure is also defined in "mips.inc", for assembly |
|
|
51 // code. Do not change this without changing that (or vice versa). |
|
|
52 |
|
|
53 typedef struct |
|
|
54 { |
|
|
55 // These are common to all saved states |
|
|
56 cyg_uint32 d[32]; /* Data regs */ |
|
|
57 cyg_uint32 hi; /* hi word of mpy/div reg */ |
|
|
58 cyg_uint32 lo; /* lo word of mpy/div reg */ |
|
|
59 |
|
|
60 // These are only saved for exceptions and interrupts |
|
|
61 cyg_uint32 vector; /* Vector number */ |
|
|
62 cyg_uint32 pc; /* Program Counter */ |
|
|
63 cyg_uint32 sr; /* Status Reg */ |
|
|
64 cyg_uint32 cache; /* Cache control register */ |
|
|
65 |
|
|
66 |
|
|
67 // These are only saved for exceptions, and are not restored |
|
|
68 // when continued. |
|
|
69 cyg_uint32 cause; /* Exception cause register */ |
|
|
70 cyg_uint32 badvr; /* Bad virtual address reg */ |
|
|
71 cyg_uint32 prid; /* Processor Version */ |
|
|
72 cyg_uint32 config; /* Config register */ |
|
|
73 } HAL_SavedRegisters; |
|
|
74 |
|
2
|
75 //-------------------------------------------------------------------------- |
|
0
|
76 // Exception handling function. |
|
|
77 // This function is defined by the kernel according to this prototype. It is |
|
|
78 // invoked from the HAL to deal with any CPU exceptions that the HAL does |
|
|
79 // not want to deal with itself. It usually invokes the kernel's exception |
|
|
80 // delivery mechanism. |
|
|
81 |
|
2
|
82 externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data ); |
|
0
|
83 |
|
2
|
84 //-------------------------------------------------------------------------- |
|
0
|
85 // Bit manipulation macros |
|
|
86 |
|
|
87 externC cyg_uint32 hal_lsbit_index(cyg_uint32 mask); |
|
|
88 externC cyg_uint32 hal_msbit_index(cyg_uint32 mask); |
|
|
89 |
|
|
90 #define HAL_LSBIT_INDEX(index, mask) index = hal_lsbit_index(mask); |
|
|
91 |
|
|
92 #define HAL_MSBIT_INDEX(index, mask) index = hal_msbit_index(mask); |
|
|
93 |
|
2
|
94 //-------------------------------------------------------------------------- |
|
0
|
95 // Context Initialization |
|
|
96 // Initialize the context of a thread. |
|
|
97 // Arguments: |
|
|
98 // _sparg_ name of variable containing current sp, will be written with new sp |
|
|
99 // _thread_ thread object address, passed as argument to entry point |
|
|
100 // _entry_ entry point address. |
|
|
101 // _id_ bit pattern used in initializing registers, for debugging. |
|
|
102 |
|
2
|
103 #define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ ) \ |
|
|
104 { \ |
|
|
105 register CYG_WORD _sp_ = ((CYG_WORD)_sparg_)-56; \ |
|
|
106 register HAL_SavedRegisters *_regs_; \ |
|
|
107 int _i_; \ |
|
|
108 _regs_ = (HAL_SavedRegisters *)((_sp_) - sizeof(HAL_SavedRegisters)); \ |
|
|
109 for( _i_ = 0; _i_ < 32; _i_++ ) (_regs_)->d[_i_] = (_id_)|_i_; \ |
|
|
110 (_regs_)->d[29] = (CYG_WORD)(_sp_); /* SP = top of stack */ \ |
|
|
111 (_regs_)->d[04] = (CYG_WORD)(_thread_); /* R4 = arg1 = thread ptr */ \ |
|
|
112 (_regs_)->lo = 0; /* LO = 0 */ \ |
|
|
113 (_regs_)->hi = 0; /* HI = 0 */ \ |
|
|
114 (_regs_)->d[30] = (CYG_WORD)(_sp_); /* FP = top of stack */ \ |
|
|
115 (_regs_)->d[31] = (CYG_WORD)(_entry_); /* LR(d[31]) = entry point*/ \ |
|
|
116 (_regs_)->pc = (CYG_WORD)(_entry_); /* PC = entry point */ \ |
|
|
117 _sparg_ = (CYG_ADDRESS)_regs_; \ |
|
0
|
118 } |
|
|
119 |
|
2
|
120 //-------------------------------------------------------------------------- |
|
0
|
121 // Context switch macros. |
|
|
122 // The arguments are pointers to locations where the stack pointer |
|
|
123 // of the current thread is to be stored, and from where the sp of the |
|
|
124 // next thread is to be fetched. |
|
|
125 |
|
|
126 externC void hal_thread_switch_context( CYG_ADDRESS to, CYG_ADDRESS from ); |
|
|
127 externC void hal_thread_load_context( CYG_ADDRESS to ) |
|
|
128 __attribute__ ((noreturn)); |
|
|
129 |
|
|
130 #define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_) \ |
|
2
|
131 hal_thread_switch_context( (CYG_ADDRESS)_tspptr_, \ |
|
|
132 (CYG_ADDRESS)_fspptr_); |
|
0
|
133 |
|
|
134 #define HAL_THREAD_LOAD_CONTEXT(_tspptr_) \ |
|
|
135 hal_thread_load_context( (CYG_ADDRESS)_tspptr_ ); |
|
|
136 |
|
2
|
137 //-------------------------------------------------------------------------- |
|
0
|
138 // Execution reorder barrier. |
|
|
139 // When optimizing the compiler can reorder code. In multithreaded systems |
|
|
140 // where the order of actions is vital, this can sometimes cause problems. |
|
|
141 // This macro may be inserted into places where reordering should not happen. |
|
|
142 // The "memory" keyword is potentially unnecessary, but it is harmless to |
|
|
143 // keep it. |
|
|
144 |
|
|
145 #define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" ) |
|
|
146 |
|
2
|
147 //-------------------------------------------------------------------------- |
|
0
|
148 // Breakpoint support |
|
2
|
149 // HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to |
|
|
150 // happen if executed. |
|
|
151 // HAL_BREAKINST is the value of the breakpoint instruction and |
|
|
152 // HAL_BREAKINST_SIZE is its size in bytes. |
|
0
|
153 |
|
2
|
154 #ifdef CYG_HAL_MIPS_SIM |
|
|
155 #define HAL_BREAKPOINT(_label_) \ |
|
|
156 /* This code causes a fake breakpoint. */ \ |
|
|
157 asm volatile ( \ |
|
|
158 "lui $24,0x0000;" \ |
|
|
159 "ori $24,0x0024;" \ |
|
|
160 "mtc0 $24,$13;" \ |
|
|
161 "lui $25,%%hi(1f);" \ |
|
|
162 "ori $25,$25,%%lo(1f);" \ |
|
|
163 "j other_vector;" \ |
|
|
164 "nop;" \ |
|
|
165 ".global " #_label_ ";" \ |
|
|
166 #_label_":" \ |
|
|
167 "1: nop;" \ |
|
|
168 : \ |
|
|
169 : \ |
|
|
170 : "t8", "t9" \ |
|
|
171 ); |
|
|
172 #else |
|
0
|
173 #define HAL_BREAKPOINT(_label_) \ |
|
2
|
174 asm volatile (" .globl " #_label_ ";" \ |
|
0
|
175 #_label_":" \ |
|
2
|
176 " break 5" \ |
|
0
|
177 ); |
|
2
|
178 #endif // CYG_HAL_MIPS_SIM |
|
0
|
179 |
|
|
180 #define HAL_BREAKINST 0x0005000d |
|
|
181 |
|
|
182 #define HAL_BREAKINST_SIZE 4 |
|
|
183 |
|
2
|
184 //-------------------------------------------------------------------------- |
|
0
|
185 // Thread register state manipulation for GDB support. |
|
|
186 |
|
|
187 // Translate a stack pointer as saved by the thread context macros above into |
|
|
188 // a pointer to a HAL_SavedRegisters structure. |
|
2
|
189 #define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ ) \ |
|
0
|
190 (_regs_) = (HAL_SavedRegisters *)(_sp_) |
|
|
191 |
|
|
192 // Copy a set of registers from a HAL_SavedRegisters structure into a |
|
|
193 // GDB ordered array. |
|
|
194 #define HAL_GET_GDB_REGISTERS( _aregval_ , _regs_ ) \ |
|
|
195 { \ |
|
|
196 CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_); \ |
|
|
197 int _i_; \ |
|
|
198 \ |
|
|
199 for( _i_ = 0; _i_ < 32; _i_++ ) \ |
|
|
200 _regval_[_i_] = (_regs_)->d[_i_]; \ |
|
|
201 \ |
|
|
202 _regval_[32] = (_regs_)->sr; \ |
|
|
203 _regval_[33] = (_regs_)->lo; \ |
|
|
204 _regval_[34] = (_regs_)->hi; \ |
|
|
205 _regval_[35] = (_regs_)->badvr; \ |
|
|
206 _regval_[36] = (_regs_)->cause; \ |
|
|
207 _regval_[37] = (_regs_)->pc; \ |
|
|
208 } |
|
|
209 |
|
|
210 // Copy a GDB ordered array into a HAL_SavedRegisters structure. |
|
|
211 #define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ ) \ |
|
|
212 { \ |
|
|
213 CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_); \ |
|
|
214 int _i_; \ |
|
|
215 \ |
|
|
216 for( _i_ = 0; _i_ < 32; _i_++ ) \ |
|
|
217 (_regs_)->d[_i_] = _regval_[_i_]; \ |
|
|
218 \ |
|
|
219 (_regs_)->sr = _regval_[32]; \ |
|
|
220 (_regs_)->lo = _regval_[33]; \ |
|
|
221 (_regs_)->hi = _regval_[34]; \ |
|
|
222 (_regs_)->badvr = _regval_[35]; \ |
|
|
223 (_regs_)->cause = _regval_[36]; \ |
|
|
224 (_regs_)->pc = _regval_[37]; \ |
|
|
225 } |
|
|
226 |
|
2
|
227 //-------------------------------------------------------------------------- |
|
0
|
228 // HAL setjmp |
|
2
|
229 // Note: These definitions are repeated in hal_arch.h. If changes are |
|
|
230 // required remember to update both sets. |
|
0
|
231 |
|
2
|
232 #define CYGARC_JMP_BUF_SP 0 |
|
|
233 #define CYGARC_JMP_BUF_R16 1 |
|
|
234 #define CYGARC_JMP_BUF_R17 2 |
|
|
235 #define CYGARC_JMP_BUF_R18 3 |
|
|
236 #define CYGARC_JMP_BUF_R19 4 |
|
|
237 #define CYGARC_JMP_BUF_R20 5 |
|
|
238 #define CYGARC_JMP_BUF_R21 6 |
|
|
239 #define CYGARC_JMP_BUF_R22 7 |
|
|
240 #define CYGARC_JMP_BUF_R23 8 |
|
|
241 #define CYGARC_JMP_BUF_R28 9 |
|
|
242 #define CYGARC_JMP_BUF_R30 10 |
|
|
243 #define CYGARC_JMP_BUF_R31 11 |
|
0
|
244 |
|
2
|
245 #define CYGARC_JMP_BUF_SIZE 12 |
|
|
246 |
|
|
247 typedef cyg_uint32 hal_jmp_buf[CYGARC_JMP_BUF_SIZE]; |
|
0
|
248 |
|
|
249 externC int hal_setjmp(hal_jmp_buf env); |
|
|
250 externC void hal_longjmp(hal_jmp_buf env, int val); |
|
|
251 |
|
2
|
252 //------------------------------------------------------------------------- |
|
0
|
253 // Idle thread code. |
|
|
254 // This macro is called in the idle thread loop, and gives the HAL the |
|
|
255 // chance to insert code. Typical idle thread behaviour might be to halt the |
|
|
256 // processor. |
|
|
257 |
|
|
258 externC void hal_idle_thread_action(cyg_uint32 loop_count); |
|
|
259 |
|
|
260 #define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_) |
|
|
261 |
|
2
|
262 //-------------------------------------------------------------------------- |
|
|
263 // Minimal and sensible stack sizes: the intention is that applications |
|
|
264 // will use these to provide a stack size in the first instance prior to |
|
|
265 // proper analysis. Idle thread stack should be this big. |
|
|
266 |
|
|
267 // THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES. |
|
|
268 // THEY ARE HOWEVER ENOUGH TO START PROGRAMMING. |
|
|
269 // YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES! |
|
|
270 |
|
|
271 // We define quite large stack needs for SPARClite, for it requires 576 |
|
|
272 // bytes (144 words) to process an interrupt and thread-switch, and |
|
|
273 // momentarily, but needed in case of recursive interrupts, it needs 208 |
|
|
274 // words - if a sequence of saves to push out other regsets is interrupted. |
|
|
275 |
|
|
276 // This is not a config option because it should not be adjusted except |
|
|
277 // under "enough rope" sort of disclaimers. |
|
|
278 |
|
|
279 // Worst case stack frame size: return link + 5 pushed registers. |
|
|
280 #define CYGNUM_HAL_STACK_FRAME_SIZE (24) |
|
|
281 |
|
|
282 // Stack needed for a context switch: |
|
|
283 #define CYGNUM_HAL_STACK_CONTEXT_SIZE (42*4) |
|
|
284 |
|
|
285 // Interrupt + call to ISR, interrupt_end() and the DSR |
|
|
286 #define CYGNUM_HAL_STACK_INTERRUPT_SIZE (4+2*CYGNUM_HAL_STACK_CONTEXT_SIZE) |
|
|
287 |
|
|
288 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK |
|
|
289 |
|
|
290 // An interrupt stack which is large enough for all possible interrupt |
|
|
291 // conditions (and only used for that purpose) exists. "User" stacks |
|
|
292 // can be much smaller |
|
|
293 |
|
|
294 #define CYGNUM_HAL_STACK_SIZE_MINIMUM (CYGNUM_HAL_STACK_CONTEXT_SIZE+ \ |
|
|
295 CYGNUM_HAL_STACK_INTERRUPT_SIZE*2+ \ |
|
|
296 CYGNUM_HAL_STACK_FRAME_SIZE*4) |
|
|
297 #define CYGNUM_HAL_STACK_SIZE_TYPICAL (2048) |
|
|
298 |
|
|
299 #else // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK |
|
|
300 |
|
|
301 // No separate interrupt stack exists. Make sure all threads contain |
|
|
302 // a stack sufficiently large. |
|
|
303 |
|
|
304 #define CYGNUM_HAL_STACK_SIZE_MINIMUM (4096) |
|
|
305 #define CYGNUM_HAL_STACK_SIZE_TYPICAL (4096) |
|
|
306 |
|
|
307 #endif |
|
|
308 |
|
|
309 //-------------------------------------------------------------------------- |
|
0
|
310 #endif // CYGONCE_HAL_HAL_ARCH_H |
|
|
311 // End of hal_arch.h |