|
2
|
1 #ifndef CYGONCE_HAL_ARCH_H |
|
|
2 #define CYGONCE_HAL_ARCH_H |
|
|
3 |
|
|
4 //========================================================================== |
|
|
5 // |
|
|
6 // hal_arch.h |
|
|
7 // |
|
|
8 // Architecture specific abstractions |
|
|
9 // |
|
|
10 //========================================================================== |
|
|
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 |
|
|
28 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. |
|
|
29 // ------------------------------------------- |
|
|
30 // |
|
|
31 //####COPYRIGHTEND#### |
|
|
32 //========================================================================== |
|
|
33 //#####DESCRIPTIONBEGIN#### |
|
|
34 // |
|
|
35 // Author(s): nickg, gthomas |
|
|
36 // Contributors: nickg, gthomas |
|
|
37 // Date: 1999-02-20 |
|
|
38 // Purpose: Define architecture abstractions |
|
|
39 // Usage: #include <cyg/hal/hal_arch.h> |
|
|
40 |
|
|
41 // |
|
|
42 //####DESCRIPTIONEND#### |
|
|
43 // |
|
|
44 //========================================================================== |
|
|
45 |
|
|
46 #include <pkgconf/hal.h> // To decide on stack usage |
|
|
47 #include <cyg/infra/cyg_type.h> |
|
|
48 |
|
|
49 // |
|
|
50 // CPSR Register defines |
|
|
51 // |
|
|
52 |
|
|
53 #define CPSR_IRQ_DISABLE 0x80 // IRQ disabled when =1 |
|
|
54 #define CPSR_FIQ_DISABLE 0x40 // FIQ disabled when =1 |
|
|
55 #define CPSR_UNDEF_MODE 0x1D |
|
|
56 #define CPSR_SUPERVISOR_MODE 0x13 |
|
|
57 #define CPSR_IRQ_MODE 0x12 |
|
|
58 |
|
|
59 #define CPSR_MODE_BITS 0x1F |
|
|
60 |
|
|
61 #define CPSR_INITIAL (CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE) |
|
|
62 #define CPSR_THREAD_INITIAL (CPSR_SUPERVISOR_MODE) |
|
|
63 |
|
|
64 //-------------------------------------------------------------------------- |
|
|
65 // Processor saved states: |
|
|
66 // The layout of this structure is also defined in "arm.inc", for assembly |
|
|
67 // code, which will be generated automatically if this file changes. |
|
|
68 |
|
|
69 #define HAL_THREAD_CONTEXT_FIRST 0 |
|
|
70 #define HAL_THREAD_CONTEXT_R0 (0-HAL_THREAD_CONTEXT_FIRST) |
|
|
71 #define HAL_THREAD_CONTEXT_R4 (4-HAL_THREAD_CONTEXT_FIRST) |
|
|
72 #define HAL_THREAD_CONTEXT_R10 (10-HAL_THREAD_CONTEXT_FIRST) |
|
|
73 #define HAL_THREAD_CONTEXT_LAST 10 |
|
|
74 #define HAL_NUM_THREAD_CONTEXT_REGS (HAL_THREAD_CONTEXT_LAST - \ |
|
|
75 HAL_THREAD_CONTEXT_FIRST+1) |
|
|
76 |
|
|
77 // It seems that r0-r3,r12 are considered scratch by function calls |
|
|
78 |
|
|
79 typedef struct |
|
|
80 { |
|
|
81 // These are common to all saved states |
|
|
82 cyg_uint32 d[HAL_NUM_THREAD_CONTEXT_REGS] ; // Data regs (r0..r10) |
|
|
83 cyg_uint32 fp; // (r11) Frame pointer |
|
|
84 cyg_uint32 sp; // (r13) Stack pointer |
|
|
85 cyg_uint32 lr; // (r14) Link Reg |
|
|
86 cyg_uint32 pc; // (r15) PC place holder |
|
|
87 // (never used) |
|
|
88 cyg_uint32 cpsr; // Condition Reg |
|
|
89 cyg_uint32 ip; // (r12) Previous stack |
|
|
90 // pointer |
|
|
91 // These are only saved for exceptions and interrupts |
|
|
92 cyg_uint32 vector; // Vector number |
|
|
93 cyg_uint32 msr; // Machine State Reg |
|
|
94 |
|
|
95 } HAL_SavedRegisters; |
|
|
96 |
|
|
97 //------------------------------------------------------------------------- |
|
|
98 // Exception handling function. |
|
|
99 // This function is defined by the kernel according to this prototype. It is |
|
|
100 // invoked from the HAL to deal with any CPU exceptions that the HAL does |
|
|
101 // not want to deal with itself. It usually invokes the kernel's exception |
|
|
102 // delivery mechanism. |
|
|
103 |
|
|
104 externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data ); |
|
|
105 |
|
|
106 //------------------------------------------------------------------------- |
|
|
107 // Bit manipulation macros |
|
|
108 |
|
|
109 externC int hal_lsbindex(int); |
|
|
110 externC int hal_msbindex(int); |
|
|
111 |
|
|
112 #define HAL_LSBIT_INDEX(index, mask) index = hal_lsbindex(mask) |
|
|
113 #define HAL_MSBIT_INDEX(index, mask) index = hal_msbindex(mask) |
|
|
114 |
|
|
115 //------------------------------------------------------------------------- |
|
|
116 // Context Initialization |
|
|
117 // Initialize the context of a thread. |
|
|
118 // Arguments: |
|
|
119 // _sparg_ name of variable containing current sp, will be changed to new sp |
|
|
120 // _thread_ thread object address, passed as argument to entry point |
|
|
121 // _entry_ entry point address. |
|
|
122 // _id_ bit pattern used in initializing registers, for debugging. |
|
|
123 |
|
|
124 #define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ ) \ |
|
|
125 CYG_MACRO_START \ |
|
|
126 register CYG_WORD _sp_ = ((CYG_WORD)_sparg_); \ |
|
|
127 register HAL_SavedRegisters *_regs_; \ |
|
|
128 int _i_; \ |
|
|
129 _regs_ = (HAL_SavedRegisters *)((_sp_) - sizeof(HAL_SavedRegisters)); \ |
|
|
130 for( _i_ = HAL_THREAD_CONTEXT_FIRST; _i_ <= HAL_THREAD_CONTEXT_LAST; \ |
|
|
131 _i_++ ) \ |
|
|
132 (_regs_)->d[_i_] = (_id_)|_i_; \ |
|
|
133 (_regs_)->d[00] = (CYG_WORD)(_thread_); /* R0 = arg1 = thread ptr */ \ |
|
|
134 (_regs_)->sp = (CYG_WORD)(_sp_); /* SP = top of stack */ \ |
|
|
135 (_regs_)->lr = (CYG_WORD)(_entry_); /* LR = entry point */ \ |
|
|
136 (_regs_)->pc = (CYG_WORD)(_entry_); /* PC = [initial] entry point */\ |
|
|
137 (_regs_)->cpsr = (CPSR_THREAD_INITIAL); /* PSR = Interrupt enabled */ \ |
|
|
138 _sparg_ = (CYG_ADDRESS)_regs_; \ |
|
|
139 CYG_MACRO_END |
|
|
140 |
|
|
141 //-------------------------------------------------------------------------- |
|
|
142 // Context switch macros. |
|
|
143 // The arguments are pointers to locations where the stack pointer |
|
|
144 // of the current thread is to be stored, and from where the sp of the |
|
|
145 // next thread is to be fetched. |
|
|
146 |
|
|
147 externC void hal_thread_switch_context( CYG_ADDRESS to, CYG_ADDRESS from ); |
|
|
148 externC void hal_thread_load_context( CYG_ADDRESS to ) |
|
|
149 __attribute__ ((noreturn)); |
|
|
150 |
|
|
151 #define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_) \ |
|
|
152 hal_thread_switch_context((CYG_ADDRESS)_tspptr_, \ |
|
|
153 (CYG_ADDRESS)_fspptr_); |
|
|
154 |
|
|
155 #define HAL_THREAD_LOAD_CONTEXT(_tspptr_) \ |
|
|
156 hal_thread_load_context( (CYG_ADDRESS)_tspptr_ ); |
|
|
157 |
|
|
158 //-------------------------------------------------------------------------- |
|
|
159 // Execution reorder barrier. |
|
|
160 // When optimizing the compiler can reorder code. In multithreaded systems |
|
|
161 // where the order of actions is vital, this can sometimes cause problems. |
|
|
162 // This macro may be inserted into places where reordering should not happen. |
|
|
163 |
|
|
164 #define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" ) |
|
|
165 |
|
|
166 //-------------------------------------------------------------------------- |
|
|
167 // Breakpoint support |
|
|
168 // HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen |
|
|
169 // if executed. |
|
|
170 // HAL_BREAKINST is the value of the breakpoint instruction and |
|
|
171 // HAL_BREAKINST_SIZE is its size in bytes. |
|
|
172 |
|
|
173 #define HAL_BREAKPOINT(_label_) \ |
|
|
174 asm volatile (" .globl " #_label_ ";" \ |
|
|
175 #_label_":" \ |
|
|
176 " .word 0xE7FFDEFE" \ |
|
|
177 ); |
|
|
178 |
|
|
179 //#define HAL_BREAKINST {0xFE, 0xDE, 0xFF, 0xE7} |
|
|
180 #define HAL_BREAKINST 0xE7FFDEFE |
|
|
181 #define HAL_BREAKINST_SIZE 4 |
|
|
182 |
|
|
183 //-------------------------------------------------------------------------- |
|
|
184 // Thread register state manipulation for GDB support. |
|
|
185 |
|
|
186 // FIX ME!! What does GDB expect? |
|
|
187 |
|
|
188 // GDB expects the registers in this structure: |
|
|
189 // r0..r10, fp, ip, sp, lr, pc - 4 bytes each |
|
|
190 // f0..f7 - 12 bytes each (N/A on ARM7) |
|
|
191 // fps - 4 bytes (N/A on ARM7) |
|
|
192 // ps - 4 bytes |
|
|
193 |
|
|
194 // Translate a stack pointer as saved by the thread context macros above into |
|
|
195 // a pointer to a HAL_SavedRegisters structure. |
|
|
196 #define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ ) \ |
|
|
197 (_regs_) = (HAL_SavedRegisters *)(_sp_) |
|
|
198 |
|
|
199 // Copy a set of registers from a HAL_SavedRegisters structure into a |
|
|
200 // GDB ordered array. |
|
|
201 #define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ ) \ |
|
|
202 CYG_MACRO_START \ |
|
|
203 CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_); \ |
|
|
204 int _i_; \ |
|
|
205 \ |
|
|
206 for( _i_ = 0; _i_ <= 10; _i_++ ) \ |
|
|
207 _regval_[_i_] = (_regs_)->d[_i_]; \ |
|
|
208 \ |
|
|
209 _regval_[11] = (_regs_)->fp; \ |
|
|
210 _regval_[12] = (_regs_)->ip; \ |
|
|
211 _regval_[13] = (_regs_)->sp; \ |
|
|
212 _regval_[14] = (_regs_)->lr; \ |
|
|
213 _regval_[15] = (_regs_)->pc; \ |
|
|
214 _regval_[25] = (_regs_)->cpsr; \ |
|
|
215 for( _i_ = 0; _i_ < 8; _i_++ ) \ |
|
|
216 _regval_[_i_+16] = 0; \ |
|
|
217 CYG_MACRO_END |
|
|
218 |
|
|
219 // Copy a GDB ordered array into a HAL_SavedRegisters structure. |
|
|
220 #define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ ) \ |
|
|
221 CYG_MACRO_START \ |
|
|
222 CYG_ADDRWORD *_regval_ = (CYG_ADDRWORD *)(_aregval_); \ |
|
|
223 int _i_; \ |
|
|
224 \ |
|
|
225 for( _i_ = 0; _i_ <= 10; _i_++ ) \ |
|
|
226 (_regs_)->d[_i_] = _regval_[_i_]; \ |
|
|
227 \ |
|
|
228 (_regs_)->fp = _regval_[11]; \ |
|
|
229 (_regs_)->ip = _regval_[12]; \ |
|
|
230 (_regs_)->sp = _regval_[13]; \ |
|
|
231 (_regs_)->lr = _regval_[14]; \ |
|
|
232 (_regs_)->pc = _regval_[15]; \ |
|
|
233 (_regs_)->cpsr = _regval_[25]; \ |
|
|
234 CYG_MACRO_END |
|
|
235 |
|
|
236 //-------------------------------------------------------------------------- |
|
|
237 // HAL setjmp |
|
|
238 |
|
|
239 #define CYGARC_JMP_BUF_SIZE 16 // Actually 11, but some room left over |
|
|
240 |
|
|
241 typedef cyg_uint32 hal_jmp_buf[CYGARC_JMP_BUF_SIZE]; |
|
|
242 |
|
|
243 externC int hal_setjmp(hal_jmp_buf env); |
|
|
244 externC void hal_longjmp(hal_jmp_buf env, int val); |
|
|
245 |
|
|
246 |
|
|
247 //-------------------------------------------------------------------------- |
|
|
248 // Idle thread code. |
|
|
249 // This macro is called in the idle thread loop, and gives the HAL the |
|
|
250 // chance to insert code. Typical idle thread behaviour might be to halt the |
|
|
251 // processor. |
|
|
252 |
|
|
253 externC void hal_idle_thread_action(cyg_uint32 loop_count); |
|
|
254 |
|
|
255 #define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_) |
|
|
256 |
|
|
257 //--------------------------------------------------------------------------- |
|
|
258 |
|
|
259 // Minimal and sensible stack sizes: the intention is that applications |
|
|
260 // will use these to provide a stack size in the first instance prior to |
|
|
261 // proper analysis. Idle thread stack should be this big. |
|
|
262 |
|
|
263 // THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES. |
|
|
264 // THEY ARE HOWEVER ENOUGH TO START PROGRAMMING. |
|
|
265 // YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES! |
|
|
266 |
|
|
267 // This is not a config option because it should not be adjusted except |
|
|
268 // under "enough rope" sort of disclaimers. |
|
|
269 |
|
|
270 // A minimal, optimized stack frame, rounded up - no autos |
|
|
271 #define CYGNUM_HAL_STACK_FRAME_SIZE (4 * 20) |
|
|
272 |
|
|
273 // Stack needed for a context switch: this is implicit in the estimate for |
|
|
274 // interrupts so not explicitly used below: |
|
|
275 #define CYGNUM_HAL_STACK_CONTEXT_SIZE (4 * 20) |
|
|
276 |
|
|
277 // Interrupt + call to ISR, interrupt_end() and the DSR |
|
|
278 #define CYGNUM_HAL_STACK_INTERRUPT_SIZE \ |
|
|
279 ((4 * 20) + 2 * CYGNUM_HAL_STACK_FRAME_SIZE) |
|
|
280 |
|
|
281 // Space for the maximum number of nested interrupts, plus room to call functions |
|
|
282 #define CYGNUM_HAL_MAX_INTERRUPT_NESTING 4 |
|
|
283 |
|
|
284 #define CYGNUM_HAL_STACK_SIZE_MINIMUM \ |
|
|
285 (CYGNUM_HAL_MAX_INTERRUPT_NESTING * CYGNUM_HAL_STACK_INTERRUPT_SIZE + \ |
|
|
286 2 * CYGNUM_HAL_STACK_FRAME_SIZE) |
|
|
287 |
|
|
288 #define CYGNUM_HAL_STACK_SIZE_TYPICAL \ |
|
|
289 (CYGNUM_HAL_STACK_SIZE_MINIMUM + \ |
|
|
290 16 * CYGNUM_HAL_STACK_FRAME_SIZE) |
|
|
291 |
|
|
292 //----------------------------------------------------------------------------- |
|
|
293 |
|
|
294 #endif // CYGONCE_HAL_ARCH_H |
|
|
295 // End of hal_arch.h |