|
2
|
1 //========================================================================== |
|
0
|
2 // |
|
2
|
3 // hal_misc.c |
|
0
|
4 // |
|
2
|
5 // HAL miscellaneous functions |
|
0
|
6 // |
|
2
|
7 //========================================================================== |
|
0
|
8 //####COPYRIGHTBEGIN#### |
|
|
9 // |
|
|
10 // ------------------------------------------- |
|
|
11 // The contents of this file are subject to the Cygnus eCos Public License |
|
|
12 // Version 1.0 (the "License"); you may not use this file except in |
|
|
13 // compliance with the License. You may obtain a copy of the License at |
|
|
14 // http://sourceware.cygnus.com/ecos |
|
|
15 // |
|
|
16 // Software distributed under the License is distributed on an "AS IS" |
|
|
17 // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the |
|
|
18 // License for the specific language governing rights and limitations under |
|
|
19 // the License. |
|
|
20 // |
|
|
21 // The Original Code is eCos - Embedded Cygnus Operating System, released |
|
|
22 // September 30, 1998. |
|
|
23 // |
|
|
24 // The Initial Developer of the Original Code is Cygnus. Portions created |
|
2
|
25 // by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved. |
|
0
|
26 // ------------------------------------------- |
|
|
27 // |
|
|
28 //####COPYRIGHTEND#### |
|
2
|
29 //========================================================================== |
|
0
|
30 //#####DESCRIPTIONBEGIN#### |
|
|
31 // |
|
2
|
32 // Author(s): nickg |
|
|
33 // Contributors: nickg, jlarmour |
|
|
34 // Date: 1999-01-21 |
|
|
35 // Purpose: HAL miscellaneous functions |
|
|
36 // Description: This file contains miscellaneous functions provided by the |
|
|
37 // HAL. |
|
0
|
38 // |
|
|
39 //####DESCRIPTIONEND#### |
|
|
40 // |
|
2
|
41 //========================================================================*/ |
|
0
|
42 |
|
|
43 #include <pkgconf/hal.h> |
|
|
44 |
|
|
45 #include <cyg/infra/cyg_type.h> // Base types |
|
|
46 #include <cyg/infra/cyg_trac.h> // tracing macros |
|
|
47 #include <cyg/infra/cyg_ass.h> // assertion macros |
|
|
48 |
|
|
49 #include <cyg/hal/hal_arch.h> // architectural definitions |
|
|
50 |
|
|
51 #include <cyg/hal/hal_intr.h> // Interrupt handling |
|
|
52 |
|
|
53 #include <cyg/hal/hal_cache.h> // Cache handling |
|
|
54 |
|
2
|
55 /*------------------------------------------------------------------------*/ |
|
|
56 /* First level C exception handler. */ |
|
0
|
57 |
|
|
58 externC void __handle_exception (void); |
|
|
59 |
|
|
60 externC HAL_SavedRegisters *_hal_registers; |
|
|
61 |
|
|
62 externC void exception_handler(HAL_SavedRegisters *regs) |
|
|
63 { |
|
|
64 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) |
|
|
65 |
|
|
66 // Set the pointer to the registers of the current exception |
|
|
67 // context. At entry the GDB stub will expand the |
|
|
68 // HAL_SavedRegisters structure into a (bigger) register array. |
|
|
69 _hal_registers = regs; |
|
|
70 __handle_exception(); |
|
|
71 |
|
|
72 #elif defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && defined(CYGPKG_HAL_EXCEPTIONS) |
|
|
73 |
|
|
74 // We should decode the vector and pass a more appropriate |
|
|
75 // value as the second argument. For now we simply pass a |
|
|
76 // pointer to the saved registers. We should also divert |
|
|
77 // breakpoint and other debug vectors into the debug stubs. |
|
|
78 |
|
2
|
79 cyg_hal_deliver_exception( regs->vector>>2, (CYG_ADDRWORD)regs ); |
|
0
|
80 |
|
|
81 #else |
|
|
82 |
|
|
83 CYG_FAIL("Exception!!!"); |
|
|
84 |
|
|
85 #endif |
|
|
86 return; |
|
|
87 } |
|
|
88 |
|
2
|
89 /*------------------------------------------------------------------------*/ |
|
|
90 /* default ISR */ |
|
0
|
91 |
|
|
92 externC cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) |
|
|
93 { |
|
|
94 CYG_TRACE1(true, "Interrupt: %d", vector); |
|
|
95 CYG_FAIL("Spurious Interrupt!!!"); |
|
|
96 return 0; |
|
|
97 } |
|
|
98 |
|
2
|
99 /*------------------------------------------------------------------------*/ |
|
|
100 /* data copy and bss zero functions */ |
|
0
|
101 |
|
|
102 typedef void (CYG_ROM_ADDRESS)(void); |
|
|
103 |
|
2
|
104 extern char __ram_data_start; |
|
|
105 extern char __ram_data_end; |
|
|
106 extern CYG_ROM_ADDRESS __rom_data_start; |
|
|
107 |
|
|
108 #ifdef CYG_HAL_STARTUP_ROM |
|
0
|
109 void hal_copy_data(void) |
|
|
110 { |
|
|
111 char *p = &__ram_data_start; |
|
|
112 char *q = (char *)&__rom_data_start; |
|
|
113 |
|
|
114 while( p != (char *)&__ram_data_end ) |
|
|
115 *p++ = *q++; |
|
|
116 } |
|
|
117 #endif |
|
|
118 |
|
2
|
119 extern CYG_ROM_ADDRESS __bss_start; |
|
|
120 extern CYG_ROM_ADDRESS __bss_end; |
|
|
121 |
|
0
|
122 void hal_zero_bss(void) |
|
|
123 { |
|
|
124 char *p = (char *)&__bss_start; |
|
|
125 |
|
2
|
126 while( p != (char *)&__bss_end ) |
|
0
|
127 *p++ = 0; |
|
|
128 } |
|
|
129 |
|
2
|
130 /*------------------------------------------------------------------------*/ |
|
0
|
131 |
|
2
|
132 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG |
|
|
133 cyg_bool cyg_hal_stop_constructors; |
|
|
134 #endif |
|
|
135 |
|
|
136 typedef void (*pfunc) (void); |
|
|
137 extern pfunc __CTOR_LIST__[]; |
|
|
138 extern void patch_dbg_syscalls(void * vector); |
|
0
|
139 |
|
|
140 void |
|
2
|
141 cyg_hal_invoke_constructors(void) |
|
0
|
142 { |
|
2
|
143 pfunc p; |
|
0
|
144 |
|
2
|
145 #ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG |
|
|
146 static long i = 0; |
|
|
147 long j = (long)(__CTOR_LIST__[0]); |
|
|
148 |
|
|
149 cyg_hal_stop_constructors=0; |
|
|
150 for ( ; i < j; i++ ) |
|
|
151 { |
|
|
152 p = __CTOR_LIST__[j - i]; |
|
|
153 p (); |
|
|
154 if (cyg_hal_stop_constructors) { |
|
|
155 i++; |
|
|
156 break; |
|
|
157 } |
|
|
158 } |
|
|
159 #else |
|
0
|
160 long i = (long)(__CTOR_LIST__[0]); |
|
|
161 |
|
|
162 for ( ; i > 0; i-- ) |
|
|
163 { |
|
|
164 p = __CTOR_LIST__[i]; |
|
|
165 p (); |
|
|
166 } |
|
2
|
167 #endif |
|
|
168 } // cyg_hal_invoke_constructors() |
|
0
|
169 |
|
2
|
170 void |
|
|
171 cyg_hal_enable_caches(void) |
|
|
172 { |
|
0
|
173 #ifdef CYG_HAL_MIPS_TX3904 |
|
|
174 |
|
|
175 // On the real hardware we also enable the cache. |
|
|
176 // doing this here is a temporary measure until we |
|
|
177 // have a proper platform specific place to do it. |
|
|
178 |
|
2
|
179 #if !defined(CYGHWR_HAL_TX39_JMR3904_ENABLE_TOE) |
|
|
180 |
|
0
|
181 HAL_ICACHE_INVALIDATE_ALL(); |
|
|
182 HAL_ICACHE_ENABLE(); |
|
|
183 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
184 HAL_DCACHE_ENABLE(); |
|
|
185 |
|
2
|
186 HAL_TX39_DEBUG_TOE_DISABLE(); |
|
|
187 |
|
|
188 #else |
|
|
189 |
|
|
190 // If TOE is enabled, caches are disabled by default |
|
|
191 // until spurious Bus Timeout problem is fixed. |
|
|
192 |
|
|
193 HAL_ICACHE_INVALIDATE_ALL(); |
|
|
194 HAL_ICACHE_DISABLE(); |
|
|
195 HAL_DCACHE_INVALIDATE_ALL(); |
|
|
196 HAL_DCACHE_DISABLE(); |
|
|
197 |
|
|
198 HAL_TX39_DEBUG_TOE_ENABLE(); |
|
|
199 |
|
0
|
200 #endif |
|
2
|
201 |
|
|
202 #endif |
|
|
203 } // cyg_hal_enable_caches() |
|
|
204 |
|
|
205 void |
|
|
206 cyg_hal_debug_init(void) |
|
|
207 { |
|
|
208 #ifdef CYGDBG_HAL_MIPS_INSTALL_CTRL_C_ISR |
|
|
209 #if defined(CYG_HAL_USE_ROM_MONITOR) && \ |
|
|
210 !defined(CYGDBG_INFRA_DIAG_USE_DEVICE) && \ |
|
0
|
211 defined(CYG_HAL_TX39_JMR3904) |
|
|
212 |
|
|
213 { |
|
|
214 static void hal_init_ctrlc_intr(void); |
|
|
215 hal_init_ctrlc_intr(); |
|
|
216 } |
|
|
217 |
|
|
218 #endif |
|
2
|
219 #endif // CYGDBG_HAL_MIPS_INSTALL_CTRL_C_ISR |
|
|
220 |
|
0
|
221 #if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ |
|
|
222 defined(CYG_HAL_USE_ROM_MONITOR) && \ |
|
|
223 defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) |
|
|
224 { |
|
2
|
225 patch_dbg_syscalls( (void *)(&hal_vsr_table[0]) ); |
|
0
|
226 } |
|
|
227 #endif |
|
2
|
228 } // cyg_hal_debug_init() |
|
0
|
229 |
|
2
|
230 /*------------------------------------------------------------------------*/ |
|
|
231 /* Determine the index of the ls bit of the supplied mask. */ |
|
0
|
232 |
|
|
233 cyg_uint32 hal_lsbit_index(cyg_uint32 mask) |
|
|
234 { |
|
|
235 cyg_uint32 n = mask; |
|
|
236 |
|
|
237 static const signed char tab[64] = |
|
|
238 { -1, 0, 1, 12, 2, 6, 0, 13, 3, 0, 7, 0, 0, 0, 0, 14, 10, |
|
|
239 4, 0, 0, 8, 0, 0, 25, 0, 0, 0, 0, 0, 21, 27 , 15, 31, 11, |
|
|
240 5, 0, 0, 0, 0, 0, 9, 0, 0, 24, 0, 0 , 20, 26, 30, 0, 0, 0, |
|
|
241 0, 23, 0, 19, 29, 0, 22, 18, 28, 17, 16, 0 |
|
|
242 }; |
|
|
243 |
|
|
244 n &= ~(n-1UL); |
|
|
245 n = (n<<16)-n; |
|
|
246 n = (n<<6)+n; |
|
|
247 n = (n<<4)+n; |
|
|
248 |
|
|
249 return tab[n>>26]; |
|
|
250 } |
|
|
251 |
|
2
|
252 /*------------------------------------------------------------------------*/ |
|
|
253 /* Determine the index of the ms bit of the supplied mask. */ |
|
0
|
254 |
|
|
255 cyg_uint32 hal_msbit_index(cyg_uint32 mask) |
|
|
256 { |
|
|
257 cyg_uint32 x = mask; |
|
|
258 cyg_uint32 w; |
|
|
259 |
|
|
260 /* Phase 1: make word with all ones from that one to the right */ |
|
|
261 x |= x >> 16; |
|
|
262 x |= x >> 8; |
|
|
263 x |= x >> 4; |
|
|
264 x |= x >> 2; |
|
|
265 x |= x >> 1; |
|
|
266 |
|
|
267 /* Phase 2: calculate number of "1" bits in the word */ |
|
|
268 w = (x & 0x55555555) + ((x >> 1) & 0x55555555); |
|
|
269 w = (w & 0x33333333) + ((w >> 2) & 0x33333333); |
|
|
270 w = w + (w >> 4); |
|
|
271 w = (w & 0x000F000F) + ((w >> 8) & 0x000F000F); |
|
|
272 return (cyg_uint32)((w + (w >> 16)) & 0xFF); |
|
|
273 |
|
|
274 } |
|
|
275 |
|
2
|
276 /*------------------------------------------------------------------------*/ |
|
|
277 /* Idle thread action */ |
|
0
|
278 |
|
|
279 void hal_idle_thread_action( cyg_uint32 count ) |
|
|
280 { |
|
|
281 #if 0 //def CYG_HAL_MIPS_SIM |
|
|
282 if( (count % 1000) == 0 ) |
|
|
283 { |
|
|
284 // This code causes a fake interrupt. |
|
|
285 asm volatile ( |
|
|
286 "xor $24,$24,$24;" |
|
|
287 "mtc0 $24,$13;" |
|
|
288 "lui $25,%%hi(1f);" |
|
|
289 "ori $25,$25,%%lo(1f);" |
|
|
290 "j other_vector;" |
|
|
291 "nop;" |
|
|
292 "1:" |
|
|
293 : |
|
|
294 : |
|
|
295 : "t8", "t9" |
|
|
296 ); |
|
|
297 } |
|
|
298 #endif |
|
|
299 #if 0 //def CYG_HAL_MIPS_JMR3904 |
|
|
300 |
|
|
301 { |
|
|
302 // cyg_uint32 tval, isr, imr, ilr; |
|
|
303 cyg_uint32 sr, cr; |
|
|
304 // HAL_CLOCK_READ( &tval ); |
|
|
305 // HAL_READ_UINT32( 0xFFFFC000, isr ); |
|
|
306 // HAL_READ_UINT32( 0xFFFFC004, imr ); |
|
|
307 // HAL_READ_UINT32( 0xFFFFC01C, ilr ); |
|
|
308 // CYG_TRACE2(1, "Timer value, ISR ",tval, isr); |
|
|
309 // CYG_TRACE2(1, "IMR ILR0 ", imr, ilr); |
|
|
310 |
|
|
311 asm volatile ( |
|
|
312 "mfc0 %0,$12;" |
|
|
313 "mfc0 %1,$13;" |
|
|
314 : "=r"(sr), "=r"(cr) |
|
|
315 ); |
|
|
316 |
|
|
317 CYG_TRACE2(1, "Status Cause ", sr, cr); |
|
|
318 |
|
|
319 // if( count == 4 ) |
|
|
320 // { |
|
|
321 // HAL_ENABLE_INTERRUPTS(); |
|
|
322 // } |
|
|
323 |
|
|
324 // if( count >= 10 ) |
|
|
325 // for(;;); |
|
|
326 } |
|
|
327 #endif |
|
|
328 } |
|
|
329 |
|
2
|
330 /*------------------------------------------------------------------------*/ |
|
|
331 /* Functions to support the detection and execution of a user provoked */ |
|
|
332 /* program break. These are usually called from interrupt routines. */ |
|
|
333 |
|
|
334 cyg_bool cyg_hal_is_break(char *buf, int size) |
|
|
335 { |
|
|
336 while( size ) |
|
|
337 if( buf[--size] == 0x03 ) return true; |
|
|
338 |
|
|
339 return false; |
|
|
340 } |
|
|
341 |
|
|
342 void cyg_hal_user_break( CYG_ADDRWORD *regs ) |
|
|
343 { |
|
|
344 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) |
|
|
345 |
|
|
346 // Ctrl-C: breakpoint. |
|
|
347 extern void breakpoint(void); |
|
|
348 breakpoint(); |
|
|
349 |
|
|
350 #elif defined(CYG_HAL_USE_ROM_MONITOR) && defined(CYG_HAL_USE_ROM_MONITOR_GDB_STUBS) |
|
|
351 |
|
|
352 // Ctrl-C: breakpoint. |
|
|
353 typedef void bpt_fn(void); |
|
|
354 bpt_fn *bfn = ((bpt_fn **)0x80000100)[61]; |
|
|
355 bfn(); |
|
|
356 |
|
|
357 #elif defined(CYG_HAL_USE_ROM_MONITOR) && defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) |
|
|
358 |
|
|
359 // Ctrl-C: breakpoint. |
|
|
360 typedef void install_bpt_fn(void *epc); |
|
|
361 HAL_SavedRegisters *sreg = (HAL_SavedRegisters *)regs; |
|
|
362 install_bpt_fn *ibp = (install_bpt_fn *)hal_vsr_table[35]; |
|
|
363 if( ibp != NULL ) ibp((void *)sreg->pc); |
|
|
364 |
|
|
365 #endif |
|
|
366 |
|
|
367 } |
|
|
368 |
|
|
369 /*------------------------------------------------------------------------*/ |
|
|
370 /* This code installs an interrupt handler to capture Ctrl-C. */ |
|
|
371 /* It's here for lack of anywhere more suitable to put it. */ |
|
|
372 |
|
|
373 #ifdef CYGDBG_HAL_MIPS_INSTALL_CTRL_C_ISR |
|
0
|
374 #if defined(CYG_HAL_USE_ROM_MONITOR) && \ |
|
|
375 !defined(CYGDBG_INFRA_DIAG_USE_DEVICE) && \ |
|
|
376 defined(CYG_HAL_TX39_JMR3904) |
|
|
377 |
|
|
378 #define DIAG_BASE 0xfffff300 |
|
|
379 #define DIAG_SLCR (DIAG_BASE+0x00) |
|
|
380 #define DIAG_SLSR (DIAG_BASE+0x04) |
|
|
381 #define DIAG_SLDICR (DIAG_BASE+0x08) |
|
|
382 #define DIAG_SLDISR (DIAG_BASE+0x0C) |
|
|
383 #define DIAG_SFCR (DIAG_BASE+0x10) |
|
|
384 #define DIAG_SBRG (DIAG_BASE+0x14) |
|
|
385 #define DIAG_TFIFO (DIAG_BASE+0x20) |
|
|
386 #define DIAG_RFIFO (DIAG_BASE+0x30) |
|
|
387 |
|
|
388 #define BRG_T0 0x0000 |
|
|
389 #define BRG_T2 0x0100 |
|
|
390 #define BRG_T4 0x0200 |
|
|
391 #define BRG_T5 0x0300 |
|
2
|
392 |
|
|
393 typedef cyg_uint32 (*original_isr_ptr_t)(CYG_ADDRWORD vector, CYG_ADDRWORD data); |
|
|
394 static original_isr_ptr_t original_isr_ptr; |
|
|
395 static CYG_ADDRWORD original_data, original_object; |
|
|
396 |
|
|
397 static cyg_uint32 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data, CYG_ADDRWORD* regs) |
|
0
|
398 { |
|
|
399 char c; |
|
|
400 CYG_WORD16 disr; |
|
|
401 |
|
|
402 HAL_READ_UINT16( DIAG_SLDISR , disr ); |
|
|
403 |
|
|
404 if( disr & 0x0001 ) |
|
|
405 { |
|
|
406 |
|
|
407 disr = disr & ~0x0001; |
|
|
408 |
|
|
409 HAL_READ_UINT8( DIAG_RFIFO, c ); |
|
|
410 |
|
|
411 HAL_WRITE_UINT16( DIAG_SLDISR , disr ); |
|
2
|
412 |
|
|
413 if( cyg_hal_is_break( &c , 1 ) ) |
|
|
414 cyg_hal_user_break( regs ); |
|
|
415 return 0; |
|
0
|
416 } |
|
2
|
417 /* else */ |
|
|
418 return (*original_isr_ptr)(vector, data); |
|
0
|
419 } |
|
|
420 |
|
|
421 |
|
|
422 static void hal_init_ctrlc_intr(void) |
|
|
423 { |
|
|
424 CYG_WORD16 dicr; |
|
|
425 |
|
2
|
426 cyg_uint32 index; |
|
|
427 HAL_TRANSLATE_VECTOR(CYGNUM_HAL_INTERRUPT_SIO_0, index); |
|
|
428 |
|
|
429 original_data = hal_interrupt_data[index]; |
|
|
430 original_object = hal_interrupt_objects[index]; |
|
|
431 original_isr_ptr = (original_isr_ptr_t) hal_interrupt_handlers[index]; |
|
0
|
432 |
|
2
|
433 hal_interrupt_handlers[index] = |
|
|
434 (CYG_ADDRESS)hal_default_isr; |
|
|
435 |
|
|
436 HAL_INTERRUPT_ATTACH( CYGNUM_HAL_INTERRUPT_SIO_0, hal_ctrlc_isr, original_data, |
|
|
437 original_object ); |
|
|
438 |
|
|
439 HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_SIO_0 ); |
|
0
|
440 |
|
|
441 HAL_READ_UINT16( DIAG_SLDICR , dicr ); |
|
|
442 dicr = 0x0001; |
|
|
443 HAL_WRITE_UINT16( DIAG_SLDICR , dicr ); |
|
|
444 } |
|
|
445 |
|
|
446 #endif |
|
2
|
447 #endif // CYGDBG_HAL_MIPS_INSTALL_CTRL_C_ISR |
|
0
|
448 |
|
2
|
449 /*------------------------------------------------------------------------*/ |
|
|
450 /* End of hal_misc.c */ |