]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/fr30/arch/v2_0/include/hal_arch.h
Initial revision
[karo-tx-redboot.git] / packages / hal / fr30 / arch / v2_0 / include / hal_arch.h
1 #ifndef CYGONCE_HAL_HAL_ARCH_H
2 #define CYGONCE_HAL_HAL_ARCH_H
3
4 //=============================================================================
5 //
6 //      hal_arch.h
7 //
8 //      Architecture specific abstractions
9 //
10 //=============================================================================
11 //####ECOSGPLCOPYRIGHTBEGIN####
12 // -------------------------------------------
13 // This file is part of eCos, the Embedded Configurable Operating System.
14 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
15 // Copyright (C) 2007 eCosCentric Ltd.
16 //
17 // eCos is free software; you can redistribute it and/or modify it under
18 // the terms of the GNU General Public License as published by the Free
19 // Software Foundation; either version 2 or (at your option) any later version.
20 //
21 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
22 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24 // for more details.
25 //
26 // You should have received a copy of the GNU General Public License along
27 // with eCos; if not, write to the Free Software Foundation, Inc.,
28 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29 //
30 // As a special exception, if other files instantiate templates or use macros
31 // or inline functions from this file, or you compile this file and link it
32 // with other works to produce a work based on this file, this file does not
33 // by itself cause the resulting work to be covered by the GNU General Public
34 // License. However the source code for this file must still be made available
35 // in accordance with section (3) of the GNU General Public License.
36 //
37 // This exception does not invalidate any other reasons why a work based on
38 // this file might be covered by the GNU General Public License.
39 //
40 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
41 // at http://sources.redhat.com/ecos/ecos-license/
42 // -------------------------------------------
43 //####ECOSGPLCOPYRIGHTEND####
44 //=============================================================================
45 //#####DESCRIPTIONBEGIN####
46 //
47 // Author(s):   larsi
48 // Contributors:
49 // Date:        2006-05-28
50 // Purpose:     Define architecture abstractions
51 // Usage:       #include <cyg/hal/hal_arch.h>
52 //
53 //####DESCRIPTIONEND####
54 //
55 //=============================================================================
56
57 #include <pkgconf/hal.h>
58 #include <cyg/infra/cyg_type.h>
59
60 #include <cyg/hal/var_arch.h>
61
62 #define CYG_HAL_FR30_REG CYG_ADDRWORD
63
64 //-----------------------------------------------------------------------------
65 // Processor saved states. This structure is also defined in fr30.inc for
66 // assembly code. Do not change this without changing that (or vice versa).
67
68 typedef struct HAL_SavedRegisters
69 {
70     cyg_uint32  r[16];  // general purpose registers with
71                         // r[13]: virtual accumulator (AC)
72                         // r[14]: frame pointer (FP)
73                         // r[15]: stack pointer (SP) r15 is not saved here!
74     cyg_uint32  pc;     // program counter
75     cyg_uint32  ps;     // program status (with ILM, SCR, CCR)
76     cyg_uint32  tbr;    // table base register (not neccessary,
77                         // as it is used system-wide not per thread)
78     cyg_uint32  rp;     // return pointer
79     // ssp is used system-wide for EIT processing and does not need to be saved here
80     // and therefore we don't store usp, because we have it already in r15
81     cyg_uint32  ssp;    // system stack pointer
82     cyg_uint32  usp;    // user stack pointer
83     cyg_uint32  mdh;    // multiplication and division regs /
84     cyg_uint32  mdl;    // with high and low words
85
86     cyg_uint32   last_trap; // the last taken trap (for GDB stubs)
87
88 } HAL_SavedRegisters;
89
90
91 //-----------------------------------------------------------------------------
92 // Exception handling function.
93 // This function is defined by the kernel according to this prototype. It is
94 // invoked from the HAL to deal with any CPU exceptions that the HAL does
95 // not want to deal with itself. It usually invokes the kernel's exception
96 // delivery mechanism. FIXME
97 // declared in src/hal_misc.c
98 externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data );
99
100 //-----------------------------------------------------------------------------
101 // Bit manipulation routines
102 // declared in src/hal_misc.c
103
104 externC cyg_uint32 hal_lsbit_index(cyg_uint32 mask);
105 externC cyg_uint32 hal_msbit_index(cyg_uint32 mask);
106
107 #define HAL_LSBIT_INDEX(index, mask) index = hal_lsbit_index(mask);
108
109 #define HAL_MSBIT_INDEX(index, mask) index = hal_msbit_index(mask);
110
111 //-----------------------------------------------------------------------------
112 // Context Initialization
113 // Initialize the context of a thread.
114 // Arguments:
115 // _sparg_ name of variable containing current sp, will be written with new sp
116 // _thread_ thread object address, passed as argument to entry point
117 // _entry_ entry point address.
118 // _id_ bit pattern used in initializing registers, for debugging.
119
120 #define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ )                     \
121     CYG_MACRO_START                                                                     \
122     register CYG_WORD _sp_ = ((CYG_WORD)_sparg_);                                       \
123     register HAL_SavedRegisters *_regs_;                                                \
124     int _i_;                                                                            \
125     _regs_ = (HAL_SavedRegisters *)(((_sp_) - sizeof(HAL_SavedRegisters)) & ~(CYGARC_ALIGNMENT - 1));             \
126     for( _i_ = 0; _i_ <= 14; _i_++ ) (_regs_)->r[_i_] = (_id_)|_i_;                     \
127     (_regs_)->r[15] = (CYG_HAL_FR30_REG)(_regs_);     /* r15 = USP = top of stack*/     \
128     (_regs_)->r[04] = (CYG_HAL_FR30_REG)(_thread_);   /* R4 = arg1 = thread ptr  */     \
129     (_regs_)->pc = (CYG_WORD)(_entry_);               /* PC = entry point        */     \
130     (_regs_)->ps = (CYG_HAL_FR30_REG)0x1f0030;        /* 0x000F0030;  set flags  */     \
131     (_regs_)->tbr = (CYG_HAL_FR30_REG)0x10ffc00;      /*system standard tbr value*/     \
132     (_regs_)->rp = (CYG_HAL_FR30_REG)0x0;             /* return pointer = 0x0    */     \
133     (_regs_)->ssp = (CYG_HAL_FR30_REG)0x0;            /* R4 = arg1 = thread ptr  */     \
134     (_regs_)->usp = (CYG_HAL_FR30_REG)(_regs_);       /* r15 = USP = top of stack*/     \
135     (_regs_)->mdh = (CYG_HAL_FR30_REG)0;              /* mdh = 0                 */     \
136     (_regs_)->mdl = (CYG_HAL_FR30_REG)0;              /* mdl = 0                 */     \
137     (_sparg_) = (CYG_ADDRESS)_regs_;                                                    \
138     CYG_MACRO_END
139
140 //-----------------------------------------------------------------------------
141 // Context switch macros.
142 // The arguments are pointers to locations where the stack pointer
143 // of the current thread is to be stored, and from where the sp of the
144 // next thread is to be fetched.
145 // declared in src/hal_misc.c
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_,(CYG_ADDRESS)_fspptr_);
153
154 #define HAL_THREAD_LOAD_CONTEXT(_tspptr_)                               \
155         hal_thread_load_context( (CYG_ADDRESS)_tspptr_ );
156
157 //-----------------------------------------------------------------------------
158 // Execution reorder barrier.
159 // When optimizing the compiler can reorder code. In multithreaded systems
160 // where the order of actions is vital, this can sometimes cause problems.
161 // This macro may be inserted into places where reordering should not happen.
162
163 #define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" )
164
165 //-----------------------------------------------------------------------------
166 // Breakpoint support
167 // HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen 
168 // if executed.
169 // HAL_BREAKINST is the value of the breakpoint instruction and
170 // HAL_BREAKINST_SIZE is its size in bytes.
171
172 #define HAL_BREAKPOINT(_label_)                 \
173 CYG_MACRO_START                                 \
174     asm volatile (" .globl  " #_label_ ";\n"    \
175                   #_label_":\n"                 \
176                   "int #0x9\n"                  \
177         );                                      \
178 CYG_MACRO_END
179
180 // 0x9F30 is the INTE instruction (vector no.9, TBR offset 0x3D8)
181 // 0x1f09 is the INT# 9 instruction (vector no.9, TBR offset 0x3D8)
182 #define HAL_BREAKINST                    0x1f09
183 #define HAL_BREAKINST_SIZE               2
184 #define HAL_BREAKINST_TYPE               unsigned short
185
186 //-----------------------------------------------------------------------------
187 // Thread register state manipulation for GDB support.
188
189 // Default to a 32 bit register size for GDB register dumps.
190 #ifndef CYG_HAL_GDB_REG
191 #define CYG_HAL_GDB_REG CYG_WORD32
192 #endif
193
194 // Register layout expected by GDB
195 typedef struct 
196 {
197     CYG_HAL_FR30_REG    r[16];          // was: r[0] GPR regs
198     CYG_HAL_FR30_REG    pc;
199     CYG_HAL_FR30_REG    ps;
200     CYG_HAL_FR30_REG    tbr;
201     CYG_HAL_FR30_REG    rp;
202     CYG_HAL_FR30_REG    ssp;
203     CYG_HAL_FR30_REG    usp;
204     CYG_HAL_FR30_REG    mdh;
205     CYG_HAL_FR30_REG    mdl;
206 } GDB_Registers;
207
208 // Translate a stack pointer as saved by the thread context macros above into
209 // a pointer to a HAL_SavedRegisters structure declared in src/fr30_stub.h
210
211 #define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ )  \
212          (_regs_) = (HAL_SavedRegisters *)(_sp_)
213
214 // Copy a set of registers from a HAL_SavedRegisters structure into a
215 // GDB ordered array.
216 #define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ )              \
217     CYG_MACRO_START                                             \
218     GDB_Registers *_gdb_ = (GDB_Registers *)(_aregval_);        \
219     int _i_;                                                    \
220                                                                 \
221     for( _i_ = 0; _i_ <  16; _i_++ ) {                          \
222         _gdb_->r[_i_] = (_regs_)->r[_i_];                       \
223     }                                                           \
224                                                                 \
225     _gdb_->pc = (_regs_)->pc;                                   \
226     _gdb_->ps = (_regs_)->ps;                                   \
227     _gdb_->tbr = (_regs_)->tbr;                                 \
228     _gdb_->rp = (_regs_)->rp;                                   \
229     _gdb_->ssp = (_regs_)->ssp;                                 \
230     _gdb_->usp = (_regs_)->usp;                                 \
231     _gdb_->mdh = (_regs_)->mdh;                                 \
232     _gdb_->mdl = (_regs_)->mdl;                                 \
233     CYG_MACRO_END
234
235 // Copy a set of registers from a GDB_Registers structure into a
236 // HAL_SavedRegisters structure.
237 #define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ )             \
238     CYG_MACRO_START                                             \
239     GDB_Registers *_gdb_ = (GDB_Registers *)(_aregval_);        \
240     int _i_;                                                    \
241                                                                 \
242     for( _i_ = 0; _i_ <  16; _i_++ )                            \
243         (_regs_)->r[_i_] = _gdb_->r[_i_];                       \
244                                                                 \
245     (_regs_)->pc = _gdb_->pc;                                   \
246     (_regs_)->ps = _gdb_->ps;                                   \
247     (_regs_)->tbr = _gdb_->tbr;                                 \
248     (_regs_)->rp = _gdb_->rp;                                   \
249     (_regs_)->ssp = _gdb_->ssp;                                 \
250     (_regs_)->usp = _gdb_->usp;                                 \
251     (_regs_)->mdh = _gdb_->mdh;                                 \
252     (_regs_)->mdl = _gdb_->mdl;                                 \
253     CYG_MACRO_END
254
255
256 // -------------------------------------------------------------------------
257 // hal_setjmp/hal_longjmp
258
259
260 // We must save all of the registers that are preserved across routine
261 // calls. The assembly code assumes that this structure is defined in the
262 // following format. Any changes to this structure will result in changes to
263 // the assembly code!!
264
265 typedef struct {
266     // registers
267     cyg_uint32 r8;
268     cyg_uint32 r9;
269     cyg_uint32 r10;
270     cyg_uint32 r11;
271     cyg_uint32 r14;
272
273     // SP and PC
274     cyg_uint32 r15; //USP
275     cyg_uint32 pc;
276 } hal_jmp_buf_t;
277
278 // This type is used by normal routines to pass the address of the structure
279 // into our routines without having to explicitly take the address
280 // of the structure.
281
282 typedef cyg_uint32 hal_jmp_buf[sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32)];
283
284 // Define the generic setjmp and longjmp routines
285 externC int hal_setjmp(hal_jmp_buf env);
286 externC void hal_longjmp(hal_jmp_buf env, int val);
287 //-----------------------------------------------------------------------------
288 // Idle thread code.
289 // This macro is called in the idle thread loop, and gives the HAL the
290 // chance to insert code. Typical idle thread behaviour might be to halt the
291 // processor. (contains an empty function call at the moment)
292 // declared in src/hal_misc.c
293
294 externC void hal_idle_thread_action(cyg_uint32 loop_count);
295
296 #define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_)
297
298 //-----------------------------------------------------------------------------
299 // Minimal and sensible stack sizes: the intention is that applications
300 // will use these to provide a stack size in the first instance prior to
301 // proper analysis.  Idle thread stack should be this big.
302 // 
303 //    THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES.
304 //           THEY ARE HOWEVER ENOUGH TO START PROGRAMMING.
305 // YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES!
306
307 // This is not a config option because it should not be adjusted except
308 // under "enough rope" sort of disclaimers.
309
310 //      Stack frame overhead per call.  13 registers (which is a maximum FIXME),
311 // frame pointer, and return address.  We  can't guess the local variables  so
312 // just assume that using all of the registers averages out.
313
314 #define CYGNUM_HAL_STACK_FRAME_SIZE ((13 + 1 + 1) * 4)
315
316 // Stack needed for a context switch.
317 // it should be sizeof(HAL_SavedRegisters)
318 //      All registers + PC + PS + RP + MDH + MDL
319
320 #ifndef CYGNUM_HAL_STACK_CONTEXT_SIZE
321 #define CYGNUM_HAL_STACK_CONTEXT_SIZE ((16+1+1+1+1+1)*4)
322 #endif // CYGNUM_HAL_STACK_CONTEXT_SIZE
323
324 // Interrupt + call to ISR, interrupt_end() and the DSR
325
326 #define CYGNUM_HAL_STACK_INTERRUPT_SIZE \
327 ((CYGNUM_HAL_STACK_CONTEXT_SIZE) + (4*CYGNUM_HAL_STACK_FRAME_SIZE))
328
329 // We define a minimum stack size as the minimum any thread could ever
330 // legitimately get away with. We can throw asserts if users ask for less
331 // than this. Allow enough for four interrupt sources - clock, serial,
332 // nic, and one other
333
334 #define CYGNUM_HAL_STACK_SIZE_MINIMUM                   \
335 ((4*CYGNUM_HAL_STACK_INTERRUPT_SIZE)            \
336  + (16*CYGNUM_HAL_STACK_FRAME_SIZE))
337
338 // Now make a reasonable choice for a typical thread size. Pluck figures
339 // from thin air and say 30 call frames with an average of 16 words of
340 // automatic variables per call frame
341
342 #define CYGNUM_HAL_STACK_SIZE_TYPICAL                   \
343 (CYGNUM_HAL_STACK_SIZE_MINIMUM +                \
344  (30 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4))))
345
346 //--------------------------------------------------------------------------
347 // Memory access macros
348
349 #define CYGARC_CACHED_ADDRESS(x)                       (x)
350 #define CYGARC_UNCACHED_ADDRESS(x)                     (x)
351 #define CYGARC_PHYSICAL_ADDRESS(x)                     (x)
352 #define CYGARC_VIRTUAL_ADDRESS(x)                      (x)
353
354 //--------------------------------------------------------------------------
355 // Macros for switching context between two eCos instances (jump from
356 // code in ROM to code in RAM or vice versa).
357
358 #define CYGARC_HAL_SAVE_GP()
359 #define CYGARC_HAL_RESTORE_GP()
360
361 //--------------------------------------------------------------------------
362 #endif // CYGONCE_HAL_HAL_ARCH_H
363 // End of hal_arch.h