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);
141 case CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE:
142 *(CYG_ADDRESS *)val = fis->flash_base;
145 case CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE:
146 *(unsigned long *)val = fis->size;
149 case CYGNUM_CALL_IF_FLASH_FIS_GET_MEM_BASE:
150 *(CYG_ADDRESS *)val = fis->mem_base;
153 case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_POINT:
154 *(CYG_ADDRESS *)val = fis->entry_point;
157 case CYGNUM_CALL_IF_FLASH_FIS_GET_DATA_LENGTH:
158 *(unsigned long *)val = fis->data_length;
161 case CYGNUM_CALL_IF_FLASH_FIS_GET_DESC_CKSUM:
162 *(unsigned long *)val = fis->desc_cksum;
165 case CYGNUM_CALL_IF_FLASH_FIS_GET_FILE_CKSUM:
166 *(unsigned long *)val = fis->file_cksum;
171 CYGARC_HAL_RESTORE_GP();
175 #include <cyg/io/flash.h>
177 extern int __flash_init;
178 extern int fisdir_size;
179 extern int flash_block_size;
180 extern void* fis_addr;
181 #ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
182 extern void* redundant_fis_addr;
184 extern void* fis_work_block;
185 extern int do_flash_init(void);
186 extern int fis_start_update_directory(int autolock);
187 extern int fis_update_directory(int autolock, int error);
189 static __call_if_flash_fis_op2_fn_t flash_fis_op2;
192 flash_fis_op2( int op, unsigned int index, struct fis_table_entry *entry)
195 CYGARC_HAL_SAVE_GP();
197 case CYGNUM_CALL_IF_FLASH_FIS_GET_VERSION:
198 res = CYG_REDBOOT_FIS_VERSION;
200 case CYGNUM_CALL_IF_FLASH_FIS_INIT:
201 __flash_init=0; //force reinitialization
202 res = do_flash_init();
204 case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_COUNT:
205 res = fisdir_size / sizeof(struct fis_image_desc);
207 case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY:
209 struct fis_image_desc* img = (struct fis_image_desc *)fis_work_block;
210 CYG_ASSERT(entry != NULL, "fis_table_entry == NULL!");
211 memcpy(entry->name, img[index].u.name, 16);
212 entry->flash_base=img[index].flash_base;
213 entry->mem_base=img[index].mem_base;
214 entry->size=img[index].size;
215 entry->entry_point=img[index].entry_point;
216 entry->data_length=img[index].data_length;
217 entry->desc_cksum=img[index].desc_cksum;
218 entry->file_cksum=img[index].file_cksum;
222 case CYGNUM_CALL_IF_FLASH_FIS_START_UPDATE:
223 fis_start_update_directory(1);
225 case CYGNUM_CALL_IF_FLASH_FIS_FINISH_UPDATE:
226 fis_update_directory(1, index);
228 case CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY:
230 if (entry->name[0]!=0xff) {
231 if ((entry->size == 0)
232 || ((entry->size % flash_block_size) !=0)
233 || (flash_verify_addr((void*)entry->flash_base)!=0)
234 || (flash_verify_addr((void*)(entry->flash_base+entry->size-1))!=0)
235 || (entry->size < entry->data_length))
240 struct fis_image_desc* img = (struct fis_image_desc *)fis_work_block;
241 memcpy(img[index].u.name, entry->name, 16);
242 img[index].flash_base=entry->flash_base;
243 img[index].mem_base=entry->mem_base;
244 img[index].size=entry->size;
245 img[index].entry_point=entry->entry_point;
246 img[index].data_length=entry->data_length;
247 img[index].desc_cksum=entry->desc_cksum;
248 img[index].file_cksum=entry->file_cksum;
252 CYGARC_HAL_RESTORE_GP();
257 //----------------------------
259 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
261 static __call_if_delay_us_t delay_us;
264 delay_us(cyg_int32 usecs)
266 CYGARC_HAL_SAVE_GP();
269 cyg_int32 start, elapsed, elapsed_usec;
271 cyg_int32 usec_per_period = CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000;
272 cyg_int32 ticks_per_usec = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/usec_per_period;
275 // Spin in slices of 1/2 the RTC period. Allows interrupts
276 // time to run without messing up the algorithm. If we
277 // spun for 1 period (or more) of the RTC, there would also
278 // be problems figuring out when the timer wrapped. We
279 // may lose a tick or two for each cycle but it shouldn't
282 // The tests against CYGNUM_KERNEL_COUNTERS_RTC_PERIOD
283 // check for a value that would cause a 32 bit signed
284 // multiply to overflow. But this also implies that just
285 // multiplying by ticks_per_usec will yield a good
286 // approximation. Otherwise we need to do the full
287 // multiply+divide to get sufficient accuracy. Note that
288 // this test is actually constant, so the compiler will
289 // eliminate it and only compile the branch that is
292 if( usecs > usec_per_period/2 )
293 slice = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2;
294 else if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2 >= 0x7FFFFFFF/usec_per_period )
295 slice = usecs * ticks_per_usec;
298 slice = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
299 slice /= usec_per_period;
302 HAL_CLOCK_READ(&start);
304 HAL_CLOCK_READ(&elapsed);
305 elapsed = (elapsed - start); // counts up!
307 elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
308 } while (elapsed < slice);
310 // Adjust by elapsed, not slice, since an interrupt may
311 // have been stalling us for some time.
313 if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period )
314 elapsed_usec = elapsed / ticks_per_usec;
317 elapsed_usec = elapsed * usec_per_period;
318 elapsed_usec = elapsed_usec / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
321 // It is possible for elapsed_usec to end up zero in some
322 // circumstances and we could end up looping indefinitely.
323 // Avoid that by ensuring that we always decrement usec by
324 // at least 1 each time.
326 usecs -= elapsed_usec ? elapsed_usec : 1;
330 #else // CYGPKG_KERNEL
332 // Use a HAL feature if defined
335 // If no accurate delay mechanism, just spin for a while. Having
336 // an inaccurate delay is much better than no delay at all. The
337 // count of 10 should mean the loop takes something resembling
338 // 1us on most CPUs running between 30-100MHz [depends on how many
339 // instructions this compiles to, how many dispatch units can be
340 // used for the simple loop, actual CPU frequency, etc]
341 while (usecs-- > 0) {
343 for (i = 0; i < 10; i++);
345 #endif // HAL_DELAY_US
346 #endif // CYGPKG_KERNEL
347 CYGARC_HAL_RESTORE_GP();
349 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
352 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET
354 static __call_if_reset_t reset;
359 CYGARC_HAL_SAVE_GP();
360 // With luck, the platform defines some magic that will cause a hardware
362 #ifdef HAL_PLATFORM_RESET
363 HAL_PLATFORM_RESET();
366 #ifdef HAL_PLATFORM_RESET_ENTRY
367 // If that's not the case (above is an empty statement) there may
368 // be defined an address we can jump to - and effectively
369 // reinitialize the system. Not quite as good as a reset, but it
371 goto *HAL_PLATFORM_RESET_ENTRY;
374 #error " no RESET_ENTRY"
376 CYG_FAIL("Reset failed");
377 CYGARC_HAL_RESTORE_GP();
382 //------------------------------------
384 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE) || \
385 defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS)
389 // This is the default service. It always returns false (0), and
390 // _does not_ trigger any assertions. Clients must either cope
391 // with the service failure or assert.
396 //----------------------------------
398 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS
400 #ifdef CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS
401 #define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \
402 (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS)
404 #define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \
405 CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
408 static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1];
411 set_debug_comm(int __comm_id)
413 static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY;
414 hal_virtual_comm_table_t* __chan;
415 int interrupt_state = 0;
416 int res = 1, update = 0;
417 CYGARC_HAL_SAVE_GP();
419 CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER
420 && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,
424 case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT:
425 if (__selected_id > 0)
426 res = __selected_id-1;
427 else if (__selected_id == 0)
428 res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER;
433 case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY:
434 CYGACC_CALL_IF_DEBUG_PROCS_SET(0);
435 __selected_id = __comm_id;
438 case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER:
444 __comm_id++; // skip mangler entry
450 // Find the interrupt state of the channel.
451 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
453 interrupt_state = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
455 __selected_id = __comm_id;
456 CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]);
458 // Set interrupt state on the new channel.
459 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
461 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);
463 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE);
466 CYGARC_HAL_RESTORE_GP();
471 set_console_comm(int __comm_id)
473 static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY;
474 int res = 1, update = 0;
475 CYGARC_HAL_SAVE_GP();
477 CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER
478 && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS,
482 case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT:
483 if (__selected_id > 0)
484 res = __selected_id-1;
485 else if (__selected_id == 0)
486 res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER;
491 case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY:
492 CYGACC_CALL_IF_CONSOLE_PROCS_SET(0);
493 __selected_id = __comm_id;
496 case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER:
502 __comm_id++; // skip mangler entry
508 __selected_id = __comm_id;
510 CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]);
513 CYGARC_HAL_RESTORE_GP();
518 //----------------------------------
520 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE
523 flush_icache(void *__p, int __nbytes)
525 CYGARC_HAL_SAVE_GP();
526 #ifdef HAL_ICACHE_FLUSH
527 HAL_ICACHE_FLUSH( __p , __nbytes );
528 #elif defined(HAL_ICACHE_INVALIDATE)
529 HAL_ICACHE_INVALIDATE();
531 CYGARC_HAL_RESTORE_GP();
535 flush_dcache(void *__p, int __nbytes)
537 CYGARC_HAL_SAVE_GP();
538 #ifdef HAL_DCACHE_FLUSH
539 HAL_DCACHE_FLUSH( __p , __nbytes );
540 #elif defined(HAL_DCACHE_INVALIDATE)
541 HAL_DCACHE_INVALIDATE();
543 CYGARC_HAL_RESTORE_GP();
547 #if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG)
548 //-----------------------------------------------------------------------------
549 // GDB console output mangler (O-packetizer)
550 // COMMS init function at end.
552 // This gets called via the virtual vector console comms entry and
553 // handles O-packetization. The debug comms entries are used for the
556 cyg_hal_diag_mangler_gdb_getc(void* __ch_data)
559 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
560 CYGARC_HAL_SAVE_GP();
562 __ch = CYGACC_COMM_IF_GETC(*__chan);
564 CYGARC_HAL_RESTORE_GP();
569 static char __mangler_line[100];
570 static int __mangler_pos = 0;
573 cyg_hal_diag_mangler_gdb_flush(void* __ch_data)
575 CYG_INTERRUPT_STATE old;
576 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
577 #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
578 int tries = CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES;
582 // Nothing to do if mangler buffer is empty.
583 if (__mangler_pos == 0)
586 // Disable interrupts. This prevents GDB trying to interrupt us
587 // while we are in the middle of sending a packet. The serial
588 // receive interrupt will be seen when we re-enable interrupts
590 #if defined(CYG_HAL_STARTUP_ROM) \
591 || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION)
592 HAL_DISABLE_INTERRUPTS(old);
594 CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
597 #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
598 // Only wait 500ms for data to arrive - avoid "stuck" connections
599 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, CYGNUM_HAL_DEBUG_GDB_PROTOCOL_TIMEOUT);
604 static const char hex[] = "0123456789ABCDEF";
609 CYGACC_COMM_IF_PUTC(*__chan, '$');
610 CYGACC_COMM_IF_PUTC(*__chan, 'O');
612 for( i = 0; i < __mangler_pos; i++ )
614 char ch = __mangler_line[i];
615 char h = hex[(ch>>4)&0xF];
616 char l = hex[ch&0xF];
617 CYGACC_COMM_IF_PUTC(*__chan, h);
618 CYGACC_COMM_IF_PUTC(*__chan, l);
622 CYGACC_COMM_IF_PUTC(*__chan, '#');
623 CYGACC_COMM_IF_PUTC(*__chan, hex[(csum>>4)&0xF]);
624 CYGACC_COMM_IF_PUTC(*__chan, hex[csum&0xF]);
627 #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
628 if (CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, &c1) == 0) {
630 if (tries && (--tries == 0)) c1 = '+';
633 c1 = CYGACC_COMM_IF_GETC(*__chan);
636 if( c1 == '+' ) break;
638 if( cyg_hal_is_break( &c1 , 1 ) ) {
639 // Caller's responsibility to react on this.
640 CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(1);
643 if( c1 != '-' ) goto nak;
647 // And re-enable interrupts
648 #if defined(CYG_HAL_STARTUP_ROM) \
649 || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION)
650 HAL_RESTORE_INTERRUPTS(old);
652 CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
657 cyg_hal_diag_mangler_gdb_putc(void* __ch_data, cyg_uint8 c)
659 // No need to send CRs
660 if( c == '\r' ) return;
662 CYGARC_HAL_SAVE_GP();
664 __mangler_line[__mangler_pos++] = c;
666 if( c == '\n' || __mangler_pos == sizeof(__mangler_line) )
667 cyg_hal_diag_mangler_gdb_flush(__ch_data);
669 CYGARC_HAL_RESTORE_GP();
673 cyg_hal_diag_mangler_gdb_write(void* __ch_data,
674 const cyg_uint8* __buf, cyg_uint32 __len)
676 CYGARC_HAL_SAVE_GP();
679 cyg_hal_diag_mangler_gdb_putc(__ch_data, *__buf++);
681 CYGARC_HAL_RESTORE_GP();
685 cyg_hal_diag_mangler_gdb_read(void* __ch_data,
686 cyg_uint8* __buf, cyg_uint32 __len)
688 CYGARC_HAL_SAVE_GP();
691 *__buf++ = cyg_hal_diag_mangler_gdb_getc(__ch_data);
693 CYGARC_HAL_RESTORE_GP();
697 cyg_hal_diag_mangler_gdb_control(void *__ch_data,
698 __comm_control_cmd_t __func, ...)
700 CYGARC_HAL_SAVE_GP();
702 if (__func == __COMMCTL_FLUSH_OUTPUT)
703 cyg_hal_diag_mangler_gdb_flush(__ch_data);
705 CYGARC_HAL_RESTORE_GP();
709 // This is the COMMS init function. It gets called both by the stubs
710 // and diag init code to initialize the COMMS mangler channel table -
711 // that's all. The callers have to decide whether to actually use this
714 cyg_hal_diag_mangler_gdb_init(void)
716 hal_virtual_comm_table_t* comm;
717 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
719 // Initialize mangler procs
720 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER);
721 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
722 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_gdb_write);
723 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_gdb_read);
724 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_gdb_putc);
725 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_gdb_getc);
726 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_gdb_control);
728 // Restore the original console channel.
729 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
732 //-----------------------------------------------------------------------------
733 // Null console output mangler
734 // COMMS init function at end.
736 // This gets called via the virtual vector console comms entry and
737 // just forwards IO to the debug comms entries.
738 // This differs from setting the console channel to the same as the
739 // debug channel in that console output will go to the debug channel
740 // even if the debug channel is changed.
742 cyg_hal_diag_mangler_null_getc(void* __ch_data)
745 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
746 CYGARC_HAL_SAVE_GP();
748 __ch = CYGACC_COMM_IF_GETC(*__chan);
750 CYGARC_HAL_RESTORE_GP();
757 cyg_hal_diag_mangler_null_putc(void* __ch_data, cyg_uint8 c)
759 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
761 CYGARC_HAL_SAVE_GP();
763 CYGACC_COMM_IF_PUTC(*__chan, c);
765 CYGARC_HAL_RESTORE_GP();
769 cyg_hal_diag_mangler_null_write(void* __ch_data,
770 const cyg_uint8* __buf, cyg_uint32 __len)
772 CYGARC_HAL_SAVE_GP();
775 cyg_hal_diag_mangler_null_putc(__ch_data, *__buf++);
777 CYGARC_HAL_RESTORE_GP();
781 cyg_hal_diag_mangler_null_read(void* __ch_data,
782 cyg_uint8* __buf, cyg_uint32 __len)
784 CYGARC_HAL_SAVE_GP();
787 *__buf++ = cyg_hal_diag_mangler_null_getc(__ch_data);
789 CYGARC_HAL_RESTORE_GP();
793 cyg_hal_diag_mangler_null_control(void *__ch_data,
794 __comm_control_cmd_t __func, ...)
800 // This is the COMMS init function. It gets called both by the stubs
801 // and diag init code to initialize the COMMS mangler channel table -
802 // that's all. The callers have to decide whether to actually use this
805 cyg_hal_diag_mangler_null_init(void)
807 hal_virtual_comm_table_t* comm;
808 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
810 // Initialize mangler procs
811 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER);
812 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
813 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_null_write);
814 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_null_read);
815 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_null_putc);
816 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_null_getc);
817 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_null_control);
819 // Restore the original console channel.
820 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
823 //-----------------------------------------------------------------------------
824 // Console IO functions that adhere to the virtual vector table semantics in
825 // order to ensure proper debug agent mangling when required.
827 externC void cyg_hal_plf_comms_init(void);
830 hal_if_diag_init(void)
832 // This function may be called from various places and the code
833 // should only run once.
834 static cyg_uint8 called = 0;
838 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE
840 #if defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN)
841 // Use the mangler channel, which in turn uses the debug channel.
842 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER);
844 // Initialize the mangler channel.
845 #if defined(CYGSEM_HAL_DIAG_MANGLER_GDB)
846 cyg_hal_diag_mangler_gdb_init();
847 #elif defined(CYGSEM_HAL_DIAG_MANGLER_None)
848 cyg_hal_diag_mangler_null_init();
851 #else // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN
853 // Use an actual (raw) IO channel
854 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL);
856 #endif // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN
858 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE
862 hal_if_diag_write_char(char c)
864 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
867 CYGACC_COMM_IF_PUTC(*__chan, c);
869 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
871 // FIXME: What should be done if assertions are not enabled?
872 // This is a bad bad situation - we have no means for diag
873 // output; we want to hit a breakpoint to alert the developer
874 // or something like that.
875 CYG_ASSERT(__chan, "No valid channel set");
877 CYGACC_COMM_IF_PUTC(*__chan, c);
880 // Check interrupt flag
881 if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) {
882 CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
883 cyg_hal_user_break(0);
888 hal_if_diag_read_char(char *c)
890 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS();
893 *c = CYGACC_COMM_IF_GETC(*__chan);
895 __chan = CYGACC_CALL_IF_DEBUG_PROCS();
897 // FIXME: What should be done if assertions are not enabled?
898 // This is a bad bad situation - we have no means for diag
899 // output; we want to hit a breakpoint to alert the developer
900 // or something like that.
901 CYG_ASSERT(__chan, "No valid channel set");
903 *c = CYGACC_COMM_IF_GETC(*__chan);
906 #endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
908 //=============================================================================
910 //=============================================================================
912 #if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \
913 || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
915 struct Hal_SavedRegisters *hal_saved_interrupt_state;
918 hal_ctrlc_isr_init(void)
920 // A ROM monitor never enables the interrupt itself. This is left
921 // to the (RAM) application.
922 #ifndef CYGSEM_HAL_ROM_MONITOR
923 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
925 #if 1 // Prevents crash on older stubs
927 // Allow only ctrl-c interrupt enabling when version in table is
928 // below legal max and above the necessary service, and _not_
929 // the value we set it to below.
930 v_m = CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK;
931 if (v_m >= CYGNUM_CALL_IF_TABLE_VERSION_CALL_MAX
932 || v_m < CYGNUM_CALL_IF_SET_DEBUG_COMM
933 || v_m == CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK)
936 // Now trash that value - otherwise downloading an image with
937 // builtin stubs on a board with older stubs (which will cause the
938 // version to be set to VERSION_CALL) may cause all subsequent
939 // runs to (wrongly) fall through to the below code. If there is
940 // a new stub on the board, it will reinitialize the version field
941 // on reset. Yes, this is a gross hack!
942 CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK);
945 // We can only enable interrupts on a valid debug channel.
947 CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE);
952 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)
954 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
955 int isr_ret = 0, ctrlc = 0;
958 isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data);
960 cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state );
966 hal_ctrlc_check(CYG_ADDRWORD vector, CYG_ADDRWORD data)
968 hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS();
969 int gdb_vector = vector-1;
970 int isr_ret, ctrlc = 0;
972 // This check only to avoid crash on older stubs in case of unhandled
973 // interrupts. It is a bit messy, but required in a transition period.
975 (CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK ==
976 (CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK))){
977 gdb_vector = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DBG_ISR_VECTOR);
979 if (vector == gdb_vector) {
980 isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data);
982 cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state );
988 #endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT || CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
990 //--------------------------------------------------------------------------
991 // Init function. It should be called from the platform initialization code.
992 // For monitor configurations it will initialize the calling interface table,
993 // for client configurations it will patch the existing table as per
998 //**********************************************************************
1000 // Note that if your RAM application is configured to initialize
1001 // the whole table _or_ the communication channels, you _cannot_
1002 // step through this function with the debugger. If your channel
1003 // configurations are set to the default, you should be able to
1004 // simply step over this function though (or use 'finish' once you
1005 // have entered this function if that GDB command works).
1007 // If you really do need to debug this code, the best approach is
1008 // to have a working RedBoot / GDB stub in ROM and then change the
1009 // hal_virtual_vector_table to reside at some other address in the
1010 // RAM configuration than that used by the ROM monitor. Then
1011 // you'll be able to use the ROM monitor to debug the below code
1012 // and check that it does the right thing.
1014 // Note that if you have a ROM monitor in ROM/flash which does
1015 // support virtual vectors, you should be able to disable the
1016 // option CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE. On some
1017 // targets (which predate the introduction of virtual vectors)
1018 // that option is enabled per default and needs to be explicitly
1019 // disabled when you have an updated ROM monitor.
1021 //**********************************************************************
1023 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE
1027 // Initialize tables with the NOP service.
1028 // This should only be done for service routine entries - data
1029 // pointers should be NULLed.
1030 for (i = 0; i < CYGNUM_CALL_IF_TABLE_SIZE; i++)
1031 hal_virtual_vector_table[i] = (CYG_ADDRWORD) &nop_service;
1034 CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL
1035 |((CYG_ADDRWORD)CYGNUM_CALL_IF_TABLE_VERSION_COMM<<CYGNUM_CALL_IF_TABLE_VERSION_COMM_shift));
1039 // Miscellaneous services with wrappers in this file.
1040 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET
1041 CYGACC_CALL_IF_RESET_SET(reset);
1043 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
1044 CYGACC_CALL_IF_DELAY_US_SET(delay_us);
1047 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE
1049 CYGACC_CALL_IF_FLUSH_ICACHE_SET(flush_icache);
1050 CYGACC_CALL_IF_FLUSH_DCACHE_SET(flush_dcache);
1053 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
1054 CYGACC_CALL_IF_FLASH_CFG_OP_SET(flash_config_op);
1057 #ifdef CYGOPT_REDBOOT_FIS
1058 CYGACC_CALL_IF_FLASH_FIS_OP_SET(flash_fis_op);
1059 CYGACC_CALL_IF_FLASH_FIS_OP2_SET(flash_fis_op2);
1062 // Data entries not currently supported in eCos
1063 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DATA
1064 CYGACC_CALL_IF_DBG_DATA_SET(0);
1067 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_VERSION
1068 CYGACC_CALL_IF_MONITOR_VERSION_SET(0);
1072 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS
1076 // Clear out tables with safe dummy function.
1077 for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1; j++)
1078 for (i = 0; i < CYGNUM_COMM_IF_TABLE_SIZE; i++)
1079 comm_channels[j][i] = (CYG_ADDRWORD) &nop_service;
1081 // Set accessor functions
1082 CYGACC_CALL_IF_SET_DEBUG_COMM_SET(set_debug_comm);
1083 CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(set_console_comm);
1085 // Initialize console/debug procs. Note that these _must_
1086 // be set to empty before the comms init call.
1087 set_debug_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY);
1088 set_console_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY);
1090 // Initialize channels. This used to be done in
1091 // hal_diag_init() and the stub initHardware() functions, but
1092 // it makes more sense to have here.
1093 cyg_hal_plf_comms_init();
1095 // Always set the debug channel. If stubs are included, it is
1096 // necessary. If no stubs are included it does not hurt and is
1097 // likely to be required by the hal_if_diag_init code anyway
1098 // as it may rely on it if using a mangler.
1099 set_debug_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);
1100 // Set console channel to a safe default. hal_if_diag_init
1101 // will override with console channel or mangler if necessary.
1102 set_console_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL);
1105 // Reset console interrupt flag.
1106 CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
1109 // Set up services provided by clients
1110 #if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \
1111 ( defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) \
1112 || defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon))
1114 patch_dbg_syscalls( (void *)(hal_virtual_vector_table) );
1117 // Init client services
1118 #if !defined(CYGPKG_KERNEL) && defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT)
1119 // Only include this code if we do not have a kernel. Otherwise
1120 // the kernel supplies the functionality for the app we are linked
1123 // Prepare for application installation of thread info function in
1125 init_thread_syscall( (void *)&hal_virtual_vector_table[CYGNUM_CALL_IF_DBG_SYSCALL] );
1128 // Finally, install async breakpoint handler if it is configured in.
1129 // FIXME: this should probably check for STUBS instead (but code is
1130 // conditional on BREAK for now)
1131 #if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
1132 // Install async breakpoint handler into vector table.
1133 CYGACC_CALL_IF_INSTALL_BPT_FN_SET(&cyg_hal_gdb_interrupt);
1136 #if 0 != CYGINT_HAL_PLF_IF_INIT
1137 // Call platform specific initializations - should only be used
1138 // to augment what has already been set up, etc.