1 #ifndef CYGONCE_HAL_HAL_ARCH_H
2 #define CYGONCE_HAL_HAL_ARCH_H
4 //=============================================================================
8 // Architecture specific abstractions
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.
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.
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
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.
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.
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.
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####
50 // Purpose: Define architecture abstractions
51 // Usage: #include <cyg/hal/hal_arch.h>
53 //####DESCRIPTIONEND####
55 //=============================================================================
57 #include <pkgconf/hal.h>
58 #include <cyg/infra/cyg_type.h>
60 #include <cyg/hal/var_arch.h>
62 #define CYG_HAL_FR30_REG CYG_ADDRWORD
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).
68 typedef struct HAL_SavedRegisters
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
86 cyg_uint32 last_trap; // the last taken trap (for GDB stubs)
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 );
100 //-----------------------------------------------------------------------------
101 // Bit manipulation routines
102 // declared in src/hal_misc.c
104 externC cyg_uint32 hal_lsbit_index(cyg_uint32 mask);
105 externC cyg_uint32 hal_msbit_index(cyg_uint32 mask);
107 #define HAL_LSBIT_INDEX(index, mask) index = hal_lsbit_index(mask);
109 #define HAL_MSBIT_INDEX(index, mask) index = hal_msbit_index(mask);
111 //-----------------------------------------------------------------------------
112 // Context Initialization
113 // Initialize the context of a thread.
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.
120 #define HAL_THREAD_INIT_CONTEXT( _sparg_, _thread_, _entry_, _id_ ) \
122 register CYG_WORD _sp_ = ((CYG_WORD)_sparg_); \
123 register HAL_SavedRegisters *_regs_; \
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_; \
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
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));
151 #define HAL_THREAD_SWITCH_CONTEXT(_fspptr_,_tspptr_) \
152 hal_thread_switch_context((CYG_ADDRESS)_tspptr_,(CYG_ADDRESS)_fspptr_);
154 #define HAL_THREAD_LOAD_CONTEXT(_tspptr_) \
155 hal_thread_load_context( (CYG_ADDRESS)_tspptr_ );
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.
163 #define HAL_REORDER_BARRIER() asm volatile ( "" : : : "memory" )
165 //-----------------------------------------------------------------------------
166 // Breakpoint support
167 // HAL_BREAKPOINT() is a code sequence that will cause a breakpoint to happen
169 // HAL_BREAKINST is the value of the breakpoint instruction and
170 // HAL_BREAKINST_SIZE is its size in bytes.
172 #define HAL_BREAKPOINT(_label_) \
174 asm volatile (" .globl " #_label_ ";\n" \
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
186 //-----------------------------------------------------------------------------
187 // Thread register state manipulation for GDB support.
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
194 // Register layout expected by GDB
197 CYG_HAL_FR30_REG r[16]; // was: r[0] GPR regs
200 CYG_HAL_FR30_REG tbr;
202 CYG_HAL_FR30_REG ssp;
203 CYG_HAL_FR30_REG usp;
204 CYG_HAL_FR30_REG mdh;
205 CYG_HAL_FR30_REG mdl;
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
211 #define HAL_THREAD_GET_SAVED_REGISTERS( _sp_, _regs_ ) \
212 (_regs_) = (HAL_SavedRegisters *)(_sp_)
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_ ) \
218 GDB_Registers *_gdb_ = (GDB_Registers *)(_aregval_); \
221 for( _i_ = 0; _i_ < 16; _i_++ ) { \
222 _gdb_->r[_i_] = (_regs_)->r[_i_]; \
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; \
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_ ) \
239 GDB_Registers *_gdb_ = (GDB_Registers *)(_aregval_); \
242 for( _i_ = 0; _i_ < 16; _i_++ ) \
243 (_regs_)->r[_i_] = _gdb_->r[_i_]; \
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; \
256 // -------------------------------------------------------------------------
257 // hal_setjmp/hal_longjmp
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!!
274 cyg_uint32 r15; //USP
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
282 typedef cyg_uint32 hal_jmp_buf[sizeof(hal_jmp_buf_t) / sizeof(cyg_uint32)];
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 //-----------------------------------------------------------------------------
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
294 externC void hal_idle_thread_action(cyg_uint32 loop_count);
296 #define HAL_IDLE_THREAD_ACTION(_count_) hal_idle_thread_action(_count_)
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.
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!
307 // This is not a config option because it should not be adjusted except
308 // under "enough rope" sort of disclaimers.
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.
314 #define CYGNUM_HAL_STACK_FRAME_SIZE ((13 + 1 + 1) * 4)
316 // Stack needed for a context switch.
317 // it should be sizeof(HAL_SavedRegisters)
318 // All registers + PC + PS + RP + MDH + MDL
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
324 // Interrupt + call to ISR, interrupt_end() and the DSR
326 #define CYGNUM_HAL_STACK_INTERRUPT_SIZE \
327 ((CYGNUM_HAL_STACK_CONTEXT_SIZE) + (4*CYGNUM_HAL_STACK_FRAME_SIZE))
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
334 #define CYGNUM_HAL_STACK_SIZE_MINIMUM \
335 ((4*CYGNUM_HAL_STACK_INTERRUPT_SIZE) \
336 + (16*CYGNUM_HAL_STACK_FRAME_SIZE))
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
342 #define CYGNUM_HAL_STACK_SIZE_TYPICAL \
343 (CYGNUM_HAL_STACK_SIZE_MINIMUM + \
344 (30 * (CYGNUM_HAL_STACK_FRAME_SIZE+(16*4))))
346 //--------------------------------------------------------------------------
347 // Memory access macros
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)
354 //--------------------------------------------------------------------------
355 // Macros for switching context between two eCos instances (jump from
356 // code in ROM to code in RAM or vice versa).
358 #define CYGARC_HAL_SAVE_GP()
359 #define CYGARC_HAL_RESTORE_GP()
361 //--------------------------------------------------------------------------
362 #endif // CYGONCE_HAL_HAL_ARCH_H