1 //=============================================================================
5 // ROM/RAM interfacing functions
7 //=============================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002, 2003 Gary Thomas
13 // Copyright (C) 2003 Nick Garnett <nickg@calivar.com>
14 // Copyright (C) 2003 Jonathan Larmour <jlarmour@eCosCentric.com>
16 // eCos is free software; you can redistribute it and/or modify it under
17 // the terms of the GNU General Public License as published by the Free
18 // Software Foundation; either version 2 or (at your option) any later version.
20 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
21 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 // You should have received a copy of the GNU General Public License along
26 // with eCos; if not, write to the Free Software Foundation, Inc.,
27 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
29 // As a special exception, if other files instantiate templates or use macros
30 // or inline functions from this file, or you compile this file and link it
31 // with other works to produce a work based on this file, this file does not
32 // by itself cause the resulting work to be covered by the GNU General Public
33 // License. However the source code for this file must still be made available
34 // in accordance with section (3) of the GNU General Public License.
36 // This exception does not invalidate any other reasons why a work based on
37 // this file might be covered by the GNU General Public License.
39 // Alternative licenses for eCos may be arranged by contacting the copyright
41 // -------------------------------------------
42 //####ECOSGPLCOPYRIGHTEND####
43 //=============================================================================
44 //#####DESCRIPTIONBEGIN####
47 // Contributors:jskov, woehler
50 //####DESCRIPTIONEND####
52 //=============================================================================
54 #include <pkgconf/hal.h>
57 # include <pkgconf/kernel.h>
60 #include <cyg/infra/cyg_ass.h> // assertions
62 #include <cyg/hal/hal_arch.h> // set/restore GP
64 #include <cyg/hal/hal_io.h> // IO macros
65 #include <cyg/hal/hal_if.h> // our interface
67 #include <cyg/hal/hal_diag.h> // Diag IO
68 #include <cyg/hal/hal_misc.h> // User break
70 #include <cyg/hal/hal_stub.h> // stub functionality
72 #include <cyg/hal/hal_intr.h> // hal_vsr_table and others
75 #include <pkgconf/redboot.h>
76 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
78 #include <flash_config.h>
80 #ifdef CYGOPT_REDBOOT_FIS
85 //--------------------------------------------------------------------------
87 externC void patch_dbg_syscalls(void * vector);
88 externC void init_thread_syscall(void * vector);
90 //--------------------------------------------------------------------------
91 // Implementations and function wrappers for monitor services
93 // flash config state queries
94 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
96 static __call_if_flash_cfg_op_fn_t flash_config_op;
99 flash_config_op(int op, struct cyg_fconfig *fc)
101 cyg_bool res = false;
103 CYGARC_HAL_SAVE_GP();
106 case CYGNUM_CALL_IF_FLASH_CFG_GET:
107 res = flash_get_config(fc->key, fc->val, fc->type);
109 case CYGNUM_CALL_IF_FLASH_CFG_NEXT:
110 res = flash_next_key(fc->key, fc->keylen, &fc->type, &fc->offset);
112 case CYGNUM_CALL_IF_FLASH_CFG_SET:
113 res = flash_set_config(fc->key, fc->val, fc->type);
116 // nothing else supported yet - though it is expected that "set"
117 // will fit the same set of arguments, potentially.
121 CYGARC_HAL_RESTORE_GP();
126 #ifdef CYGOPT_REDBOOT_FIS
128 static __call_if_flash_fis_op_fn_t flash_fis_op;
131 flash_fis_op( int op, char *name, void *val)
133 cyg_bool res = false;
134 struct fis_image_desc *fis;
137 CYGARC_HAL_SAVE_GP();
138 fis = fis_lookup(name, &num);
142 case CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE:
143 *(CYG_ADDRESS *)val = fis->flash_base;
146 case CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE:
147 *(unsigned long *)val = fis->size;
150 case CYGNUM_CALL_IF_FLASH_FIS_GET_MEM_BASE:
151 *(CYG_ADDRESS *)val = fis->mem_base;
154 case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_POINT:
155 *(CYG_ADDRESS *)val = fis->entry_point;
158 case CYGNUM_CALL_IF_FLASH_FIS_GET_DATA_LENGTH:
159 *(unsigned long *)val = fis->data_length;
162 case CYGNUM_CALL_IF_FLASH_FIS_GET_DESC_CKSUM:
163 *(unsigned long *)val = fis->desc_cksum;
166 case CYGNUM_CALL_IF_FLASH_FIS_GET_FILE_CKSUM:
167 *(unsigned long *)val = fis->file_cksum;
174 CYGARC_HAL_RESTORE_GP();
179 //----------------------------
181 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
183 static __call_if_delay_us_t delay_us;
186 delay_us(cyg_int32 usecs)
188 CYGARC_HAL_SAVE_GP();
191 cyg_int32 start, elapsed, elapsed_usec;
193 cyg_int32 usec_per_period = CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000;
194 cyg_int32 ticks_per_usec = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/usec_per_period;
197 // Spin in slices of 1/2 the RTC period. Allows interrupts
198 // time to run without messing up the algorithm. If we
199 // spun for 1 period (or more) of the RTC, there would also
200 // be problems figuring out when the timer wrapped. We
201 // may lose a tick or two for each cycle but it shouldn't
204 // The tests against CYGNUM_KERNEL_COUNTERS_RTC_PERIOD
205 // check for a value that would cause a 32 bit signed
206 // multiply to overflow. But this also implies that just
207 // multiplying by ticks_per_usec will yield a good
208 // approximation. Otherwise we need to do the full
209 // multiply+divide to get sufficient accuracy. Note that
210 // this test is actually constant, so the compiler will
211 // eliminate it and only compile the branch that is
214 if( usecs > usec_per_period/2 )
215 slice = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2;
216 else if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2 >= 0x7FFFFFFF/usec_per_period )
217 slice = usecs * ticks_per_usec;
220 slice = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
221 slice /= usec_per_period;
224 HAL_CLOCK_READ(&start);
226 HAL_CLOCK_READ(&elapsed);
227 elapsed = (elapsed - start); // counts up!
229 elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
230 } while (elapsed < slice);
232 // Adjust by elapsed, not slice, since an interrupt may
233 // have been stalling us for some time.
235 if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period )
236 elapsed_usec = elapsed / ticks_per_usec;
239 elapsed_usec = elapsed * usec_per_period;
240 elapsed_usec = elapsed_usec / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
243 // It is possible for elapsed_usec to end up zero in some
244 // circumstances and we could end up looping indefinitely.
245 // Avoid that by ensuring that we always decrement usec by
246 // at least 1 each time.
248 usecs -= elapsed_usec ? elapsed_usec : 1;
252 #else // CYGPKG_KERNEL
254 // Use a HAL feature if defined
257 // If no accurate delay mechanism, just spin for a while. Having
258 // an inaccurate delay is much better than no delay at all. The
259 // count of 10 should mean the loop takes something resembling
260 // 1us on most CPUs running between 30-100MHz [depends on how many
261 // instructions this compiles to, how many dispatch units can be
262 // used for the simple loop, actual CPU frequency, etc]
263 while (usecs-- > 0) {
265 for (i = 0; i < 10; i++);
267 #endif // HAL_DELAY_US
268 #endif // CYGPKG_KERNEL
269 CYGARC_HAL_RESTORE_GP();
271 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
274 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET
276 static __call_if_reset_t reset;
281 CYGARC_HAL_SAVE_GP();
282 // With luck, the platform defines some magic that will cause a hardware
284 #ifdef HAL_PLATFORM_RESET
285 HAL_PLATFORM_RESET();
288 #ifdef HAL_PLATFORM_RESET_ENTRY
289 // If that's not the case (above is an empty statement) there may
290 // be defined an address we can jump to - and effectively
291 // reinitialize the system. Not quite as good as a reset, but it
293 goto *HAL_PLATFORM_RESET_ENTRY;
296 #error " no RESET_ENTRY"
298 CYG_FAIL("Reset failed");
299 CYGARC_HAL_RESTORE_GP();
304 //------------------------------------
306 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE) || \
307 defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)
311 // This is the default service. It always returns false (0), and
312 // _does not_ trigger any assertions. Clients must either cope
313 // with the service failure or assert.
318 //----------------------------------
320 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS
322 #ifdef CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS
323 #define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \
324 (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS)
326 #define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \
327 CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
330 static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1];
333 set_debug_comm(int __comm_id)
335 static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY;
336 hal_virtual_comm_table_t* __chan;
337 int interrupt_state = 0;
338 int res = 1, update = 0;
339 CYGARC_HAL_SAVE_GP();
341 CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER
342 && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,
346 case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT:
347 if (__selected_id > 0)
348 res = __selected_id-1;
349 else if (__selected_id == 0)
350 res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER;
355 case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY:
356 CYGACC_CALL_IF_DEBUG_PROCS_SET(0);
357 __selected_id = __comm_id;
360 case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER:
366 __comm_id++; // skip mangler entry
372 // Find the interrupt state of the channel.
373 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
375 interrupt_state = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
377 __selected_id = __comm_id;
378 CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]);
380 // Set interrupt state on the new channel.
381 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
383 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);
385 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
388 CYGARC_HAL_RESTORE_GP();
393 set_console_comm(int __comm_id)
395 static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY;
396 int res = 1, update = 0;
397 CYGARC_HAL_SAVE_GP();
399 CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER
400 && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,
404 case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT:
405 if (__selected_id > 0)
406 res = __selected_id-1;
407 else if (__selected_id == 0)
408 res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER;
413 case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY:
414 CYGACC_CALL_IF_CONSOLE_PROCS_SET(0);
415 __selected_id = __comm_id;
418 case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER:
424 __comm_id++; // skip mangler entry
430 __selected_id = __comm_id;
432 CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]);
435 CYGARC_HAL_RESTORE_GP();
440 //----------------------------------
442 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE
445 flush_icache(void *__p, int __nbytes)
447 CYGARC_HAL_SAVE_GP();
448 #ifdef HAL_ICACHE_FLUSH
449 HAL_ICACHE_FLUSH( __p , __nbytes );
450 #elif defined(HAL_ICACHE_INVALIDATE)
451 HAL_ICACHE_INVALIDATE();
453 CYGARC_HAL_RESTORE_GP();
457 flush_dcache(void *__p, int __nbytes)
459 CYGARC_HAL_SAVE_GP();
460 #ifdef HAL_DCACHE_FLUSH
461 HAL_DCACHE_FLUSH( __p , __nbytes );
462 #elif defined(HAL_DCACHE_INVALIDATE)
463 HAL_DCACHE_INVALIDATE();
465 CYGARC_HAL_RESTORE_GP();
469 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG)
470 //-----------------------------------------------------------------------------
471 // GDB console output mangler (O-packetizer)
472 // COMMS init function at end.
474 // This gets called via the virtual vector console comms entry and
475 // handles O-packetization. The debug comms entries are used for the
478 cyg_hal_diag_mangler_gdb_getc(void* __ch_data)
481 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
482 CYGARC_HAL_SAVE_GP();
484 __ch = CYGACC_COMM_IF_GETC(*__chan);
486 CYGARC_HAL_RESTORE_GP();
491 static char __mangler_line[100];
492 static int __mangler_pos = 0;
495 cyg_hal_diag_mangler_gdb_flush(void* __ch_data)
497 CYG_INTERRUPT_STATE old;
498 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
499 #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
500 int tries = CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES;
504 // Nothing to do if mangler buffer is empty.
505 if (__mangler_pos == 0)
508 // Disable interrupts. This prevents GDB trying to interrupt us
509 // while we are in the middle of sending a packet. The serial
510 // receive interrupt will be seen when we re-enable interrupts
512 #if defined(CYG_HAL_STARTUP_ROM) \
513 || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION)
514 HAL_DISABLE_INTERRUPTS(old);
516 CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
519 #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
520 // Only wait 500ms for data to arrive - avoid "stuck" connections
521 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, CYGNUM_HAL_DEBUG_GDB_PROTOCOL_TIMEOUT);
526 static const char hex[] = "0123456789ABCDEF";
527 cyg_uint8 csum = 0, c1;
530 CYGACC_COMM_IF_PUTC(*__chan, '$');
531 CYGACC_COMM_IF_PUTC(*__chan, 'O');
533 for( i = 0; i < __mangler_pos; i++ )
535 char ch = __mangler_line[i];
536 char h = hex[(ch>>4)&0xF];
537 char l = hex[ch&0xF];
538 CYGACC_COMM_IF_PUTC(*__chan, h);
539 CYGACC_COMM_IF_PUTC(*__chan, l);
543 CYGACC_COMM_IF_PUTC(*__chan, '#');
544 CYGACC_COMM_IF_PUTC(*__chan, hex[(csum>>4)&0xF]);
545 CYGACC_COMM_IF_PUTC(*__chan, hex[csum&0xF]);
548 #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
549 if (CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, &c1) == 0) {
551 if (tries && (--tries == 0)) c1 = '+';
554 c1 = CYGACC_COMM_IF_GETC(*__chan);
557 if( c1 == '+' ) break;
559 if( cyg_hal_is_break( &c1 , 1 ) ) {
560 // Caller's responsibility to react on this.
561 CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(1);
564 if( c1 != '-' ) goto nak;
568 // And re-enable interrupts
569 #if defined(CYG_HAL_STARTUP_ROM) \
570 || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION)
571 HAL_RESTORE_INTERRUPTS(old);
573 CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
578 cyg_hal_diag_mangler_gdb_putc(void* __ch_data, cyg_uint8 c)
580 // No need to send CRs
581 if( c == '\r' ) return;
583 CYGARC_HAL_SAVE_GP();
585 __mangler_line[__mangler_pos++] = c;
587 if( c == '\n' || __mangler_pos == sizeof(__mangler_line) )
588 cyg_hal_diag_mangler_gdb_flush(__ch_data);
590 CYGARC_HAL_RESTORE_GP();
594 cyg_hal_diag_mangler_gdb_write(void* __ch_data,
595 const cyg_uint8* __buf, cyg_uint32 __len)
597 CYGARC_HAL_SAVE_GP();
600 cyg_hal_diag_mangler_gdb_putc(__ch_data, *__buf++);
602 CYGARC_HAL_RESTORE_GP();
606 cyg_hal_diag_mangler_gdb_read(void* __ch_data,
607 cyg_uint8* __buf, cyg_uint32 __len)
609 CYGARC_HAL_SAVE_GP();
612 *__buf++ = cyg_hal_diag_mangler_gdb_getc(__ch_data);
614 CYGARC_HAL_RESTORE_GP();
618 cyg_hal_diag_mangler_gdb_control(void *__ch_data,
619 __comm_control_cmd_t __func, ...)
621 CYGARC_HAL_SAVE_GP();
623 if (__func == __COMMCTL_FLUSH_OUTPUT)
624 cyg_hal_diag_mangler_gdb_flush(__ch_data);
626 CYGARC_HAL_RESTORE_GP();
630 // This is the COMMS init function. It gets called both by the stubs
631 // and diag init code to initialize the COMMS mangler channel table -
632 // that's all. The callers have to decide whether to actually use this
635 cyg_hal_diag_mangler_gdb_init(void)
637 hal_virtual_comm_table_t* comm;
638 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
640 // Initialize mangler procs
641 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER);
642 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
643 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_gdb_write);
644 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_gdb_read);
645 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_gdb_putc);
646 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_gdb_getc);
647 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_gdb_control);
649 // Restore the original console channel.
650 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
653 //-----------------------------------------------------------------------------
654 // Null console output mangler
655 // COMMS init function at end.
657 // This gets called via the virtual vector console comms entry and
658 // just forwards IO to the debug comms entries.
659 // This differs from setting the console channel to the same as the
660 // debug channel in that console output will go to the debug channel
661 // even if the debug channel is changed.
663 cyg_hal_diag_mangler_null_getc(void* __ch_data)
666 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
667 CYGARC_HAL_SAVE_GP();
669 __ch = CYGACC_COMM_IF_GETC(*__chan);
671 CYGARC_HAL_RESTORE_GP();
678 cyg_hal_diag_mangler_null_putc(void* __ch_data, cyg_uint8 c)
680 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
682 CYGARC_HAL_SAVE_GP();
684 CYGACC_COMM_IF_PUTC(*__chan, c);
686 CYGARC_HAL_RESTORE_GP();
690 cyg_hal_diag_mangler_null_write(void* __ch_data,
691 const cyg_uint8* __buf, cyg_uint32 __len)
693 CYGARC_HAL_SAVE_GP();
696 cyg_hal_diag_mangler_null_putc(__ch_data, *__buf++);
698 CYGARC_HAL_RESTORE_GP();
702 cyg_hal_diag_mangler_null_read(void* __ch_data,
703 cyg_uint8* __buf, cyg_uint32 __len)
705 CYGARC_HAL_SAVE_GP();
708 *__buf++ = cyg_hal_diag_mangler_null_getc(__ch_data);
710 CYGARC_HAL_RESTORE_GP();
714 cyg_hal_diag_mangler_null_control(void *__ch_data,
715 __comm_control_cmd_t __func, ...)
721 // This is the COMMS init function. It gets called both by the stubs
722 // and diag init code to initialize the COMMS mangler channel table -
723 // that's all. The callers have to decide whether to actually use this
726 cyg_hal_diag_mangler_null_init(void)
728 hal_virtual_comm_table_t* comm;
729 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
731 // Initialize mangler procs
732 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER);
733 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
734 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_null_write);
735 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_null_read);
736 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_null_putc);
737 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_null_getc);
738 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_null_control);
740 // Restore the original console channel.
741 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
744 //-----------------------------------------------------------------------------
745 // Console IO functions that adhere to the virtual vector table semantics in
746 // order to ensure proper debug agent mangling when required.
748 externC void cyg_hal_plf_comms_init(void);
751 hal_if_diag_init(void)
753 // This function may be called from various places and the code
754 // should only run once.
755 static cyg_uint8 called = 0;
759 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE
761 #if defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN)
762 // Use the mangler channel, which in turn uses the debug channel.
763 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER);
765 // Initialize the mangler channel.
766 #if defined(CYGSEM_HAL_DIAG_MANGLER_GDB)
767 cyg_hal_diag_mangler_gdb_init();
768 #elif defined(CYGSEM_HAL_DIAG_MANGLER_None)
769 cyg_hal_diag_mangler_null_init();
772 #else // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN
774 // Use an actual (raw) IO channel
775 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL);
777 #endif // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN
779 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE
783 hal_if_diag_write_char(char c)
785 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
788 CYGACC_COMM_IF_PUTC(*__chan, c);
790 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
792 // FIXME: What should be done if assertions are not enabled?
793 // This is a bad bad situation - we have no means for diag
794 // output; we want to hit a breakpoint to alert the developer
795 // or something like that.
796 CYG_ASSERT(__chan, "No valid channel set");
798 CYGACC_COMM_IF_PUTC(*__chan, c);
801 // Check interrupt flag
802 if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) {
803 CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
804 cyg_hal_user_break(0);
809 hal_if_diag_read_char(char *c)
811 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
814 *c = CYGACC_COMM_IF_GETC(*__chan);
816 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
818 // FIXME: What should be done if assertions are not enabled?
819 // This is a bad bad situation - we have no means for diag
820 // output; we want to hit a breakpoint to alert the developer
821 // or something like that.
822 CYG_ASSERT(__chan, "No valid channel set");
824 *c = CYGACC_COMM_IF_GETC(*__chan);
827 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
829 //=============================================================================
831 //=============================================================================
833 #if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \
834 || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
836 struct Hal_SavedRegisters *hal_saved_interrupt_state;
839 hal_ctrlc_isr_init(void)
841 // A ROM monitor never enables the interrupt itself. This is left
842 // to the (RAM) application.
843 #ifndef CYGSEM_HAL_ROM_MONITOR
844 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
846 #if 1 // Prevents crash on older stubs
848 // Allow only ctrl-c interrupt enabling when version in table is
849 // below legal max and above the necessary service, and _not_
850 // the value we set it to below.
851 v_m = CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK;
852 if (v_m >= CYGNUM_CALL_IF_TABLE_VERSION_CALL_MAX
853 || v_m < CYGNUM_CALL_IF_SET_DEBUG_COMM
854 || v_m == CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK)
857 // Now trash that value - otherwise downloading an image with
858 // builtin stubs on a board with older stubs (which will cause the
859 // version to be set to VERSION_CALL) may cause all subsequent
860 // runs to (wrongly) fall through to the below code. If there is
861 // a new stub on the board, it will reinitialize the version field
862 // on reset. Yes, this is a gross hack!
863 CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK);
866 // We can only enable interrupts on a valid debug channel.
868 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);
873 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)
875 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
876 int isr_ret = 0, ctrlc = 0;
879 isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data);
881 cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state );
887 hal_ctrlc_check(CYG_ADDRWORD vector, CYG_ADDRWORD data)
889 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
890 int gdb_vector = vector-1;
891 int isr_ret, ctrlc = 0;
893 // This check only to avoid crash on older stubs in case of unhandled
894 // interrupts. It is a bit messy, but required in a transition period.
896 (CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK ==
897 (CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK))){
898 gdb_vector = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DBG_ISR_VECTOR);
900 if (vector == gdb_vector) {
901 isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data);
903 cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state );
909 #endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT || CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
911 //--------------------------------------------------------------------------
912 // Init function. It should be called from the platform initialization code.
913 // For monitor configurations it will initialize the calling interface table,
914 // for client configurations it will patch the existing table as per
919 //**********************************************************************
921 // Note that if your RAM application is configured to initialize
922 // the whole table _or_ the communication channels, you _cannot_
923 // step through this function with the debugger. If your channel
924 // configurations are set to the default, you should be able to
925 // simply step over this function though (or use 'finish' once you
926 // have entered this function if that GDB command works).
928 // If you really do need to debug this code, the best approach is
929 // to have a working RedBoot / GDB stub in ROM and then change the
930 // hal_virtual_vector_table to reside at some other address in the
931 // RAM configuration than that used by the ROM monitor. Then
932 // you'll be able to use the ROM monitor to debug the below code
933 // and check that it does the right thing.
935 // Note that if you have a ROM monitor in ROM/flash which does
936 // support virtual vectors, you should be able to disable the
937 // option CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE. On some
938 // targets (which predate the introduction of virtual vectors)
939 // that option is enabled per default and needs to be explicitly
940 // disabled when you have an updated ROM monitor.
942 //**********************************************************************
944 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE
948 // Initialize tables with the NOP service.
949 // This should only be done for service routine entries - data
950 // pointers should be NULLed.
951 for (i = 0; i < CYGNUM_CALL_IF_TABLE_SIZE; i++)
952 hal_virtual_vector_table[i] = (CYG_ADDRWORD) &nop_service;
955 CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL
956 |((CYG_ADDRWORD)CYGNUM_CALL_IF_TABLE_VERSION_COMM<<CYGNUM_CALL_IF_TABLE_VERSION_COMM_shift));
960 // Miscellaneous services with wrappers in this file.
961 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET
962 CYGACC_CALL_IF_RESET_SET(reset);
964 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
965 CYGACC_CALL_IF_DELAY_US_SET(delay_us);
968 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE
970 CYGACC_CALL_IF_FLUSH_ICACHE_SET(flush_icache);
971 CYGACC_CALL_IF_FLUSH_DCACHE_SET(flush_dcache);
974 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
975 CYGACC_CALL_IF_FLASH_CFG_OP_SET(flash_config_op);
978 #ifdef CYGOPT_REDBOOT_FIS
979 CYGACC_CALL_IF_FLASH_FIS_OP_SET(flash_fis_op);
982 // Data entries not currently supported in eCos
983 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DATA
984 CYGACC_CALL_IF_DBG_DATA_SET(0);
987 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_VERSION
988 CYGACC_CALL_IF_MONITOR_VERSION_SET(0);
992 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS
996 // Clear out tables with safe dummy function.
997 for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1; j++)
998 for (i = 0; i < CYGNUM_COMM_IF_TABLE_SIZE; i++)
999 comm_channels[j][i] = (CYG_ADDRWORD) &nop_service;
1001 // Set accessor functions
1002 CYGACC_CALL_IF_SET_DEBUG_COMM_SET(set_debug_comm);
1003 CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(set_console_comm);
1005 // Initialize console/debug procs. Note that these _must_
1006 // be set to empty before the comms init call.
1007 set_debug_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY);
1008 set_console_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY);
1010 // Initialize channels. This used to be done in
1011 // hal_diag_init() and the stub initHardware() functions, but
1012 // it makes more sense to have here.
1013 cyg_hal_plf_comms_init();
1015 // Always set the debug channel. If stubs are included, it is
1016 // necessary. If no stubs are included it does not hurt and is
1017 // likely to be required by the hal_if_diag_init code anyway
1018 // as it may rely on it if using a mangler.
1019 set_debug_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);
1020 // Set console channel to a safe default. hal_if_diag_init
1021 // will override with console channel or mangler if necessary.
1022 set_console_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);
1025 // Reset console interrupt flag.
1026 CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
1029 // Set up services provided by clients
1030 #if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \
1031 ( defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) \
1032 || defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon))
1034 patch_dbg_syscalls( (void *)(hal_virtual_vector_table) );
1037 // Init client services
1038 #if !defined(CYGPKG_KERNEL) && defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT)
1039 // Only include this code if we do not have a kernel. Otherwise
1040 // the kernel supplies the functionality for the app we are linked
1043 // Prepare for application installation of thread info function in
1045 init_thread_syscall( (void *)&hal_virtual_vector_table[CYGNUM_CALL_IF_DBG_SYSCALL] );
1048 // Finally, install async breakpoint handler if it is configured in.
1049 // FIXME: this should probably check for STUBS instead (but code is
1050 // conditional on BREAK for now)
1051 #if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
1052 // Install async breakpoint handler into vector table.
1053 CYGACC_CALL_IF_INSTALL_BPT_FN_SET(&cyg_hal_gdb_interrupt);
1056 #if 0 != CYGINT_HAL_PLF_IF_INIT
1057 // Call platform specific initializations - should only be used
1058 // to augment what has already been set up, etc.