]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/coldfire/arch/v2_0/include/hal_arch.h
Initial revision
[karo-tx-redboot.git] / packages / hal / coldfire / arch / v2_0 / include / hal_arch.h
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 //####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) 2006 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 //####ECOSGPLCOPYRIGHTEND####
41 //========================================================================
42 //#####DESCRIPTIONBEGIN####
43 //
44 // Author(s):     Enrico Piria
45 // Contributors:  Wade Jensen
46 // Date:          2005-25-06
47 // Purpose:       
48 // Description:   Definitions for the ColdFire architecture HAL.
49 //
50 //####DESCRIPTIONEND####
51 //========================================================================
52
53 #include <pkgconf/hal.h>
54 #include <cyg/infra/cyg_type.h>
55
56 // Include some variant specific architectural defines
57 #include <cyg/hal/var_arch.h>
58
59 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
60 #include <cyg/hal/coldfire_stub.h>
61 #endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
62
63 // ----------------------------------------------------------------------------
64 // Macros to deal with exception stack frame fields
65
66 // The ColdFire family of processors has a simplified exception stack
67 // frame that looks like the following:
68 //
69 //          8 +----------------+----------------+
70 //            |         Program Counter         |
71 //          4 +----------------+----------------+
72 //            |Fmt/FS/Vector/FS|      SR        |
73 //  SP -->  0 +----------------+----------------+
74 // The stack self-aligns to a 4-byte boundary at an exception, with
75 // the Fmt/FS/Vector/FS field indicating the size of the adjustment
76 // (SP += 0,1,2,3 bytes).
77
78 // Define the Fmt/FS/Vector/FS word.
79 // Bits 31-28 are the format word which tells the
80 // RTI instruction how to align the stack.
81 #define HAL_CF_EXCEPTION_FORMAT_MSK ((CYG_WORD16)0xF000)
82 // Bits 25-18 are the vector number of the exception.
83 #define HAL_CF_EXCEPTION_VECTOR_MSK ((CYG_WORD16)0x03FC)
84 // Bits 27-26, and 17-16 are the fault status used
85 // for bus and address errors.
86 #define HAL_CF_EXCEPTION_FS32_MSK   ((CYG_WORD16)0x0C00)
87 #define HAL_CF_EXCEPTION_FS10_MSK   ((CYG_WORD16)0x0003)
88
89 // Macros to access fields in the format vector word.
90
91 #define HAL_CF_EXCEPTION_FORMAT(_fmt_vec_word_)                            \
92     ((((CYG_WORD16)(_fmt_vec_word_)) & HAL_CF_EXCEPTION_FORMAT_MSK) >> 12)
93
94 #define HAL_CF_EXCEPTION_VECTOR(_fmt_vec_word_)                            \
95     ((((CYG_WORD16)(_fmt_vec_word_)) & HAL_CF_EXCEPTION_VECTOR_MSK) >> 2)
96
97 #define HAL_CF_EXCEPTION_FS(_fmt_vec_word_)                                \
98      (((((CYG_WORD16)(_fmt_vec_word_)) & HAL_CF_EXCEPTION_FS32_MSK) >> 8)  \
99      | (((CYG_WORD16)(_fmt_vec_word_)) & HAL_CF_EXCEPTION_FS10_MSK))
100
101 // ----------------------------------------------------------------------------
102 // HAL_SavedRegisters -- Saved by a context switch or by an exception/interrupt
103
104 typedef struct
105 {
106     // These are common to all saved states and are in the order
107     // stored and loaded by the movem instruction.
108
109     // Data regs D0-D7
110     CYG_WORD32 d[8];
111
112     // Address regs A0-A7
113     CYG_ADDRESS a[8];
114
115 #ifdef CYGHWR_HAL_COLDFIRE_MAC
116     // MAC registers
117     CYG_WORD32 macc;
118     CYG_WORD32 macsr;
119     CYG_WORD32 mask;
120 #endif
121
122     // On exception/interrupt PC, SR and exception are pushed on the
123     // stack automatically, so there is no need to allocate the entire
124     // structure.
125     
126     // 16-bit format/vector word
127     CYG_WORD16 fmt_vec_word;
128
129     // Status register
130     CYG_WORD16 sr;
131
132     // Program counter
133     CYG_ADDRESS pc;
134
135 } __attribute__ ((aligned, packed)) HAL_SavedRegisters;
136
137 #ifndef HAL_THREAD_SWITCH_CONTEXT
138
139 // ***************************************************************************
140 // HAL_THREAD_SWITCH_CONTEXT
141 // 
142 // This macro saves the state of the currently running thread and writes
143 // its stack pointer to *(_fspptr_).
144 // It then switches to the thread context that *(_tspptr_) points to.
145 // 
146 // INPUT:
147 //  _fspptr_: A pointer to the location to save the current thread's stack
148 //      pointer to.
149 // 
150 //   _tspptr_: A pointer to the location containing the stack pointer of
151 //      the thread context to switch to.
152 // 
153 // OUTPUT:
154 //   *(_fspptr_): Contains the stack pointer of the previous thread's context.
155 // 
156 // ***************************************************************************
157
158 externC void hal_thread_switch_context( CYG_ADDRESS to, CYG_ADDRESS from );
159 externC void hal_thread_load_context( CYG_ADDRESS to )
160     CYGBLD_ATTRIB_NORET;
161
162 #define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_)                    \
163         hal_thread_switch_context((CYG_ADDRESS)_tspptr_,(CYG_ADDRESS)_fspptr_);
164 #endif // HAL_THREAD_SWITCH_CONTEXT
165
166 #ifndef HAL_THREAD_LOAD_CONTEXT
167
168 // ***************************************************************************
169 // hal_thread_load_context
170 // 
171 // This routine loads the thread context that *(_tspptr_) points to.
172 // This routine does not return.
173 // 
174 // INPUT:
175 //   _tspptr_: A pointer to  the location containing  the stack pointer  of
176 //      the thread context to switch to.
177 // 
178 // ***************************************************************************
179
180 #define HAL_THREAD_LOAD_CONTEXT(_tspptr_)                               \
181         hal_thread_load_context( (CYG_ADDRESS)_tspptr_ );
182 #endif // HAL_THREAD_LOAD_CONTEXT
183
184
185 #ifndef HAL_THREAD_INIT_CONTEXT
186
187 // ***************************************************************************
188 // HAL_THREAD_INIT_CONTEXT -- Context Initialization
189 // 
190 // Initialize the context of a thread.
191 // 
192 // INPUT:
193 //   _sparg_: The name of the variable containing the current sp. This
194 //      will be written with the new sp.
195 // 
196 //   _thread_: The thread object address, passed as argument to entry
197 //      point.
198 // 
199 //   _entry_: The thread's entry point address.
200 // 
201 //   _id_: A bit pattern used in initializing registers, for debugging.
202 // 
203 // OUTPUT:
204 //   _sparg_: Updated with the value of the new sp.
205 // 
206 // ***************************************************************************
207
208 #define HAL_THREAD_INIT_CONTEXT(_sparg_, _thread_, _entry_, _id_)           \
209     CYG_MACRO_START                                                         \
210     CYG_WORD32 * _sp_ = ((CYG_WORD32*)((CYG_WORD32)(_sparg_) & ~15));       \
211     HAL_SavedRegisters * _regs_;                                            \
212     int _i_;                                                                \
213                                                                             \
214     /* Thread's parameter. */                                               \
215     *(--_sp_) = (CYG_WORD32)(_thread_);                                     \
216     /* Fake thread's return addr. Needed because thread is a function */    \
217     /* and parameters to functions are always follwed by the return   */    \
218     /* address on the stack.                                          */    \
219     *(--_sp_) = (CYG_WORD32)(0xDEADC0DE);                                   \
220      /* Thread's return addr. (used by hal_thread_load_context) */          \
221     *(--_sp_) = (CYG_WORD32)(_entry_);                                      \
222                                                                             \
223     _regs_ = (HAL_SavedRegisters *)                                         \
224               ((CYG_WORD32)_sp_ - sizeof(HAL_SavedRegisters));              \
225                                                                             \
226     for (_i_=0; _i_ < 8; _i_++)                                             \
227         _regs_->a[_i_] = _regs_->d[_i_] = (_id_);                           \
228     /* A6, initial frame pointer should be null */                          \
229     _regs_->a[6] = (CYG_ADDRESS)0;                                          \
230                                                                             \
231     /* Thread's starting SR. All interrupts enabled. */                     \
232     _regs_->sr = 0x3000;                                                    \
233                                                                             \
234     /* Thread's starting PC */                                              \
235     _regs_->pc = (CYG_ADDRESS)(_entry_);                                    \
236                                                                             \
237     (_sparg_) = (CYG_ADDRESS)_regs_;                                        \
238     CYG_MACRO_END
239 #endif // HAL_THREAD_INIT_CONTEXT
240     
241 // ----------------------------------------------------------------------------
242 // Bit manipulation routines.
243
244 externC cyg_uint32 hal_lsbit_index(cyg_uint32 mask);
245 externC cyg_uint32 hal_msbit_index(cyg_uint32 mask);
246
247 #define HAL_LSBIT_INDEX(index, mask) (index) = hal_lsbit_index(mask);
248
249 #define HAL_MSBIT_INDEX(index, mask) (index) = hal_msbit_index(mask);
250
251 // ----------------------------------------------------------------------------
252 // Idle thread code.
253 // This macro is called in the idle thread loop, and gives the HAL the
254 // chance to insert code. Typical idle thread behaviour might be to halt the
255 // processor.
256
257 externC void hal_idle_thread_action(cyg_uint32 loop_count);
258
259 #define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_)
260
261 // ----------------------------------------------------------------------------
262 // Execution reorder barrier.
263 // When optimizing the compiler can reorder code. In multithreaded systems
264 // where the order of actions is vital, this can sometimes cause problems.
265 // This macro may be inserted into places where reordering should not happen.
266
267 #define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" )
268
269 // ----------------------------------------------------------------------------
270 // Breakpoint support
271 // HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen
272 // if executed.
273 // HAL_BREAKINST is the value of the breakpoint instruction and
274 // HAL_BREAKINST_SIZE is its size in bytes.
275
276 // The host side of GDB debugger uses trap #15 to install breakpoints.
277
278 #define CYGNUM_HAL_VECTOR_DEBUGTRAP         47
279
280 #define HAL_BREAKPOINT(_label_)                 \
281 asm volatile (" .globl  " #_label_ ";"          \
282               #_label_":"                       \
283               " trap #15"                       \
284     );
285
286 #define HAL_BREAKINST           0x4E4F
287
288 #define HAL_BREAKINST_SIZE      2
289
290
291 // ----------------------------------------------------------------------------
292 // Thread register state manipulation for GDB support.
293
294 typedef struct {
295     cyg_uint32  d[8];
296     cyg_uint32  a[8];
297     cyg_uint32  pc;
298     cyg_uint32  sr;
299 } GDB_Registers;
300
301 // Translate a stack pointer as saved by the thread context macros above into
302 // a pointer to a HAL_SavedRegisters structure.
303 #define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ )  \
304         (_regs_) = (HAL_SavedRegisters *)(_sp_)
305
306
307 // Copy a set of registers from a HAL_SavedRegisters structure into a
308 // GDB ordered array.
309 #define HAL_GET_GDB_REGISTERS( _aregval_, _regs_ )              \
310     CYG_MACRO_START                                             \
311     union __gdbreguniontype {                                   \
312       __typeof__(_aregval_) _aregval2_;                         \
313       GDB_Registers *_gdbr;                                     \
314     } __gdbregunion;                                            \
315     __gdbregunion._aregval2_ = (_aregval_);                     \
316     GDB_Registers *_gdb_ = __gdbregunion._gdbr;                 \
317     int _i_;                                                    \
318                                                                 \
319     for( _i_ = 0; _i_ < 8; _i_++ )                              \
320     {                                                           \
321         _gdb_->d[_i_] = (_regs_)->d[_i_];                       \
322         _gdb_->a[_i_] = (_regs_)->a[_i_];                       \
323     }                                                           \
324                                                                 \
325     _gdb_->pc = (_regs_)->pc;                                   \
326     _gdb_->sr = (cyg_uint32) ((_regs_)->sr);                    \
327     CYG_MACRO_END
328
329 // Copy a GDB ordered array into a HAL_SavedRegisters structure.
330 #define HAL_SET_GDB_REGISTERS( _regs_ , _aregval_ )             \
331     CYG_MACRO_START                                             \
332     union __gdbreguniontype {                                   \
333       __typeof__(_aregval_) _aregval2_;                         \
334       GDB_Registers *_gdbr;                                     \
335     } __gdbregunion;                                            \
336     __gdbregunion._aregval2_ = (_aregval_);                     \
337     GDB_Registers *_gdb_ = __gdbregunion._gdbr;                 \
338     int _i_;                                                    \
339                                                                 \
340     for( _i_ = 0; _i_ < 8; _i_++ )                              \
341     {                                                           \
342         (_regs_)->d[_i_] = _gdb_->d[_i_];                       \
343         (_regs_)->a[_i_] = _gdb_->a[_i_];                       \
344     }                                                           \
345                                                                 \
346     (_regs_)->pc = _gdb_->pc;                                   \
347     (_regs_)->sr = (CYG_WORD16)(_gdb_->sr);                     \
348     CYG_MACRO_END
349
350
351 #if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \
352       defined(CYGPKG_HAL_EXCEPTIONS)
353
354 // ----------------------------------------------------------------------------
355 // Exception handling function.
356 // This function is defined by the kernel according to this prototype. It is
357 // invoked from the HAL to deal with any CPU exceptions that the HAL does
358 // not want to deal with itself. It usually invokes the kernel's exception
359 // delivery mechanism.
360
361 externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data );
362
363 #endif // defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT)
364
365 // ----------------------------------------------------------------------------
366 // Minimal and sensible stack sizes: the intention is that applications
367 // will use these to provide a stack size in the first instance prior to
368 // proper analysis. Idle thread stack should be this big.
369
370 //    THESE ARE NOT INTENDED TO BE MICROMETRICALLY ACCURATE FIGURES.
371 //           THEY ARE HOWEVER ENOUGH TO START PROGRAMMING.
372 // YOU MUST MAKE YOUR STACKS LARGER IF YOU HAVE LARGE "AUTO" VARIABLES!
373
374 // This is not a config option because it should not be adjusted except
375 // under "enough rope" sort of disclaimers.
376
377 // Stack frame overhead per call: 6 data registers, 5 address registers,
378 // frame pointer, and return address. We can't guess the local variables so
379 // just assume that using all of the registers averages out.
380
381 #define CYGNUM_HAL_STACK_FRAME_SIZE ((6 + 5 + 1 + 1) * 4)
382
383 // Stack needed for a context switch.
384 // All registers + pc + sr + vector.
385
386 #ifndef CYGNUM_HAL_STACK_CONTEXT_SIZE
387 #define CYGNUM_HAL_STACK_CONTEXT_SIZE ((8+8+1)*4 + (1+1)*2)
388 #endif // CYGNUM_HAL_STACK_CONTEXT_SIZE
389
390 // Interrupt (rounded up) + call to ISR, interrupt_end() and the DSR.
391
392 #define CYGNUM_HAL_STACK_INTERRUPT_SIZE \
393     ((CYGNUM_HAL_STACK_CONTEXT_SIZE) + (2*CYGNUM_HAL_STACK_FRAME_SIZE))
394
395 // We define a minimum stack size as the minimum any thread could ever
396 // legitimately get away with. We can throw asserts if users ask for less
397 // than this. Allow enough for four interrupt sources - clock, serial,
398 // nic, and one other.
399
400 // No separate interrupt stack exists. Make sure all threads contain
401 // a stack sufficiently large.
402
403 #define CYGNUM_HAL_STACK_SIZE_MINIMUM                   \
404         ((4*CYGNUM_HAL_STACK_INTERRUPT_SIZE)            \
405          + (16*CYGNUM_HAL_STACK_FRAME_SIZE))
406
407 // Now make a reasonable choice for a typical thread size. Pluck figures
408 // from thin air and say 30 call frames with an average of 16 words of
409 // automatic variables per call frame.
410
411 #define CYGNUM_HAL_STACK_SIZE_TYPICAL                   \
412         (CYGNUM_HAL_STACK_SIZE_MINIMUM +                \
413          (30 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4))))
414
415 // -------------------------------------------------------------------------
416 // Macros for switching context between two eCos instances (jump from
417 // code in ROM to code in RAM or vice versa).
418
419 #define CYGARC_HAL_SAVE_GP()
420 #define CYGARC_HAL_RESTORE_GP()
421
422 // -------------------------------------------------------------------------
423 // hal_setjmp/hal_longjmp
424
425
426 // We must save all of the registers that are preserved across routine
427 // calls. The assembly code assumes that this structure is defined in the
428 // following format. Any changes to this structure will result in changes to
429 // the assembly code!!
430
431 typedef struct {
432     // D registers
433     cyg_uint32 d2;
434     cyg_uint32 d3;
435     cyg_uint32 d4;
436     cyg_uint32 d5;
437     cyg_uint32 d6;
438     cyg_uint32 d7;
439
440     // A registers
441     cyg_uint32 a2;
442     cyg_uint32 a3;
443     cyg_uint32 a4;
444     cyg_uint32 a5;
445     cyg_uint32 a6;
446     
447 #ifdef CYGHWR_HAL_COLDFIRE_MAC
448     // MAC registers
449     cyg_uint32 macc;
450     cyg_uint32 macsr;
451     cyg_uint32 mask;
452 #endif
453
454     // SP and PC
455     cyg_uint32 sp;
456     cyg_uint32 pc;
457 } hal_jmp_buf_t;
458
459 // This type is used by normal routines to pass the address of the structure
460 // into our routines without having to explicitly take the address
461 // of the structure.
462
463 typedef cyg_uint32 hal_jmp_buf[sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32)];
464
465 // Define the generic setjmp and longjmp routines
466 externC int hal_setjmp(hal_jmp_buf env);
467 externC void hal_longjmp(hal_jmp_buf env, int val);
468 #define hal_setjmp(_env) hal_setjmp(_env)
469 #define hal_longjmp(_env, _val) hal_longjmp(_env, _val)
470
471 // ---------------------------------------------------------------------------
472 // End of hal_arch.h
473 #endif // CYGONCE_HAL_ARCH_H