diff options
author | Michael Gielda <mgielda@antmicro.com> | 2014-04-03 14:53:04 +0200 |
---|---|---|
committer | Michael Gielda <mgielda@antmicro.com> | 2014-04-03 14:53:04 +0200 |
commit | ae1e4e08a1005a0c487f03ba189d7536e7fdcba6 (patch) | |
tree | f1c296f8a966a9a39876b0e98e16d9c5da1776dd /ecos/packages/hal/common | |
parent | f157da5337118d3c5cd464266796de4262ac9dbd (diff) |
Added the OS files
Diffstat (limited to 'ecos/packages/hal/common')
38 files changed, 23023 insertions, 0 deletions
diff --git a/ecos/packages/hal/common/current/ChangeLog b/ecos/packages/hal/common/current/ChangeLog new file mode 100644 index 0000000..03a7c83 --- /dev/null +++ b/ecos/packages/hal/common/current/ChangeLog @@ -0,0 +1,2403 @@ +2013-06-13 Ilija Kocho <ilijak@siva.com.mk> + + * tests/cache.c : Fix compiler warning about variable set but not used. + [ Bugzilla 1001865 ] + +2012-04-25 Ilija Kocho <ilijak@siva.com.mk> + + * include/hal_stub.h, src/hal_stub.c, src/thread-packets.c: + NUMREGS replaced by HAL_STUB_REGISTERS_SIZE in thread-packets.c + [Bugzilla 1001558] + +2012-03-14 Grant Edwards <grant.b.edwards@gmail.com> + + * src/generic-stub.c (process_query): Fix compiler warning about + variable that is set but not used (only used in conditionally + compiled code). [ Bugzilla 1001535 ] + +2012-03-09 Sergei Gavrikov <sergei.gavrikov@gmail.com> + + * src/hal_if.c (hal_ctrlc_check): Fix compiler warning about + variable that is set but not used (isr_ret has been removed). + +2011-01-13 John Dallaway <john@dallaway.org.uk> + + * cdl/hal.cdl: Add a CDL interface to control whether interrupt + state must be saved. [ Bugzilla 1001111 ] + * cdl/debugging.cdl: Implement the new interface within GDB Ctrl-C + break options. + * src/hal_if.c: Make declaration of the hal_saved_interrupt_state + variable conditional on an implementation of the new CDL interface. + +2010-11-20 John Dallaway <john@dallaway.org.uk> + + * cdl/hal.cdl: Suppress -fprofile-arcs (which implies -lgcov) when + generating extras.o. + +2010-10-09 John Dallaway <john@dallaway.org.uk> + + * doc/porting.sgml: Delete references to the memory layout editor. + +2009-02-02 Bart Veer <bartv@ecoscentric.com> + + * cdl/hal.cdl: add CYGBLD_GLOBAL_WARNFLAGS, as part of global + compiler flags update. + +2008-11-21 Bart Veer <bartv@ecoscentric.com> + + * include/hal_if.h (CYGNUM_CALL_IF_available_x): fix typo in + previous patch. + +2008-11-20 Bart Veer <bartv@ecoscentric.com> + + * cdl/hal.cdl, include/hal_if.h, src/hal_if.c: expunge + CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE and the corresponding code. + +2008-05-20 Jonathan Larmour <jifl@eCosCentric.com> + + * src/thread-packets.c (threadmatch): Silence pointer signedness + warning. + (threadref_to_int): Ditto. + * src/generic-stub.c (__mem2hex): Ditto. + (__mem2hex_safe): Ditto. + (__hex2mem): Ditto. + (__hex2mem_safe): Ditto. + * src/hal_if.c (delay_us): Ditto. + * include/hal_stub.h (CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION): + Instead of using a local variable to avoid compiler reordering + when taking the address of a label, instead call an external function. + (NB making the variable volatile isn't sufficient). + +2008-05-13 Chris Zimman <czimman@bloomberg.com> + + * cdl/hal.cdl: Work around problem with current ARM EABI tools by + using /dev/null as linker script. Should be safe with other tools. + +2007-11-27 Bart Veer <bartv@ecoscentric.com> + + * src/hal_if.c (delay_us): use HAL_DELAY_US() rather than the + fancy implementation if the port cannot provide HAL_CLOCK_READ() + +2007-09-27 Grant Edwards <grante@visi.com> + + * include/hal_endian.h (SWAP16): Fix "return value" so + that it only returns data in lower 16 bits instead of 24. + +2006-05-09 Andrew Lunn <andrew.lunn@ascom.ch> + + * src/hal_if.c (cyg_hal_diag_mangler_gdb_flush): Fix compiler + warning about signed/unsigned. + +2006-04-19 Alexander Neundorf <alexander.neundorf@jenoptik.com + + * include/hal_if.h, src/hal_if.c: add a VV call for modifying + the FIS table from eCos applications + +2005-06-27 Andrew Lunn <andrew.lunn@ascom.ch> + + * include/hal_tables.h (CYG_HAL_TABLE_{QUALIFIED_}ENTRY): added + CYGBLD_ATTRIB_USED so that gcc 3.4.4 does not discard entries + which are not refereced explicitly. Problem reported by + Oliver Munz. + +2005-06-26 Bart Veer <bartv@ecoscentric.com> + + * doc/hal.sgml: make HAL_DELAY_US() mandatory and define it to be + thread-safe. + +2005-05-19 Peter Korsgaard <jacmet@sunsite.dk> + + * doc/porting.sgml: Changed dead sourceware.cygnus.com links to + ecos.sourceware.org. + +2005-04-27 Enrico Piria <epiria@libero.it> + + * src/hal_if.c Added missing declarations of tries when compiling + with CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0. + +2005-02-17 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/common.cdl: Add CYGBLD_HAL_LINKER_GROUPED_LIBS to allow + CDL setting of libraries used for GROUP() directive in linker + script. + +2004-11-20 Andrew Lunn <andrew.lunn@ascom.ch> + + * tests/intr.c: Make the ISR call the DSR to make sure this works + correctly. + +2004-08-22 Gary Thomas <gary@mlbassoc.com> + + * doc/porting.sgml: Replace [very misleading dated] comments + about CygMon and platforms which use/need GDB stubs. + +2004-08-12 Jani Monoses <jani@iv.ro> + + * include/hal_if.h: Make monitor locking work with CYGPKG_LWIP. + +2004-05-19 John Newlin <jnewlin@stretchinc.com> + + * src/hal_stub.c: + (cyg_hal_gdb_interrupt) + (cyg_hal_gdb_remove_break): Changed both to use + _read_mem_safe/__write_mem_safe for inserting a breakpoint, and + restoring the original instruction. + The Xtensa architecture (and others maybe?) can have unaligned + instructions, which caused unaligned load/store exception. + +2004-04-22 Jani Monoses <jani@iv.ro> + + * cdl/hal.cdl : + Invoke tail with stricter syntax that works in latest coreutils. + +2004-02-23 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/debugging.cdl (CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS): Included + stubs should always mean saving full context both on interrupts + and context swaps, so make it explicit. + +2004-01-05 Gary Thomas <gary@mlbassoc.com> + + * include/hal_if.h: Minor fixup - new 'fconfig' functions broke + existing uses of CYGACC_CALL_IF_FLASH_CFG_OP. Added a new macro + CYGACC_CALL_IF_FLASH_CFG_OP2 which handles new API and a wrapper + to handle the old way (backwards compatability). + +2003-12-21 Gary Thomas <gary@mlbassoc.com> + + * src/hal_if.c (flash_config_op): + * include/hal_if.h: New expanded functions for RedBoot 'fconfig' + database. + +2003-09-04 Patrick Doyle <wpd@dtccom.com> + + * include/hal_if.h: + * src/hal_if.c (flash_fis_op): Added support for the rest of the + FIS operations. + +2003-08-06 Bob Koninckx <bob.koninckx@mech.kuleuven.ac.be> + + * src/drv_api.c: Added definition of cyg_interrupt_post_dsr() for + use in those HALs that need it. + + * include/hal_arbiter.h (hal_call_isr): Removed ifdef on + CYGFUN_HAL_COMMON_KERNEL_SUPPORT around test and call to + cyg_interrupt_post_dsr(). + +2003-07-21 Nick Garnett <nickg@balti.calivar.com> + + * doc/hal.sgml: Reorganized description of clock and timer related + stuff into their own section and added a piece about how to change + the clock frequency. + +2003-06-25 Nick Garnett <nickg@balti.calivar.com> + + * src/hal_if.c (delay_us): The first test against + CYGNUM_KERNEL_COUNTERS_RTC_PERIOD is now against the period + divided by two. By the time we get to this test we know that usecs + can never be > usec_per_period/2 so we can double the range of + period values that we can handle without overflow and use the more + efficient approximation. The second test is not changed since we + cannot make the same assumptions about the elapsed count. + +2003-06-24 Jonathan Larmour <jifl@eCosCentric.com> + + * src/generic-stub.c (crc32): Fix crctable option name typo. + + * src/hal_if.c (hal_if_init): Remove kill_by_reset. + (kill_by_reset): Remove, unused. + (reset): ifdef test on HAL_PLATFORM_RESET and assert on reset failure. + + * cdl/interrupts.cdl (CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE): No + reason to forbid people setting this quite small. + +2003-06-19 Nick Garnett <nickg@balti.calivar.com> + + * src/hal_if.c (delay_us): Reorganized to cope with high frequency + timers by eliminating a source of arithmetic overflow. + +2003-05-06 Mark Salter <msalter@redhat.com> + + * src/hal_stub.c (handle_exception_exit): Call sys_profile_reset from + here. Setup to return through return_from_stub() when appropriate. + (return_from_stub): New function to call CYGACC_CALL_IF_MONITOR_RETURN + from thread context. + + * src/generic-stub.c (__handle_exception): Call exit_vec if + hal_syscall_handler returns negative number. + +2003-04-08 Mark Salter <msalter@redhat.com> + + * src/hal_misc.c (hal_default_isr): Allow HAL to override default + GDB vector matching test. + +2003-04-08 Yoshinori Sato <qzb04471@nifty.ne.jp> +2003-04-08 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/debugging.cdl: Allow CRC to be allocated in ROM as well as RAM. + * src/generic-stub.c: as above. + +2003-04-02 Gary Thomas <gary@mlbassoc.com> + + * src/generic-stub.c: + * include/generic-stub.h: Cleanup when program args are not + supported (remove some unused static storage). + +2003-03-03 Knud Woehler <knud.woehler@microplex.de> + + * src/hal_if.c: + * include/hal_if.h: Add CYGNUM_CALL_IF_FLASH_FIS_OP. FIS read + via the virtual vector table. + +2003-02-24 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/hal.cdl: Fix doc links. + + * doc/hal.sgml: hal-common-current-doc-porting-sgml entity -> + hal-common-porting-sgml in line with other docs. + +2003-02-13 Mark Salter <msalter@redhat.com> + + * src/gdb-fileio.h (FILEIO_O_BINARY): New flag. + (FILEIO_O_TEXT): New flag. + +2003-01-31 Mark Salter <msalter@redhat.com> + + * include/hal_if.h: Add CYGNUM_CALL_IF_MONITOR_RETURN. + +2002-12-04 Gary Thomas <gthomas@ecoscentric.com> + + * cdl/hal.cdl: RAM applications should not claim (reset) version + string by default. + +2002-12-03 Gary Thomas <gthomas@ecoscentric.com> + + * src/hal_if.c (hal_if_init): + * include/hal_if.h: + * cdl/hal.cdl: Allow monitor (RedBoot) version string to be exported + via the virtual vector table. + +2002-11-13 Gary Thomas <gthomas@ecoscentric.com> + + * cdl/hal.cdl: Add CDL control over DATA cache startup mode. + +2002-09-11 Mark Salter <msalter@redhat.com> + + * include/hal_if.h: Add __COMMCTL_ENABLE_LINE_FLUSH and + __COMMCTL_DISABLE_LINE_FLUSH. + +2002-08-29 Mark Salter <msalter@redhat.com> + + * include/generic-stub.h: Add defines for Z packet types. + * src/bplist-dynamic.c: Add support for deferred hardware breakpoint + and watchpoint insertion/deletion. This gets around gdb problem where + gdb tries accessing watched memory before removing watchpoint. + * src/generic-stub.c (__process_packet): Ditto. + * include/hal_stub.h: Ditto. + +2002-05-23 Jesper Skov <jskov@redhat.com> + + * cdl/hal.cdl: Don't build tests that are not applicable with the + current configuration. + Added CYGINT_HAL_TESTS_NO_CACHES which allows cache tests to be + suppressed. + +2002-05-13 Jesper Skov <jskov@redhat.com> + + * cdl/hal.cdl: Removed + CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT_NOT_GUARANTEED option and its + dependencies. + +2002-05-02 Nick Garnett <nickg@redhat.com> + + * doc/hal.sgml: Added description of HAL_DELAY_US(). + + * doc/porting.sgml: Expanded section on architecture porting. + +2002-04-30 Jonathan Larmour <jlarmour@redhat.com> + + * src/gdb-fileio.c (cyg_hal_gdbfileio_process_F_packet): Reset + retcode/errno/ctrlc status every F packet. + +2002-04-23 Jesper Skov <jskov@redhat.com> + + * doc/porting.sgml: Fix some typos. + +2002-04-22 Jonathan Larmour <jlarmour@redhat.com> + + * include/generic-stub.h: Prototype __getpacket(). + * src/generic-stub.c: Rename getpacket() -> __getpacket(), + remcomInBuffer -> __remcomInBuffer, and + remcomOutBuffer -> __remcomOutBuffer throughout file, and export + them (i.e. not file local). + (__process_packet): Handle $F packets file I/O protocol responses. + + * src/gdb-fileio.c: New file to implement file I/O operations over + the GDB remote protocol. + * src/gdb-fileio.h: New file. Header for above. + +2002-03-15 Nick Garnett <nickg@redhat.com> + + * doc/porting.sgml: Platform HAL porting guide tidied up and + expanded somewhat. Some work also done on variant + guide. Architecture guided needs a lot more work. + + * doc/hal.sgml: Changed explicit section tags to recursive section + tags to make any future restructuring easier. + +2002-03-14 Nick Garnett <nickg@redhat.com> + + * src/hal_stub.c: Add calls to HAL memory access check macros in + memory access functions. + + * include/hal_stub.h: Added default definitions for HAL memory access + check macros. + +2002-03-06 Nick Garnett <nickg@redhat.com> + + * tests/cache.c: Changed tests so that zero sized caches and HALs + that define HAL_DCACHE_PURGE_ALL() don't cause this test to throw + a compilation error. + +2002-02-28 Jesper Skov <jskov@redhat.com> + + * src/generic-stub.c (__handle_exception): Pay attention to return + value from hal_syscall_handler. + +2002-02-21 Mark Salter <msalter@redhat.com> + + * src/hal_if.c (cyg_hal_diag_mangler_gdb_flush): Don't do anything + if buffer is empty. + +2002-02-20 Nick Garnett <nickg@redhat.com> + + * doc/hal.sgml: Updated and tidied. Now includes porting guide + from a separate file. + + * doc/porting.sgml: Added this file to contain the porting guide + section of the HAL document. This is currently largely a + conversion of Jesper's porting guide from the website. + Unfortunately I have had no time to do much more than include it + wholesale, with only minor edits. There are some notes at the end + of the file describing what I would like to do. + +2002-02-18 Nick Garnett <nickg@redhat.com> + + * doc/hal.sgml: Restructured most of this document and rewrote + large chunks of the basic HAL description stuff. Only the skeleton + of the porting guided is currently done. This checkin in mostly + for safety and to let others read the current state. + +2002-02-06 Mark Salter <msalter@redhat.com> + + * src/hal_if.c (cyg_hal_diag_mangler_gdb_control): Add flush support. + (cyg_hal_diag_mangler_gdb_flush): New function to flush mangler output. + (cyg_hal_diag_mangler_gdb_putc): Use new function to flush output. + +2002-01-30 Hugo Tyson <hmt@redhat.com> + + * include/hal_if.h (CYGNUM_FLASH_CFG_OP_CONFIG_INT): New defines for + getting Flash Config options out of RedBoot using VV call + CYGACC_CALL_IF_FLASH_CFG_OP(). These need to be kept uptodate + with (or must override) those in RedBoot's flash_config.h + Previously only used for getting an ESA. + +2002-01-25 Hugo Tyson <hmt@redhat.com> + + * src/generic-stub.c (__process_packet): If detach or kill, call + sys_profile_reset() if BSP_SYSCALLS_GPROF are enabled, to clear + out any dangerous state there. Such as a callback function + pointer into application code. + +2002-01-23 Jonathan Larmour <jlarmour@redhat.com> + + * include/drv_api.h: Add cyg_drv_interrupt_mask/unmask_intunsafe + * src/drv_api.c: Ditto. And modify + cyg_drv_interrupt_mask/unmask to be interrupt safe. + +2002-01-21 Mark Salter <msalter@redhat.com> + + * include/hal_spd.h: New file. Definitions for SDRAM module SPD. + +2002-01-18 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c (__build_t_packet): don't declare extend_val + twice. + +2001-12-12 Jesper Skov <jskov@redhat.com> + + * include/hal_stub.h: Add goto to the used label. + * src/hal_misc.c: Added (dummy) got for label used in + CYGARC_HAL_GET_RETURN_ADDRESS_BACKUP. + +2001-12-05 Jonathan Larmour <jlarmour@redhat.com> + + * src/dbg-threads-syscall.c (dbg_thread_syscall): Don't bother to + deref a func ptr. The opcode could theoretically be 0x0! + +2001-12-04 Richard Sandiford <rsandifo@redhat.com> + + * src/generic-stub.c (__add_char_to_packet): Reverse check for + end of buffer and end of packet to fix potential buffer overrun. + +2001-12-01 Jonathan Larmour <jlarmour@redhat.com> + + * src/dbg-threads-syscall.c (dbg_thread_syscall): check for + NULL dbg_syscall_ptr. + + * cdl/hal.cdl: require CYGPKG_INFRA since all HALs do! + +2001-11-29 Hugo Tyson <hmt@redhat.com> + + * src/hal_stub.c: Enable HAL_STUB_HW_SEND_STOP_REASON_TEXT for + XScale architectures per Mark's request; XScale GDB needs to know + what's happening with watchpoints (= work around previous change) + +2001-11-29 Hugo Tyson <hmt@redhat.com> + + * src/hal_stub.c: Condition out sending the reason for hardware + watchpoint stop in the stop packet as $T05watch:01234568;... most + GDBs do not understand it and in fact object to it. + +2001-11-23 Nick Garnett <nickg@redhat.com> + + * src/generic-stub.c (__process_packet): Fixed bogosity in + handling of 'r' packet. It tried to send two replies, messing up + the protocol and confusing GDB. + +2001-11-02 Hugo Tyson <hmt@redhat.com> + + * include/hal_stub.h (CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION): + Permit this too to be defined externally ie. in a platform HAL. + +2001-10-25 Gary Thomas <gthomas@redhat.com> + + * cdl/hal.cdl: + * cdl/debugging.cdl: Reorg CDL a little so that GDB stub routines + are only compiled when needed (instead of being compiled "empty"). + +2001-10-24 Gary Thomas <gthomas@redhat.com> + + * cdl/hal.cdl: Add 'basic' test. + + * tests/basic.c: New test of some minimal HAL functionality. + +2001-10-18 Gary Thomas <gthomas@redhat.com> + + * src/hal_if.c (cyg_hal_diag_mangler_gdb_putc): + * cdl/debugging.cdl: CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES is now + defined as CDL 'data' flavor (tested via #if vs. #ifdef) + +2001-10-17 Jesper Skov <jskov@redhat.com> + + * src/generic-stub.c: Prefixed local version of memcpy and memset + with _. + +2001-10-17 Gary Thomas <gthomas@redhat.com> + + * cdl/debugging.cdl: + * src/hal_if.c (cyg_hal_diag_mangler_gdb_putc): Make retry/abort optional, + only attemped if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES is configured to + be non-zero (default now 0). + +2001-10-16 Jesper Skov <jskov@redhat.com> + + * include/hal_stub.h: Allow ISOINFRA/LIBC to provide string + functions. + +2001-10-16 Gary Thomas <gthomas@redhat.com> + + * include/generic-stub.h: Add prototypes for breakpoint_list functions. + +2001-10-15 David Howells <dhowells@redhat.com> + + * include/hal_stub.h: put semicolon between goto-label and close curly. + +2001-10-12 Mark Salter <msalter@redhat.com> + + * src/thread-packets.c: Don't specify array sizes in extern decls. + + * src/hal_stub.c: Use HAL_STUB_REGISTERS_SIZE to set number of elements + in register save areas. Default to NUMREGS if not defined by HAL. + Allow HALs to provide specialized get_register()/put_register(). + + * src/generic-stub.c (stub_format_registers): Support 'p' packet. + (__process_packet): Rearrange ifdefs so error is sent for unsupported + Z packet types. + (process_query): Add hook for HAL specific queries. + (process_set): Add hook for HAL specific sets. + + * include/generic-stub.h: Add extern decls to quiet compiler warnings. + +2001-10-11 Gary Thomas <gthomas@redhat.com> + + * include/generic-stub.h: + * src/generic-stub.c: Improve error handling more. Make sure that + packets are consumed, even if they are going to be tossed (overflow). + This keeps TCP based connections going, even when the data is bad. + (getpacket): Only send NAK in case of overflow. + +2001-10-09 Jesper Skov <jskov@redhat.com> + + * src/hal_if.c (flash_config_op): Protect with + CYGARC_HAL_SAVE_GP. + +2001-10-04 Jesper Skov <jskov@redhat.com> + + * include/hal_endian.h: Added. + Fix typo. + +2001-10-03 Jonathan Larmour <jlarmour@redhat.com> + + * include/hal_tables.h (CYG_HAL_TABLE_BEGIN): Use plain "object" + because some (only some though) MIPS tools complain with %object. + (CYG_HAL_TABLE_END): Ditto. + +2001-10-02 Jonathan Larmour <jlarmour@redhat.com> + + * include/hal_tables.h (CYG_HAL_TABLE_BEGIN): Use %object syntax + rather than @object since @ is a comment character on ARM. gas + accepts either syntax. + (CYG_HAL_TABLE_END): Ditto. + +2001-10-01 Gary Thomas <gthomas@redhat.com> + + * src/generic-stub.c (getpacket): Send back error response (E01) if + packet received which overflows buffers. GDB doesn't always do much + with this error, but at least it keeps the protocol moving. + +2001-09-26 Gary Thomas <gthomas@redhat.com> + + * cdl/common.cdl: New interface CYGINT_HAL_SUPPORTS_MMU_TABLES which + indicates if the HAL supports MMU tables (few do). + +2001-09-25 Gary Thomas <gthomas@redhat.com> + + * cdl/common.cdl (CYGSEM_HAL_INSTALL_MMU_TABLES): Change to be + default for ROM startup. + +2001-09-20 Jesper Skov <jskov@redhat.com> + + * tests/vaargs.c (cyg_start): Call CYG_TEST_INIT. + +2001-09-10 Nick Garnett <nickg@redhat.com> + + * include/hal_stub.h (strlen): Changed return type to size_t from + int so it matches <string.h>. For some reason the compiler has + suddenly started complaining about the type mismatch. Strange. + +2001-09-07 Nick Garnett <nickg@redhat.com> + + * src/hal_stub.c (put_register): Added kludge for VR4300 targets + to sign extent the PC when it is being set. This is due to the + age of the VR4300 toolchain and the fact that the VR4300 is the + only target to do full 64bit register saves/restores. + +2001-09-07 Jesper Skov <jskov@redhat.com> + + * include/hal_if.h: Fix typo in below change. + +2001-09-07 Jonathan Larmour <jlarmour@redhat.com> + + * include/hal_if.h (CYGACC_CALL_IF_DBG_SYSCALL): Define and call + with correct arguments. + +2001-08-24 Mark Salter <msalter@redhat.com> + + * src/generic-stub.c (__process_packet): Add support for 'D' packet. + (__process_packet): Check for impossible mem write length. + +2001-08-17 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/hal.cdl: Add CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT + interface. + +2001-08-16 Gary Thomas <gthomas@redhat.com> + + * cdl/hal.cdl: Add CDL options to control GDB protocol retries. + +2001-08-14 Gary Thomas <gthomas@redhat.com> + + * src/hal_if.c (cyg_hal_diag_mangler_gdb_putc): Use timeout + functions to allow for retries. This should improve the case + where [for whatever reason] the host GDB misses or ignores + a $O packet - it will get resent after a reasonable timeout. + +2001-08-03 Gary Thomas <gthomas@redhat.com> +2001-08-03 Jesper Skov <jskov@redhat.com> + + * include/hal_if.h: Use inline functions for calls - allowing + interrupts to be disabled while services are called + [CYGACC_COMM_IF_CONTROL is an exception since it's using variable + arguments - so it's still a macro]. + Pruned unused IF vectors: ICTRL_TABLE, EXC_TABLE, DBG_VECTOR, + CPU_DATA, BOARD_DATA, SYSINFO, SET_SERIAL_BAUD. + Note: this should fix bug CR 902745-CR. + + * cdl/hal.cdl: Removed CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_ICTRL. + * src/hal_if.c (hal_if_init): Removed initialization of + ICTRL_TABLE, EXC_TABLE, CPU_DATA and BOARD_DATA entries. + +2001-08-03 Nick Garnett <nickg@redhat.com> + + Imported from a development branch: + + 2001-07-11 Nick Garnett <nickg@redhat.com> + + * include/drv_api.h: + * src/drv_api.c: + Added API for controlling routing of interrupts to CPUs in SMP + configurations. + + 2001-06-29 Nick Garnett <nickg@cygnus.co.uk> + + * include/drv_api.h: + * src/drv_api.c: + Added API for using spinlocks. + +2001-08-03 Jesper Skov <jskov@redhat.com> + + * tests/vaargs.c: Added. + * cdl/hal.cdl: Added CYGPKG_HAL_BUILD_COMPILER_TESTS to allow cpp1 + and vaargs tests to be compiled conditionally. + +2001-07-27 Jesper Skov <jskov@redhat.com> + + * tests/intr.c: Set up interrupt ISR using driver API so it works + properly in chained mode in the presence of arbiters. + + * src/drv_api.c (chain_isr): Call default ISR when + appropriate. Return ISR return value. + + * include/hal_arbiter.h (hal_call_isr): Added version to be used + with interrupt chaining. + +2001-07-24 Mark Salter <msalter@redhat.com> + + * cdl/hal.cdl (CYGINT_HAL_PLF_IF_IDE): New interface which + indicates platform supports IDE controller I/F macros. + +2001-06-29 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/hal.cdl (CYGPKG_HAL_TESTS): Remove redundant .c extension + +2001-06-29 Jesper Skov <jskov@redhat.com> + + * include/hal_misc.h: Moved arbiter helper to + * include/hal_arbiter.h: this file to avoid header file inclusion + order problems. + +2001-06-28 Jesper Skov <jskov@redhat.com> + + * include/hal_misc.h (hal_call_isr): Added. Used by ISR arbiters. + +2001-06-22 Gary Thomas <gthomas@redhat.com> + + * src/generic-stub.c (BUFMAX): Define as platform specific, thus + reducing memory requirements. + (__process_packet): Eliminate program arguments support until eCos + makes use of them (more memory savings). + +2001-06-22 Mark Salter <msalter@redhat.com> + + * src/hal_stub.c (__do_copy_mem): Add goto statement to prevent + compiler from moving instructions across 'err' label. + +2001-06-14 Jonathan Larmour <jlarmour@redhat.com> + + * src/generic-stub.c (__process_packet): Don't reset the board + straight away with a 'r' packet. Let a 'k' packet do it instead. + + * src/hal_stub.c (__install_traps): Remove redundant comment. + +2001-06-11 Jonathan Larmour <jlarmour@redhat.com> + + * src/hal_if.c (delay_us): Revert below change of 2001-05-17 + +2001-06-05 Hugo Tyson <hmt@redhat.com> + + * src/hal_if.c (cyg_hal_diag_mangler_gdb_putc): The nesting of + CYGARC_HAL_SAVE_GP() and the instant-out if sending a carriage + return "\r" was wrong - it scrambled the gp for the caller! Since + the return-test is trivial, I simply re-ordered rather than making + the exit clause complex with a restore in it. + +2001-05-17 Jonathan Larmour <jlarmour@redhat.com> + + * src/hal_if.c (delay_us): Warn if using default + +2001-05-14 Jonathan Larmour <jlarmour@redhat.com> + + * cdl/interrupts.cdl (CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE): + Default stack size to 32K for non-kernel configs, and describe + why. + +2001-05-07 Gary Thomas <gthomas@redhat.com> + + * src/hal_if.c (hal_ctrlc_check): Only return 'true' if the ISR/DSR + actually processes a ^C. Otherwise, interrupts/date can be lost on + a shared channel (like an ethernet device). + +2001-04-30 Gary Thomas <gthomas@redhat.com> + + * cdl/hal.cdl: Add configury to control initial cache behaviour. + +2001-04-30 Hugo Tyson <hmt@redhat.com> + + * cdl/hal.cdl: Add tests/cpp1.c to the tests list. + + * tests/cpp1.c: New test, to test for regressions in the tools. + This one is for a CPP bug in the XScale tools where '+' binds too + strongly following a ')' because it is mistaken for unary plus. + +2001-04-25 Bart Veer <bartv@redhat.com> + + * tests/cache.c: + Fix test for cache presence. + + * src/drv_api.c (cyg_drv_interrupt_detach): + Added missing indirection. + +2001-03-28 Jonathan Larmour <jlarmour@redhat.com> + + * include/dbg-threads-api.h: Add dbg_thread_id() function prototype. + +2001-03-21 Mark Salter <msalter@redhat.com> + + * src/hal_if.c (hal_if_init): Add explicit typecast when setting + version. Needed when sizeof(int) < sizeof(CYG_ADDRWORD). + +2001-03-21 Jesper Skov <jskov@redhat.com> + + * src/hal_if.c (hal_if_init): Added warning about debugging. + +2001-03-20 Jonathan Larmour <jlarmour@redhat.com> + + * include/hal_if.h: Add argument names to __call_if_flash_cfg_op_fn_t + +2001-03-16 Mark Salter <msalter@redhat.com> + + * src/hal_stub.c (__build_t_packet): Add hook for adding arch-specific + registers to T packet. + (handle_exception_cleanup): Skip orig_registers past breakpoint so we + return to original context rather than hit breakpoint again. + +2001-03-16 Hugo Tyson <hmt@redhat.com> + + * include/hal_if.h: Define types and slots and macros themed with + the phrase CALL_IF_FLASH_CFG_OP following the pattern of what's + there for the other slots. Thus CYGNUM_CALL_IF_FLASH_CFG_OP, + CYGACC_CALL_IF_FLASH_CFG_OP(...) and __call_if_flash_cfg_op_fn_t + are all newly defined. Also CYGNUM_CALL_IF_FLASH_CFG_GET which is + the only operation supported in this initial version. + + Also changed many typedef'd function pointers to not include the + pointerness; that way the type can be used to validate the + correctness of arguments in the called function. + + * src/hal_stub.c (__reset): Minor change to reset function + handling; pointerness of typedef removed. + + * src/hal_if.c (flash_config_op): New function to call flash ops + in RedBoot. This is so that RedBoot can manage ethernet addresses + for you, and the application can get at the data "cleanly". + (hal_if_init): Install flash_config_op() in the table if defined. + +2001-03-12 Mark Salter <msalter@redhat.com> + + * src/hal_misc.c (cyg_hal_user_break): Use macro to find PC + in saved regs. + + * src/generic-stub.c: Add support for harvard memories. + * src/bplist-dynamic.c: Ditto. + * include/generic-stub.h: Ditto. + * include/hal_stub.h: Add dummy harvard memory macros for + princeton memory systems. + +2001-03-12 Jesper Skov <jskov@redhat.com> + + * src/drv_api.c (cyg_drv_interrupt_detach): Fix missing intr-> + change. + +2001-03-08 Jesper Skov <jskov@redhat.com> + + * cdl/hal.cdl: Change sense of + CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT_GUARANTEED to new + CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT_NOT_GUARANTEED. + +2001-03-07 Jesper Skov <jskov@redhat.com> + + * src/drv_api.c: Use macro to provide symbol alias. + +2001-03-05 Jesper Skov <jskov@redhat.com> + + * src/hal_if.c (hal_if_diag_init): Ensure the function only + executes once. + +2001-03-02 Gary Thomas <gthomas@redhat.com> + + * cdl/hal.cdl: + * include/hal_if.h: + * src/hal_if.c (hal_if_init): + Support platform specific initializations. + +2001-02-26 Mark Salter <msalter@redhat.com> + + * src/generic-stub.c (__process_packet): Change 'k' packet to cause + return to original context. Change 'r' packet to respond with empty + packet before resetting board. + + * src/hal_stub.c (handle_exception_exit): New function. Restores + original context saved when stub was entered for the first time. + (handle_exception_cleanup): Save original context. + (__install_traps): Set __process_exit_vec to handle_exception_exit. + +2001-02-09 Jesper Skov <jskov@redhat.com> + + * cdl/debugging.cdl: Make CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT and + CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT options have sensible defaults. + +2001-02-08 Jesper Skov <jskov@redhat.com> + + * cdl/hal.cdl: Added CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE and + CHANNEL_CONFIGURABLE options. + * cdl/common.cdl: Added CYGDBG_HAL_DIAG_TO_DEBUG_CHAN option. + * src/hal_if.c: Changes to respect new options. Always do platform + driver init from CLAIM_COMMS code. + * src/hal_stub.c: Leave channel setup to CLAIM_COMMS code. + + * src/hal_if.c: Added null mangler that gets called via the + virtual vector console comms entry and just forwards IO to the + debug comms entries. This differs from setting the console + channel to the same as the debug channel in that console output + will go to the debug channel even if the debug channel is changed. + +2001-02-07 Jesper Skov <jskov@redhat.com> + + * include/hal_if.h: Allow architecture to override COMM and CALL + accessor macros. + +2001-02-03 Gary Thomas <gthomas@redhat.com> + + * src/bplist-dynamic.c (__set_breakpoint, __remove_breakpoint): + Fix error introduced below when no breakpoint list defined. + +2001-02-02 Mark Salter <msalter@redhat.com> + + * src/generic-stub.c: __set_breakpoint and __remove_breakpoint now + take a length argument. + + * src/bplist-dynamic.c: Support breakpoint length. Use + HAL_BREAKINST_ADDR macro (if defined) to get actual breakpoint based + on breakpoint length. + + * include/hal_stub.h: Add len argument to __set_breakpoint and + __remove_breakpoint. + +2001-02-01 Jesper Skov <jskov@redhat.com> + + * src/drv_api.c: Make it build with chaining. + + * include/hal_if.h: Introduce macros for legal version range and + special hacked version number used by ctrlc magic. + * src/hal_if.c (hal_ctrlc_isr_init): Be more careful with how the + version number is checked (and trashed) by the ctrlc init code. + * src/hal_misc.c (hal_default_isr): Same. + + * src/hal_stub.c: Moved mangling code to hal_if.c + * src/hal_if.c: New policies for when and how to initialize the + IO channels. Mangler code now set up by diag_init to allow for + mangling when no stub is included. + + * include/hal_if.h: Added COMM version in upper 16 bits of version + word. Removed CYGPRI_HAL_IMPLEMENTS_IF_SERVICES. + * src/hal_misc.c: Use masks when checking vv versions. + + * cdl/hal.cdl: Add new options for selecting which parts of the + virtual vector table to initialize. + * src/hal_if.c: Matching granularity in initialization code. + Extra checking of services before using these. + + * cdl/debugging.cdl: Require channel initialization when enabling + stubs. + +2001-01-31 Jesper Skov <jskov@redhat.com> + + * cdl/common.cdl: Get rid of CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL + options. They are replaced by the CYGSEM_HAL_DIAG_MANGLER option. + +2001-01-31 Hugo Tyson <hmt@redhat.com> + + * include/hal_if.h: Make it possible to build logical ether driver + even without virtual vectors present, by defining a dummy + HAL_CTRLC_CHECK in that case; other code invokes it if debugging + per se is enabled. + +2001-01-26 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c (__reset): Rename HAL_STUB_PLATFORM_RESETx macros + to HAL_PLATFORM_RESETx. + * src/hal_if.c (reset): Same. + +2001-01-15 Nick Garnett <nickg@cygnus.co.uk> + + * src/drv_api.c: Initialized isr_disable_counter to 1 so that it + indicates that interrupts are initially disabled. + +2000-12-15 Gary Thomas <gthomas@redhat.com> + + * src/generic-stub.c: Define 'version' string to be a weak + symbol that can be easily overridden (e.g. by RedBoot). + +2000-12-11 Gary Thomas <gthomas@redhat.com> + + * src/hal_if.c: Remove unnecessary (polluting) include file. + + * include/hal_stub.h: Support platform/variant supplied + include files. <cyg/hal/plf_XXX.h> can now be layered + as <cyg/hal/var_XXX.h> which includes <cyg/hal/plf_XXX.h>. + +2000-12-06 Jesper Skov <jskov@redhat.com> + + * src/hal_if.c (delay_us): Ensure proper _GP save/restore. + Reduce number of loops in fall-back code. + +2000-12-05 Drew Moseley <dmoseley@redhat.com> + + * src/hal_stub.c (__build_t_packet): Handle + CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T with Little Endian + target. + + * include/hal_misc.h: Added BIT and SZ_ defines. + +2000-11-22 Mark Salter <msalter@redhat.com> + + * src/hal_misc.c (hal_default_isr): Version check only when + CYGSEM_HAL_ROM_MONITOR not defined. + +2000-11-20 Mark Salter <msalter@redhat.com> + + * src/hal_stub.c (hal_flush_output): New function to flush debug + comm interface. + + * src/generic-stub.c (__process_packet): Use hal_flush_output when + killing or continuing. + + * include/hal_stub.h: Add declaration for hal_flush_output(). + + * include/hal_if.h (__COMMCTL_FLUSH_OUTPUT): New comm control cmd. + +2000-11-17 Jesper Skov <jskov@redhat.com> + + * src/hal_if.c (delay_us): Add dummy loop. + Duh! Take usecs argment into account. + +2000-11-06 Mark Salter <msalter@redhat.com> + + * src/generic-stub.c (__handle_exception): Add support for GNUPro bsp + syscall handling. + + * src/board.h: Include pkgconf/redboot.h for CYGSEM_REDBOOT_BSP_SYSCALLS. + +2000-11-06 Jesper Skov <jskov@redhat.com> + + * src/hal_if.c (hal_if_diag_write_char): Clear interrupt flag before + setting breakpoint. + +2000-11-04 Mark Salter <msalter@redhat.com> + + * src/hal_stub.c (__build_t_packet): Report reason and data + address if stopped by hw watchpoint. + + * src/generic-stub.c (__process_packet): Remove experimental + support for type 5 Z packet. + + * include/hal_stub.h: Define HAL_STUB_STOP_* reasons returned + by HAL_IS_STOPPED_BY_HARDWARE. + +2000-10-27 Mark Salter <msalter@redhat.com> + + * src/generic-stub.c: Fixed preprocessor warning. + +2000-10-27 Gary Thomas <gthomas@redhat.com> + + * src/generic-stub.c (__process_packet): Remove warnings when + hardware breakpoint support (Z packet) not enabled. + +2000-10-26 Mark Salter <msalter@redhat.com> + + * src/generic-stub.c (__process_packet): Add Z packet support. + + * src/bplist-dynamic.c: Include <pkgconf/hal.h> to pick up + CYGNUM_HAL_BREAKPOINT_LIST_SIZE. + +2000-10-24 Jesper Skov <jskov@redhat.com> + + * src/generic-stub.c (__process_packet): Disable buffer size + z-packet. + +2000-10-23 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c: Made __mem_fault_handler pointer volatile. + +2000-10-20 Jonathan Larmour <jlarmour@redhat.com> + + * include/drv_api.h (cyg_interrupt): Make dsr_count volatile to + prevent compilers optimizing accesses in the wrong place. + +2000-10-20 Jesper Skov <jskov@redhat.com> + + * include/drv_api.h: Correct location of volatile keyword. + * src/drv_api.c: Same. + +2000-10-19 Gary Thomas <gthomas@redhat.com> + + * src/generic-stub.c (__process_packet): Add RedBoot identifier + in maintenance 'd' packet reply. + +2000-10-18 Jesper Skov <jskov@redhat.com> + + * include/hal_if.h (CYGPRI_HAL_IMPLEMENTS_IF_SERVICES): Set for + all non-RAM startup types. + +2000-10-13 Jonathan Larmour <jlarmour@redhat.com> + + * src/stubrom/stubrom.c (cyg_start): Remove unnecessary call to + initialize_stub() + +2000-09-11 Jonathan Larmour <jlarmour@redhat.com> + + * include/hal_tables.h (CYG_HAL_TABLE_EXTRA): Use new definition of + CYGBLD_ATTRIB_SECTION, and fix the string name up better. + (CYG_HAL_TABLE_ENTRY): Ditto + (CYG_HAL_TABLE_QUALIFIED_ENTRY): Ditto + +2000-09-07 Jonathan Larmour <jlarmour@redhat.com> + + * include/hal_tables.h: Fix non-standard use of paste operator to + remove warnings with recent gcc + +2000-09-04 Jonathan Larmour <jlarmour@redhat.com> + + * include/hal_tables.h (CYG_HAL_TABLE_END): Use CYGARC_P2ALIGNMENT + to align label + (CYG_HAL_TABLE_TYPE): Define + +2000-09-01 Jonathan Larmour <jlarmour@redhat.com> + + * src/hal_stub.c (__build_t_packet): Ensure sign extension applies + in the higher word, not the lower. + (__build_t_packet): Don't need to conditionalize on + CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T as there should be no + problems with the current code. + * src/generic-stub.c (stub_format_registers): Likewise + + * include/hal_if.h (CYGACC_COMM_IF_CONTROL): Remove warning due to + unnecessary use of cpp paste operator + +2000-08-28 Gary Thomas <gthomas@redhat.com> + + * src/hal_if.c: + * include/hal_if.h (hal_ctrlc_check): Define new routine to be + called by interrupt handlers (DSRs) which may be using hardware + shared with a debug channel. In particular, network adaptors + need to call this function to see if a ^C has occurred on the + network debug connection. + +2000-08-24 Gary Thomas <gthomas@redhat.com> + + * include/hal_tables.h: Need descriminated tables (for proper sorting). + +2000-08-14 Drew Moseley <dmoseley@redhat.com> + + * src/hal_if.c: Added an extern declaration for + cyg_hal_plf_comms_init. + + * src/bplist-dynamic.c: Only use breakpoint lists when building + stubs. + +2000-08-10 Drew Moseley <dmoseley@redhat.com> + + * include/generic-stub.h: Added support for register validity + checking. + * src/generic-stub.c: Ditto. + * src/hal_stub.c: Ditto. + + * include/drv_api.h: Added cyg_code_t. + +2000-08-03 Gary Thomas <gthomas@redhat.com> + + * include/hal_if.h (CYGNUM_CALL_IF_DBG_DATA): Move to avoid + conflict. + +2000-07-26 Gary Thomas <gthomas@redhat.com> + + * src/hal_stub.c (cyg_hal_gdb_diag_putc): Ignore any characters + other than the protocol chars of ACK/NAK/^C. + + * src/hal_if.c (hal_if_diag_init): Only reset console channel + if user has configured a non-default choice. + +2000-07-24 Drew Moseley <dmoseley@redhat.com> + + * src/bplist-dynamic.c (__install_breakpoint_list): Call + HAL_ICACHE_SYNC() rather than HAL_ICACHE_INVALIDATE_ALL(). + +2000-07-21 Drew Moseley <dmoseley@cygnus.com> + + * src/hal_stub.c: Cleanup of #define's. + + * src/generic-stub.c: Rearrange the linkage between Cygmon and HAL so + that Cygmon needs HAL but not vice-versa. ie HAL no longer calls + any Cygmon functions. + * src/hal_misc.c: Ditto. + + * src/bplist-dynamic.c: Use HAL macros rather than Cygmon + functions for flushing the cache. + Also handle the case where target_register_t is not defined. + +2000-07-21 Gary Thomas <gthomas@redhat.com> + + * src/hal_if.c (CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS): Define to allow + the number of channels to be extended by "AUX" packages. + +2000-07-20 Drew Moseley <dmoseley@redhat.com> + + * src/generic-stub.c (stub_format_registers): Make the previous patch + effective only if CYGARC_REGSIZE_DIFFERS_FROM_TARGET_REGISTER_T is + defined so as to not affect any other targets. + * src/hal_stub.c: Ditto. + +2000-07-19 Drew Moseley <dmoseley@redhat.com> + + * src/generic-stub.c (stub_format_registers): Handle the case + where GDB is expecting registers larger than we are storing. ie + MIPS gdb expects 64 bit registers even if we are on a 32 bit + architecture. Also, handle the sign-extension correctly if + necessary. + * src/hal_stub.c (__build_t_packet): Ditto. + +2000-07-18 Jesper Skov <jskov@redhat.com> + + * src/hal_misc.c (hal_default_isr): + Version gets hacked by hal_if_init - check for the hacked value. + +2000-07-18 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c (__mem_fault_handler): Made volatile. + +2000-07-14 Drew Moseley <dmoseley@redhat.com> + + * src/generic-stub.c: Cleanups for better coexistence with Cygmon. + * include/generic-stub.h: Ditto. + * include/hal_if.h: Ditto. + * include/hal_stub.h: Ditto. + * src/hal_stub.c: Ditto. + + * cdl/hal.cdl: Compile bplist-dynamic.c. + + * src/bplist-dynamic.c: New file for supporting breakpoints in the HAL. + +2000-07-14 Gary Thomas <gthomas@redhat.com> + + * src/hal_if.c (delay_us): Use HAL_DELAY_US() if defined. + +2000-07-07 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c (initHardware): Fix #endif location. + + * src/hal_if.c (hal_ctrlc_isr_init): Added hack to work around a + silly but critical problem. + + * src/hal_stub.c: Removed some CygMon conditional exclusions. + + * src/hal_if.c (hal_ctrlc_isr_init): Don't enable interrupts when + configured as ROM monitor. + +2000-07-05 Jesper Skov <jskov@redhat.com> + + * cdl/debugging.cdl: Only allow CTRLC support if there's stubs or + a ROM monitor to handle it. (Haruki Kashiwaya (kashiwaya at redhat + dot com)). + +2000-06-30 Jesper Skov <jskov@redhat.com> + + * include/hal_if.h: Make CYGACC macros call functions. May have to + add some _GET macros at some time if anyone needs to access the + function pointers. + + * src/hal_stub.c: + * src/hal_misc.c: + * src/hal_if.c: + Matching changes of CYGACC clients. + +2000-06-29 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c (cyg_hal_gdb_diag_putc): Check console interrupt + flag and breakpoint if set. + +2000-06-28 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c (cyg_hal_gdb_diag_putc): Don't try to set + breakpoints in ROM startup - just disable interrupts. Also, use + procs table function to disable device interrupts. + + * include/hal_if.h: Mark vector/comms arrays volatile to avoid + compiler confusion. + + * include/dbg-threads-api.h: Fix C/C++ declaration issues. + + * src/hal_stub.c: Moved stub platform init call below vector table + setup. + + * src/hal_misc.c: + * src/hal_if.c: + * include/hal_if.h: DBG_ISR_VECTOR and SET_TIMEOUT functions added + to comms table. Added DELAY_US function to vector table. Made + switching of debug channel dis/enable Ctrl-c interrupts as + well. Made ctrlc_isr code use new vector entries. All this amounts + to a properly switchable debug channel. + +2000-06-21 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c: Fixed clients of vector procs tables to pass + in the correct arguments. Hook O-packetizer up on procs slot + reserved for IO mangler. Install mangler when necessary. + + * src/hal_if.c: Extended set procs functions to allow temporarily + switching console procs in a safe manner. Removed debug and + console wrappers - all IO happens via drivers hooked up in tables + rather than through hardwired macros. Proper initialization of + console proc entry. Fixed clients of vector procs tables to pass + in the correct arguments. Stub now does its own vector table + initialization. Added special procs slot for IO manglers. + + * include/hal_if.h: Define special IDs used by the set procs + functions. PROCS_HANDLED removed since the procs table will now + always service any port. + +2000-06-21 Nick Garnett <nickg@cygnus.co.uk> + + * include/hal_stub.h: Added underscore to breakinst(). + + * include/hal_tables.h: + Added this file to contain macros for defining datatables in a + systematic and extensible way. + +2000-06-19 Gary Thomas <gthomas@redhat.com> + + * cdl/hal.cdl: Revert change below - GUARANTEED can exist + with STUBS defined. + +2000-06-18 Gary Thomas <gthomas@redhat.com> + + * cdl/hal.cdl: Use of virtual vector functions for diagnostic + output must be disabled when building with stubs. Note: this + lets stubs be built for platforms with guaranteed virtual + vector support. + +2000-06-16 Jesper Skov <jskov@redhat.com> + + * include/hal_if.h: All vector-dependant features hidden when + config option not enabled. + + * src/hal_if.c (hal_if_init): Fix warning. + +2000-06-15 Jesper Skov <jskov@redhat.com> + + * include/hal_if.h: Added console-include decision logic. + +2000-06-15 Nick Garnett <nickg@cygnus.co.uk> + + * src/drv_api.c: + * include/drv_api.h: Added boolean result to cyg_drv_cond_wait() + to match change to the kernel and KAPI functionality. + +2000-06-14 Jesper Skov <jskov@redhat.com> + + * src/hal_stub.c: Added O-packetizer used by GDB stubs for virtual + vector table configs. + + * src/hal_misc.c (hal_default_isr): Check Ctrlc for both CTRLC + or BREAK options. + + * src/hal_if.c: + * include/hal_if.h: + Define console wrappers when necessary. Platform HALs can use + these by providing raw IO functions and some config data. + +2000-06-09 Jesper Skov <jskov@redhat.com> + + * src/hal_if.c: Implemented most of the remaining services. Some + just don't have an eCos equivalent at the moment. + + * cdl/hal.cdl: Allow virtual_vector options to have sensible + default values depending on when the platform HAL port was + written. + + * src/hal_misc.c (cyg_hal_user_break): Also expect CygMon to + provide the breakpoint service. + + * src/stubrom/stubrom.c (cyg_start): Reverted change. Now handled + by hal_if_init. + + * cdl/hal.cdl: Added option for controlling use of diag services + in the virtual vector table. + +2000-06-08 Jesper Skov <jskov@redhat.com> + + * src/stubrom/stubrom.c: Call hal_diag_init to ensure IF table + entries related to diag IO get initialized. + + * src/hal_stub.c (cyg_hal_gdb_interrupt): save/restore GP so it + can be used by MIPS platforms. + Use reset function in ROM if available. + + * src/hal_misc.c: + * include/hal_misc.h: Functions shared between HALs. More + functions are likely to be moved here if appropriate. + + * src/hal_if.c: Interfacing related functions: table init code and + function wrappers. + + * include/hal_if.h: ROM/RAM calling interface table + definitions. The layout is a combination of libbsp and vectors + already in use by some eCos platforms. + + + * cdl/hal.cdl: Added CYGxxx_HAL_VIRTUAL_VECTOR_SUPPORT + options. These are used to control whether a platform uses the new + ROM/RAM calling interface. All platforms will be converted to use + this, but piecemeal over a period of time, thus the requirement + for selecting behavior. + +2000-06-04 Gary Thomas <gthomas@redhat.com> + + * cdl/hal.cdl: Support variant 'pkgconf' headers. This will allow + [variant] common symbols to be defined, rather than duplicating + them over all platforms using that variant. + +2000-05-25 Jesper Skov <jskov@redhat.com> + + * cdl/debugging.cdl: Allow thread support to included for ROM + monitor builds. + +2000-05-22 Jesper Skov <jskov@redhat.com> + + * cdl/debugging.cdl: Allow platform to prevent CTRLC inclusion. + +2000-04-12 Jesper Skov <jskov@redhat.com> + + * cdl/debugging.cdl: Don't let interfaces define anything. + +2000-04-07 Jesper Skov <jskov@redhat.com> + + * cdl/hal.cdl: Fix dependencies for stub. + +2000-03-28 Jesper Skov <jskov@redhat.com> + + * src/generic-stub.c (__process_packet): Added 'z' packet reply. + +2000-03-28 John Dallaway <jld@cygnus.co.uk> + + * cdl/hal.cdl: + + Adjust documentation URLs. + +2000-03-24 Jesper Skov <jskov@redhat.com> + + * include/hal_stub.h: Fixed a bad function name. Made it opssible + for archs to define CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION. + +2000-03-20 Jesper Skov <jskov@redhat.com> + + * cdl/debugging.cdl: Preclude USE_MONITOR when including stubs. + +2000-03-01 Gary Thomas <gthomas@cygnus.co.uk> + + * cdl/common.cdl: + Define CYGINT_HAL_DIAG_DISABLE_GDB_PROTOCOL_SUPPORTED as an + 'interface' so implementations can be properly specified. + +2000-02-29 Gary Thomas <gthomas@cygnus.co.uk> + + * cdl/common.cdl: Option to disable GDB protocol now supported + by QUICC based PowerPC systems. + +2000-02-29 Jonathan Larmour <jlarmour@redhat.co.uk> + + * include/generic-stub.h: Make header C++ safe + +2000-02-16 Jesper Skov <jskov@redhat.com> + + * include/hal_stub.h: fixed endian definitions. + +2000-02-10 Jesper Skov <jskov@redhat.com> + + * include/pkgconf/hal.h: Added CYGSEM_HAL_ROM_MONITOR + * src/hal_stub.c (initHardware): CYG_HAL_STARTUP_STUBS -> + CYGSEM_HAL_ROM_MONITOR. + Removed HAL_STUB_PLATFORM_STUBS_INIT. + +2000-02-09 Jesper Skov <jskov@redhat.com> + + * cdl/hal.cdl: Added remaining build dependencies. + +2000-02-04 Jesper Skov <jskov@redhat.com> + + * cdl/hal.cdl: Fix test list display. + +2000-02-03 Jesper Skov <jskov@redhat.com> + + * include/pkgconf/hal.h: CYG_HAL_POWERPC_x->CYGPKG_... + +2000-02-03 Jesper Skov <jskov@redhat.com> + + * cdl/debugging.cdl: Use interfaces for stub capabilities instead + of exclude list. + * cdl/hal.cdl: Add extra dependencies to common stub build rule. + +2000-02-02 Jesper Skov <jskov@redhat.com> + + * cdl/hal.cdl: Added HAL tests. + +2000-01-31 Simon FitzMaurice <sdf@cygnus.co.uk> + * cdl/hal.cdl: + + Adjust help URLs in line with new doc layout. + +2000-01-28 Simon FitzMaurice <sdf@cygnus.co.uk> + * cdl/hal.cdl: + + Adjust help URLs in line with new doc layout. + +2000-01-27 Jesper Skov <jskov@redhat.com> + + * cdl/hal.cdl: Added simple build rules for common stub. + +2000-01-26 Jonathan Larmour <jlarmour@redhat.co.uk> + + * src/hal_stub.c (__reset): Replace CYGDAT_CYGMON_ENABLE + dependency with just CYGPKG_CYGMON + (initHardware): Likewise + (__set_baud_rate): Likewise + (putDebugChar): Likewise + +2000-01-17 John Dallaway <jld@cygnus.co.uk> + + * cdl/common.cdl, + cdl/debugging.cdl: + + Modify the default_value attribute for + CYGFUN_HAL_COMMON_KERNEL_SUPPORT, CYGPKG_HAL_EXCEPTIONS + and CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT to do the right + thing in the absence of the eCos kernel package. + +1999-12-22 John Dallaway <jld@cygnus.co.uk> + + * cdl/hal.cdl: + + Add CFLAGS to the custom rule for extras.o to accommodate + arm big-endian targets. + +1999-12-21 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/pkgconf/hal.h: Rename all CYG_HAL_USE_ROM_MONITOR_GDB_STUBS + -> CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs + Rename all CYG_HAL_USE_ROM_MONITOR_CYGMON -> + CYGSEM_HAL_USE_ROM_MONITOR_CygMon + Rename all CYG_HAL_USE_ROM_MONITOR -> CYGSEM_HAL_USE_ROM_MONITOR + Don't need to define CYG_HAL_SH_SH7708 any more + + * cdl/hal.cdl: Add CYGPKG_HAL_ROM_MONITOR container package for + platforms to put ROM-monitor related options into + Move all ROM-monitor related options into individual platform CDL + +1999-12-02 John Dallaway <jld@cygnus.co.uk> + + * cdl/hal.cdl: + + Use '$<' to reference custom rule dependency. + +1999-12-01 John Dallaway <jld@cygnus.co.uk> + + * cdl/hal.cdl: + + Use the <PREFIX> token in custom rules. + +1999-11-29 John Dallaway <jld@cygnus.co.uk> + + * cdl/hal.cdl: + + Use wildcard in the custom rule for extras.o to + accommodate 'make -n'. + +1999-11-23 Simon Fitzmaurice <sdf@cygnus.co.uk> + * cdl\common.cdl: Correct example of illiteracy + +1999-11-20 Gary Thomas <gthomas@cygnus.co.uk> + + * cdl/common.cdl: Add MMU tables options. + + * include/pkgconf/hal.h (CYGSEM_HAL_INSTALL_MMU_TABLES): + (CYGSEM_HAL_STATIC_MMU_TABLES): New options to control MMU table + flavour and placement. + +1999-11-15 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/dbg-threads-api.h, include/generic-stub.h, + include/hal_stub.h: Add comments to explain these header files should + not be included by user programs + +1999-11-09 Gary Thomas <gthomas@cygnus.co.uk> + + * cdl/common.cdl: Add CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL. + + * include/pkgconf/hal.h (CYGDBG_HAL_DIAG_DISABLE_GDB_PROTOCOL): + New option which [explicitly] controls use of GDB protocol + for diagnostic I/O. + +1999-11-03 Jesper Skov <jskov@cygnus.co.uk> + + * cdl/hal.cdl: More crud out + mn10300 fixes. + +1999-11-02 Jesper Skov <jskov@cygnus.co.uk> + + * cdl/hal.cdl: Cleaned out some of the CPU config entries. + +1999-10-29 Gary Thomas <gthomas@cygnus.co.uk> + + * tests/PKGconf.mak: Add cache tests for Cirrus Logic boards. + +1999-10-29 Jesper Skov <jskov@cygnus.co.uk> + + * tests/cache.c: Made safe for targets with no cache. + + * tests/PKGconf.mak: Don't build cache test for ARM unless + explicitly enabled. + +1999-10-28 Jesper Skov <jskov@cygnus.co.uk> + + * tests/cache.c: Fix array size. + +1999-10-27 Gary Thomas <gthomas@cygnus.co.uk> + + * src/hal_stub.c: Fix typo (CYGDAT_CYGMON_ENABLE). Also need + to include <pkgconf/cygmon.h> + +1999-10-27 Gary Thomas <gthomas@cygnus.co.uk> + + * src/hal_stub.c: Add explicit enable for CygMon package. + +1999-10-27 Hugo Tyson <hmt@cygnus.co.uk> + + * src/hal_stub.c (cyg_hal_gdb_interrupt): Bugfix to previous: ^Cs + were being ignored when received by the diag output code, because + there was already a break in place. Solution is to let + cyg_hal_gdb_interrupt() override any previous break, and tidy up + state of course. + +1999-10-26 Hugo Tyson <hmt@cygnus.co.uk> + + * include/hal_stub.h (CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION): Place + the break at the address of a label within the calling context + [normally hal_diag_write_char()]; this is neater and more + portable; it's supported for more targets. Also use + cyg_hal_place_break() to place it, define that, &c. + + * src/hal_stub.c (cyg_hal_gdb_place_break): New routine to + specially handle the inline breakpoint. It basically does the + same as cyg_hal_gdb_interrupt(), except on some platforms where + you must do different things to set a bp from a non-interrupt + context. + +1999-10-25 Gary Thomas <gthomas@cygnus.co.uk> + + * src/hal_stub.c (putDebugChar, getDebugChar): When building with + CygMon, these functions are defined by CygMon. + +1999-10-26 John Dallaway <jld@cygnus.co.uk> + + * cdl/hal.cdl: + + Modify custom make rule to specify file paths relative + to the package version directory. + +1999-10-22 Hugo Tyson <hmt@cygnus.co.uk> + + * include/hal_stub.h (CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION): + (CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION): new macros to be invoked + in hal_diag routines to make atomic the code that outputs a + complete GDB $O packet. This is required so that watching + variables (which is implemented by stepping) and stepping itself + does not try to ss through that $O output code. CASE 102327. + + * src/hal_stub.c (cyg_hal_gdb_break_is_set): new routine to query + whether a break is set: used by step in the stubs to decide to + continue instead, because we are in a critical region. + (cyg_hal_gdb_running_step): communication between generic stub and + here: if set, a step has been converted into a continue, so we do + NOT obey cyg_hal_gdb_remove_break until it is cleared, in + handle_exception_cleanup(). + + * src/generic-stub.c (__process_packet): If there is a break set + by the hal_stub.c, convert a step to continue, and set + cyg_hal_gdb_running_step to say we did so. + +1999-10-22 Jesper Skov <jskov@cygnus.co.uk> + Case 102379 + * src/generic-stub.c (__handle_exception): Flush and clear caches + after cleaning up after single-stepping. + + (memcpy, memset): Added to prevent stub hanging if user puts + breakpoints in either function. + +1999-10-19 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: Added monitor configury for Brother + board. + +1999-10-10 Gary Thomas <gthomas@cygnus.co.uk> + + * src/thread-packets.c (stub_pkt_currthread): Fix typo in comment. + + * src/generic-stub.c: Reorg to expose register get/set functions. + +1999-10-08 Simon Fitzmaurice <sdf@cygnus.co.uk> + * cdl\interrupts.cdl: Quoted '[' and ']' (significant in TCL and thus CDL) + +1999-10-08 Jesper Skov <jskov@cygnus.co.uk> + + * cdl/interrupts.cdl: Added + CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS. + +1999-09-22 Simon FitzMaurice <sdf@cygnus.co.uk> + + * cdl\hal.cdl : add priority field to "extras.o" rule + +1999-09-21 Gary Thomas <gthomas@cygnus.co.uk> + + * src/thread-packets.c: Fix some typos in comments. + +1999-09-15 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_stub.c: Override generic GDB interrupt functions for + ARM. Need them to be thumb aware. + +1999-09-13 Gary Thomas <gthomas@cygnus.co.uk> + + * include/pkgconf/hal.h: Add new config option to allow spurious + interrupts to be ignored by the HAL. + + * src/generic-stub.c (__process_packet): Build in version string + (date/time) for stubs in ROM to be returned via 'd' packet. + +1999-09-09 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/pkgconf/hal.h (CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS): Rename + CYGPKG_HAL_MN10300_SIM to CYGPKG_HAL_MN10300_AM31_SIM + +1999-09-07 Nick Garnett <nickg@cygnus.co.uk> + + * src/dbg-threads-syscall.c (dbg_currthread_id): Fixed to return + zero if dbg_currthread() returns false. Previously it could have + returned a random value which would have made GDB think there had + been a thread switch when there hadn't. It was particularly prone + to do this in configurations where the kernel was absent. + +1999-09-01 Gary Thomas <gthomas@cygnus.co.uk> + + * include/pkgconf/hal.h: Always include target and platform package + include (pkgconf) files. + +1999-08-26 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * src/generic-stub.c (__hex2mem_helper): + Use target_register_t when casting to address type, rather than long + Since the compiler can choose arbitrary alignment of unions, force + to use byte array only + Restore use of loop termination test for *hexMemSrc, just in case + since that's how it used to be + Increment destination, not source at end of loop + + (__mem2hex_helper): + Use target_register_t when casting to address type, rather than long. + Since the compiler can choose arbitrary alignment of unions, force + to use byte array only. Therefore use single __read_mem_safe() call + + * src/hal_stub.c (__do_copy_mem): Reassign back from dst/src at start + of each "if" clause in case we go round the loop again. + +1999-08-24 Gary Thomas <gthomas@cygnus.co.uk> + + * src/hal_stub.c (__do_copy_mem): Move temp variables to top of + function - potentially safer if there is an error. + +1999-08-23 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * src/generic-stub.c (__process_packet): For 'g' and 'G' packets, + when the register size differs from sizeof(target_register_t) we must + adjust according to the endianness + + * include/hal_stub.h: Ensure __LITTLE_ENDIAN__ is defined on + little-endian targets + + * src/hal_stub.c (__build_t_packet): Use the correct register sizes + for PC and SP rather than assuming they are the same as target_register_t + +1999-08-23 Gary Thomas <gthomas@cygnus.co.uk> + + * include/generic-stub.h: Change prototypes for internal functions. + + * src/hal_stub.c (__do_copy_mem): + * src/generic-stub.c (__mem2hex_helper): Rework to perform aligned, + multi-byte operations when conditions allow. This should handle + most "hardware register" access cases. Note: there currently is + no good way to force GDB to require/use such accesses. + +1999-08-17 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * tests/intr.c (cyg_start): Use CYG_TEST_NA rather than a pass saying + it's inapplicable + +1999-08-16 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/pkgconf/hal.h: Rename CYG_HAL_MN10300_AM32_STDEVAL1 to + CYG_HAL_MN10300_AM31_STDEVAL1 + +1999-08-13 Nick Garnett <nickg@cygnus.co.uk> + + * src/hal_stub.c: Removed superfluous trace() extern. + +1999-08-12 Nick Garnett <nickg@cygnus.co.uk> + + Imported following changes from AM33 branch: + + 1999-07-27 Nick Garnett <nickg@cygnus.co.uk> + + * src/hal_stub.c: Added support for 1 byte breakpoints. + Removed invalidates for cache flushes - I am not entirely sure why + we have these here, since HAL_DCACHE_SYNC() should do what we + need, and these invalidates are causing a problem on the MIPS and + MN10300 targets. + + * include/pkgconf/hal.h: Added Monitor selection for AM33. + + 1999-06-29 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: Modified to match new MN10300 HAL + organization. + +1999-08-06 Jesper Skov <jskov@cygnus.co.uk> + + * src/generic-stub.c (__process_packet): FLush and clear caches + after call to __single_step. + +1999-07-05 Jesper Skov <jskov@cygnus.co.uk> + + * tests/intr.c: Don't use kernel's RTC definitions. + +1999-07-02 Jesper Skov <jskov@cygnus.co.uk> + PR20157 + * tests/cache.c: Print stride values, preventing timeout on slow + targets. + +1999-06-28 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h (CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT): + Fixed parent. + +1999-06-24 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/pkgconf/hal.h: Clarify descriptions of + CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT and + CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT. + +1999-06-17 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: Added CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT + to enable inclusion of ^C interrupt handler. Added CDL to control + it. + +1999-06-10 Hugo Tyson <hmt@cygnus.co.uk> + + * include/pkgconf/hal.h: Add support for the PowerPC target MBX860 + platform, CYG_HAL_POWERPC_MBX. + +1999-06-10 Gary Thomas <gthomas@cygnus.co.uk> + + * src/hal_stub.c: Need to init register pointer. + +1999-06-08 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Added CYG_HAL_ROM_MONITOR for EDK7708. + +1999-05-31 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_stub.c: Respect HAL_BREAKINST_SIZE setting. + +1999-05-28 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Renamed SH platform package to edk7708. + +1999-05-28 Nick Garnett <nickg@cygnus.co.uk> + + * src/hal_stub.c (initHardware): Added call to + HAL_STUB_PLATFORM_INIT if it is defined. + + * include/pkgconf/hal.h: Added a #undef for CYG_HAL_ROM_MONITOR, + largely so that a stubrom permutation can define it. + +1999-05-27 Nick Garnett <nickg@cygnus.co.uk> + + * src/hal_stub.c: Do not call HAL_ICACHE_INVALIDATE_ALL() and + HAL_DCACHE_INVALIDATE_ALL() in __instruction_cache() and + __data_cache() for MIPS targets. These macros are simply + duplicates. + +1999-05-27 Jesper Skov <jskov@cygnus.co.uk> + + * tests/cache.c: Added handling of unified caches. + +1999-05-25 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * tests/cache.c: Use HAL_DCACHE_SYNC if available + +1999-05-24 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Added CPU specifier for EDK board. + +1999-05-21 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_stub.c (__install_traps): Set exit vector to __reset. + +1999-05-21 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: Switched VR4300 over to using GDB STUBS + monitor from PMON. + +1999-05-21 Jesper Skov <jskov@cygnus.co.uk> + + * tests/intr.c: Get RTC values from CYGBLD_HAL_PLATFORM_H. + Ensure there are fallback definitions. + + * src/hal_stub.c (handle_exception_cleanup): Added optional call + of HAL_STUB_PLATFORM_STUBS_FIXUP macro. + +1999-05-18 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_stub.c (hal_output_gdb_string): Added missing ; + +1999-05-13 Nick Garnett <nickg@cygnus.co.uk> + + The following changes were all made on a branch and imported into + the main trunk later. + + 1999-05-11 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: + tidied up all MIPS targets to include CYGBLD_HAL_TARGET_H. This + will eventually apply to all configurations. + + 1999-05-06 Nick Garnett <nickg@cygnus.co.uk> + + * src/PKGconf.mak (COMPILE): Added dbg-threads-syscall.c. + + * include/dbg-thread-syscall.h: + * src/dbg-threads-syscall.c: + Files added to enable support for thread-awareness in GDB stub + ROMs. The .h file has been moved from kernel/src/debug. + + 1999-04-28 Nick Garnett <nickg@cygnus.co.uk> + + * src/hal_stub.c (__build_t_packet): Changed sp variable to a + non-pointer type to force it to be installed in the T packet with + the right size. + + * src/drv_api.c: Added cyg_interrupt_call_pending_DSRs() to keep + HAL happy in non-kernel configurations. + + 1999-04-21 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: + Added VR4300 configury for ROM monitor use and inclusion of + variant-specific configuration header. This needs some further + tidying up. + +1999-04-28 Bart Veer <bartv@cygnus.co.uk> + + * src/PKGconf.mak: + Use the new rules for generating libextras.a + +1999-04-27 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: GDB_BREAK support now available for ARM + targets. + +1999-04-16 Bart Veer <bartv@cygnus.co.uk> + + * src/PKGconf.mak: + * src/dummy.c: + New file that can always be added to libextras.a without + affecting image sizes. + +1999-04-14 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/hal_stub.h: + Make sure all functions have C linkage even in C++ + +1999-04-14 Jesper Skov <jskov@cygnus.co.uk> + PR 19845 + * src/generic-stub.c (__process_packet): Reset _register pointer + to the exception state before attempting to set up single-step + magic. + +1999-04-14 Jesper Skov <jskov@cygnus.co.uk> + + * include/hal_stub.h: Added declaration for __stub_copy_registers. + +1999-04-14 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_stub.c: Use HAL_xCACHE_IS_ENABLED if defined. + +1999-04-09 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_stub.c: + Moved get_register and put_register here. Made them access the + currently selected register set. + +1999-03-22 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/dbg-threads-api.h: Update copyright + + * src/generic-stub.c: Change Cygnus Support->Cygnus Solutions + + * src/thread-packets.c: Update copyright + + * src/thread-pkts.h: Update copyright + +1999-03-19 Nick Garnett <nickg@cygnus.co.uk> + + * tests/cache.c: Added interrupt disable and enable to cache state + change blocks, in line with similar changes to kcache1. + +1999-03-17 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_stub.c (hal_output_gdb_string): Use disable/restore + macros to make sure it works even when interruptible() is a NOP + function. + +1999-03-10 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: + Changed include of hal_tx39_jmr3904.h to hal_tx39.h. + +1999-03-05 Nick Garnett <nickg@cygnus.co.uk> + + * include/drv_api.h: + * src/drv_api.c: + Fixed some typos in non-kernel configuration support. + +1999-03-04 Jesper Skov <jskov@cygnus.co.uk> + PR 19367 + * include/pkgconf/hal.h: Exclude GDB stubs on sparc. + +1999-02-26 Jesper Skov <jskov@cygnus.co.uk> + + * src/generic-stub.c: + * include/generic-stub.h: + Added binary download patches from libstub. + +1999-02-25 Nick Garnett <nickg@cygnus.co.uk> + + * include/drv_api.h: + * src/drv_api.c: + Added these files to define driver API. + +1999-02-23 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: + Added include of <pkgconf/hal_tx39_jmr3904.h> to get TX39 speed + configuration options. + +1999-02-20 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * tests/intr.c: + Rename CYGNUM_VECTOR_RTC -> CYGNUM_HAL_INTERRUPT_RTC in line with + HAL changes + +1999-02-17 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_stub.c: + * src/generic-stub.c (__handle_exception): + Only include cyg_hal_gdb_break magic when stub is configured to + handle GDB BREAK signals. + +1999-02-17 Jesper Skov <jskov@cygnus.co.uk> + + * src/generic-stub.c (__handle_exception): Moved special signal + handling here to avoid duplication for all architectures. + +1999-02-16 Jesper Skov <jskov@cygnus.co.uk> + + * src/stubrom/stubrom.c: Changed set_debug_traps to initialize_stub. + + * include/hal_stub.h: [added] + * include/generic-stub.h: + * src/hal_stub.c: [added] + * src/board.h: [added] + * src/thread-pkts.h: + * src/thread-packets.c: + * src/generic-stub.c: + * src/PKGconf.mak: + Merged in latest libstub changes. Moved most eCos specific changes + into hal_stub.[ch], reducing effort required for further + merging/integration. + +1999-02-05 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Cleaned up the MPC8xx configuration. + +1999-01-29 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Added simple MPC8xx configuration. + +1999-01-26 Hugo Tyson <hmt@cygnus.co.uk> + + * tests/cache.c (time0): Waste much less time if running in a + simulator. Do only 40 loops instead of 4000. + In consequence the nasty meddling with MAX_STRIDE depending on + HAL_xxx_SIM package definitions can go. + +1999-01-22 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Renamed CYG_HAL_POWERPC_FADS to + CYGPKG_HAL_POWERPC_FADS. + +1999-01-21 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/pkgconf/hal.h: + Tidy up and update description + Add new CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG option to allow default + priority static constructors to be deferred + Remove all traces of non-CYG_KERNEL_USE_INIT_PRIORITY code + +1999-01-21 Jesper Skov <jskov@cygnus.co.uk> + Merge with FADS branch. + + 1998-12-17 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Don't allow GDB BREAK support on FADS. + Define _MPC860, not _MP860. + + 1998-12-17 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: + Added FADS entry from Kevin Hester <KHester@opticworks.com>. + + 1999-01-19 Hugo Tyson <hmt@cygnus.co.uk> + + * include/pkgconf/hal.h: + Add CYG_KERNEL_USE_INIT_PRIORITY for SPARCLITE. + +1999-01-18 Jesper Skov <jskov@cygnus.co.uk> + PR 18823 + * include/pkgconf/hal.h: Don't allow GDB stubs to be configured + for Linux target. + +1999-01-18 Jesper Skov <jskov@cygnus.co.uk> + PR 18822 + * include/pkgconf/hal.h: GDB_BREAK support not available for ARM + targets. + +1999-01-14 Gary Thomas <gthomas@cygnus.co.uk> + + * src/stubrom/PKGconf.mak: Rename 'TESTS' to 'PROGS' due to + changes in 'makrules.prv'. + +1999-01-14 Jesper Skov <jskov@cygnus.co.uk> + + * src/stubrom/stubrom.c (cyg_start): Fix compiler warning. + + * include/dbg-threads-api.h: Include cyg_type.h to get externC + definition. + +1999-01-14 Nick Garnett <nickg@cygnus.co.uk> + + * include/dbg-threads-api.h: Added prototype for dbg_scheduler(). + +1999-01-13 Gary Thomas <gthomas@cygnus.co.uk> + + * src/generic-stub.c (__output_hex_value): Change buffer size + [2048 was rather large] and make stack based. Also don't + allow for string to exceed buffer. + +1999-01-13 Jesper Skov <jskov@cygnus.co.uk> + + * src/generic-stub.c (strcpy): Terminate copied string. + +1999-01-11 Jesper Skov <jskov@cygnus.co.uk> + + * tests/intr.c (CYGNUM_KERNEL_COUNTERS_RTC_PERIOD): Added RTC data + for Linux. + +Wed Dec 9 14:07:30 GMT 1998 Chris Provenzano <proven@cygnus.com> + + * include/pkgconf/hal.h: Compile the i386 linux target with + CYG_KERNEL_USE_INIT_PRIORITY defined. + +1999-01-04 Jesper Skov <jskov@cygnus.co.uk> + + * src/generic-stub.c (interruptible): Cleaned up a bit. + +1999-01-04 Jesper Skov <jskov@cygnus.co.uk> + PR 18572 + + * tests/cache.c: Purge data cache before invalidating it. + +1998-12-09 Gary Thomas <gthomas@cygnus.co.uk> + + * src/generic-stub.c: Better handling of errors while stubs + are accessing memory on behalf of GDB. Requires support for + GCC 'computed goto label' in top-level exception handler. + +1998-12-09 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Removed the + CYGARC_HAL_COMMON_EXPORT_CPU_MACROS option. Causing failures in + permutation tests. + +1998-12-07 Jesper Skov <jskov@cygnus.co.uk> + + * src/generic-stub.c (process_exception): Send an acknowledge char + on first entry so GDB doesn't timeout before resending its initial + packet. + +1998-11-26 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Added + CYGARC_HAL_COMMON_EXPORT_CPU_MACROS. + +1998-11-23 Jesper Skov <jskov@cygnus.co.uk> + + * tests/cache.c: Only run with stride 1 on SIMs. + +1998-11-23 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Define SIM as a 603 CPU. + +1998-11-19 Jesper Skov <jskov@cygnus.co.uk> + + * tests/intr.c: + Make the test do nothing if kernel real-time clock is enabled. + Added different timer constants for PPC SIM and HW. + +1998-11-17 Jesper Skov <jskov@cygnus.co.uk> + + * tests/intr.c: + * include/pkgconf/hal.h: + Renamed CYG_HAL_POWERPC_MP860 to CYG_HAL_POWERPC_MPC860. + +1998-11-04 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Made CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT a + sub-option of CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS. + +1998-11-16 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Allow GDB stubs to be configured for + MN10300 HW. Allow GDB_BREAK for all but tx39. + +1998-11-04 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Made CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT a + sub-option of CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS. + +1998-11-04 Jesper Skov <jskov@cygnus.co.uk> + + * src/generic-stub.c (process_packet): Flush D cache before + invalidating I cache. + +1998-11-02 Jesper Skov <jskov@cygnus.co.uk> + + * src/generic-stub.c (__handle_exception): Check for breakpoints + set by GDB interrupt handler. + +1998-10-25 Jesper Skov <jskov@cygnus.co.uk> + + * src/thread-packets.c: Fixed closing #endif comment. + + * src/generic-stub.c: Fixed closing #endif comment. + +1998-10-23 Jesper Skov <jskov@cygnus.co.uk> + + * src/hal_common.c: Removed. We can't use weak default functions + when they may conflict with strong functions in the library. + +1998-10-23 Jesper Skov <jskov@cygnus.co.uk> + + * include/generic-stub.h: Added __interruptible_control. + +1998-10-23 Jesper Skov <jskov@cygnus.co.uk> + PR 17460, PR 17913 + + * include/pkgconf/hal.h: Let HAL exception support require Kernel + exception support. + +1998-10-21 Jesper Skov <jskov@cygnus.co.uk> + PR 17842 + + * include/pkgconf/hal.h: Let HAL GDB thread support require Kernel + GDB thread support. + +1998-10-20 Jesper Skov <jskov@lassi.cygnus.co.uk> + PR 17460 + + * src/hal_common.c: Added. Includes a weak handle_exception + definition. + +1998-10-20 Jesper Skov <jskov@cygnus.co.uk> + PR 17885, 17880, 17841 + + * include/pkgconf/hal.h: Don't allow GDB stubs to be configured + for SIMs or MN10300. + +1998-10-19 Jesper Skov <jskov@lassi.cygnus.co.uk> + + * src/thread-packets.c: Sync'd with libstub source. + +1998-10-16 Bart Veer <bartv@cygnus.co.uk> + + * include/pkgconf/hal.h (CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE): + Added new configuration option for interrupt stack size. + +Thu Oct 15 21:25:55 1998 Jonathan Larmour <jlarmour@cygnus.co.uk> + + * include/pkgconf/hal.h: + Make CYGFUN_HAL_COMMON_KERNEL_SUPPORT require the kernel, as it + is enabling this is eCos-kernel specific, and relies on + configuration options defined only in the kernel + Required for PR 17229 + +1998-10-15 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h (CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT): + Added config option. + +1998-10-14 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: + Move some configury from kernel.h to here. Particularly the + support for GDB stubs. + + * tests/cache.c: + * tests/context.c: + * tests/intr.c: + * tests/PKGconf.mak: + New directory of HAL-only test programs. Currently contains some + very basic test programs. + + * include/generic-stub.h: + * include/dbg-threads-api.h: + * src/generic-stub.c: + * src/thread-packets.c: + * src/thread-pkts.h: + * src/stubrom/PKGconf.mak: + * src/stubrom/stubrom.c: + Moved these files here from kernel. + +1998-10-08 Gary Thomas <gthomas@penang.cygnus.co.uk> + + * include/pkgconf/hal.h: + Add support for new architecture. + +1998-09-23 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: + Switched TX39 over to using CYGMON from GDB stubs. + +Tue Sep 15 19:13:04 1998 David Moore <dsm@keema.cygnus.co.uk> + + * include/pkgconf/hal.h: Cleaned up comments. + +Mon Sep 14 11:08:26 1998 Jesper Skov <jskov@lassi.cygnus.co.uk> + PR 17230 + + * include/pkgconf/hal.h: Added IMP_HAL_COMMON_INTERRUPTS_CHAIN + option. + +1998-09-14 Bart Veer <bartv@cygnus.co.uk> + + * include/pkgconf/hal.h: + Fixed typo in description. + +1998-09-12 Bart Veer <bartv@cygnus.co.uk> + + * include/pkgconf/hal.h: + Sort out exception handling options (PR 16953) + Added missing descriptions (PR 17184) + +Tue Sep 8 17:16:39 1998 Hugo Tyson <hmt@cygnus.co.uk> + + * include/pkgconf/hal.h: + Elide some spurious redefines of CYG_HAL_MN10300_STDEVAL1 and + CYG_HAL_MN10300_SIM within ifdefs conditioned on same. + +1998-09-03 Bart Veer <bartv@cygnus.co.uk> + + * include/pkgconf/hal.h: + CYGPKG_HAL_COMMON is now a component, not a package. + +1998-09-02 Bart Veer <bartv@cygnus.co.uk> + + * include/pkgconf/hal.h: + Moved target and platform specific configuration data to + the appropriate packages. + + Symbols identifying the target hardware should be just defined, + not given a value, as per the coding standards. + +Mon Aug 31 09:16:08 1998 Jesper Skov <jskov@cygnus.co.uk> + + * include/pkgconf/hal.h: Added INIT_PRIORITY default setting for + powerpc. + +1998-08-28 Bart Veer <bartv@cygnus.co.uk> + + * include/pkgconf/hal.h: + Added configuration data. + +1998-08-20 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: + Moved definition of CYG_KERNEL_USE_INIT_PRIORITY here from + kernel.h. + +1998-08-18 Nick Garnett <nickg@cygnus.co.uk> + + * include/pkgconf/hal.h: + Created this file to contain HAL config options. + +//=========================================================================== +// ####GPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2010, 2011 Free Software Foundation, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 or (at your option) any +// later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., 51 Franklin Street, +// Fifth Floor, Boston, MA 02110-1301, USA. +// ------------------------------------------- +// ####GPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/ecos/packages/hal/common/current/cdl/common.cdl b/ecos/packages/hal/common/current/cdl/common.cdl new file mode 100644 index 0000000..245f731 --- /dev/null +++ b/ecos/packages/hal/common/current/cdl/common.cdl @@ -0,0 +1,194 @@ +# ==================================================================== +# +# common.cdl +# +# HAL common configuration data +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later +## version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License +## along with eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: nickg,jskov,jlarmour +# Contributors: +# Date: 1999-07-02 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGFUN_HAL_COMMON_KERNEL_SUPPORT { + display "Provide eCos kernel support" + requires CYGPKG_KERNEL + default_value CYGPKG_KERNEL + description " + The HAL can be configured to either support the full eCos + kernel, or to support only very simple applications which do + not require a full kernel. If kernel support is not required + then some of the startup, exception, and interrupt handling + code can be eliminated." +} + +# NOTE: The requirement for kernel exception support is bogus in that +# the user can supply a deliver_exception function herself. In that +# case, however, it is easy to force the kernel option off while leaving +# this one on. Having the requirement prevents accidental invalid +# configurations of the kernel. +cdl_option CYGPKG_HAL_EXCEPTIONS { + display "HAL exception support" + requires CYGPKG_KERNEL_EXCEPTIONS + default_value CYGPKG_KERNEL_EXCEPTIONS + description " + When a processor exception occurs, for example an attempt to + execute an illegal instruction or to perform a divide by + zero, this exception may be handled in a number of different + ways. If the target system has gdb support then typically + the exception will be handled by gdb code. Otherwise if the + HAL exception support is enabled then the HAL will invoke a + routine deliver_exception(). Typically this routine will be + provided by the eCos kernel, but it is possible for + application code to provide its own implementation. If the + HAL exception support is not enabled and a processor + exception occurs then the behaviour of the system is + undefined." +} + +cdl_option CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG { + display "Stop calling constructors early" + requires CYGSEM_LIBC_INVOKE_DEFAULT_STATIC_CONSTRUCTORS + default_value 0 + description " + This option supports environments where some constructors + must be run in the context of a thread rather than at + simple system startup time. A boolean flag named + cyg_hal_stop_constructors is set to 1 when constructors + should no longer be invoked. It is up to some other + package to deal with the rest of the constructors. + In the current version this is only possible with the + C library." +} + +cdl_interface CYGINT_HAL_SUPPORTS_MMU_TABLES { + display "HAL uses the MMU and allows for CDL manipulation of it's use" +} + +cdl_option CYGSEM_HAL_INSTALL_MMU_TABLES { + display "Install MMU tables." + default_value { CYG_HAL_STARTUP != "RAM" } + active_if CYGINT_HAL_SUPPORTS_MMU_TABLES + description "This option controls whether this application installs + its own Memory Management Unit (MMU) tables, or relies on the + existing environment to run." +} + +cdl_option CYGSEM_HAL_STATIC_MMU_TABLES { + display "Use static MMU tables." + default_value 0 + requires CYGSEM_HAL_INSTALL_MMU_TABLES + description "This option defines an environment where any Memory + Management Unit (MMU) tables are constant. Normally used by ROM + based environments, this provides a way to save RAM usage which + would otherwise be required for these tables." +} + +cdl_component CYGDBG_HAL_DIAG_TO_DEBUG_CHAN { + display "Route diagnostic output to debug channel" + default_value { (CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS \ + || CYG_HAL_STARTUP == "RAM") ? 1 : 0} + active_if !CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE + active_if { CYGPKG_HAL_ARM || CYGPKG_HAL_POWERPC_MPC8xx \ + || CYGPKG_HAL_V85X_V850 || CYGSEM_HAL_VIRTUAL_VECTOR_DIAG } + description " + If not inheriting the console setup from the ROM monitor, + it is possible to redirect diagnostic output to the debug + channel by enabling this option. Depending on the debugger + used it may also be necessary to select a mangler for the + output to be displayed by the debugger." + + cdl_option CYGSEM_HAL_DIAG_MANGLER { + display "Mangler used on diag output" + flavor data + legal_values {"GDB" "None"} + default_value { "GDB" } + description " + It is sometimes necessary to mangle (encode) the + diag ASCII text output in order for it to show up at the + other end. In particular, GDB may silently ignore raw + ASCII text." + } +} + +cdl_component CYGBLD_HAL_LINKER_GROUPED_LIBS { + display "Grouped libraries for linking" + flavor data + default_value CYGBLD_HAL_LINKER_GROUPED_LIBS_DEFAULT + requires { is_substr(CYGBLD_HAL_LINKER_GROUPED_LIBS, "libtarget.a") } + description " + This option provides a list of libraries used to satisfy + linker dependencies, but necessary for building eCos. It is passed + to a GROUP() directive in the linker script, which is analogous + to using the \"-(\" aka \"--start-group\", and \"-)\" aka + \"--end-group\" options on the linker command line. + + It provides a similar function to adding \"-llibname\" to the + linker, but with the added feature that each library in the group + is scanned in turn for unresolved symbols, and this process is + repeated until there are no more unresolved symbols. This is important + for system libraries as there are often mutual dependencies. + + This option should not be used for adding application specific + libraries. That should be done in the application's own makefile + or link line. + + Users wishing to use the GNU Compiler prior to GCC 3.0 will + need to remove libsupc++.a from this option. + + Note that libtarget.a is always required to build eCos." + + cdl_option CYGBLD_HAL_LINKER_GROUPED_LIBS_DEFAULT { + display "Default setting" + flavor data + default_value { "libtarget.a libgcc.a libsupc++.a" } + description " + This option is intended to be used by other eCos packages (including + HAL packages) to provide a different default value for + CYGBLD_HAL_LINKER_GROUPED_LIBS. + + This is separated into its own option to continue to + allow the user to make customisations to the grouped library + list." + } +} + +# EOF common.cdl diff --git a/ecos/packages/hal/common/current/cdl/debugging.cdl b/ecos/packages/hal/common/current/cdl/debugging.cdl new file mode 100644 index 0000000..d5fa559 --- /dev/null +++ b/ecos/packages/hal/common/current/cdl/debugging.cdl @@ -0,0 +1,169 @@ +# ==================================================================== +# +# debugging.cdl +# +# HAL debugging configuration data +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2011 Free Software Foundation, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later +## version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License +## along with eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: nickg,jskov,jlarmour +# Contributors: jld +# Date: 1999-07-02 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_interface CYGINT_HAL_DEBUG_GDB_STUBS { + display "Support for GDB stubs" + no_define + description " + The HAL implements GDB stubs for the target." +} + +cdl_option CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS { + display "Include GDB stubs in HAL" + active_if CYGINT_HAL_DEBUG_GDB_STUBS + default_value 0 + requires ! CYGSEM_HAL_USE_ROM_MONITOR + requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT + requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM + requires { !CYGSEM_HAL_VIRTUAL_VECTOR_DIAG \ + || CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS } + description " + This option causes a set of GDB stubs to be included into the + system. On some target systems the GDB support will be + provided by other means, for example by a ROM monitor. On + other targets, especially when building a ROM-booting system, + the necessary support has to go into the target library + itself. When GDB stubs are include in a configuration, HAL + serial drivers must also be included." + + compile generic-stub.c thread-packets.c hal_stub.c drv_api.c bplist-dynamic.c +} + +cdl_interface CYGINT_HAL_DEBUG_GDB_STUBS_BREAK { + display "Support for external break support in GDB stubs" + no_define + description " + The HAL implements external break (or asynchronous interrupt) + in the GDB stubs for the target." +} + +cdl_option CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT { + display "Include GDB external break support for stubs" + active_if CYGINT_HAL_DEBUG_GDB_STUBS_BREAK + requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + default_value CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + implements CYGINT_HAL_COMMON_SAVED_INTERRUPT_STATE_REQUIRED + description " + This option causes the GDB stub to add a serial interrupt handler + which will listen for GDB break packets. This lets you stop the + target asynchronously when using GDB, usually by hitting Control+C + or pressing the STOP button. This option differs from + CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT in that it is used when + GDB stubs are present." +} + +cdl_interface CYGINT_HAL_DEBUG_GDB_CTRLC_UNSUPPORTED { + display "Platform does not support CTRLC" + no_define +} + +cdl_option CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT { + display "Include GDB external break support when no stubs" + requires !CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + active_if { CYGSEM_HAL_USE_ROM_MONITOR || CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS } + active_if { CYGINT_HAL_DEBUG_GDB_CTRLC_UNSUPPORTED == 0 } + default_value { !CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS } + implements CYGINT_HAL_COMMON_SAVED_INTERRUPT_STATE_REQUIRED + description " + This option adds an interrupt handler for the GDB serial line + which will listen for GDB break packets. This lets you stop the + target asynchronously when using GDB, usually by hitting Control+C + or pressing the STOP button. This option differs from + CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT in that it is used when the GDB + stubs are NOT present." +} + +cdl_option CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT { + display "Include GDB multi-threading debug support" + active_if { CYGSEM_HAL_ROM_MONITOR || CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT } + default_value 1 + description " + This option enables some extra HAL code which is needed + to support multi-threaded source level debugging." + + compile dbg-threads-syscall.c +} + +cdl_option CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES { + display "Number of times to retry sending a \$O packet" + default_value 0 + flavor data + description " + This option controls the number of attempts that eCos programs + will make to send a \$O packet to a host GDB process. If it is + set non-zero, then the target process will attempt to resend the + \$O packet data up to this number of retries. Caution: use of + this option is not recommended as it can thoroughly confuse the + host GDB process." +} + +cdl_option CYGNUM_HAL_DEBUG_GDB_PROTOCOL_TIMEOUT { + display "Timeout period for GDB packets" + default_value 500 + flavor data + description " + This option controls the time (in milliseconds) that eCos programs + will wait for a response when sending packets to a host GDB process. + If this time elapses, then the packet will be resent, up to some + maximum number of times (CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES)." +} + +cdl_option CYGDBG_HAL_CRCTABLE_LOCATION { + display "Location of CRC32 table" + flavor data + legal_values {"ROM" "RAM"} + default_value {"RAM"} + description " + The stubs use a 1 kilobyte CRC table that can either be pregenerated + and placed in ROM, or generated at runtime in RAM. Depending on + your memory constraints, one of these options may be better." +} + +# EOF debugging.cdl diff --git a/ecos/packages/hal/common/current/cdl/hal.cdl b/ecos/packages/hal/common/current/cdl/hal.cdl new file mode 100644 index 0000000..3bc2d8f --- /dev/null +++ b/ecos/packages/hal/common/current/cdl/hal.cdl @@ -0,0 +1,481 @@ +# ==================================================================== +# +# hal.cdl +# +# HAL configuration data +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2010, 2011 Free Software Foundation, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later +## version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License +## along with eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Original data: nickg,jskov,jlarmour +# Contributors: dmoseley, jld +# Date: 1999-06-13 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL { + display "eCos HAL" + include_dir cyg/hal + description " + The eCos HAL package provide a porting layer for + higher-level parts of the system such as the kernel and the + C library. Each installation should have HAL packages for + one or more architectures, and for each architecture there + may be one or more supported platforms. It is necessary to + select one target architecture and one platform for that + architecture. There are also a number of configuration + options that are common to all HAL packages." + doc ref/the-ecos-hardware-abstraction-layer.html + + compile drv_api.c + compile -library=libextras.a dummy.c + + requires CYGPKG_INFRA + + make -priority 250 { + <PREFIX>/lib/extras.o: <PREFIX>/lib/libextras.a + $(CC) $(CFLAGS) -fno-profile-arcs -nostdlib -Wl,-r -T /dev/null -Wl,--whole-archive -o $@ $< + } + + cdl_option CYGBLD_GLOBAL_WARNFLAGS { + display "Standard compiler warning flags" + parent CYGBLD_GLOBAL_OPTIONS + flavor data + no_define + calculated { "-Wall -Wpointer-arith -Wstrict-prototypes -Wundef -Woverloaded-virtual -Wno-write-strings " } + description " + This option specifies the default warning-related compiler flags used + on all eCos platforms." + } + + cdl_component CYGPKG_HAL_COMMON { + display "Platform-independent HAL options" + flavor none + description " + A number of configuration options are common to most or all + HAL packages, for example options controlling how much state + should be saved during a context switch. The implementations + of these options will vary from architecture to architecture." + + script common.cdl + } + + cdl_component CYGPKG_HAL_COMMON_INTERRUPTS { + display "HAL interrupt handling" + flavor none + description " + A number of configuration options related to interrupt + handling are common to most or all HAL packages, even though + the implementations will vary from architecture to + architecture." + + script interrupts.cdl + } + + cdl_component CYGPKG_HAL_COMMON_CONTEXT { + display "HAL context switch support" + flavor none + description " + A number of configuration options related to thread contexts + are common to most or all HAL packages, even though the + implementations will vary from architecture to architecture." + + cdl_option CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM { + display "Use minimum thread context" + parent CYGPKG_HAL_COMMON_CONTEXT + default_value 1 + description " + The thread context switch code can exploit the calling + conventions defined for a given architecture to reduce the + amount of state that has to be saved during a context + switch. Generally this improves performance and reduces + code size. However it can make source-level debugging more + difficult." + } + } + + cdl_component CYGPKG_HAL_CACHE_CONTROL { + display "Explicit control over cache behaviour" + flavor none + no_define + description " + These options let the default behaviour of the caches + be easily configurable." + + cdl_component CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP { + display "Enable DATA cache on startup" + default_value 1 + description " + Enabling this option will cause the data cache to be enabled + as soon as practicable when eCos starts up. One would choose + to disable this if the data cache cannot safely be turned on, + such as a case where the cache(s) require additional platform + specific setup." + cdl_option CYGSEM_HAL_DCACHE_STARTUP_MODE { + display "DATA cache mode on startup" + flavor data + legal_values { "COPYBACK" "WRITETHRU" } + default_value { "COPYBACK" } + description " + This option controls the mode the cache will be set to + when enabled on startup." + } + } + + cdl_option CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP { + display "Enable INSTRUCTION cache on startup" + default_value 1 + description " + Enabling this option will cause the instruction cache to be enabled + as soon as practicable when eCos starts up. One would choose + to disable this if the instruction cache cannot safely be turned on, + such as a case where the cache(s) require additional platform + specific setup." + } + } + + cdl_component CYGPKG_HAL_DEBUG { + display "Source-level debugging support" + flavor none + description " + If the source level debugger gdb is to be used for debugging + application code then it may be necessary to configure in support + for this in the HAL." + + script debugging.cdl + } + + cdl_component CYGPKG_HAL_ROM_MONITOR { + display "ROM monitor support" + flavor none + no_define + description " + Support for ROM monitors can be built in to your application. + It may also be relevant to build your application as a ROM monitor + itself. Such options are contained here if relevant for your chosen + platform. The options and ROM monitors available to choose are + platform-dependent." + + + + cdl_interface CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT { + display "Target has virtual vector support" + no_define + } + + + cdl_interface CYGINT_HAL_VIRTUAL_VECTOR_COMM_BAUD_SUPPORT { + display "Target supports baud rate control via vectors" + no_define + description " + Whether this target supports the __COMMCTL_GETBAUD + and __COMMCTL_SETBAUD virtual vector comm control operations." + } + + cdl_component CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT { + display "Enable use of virtual vector calling interface" + active_if CYGINT_HAL_VIRTUAL_VECTOR_SUPPORT + calculated 1 + description " + Virtual vector support allows the HAL to let the ROM + monitor handle certain operations. The virtual vector table + defines a calling interface between applications running in + RAM and the ROM monitor." + compile hal_if.c hal_misc.c + + + cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE { + display "Inherit console settings from ROM monitor" + active_if CYGSEM_HAL_USE_ROM_MONITOR + default_value { !CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS } + description " + When this option is set, the application will inherit + the console as set up by the ROM monitor. This means + that the application will use whatever channel and + mangling style was used by the ROM monitor when + the application was launched." + } + + cdl_option CYGPRI_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_CONFIGURABLE { + display "Debug channel is configurable" + calculated { CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS } + description " + This option is a configuration hint - it is enabled + when the HAL initialization code will make use + of the debug channel configuration option." + } + + cdl_option CYGPRI_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_CONFIGURABLE { + display "Console channel is configurable" + calculated { !CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE \ + && !CYGDBG_HAL_DIAG_TO_DEBUG_CHAN } + description " + This option is a configuration hint - it is enabled + when the HAL initialization code will make use + of the console channel configuration option." + } + + + cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE { + display "Initialize whole of virtual vector table" + default_value { CYG_HAL_STARTUP != "RAM" || !CYGSEM_HAL_USE_ROM_MONITOR } + requires CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET + requires CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US + requires CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DATA + requires CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS + description " + This option will cause the whole of the virtual + vector table to be initialized with dummy values on + startup. When this option is enabled, all the + options below must also be enabled - or the + table would be empty when the application + launches. + + On targets where older ROM monitors without + virtual vector support may still be in use, it is + necessary for RAM applictions to initialize the + table (since all HAL diagnostics and debug IO + happens via the table)." + } + + cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DEFAULT { + display "Claim virtual vector table entries by default" + active_if !CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE + default_value 1 + description " + By default most virtual vectors will be claimed by + RAM startup configurations, meaning that the RAM + application will provide the services. The + exception is COMMS support (HAL + diagnostics/debugging IO) which is left in the + control of the ROM monitor. + + The reasoning behind this is to get as much of the + code exercised during regular development so it + is known to be working the few times a new ROM + monitor or a ROM production configuration is used + - COMMS are excluded only by necessity in order to + avoid breaking an existing debugger connections + (there may be ways around this). + + For production RAM configurations this option can + be switched off, causing the appliction to rely on + the ROM monitor for these services, thus + saving some space. + + Individual vectors may also be left unclaimed, + controlled by the below options (meaning that the + associated service provided by the ROM monitor + will be used)." + } + + cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET { + display "Claim reset virtual vectors" + default_value { CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE \ + || CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DEFAULT } + description " + This option will cause the reset and kill_by_reset + virtual vectors to be claimed." + } + + cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_VERSION { + display "Claim version virtual vectors" + default_value { CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE } + description " + This option will cause the version + virtual vectors to be claimed." + } + + cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US { + display "Claim delay_us virtual vector" + default_value { CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE \ + || CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DEFAULT } + description " + This option will cause the delay_us + virtual vector to be claimed." + } + + cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DATA { + display "Claim data virtual vectors" + default_value { CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE \ + || CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DEFAULT } + description " + This option will cause the data virtual vectors + to be claimed. At present there is only one, used + by the RedBoot ethernet driver to share diag output." + } + + cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS { + display "Claim comms virtual vectors" + default_value { CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE \ + || CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS } + description " + This option will cause the communication tables + that are part of the virtual vectors mechanism to + be claimed. Note that doing this may cause an + existing ROM monitor communication connection to + be closed. For this reason, the option is disabled + per default for normal application + configurations." + } + + cdl_option CYGSEM_HAL_VIRTUAL_VECTOR_DIAG { + display "Do diagnostic IO via virtual vector table" + calculated 1 + description " + All HAL IO happens via the virtual vector table / comm + tables when those tables are supported by the HAL. + + If so desired, the low-level IO functions can + still be provided by the RAM application by + enabling the CLAIM_COMMS option." + } + } + + cdl_option CYGBLD_BUILD_COMMON_GDB_STUBS { + display "Build common GDB stub ROM image" + default_value 0 + parent CYGBLD_GLOBAL_OPTIONS + requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + no_define + description " + Unless a target board has specific requirements to the + stub implementation, it can use a simple common stub. + This option, which gets enabled by platform HALs as + appropriate, controls the building of the common stub." + + make -priority 315 { + <PREFIX>/bin/gdb_module.img : <PACKAGE>/src/stubrom/stubrom.c <PREFIX>/lib/extras.o <PREFIX>/lib/libtarget.a <PREFIX>/lib/target.ld <PREFIX>/lib/vectors.o + @sh -c "mkdir -p src/stubrom $(dir $@)" + $(CC) -c $(INCLUDE_PATH) -Wp,-MD,deps.tmp -I$(dir $<) $(CFLAGS) -o src/stubrom/gdb_module.o $< + @echo $@ ": \\" > $(notdir $@).deps + @echo $(wildcard $(PREFIX)/lib/*) " \\" >> $(notdir $@).deps + @tail -n +2 deps.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm deps.tmp + $(CC) $(LDFLAGS) -L$(PREFIX)/lib -Ttarget.ld -o $@ src/stubrom/gdb_module.o + } + } + + + } + + # Does platform need special I/O initializations? + cdl_interface CYGINT_HAL_PLF_IF_INIT { + display "Platform defined I/O channels" + description " + Platforms which provide additional I/O channels can implement + this interface, indicating that the function plf_if_init() + needs to be called." + } + + # Does platform provide IDE I/O macros? + cdl_interface CYGINT_HAL_PLF_IF_IDE { + display "Platform IDE I/O support" + description " + Platforms which provide IDE controllers can implement + this interface, indicating that IDE I/O macros are + available." + } + + # Does anything require access to saved interrupt state? + cdl_interface CYGINT_HAL_COMMON_SAVED_INTERRUPT_STATE_REQUIRED { + display "Saved interrupt state required" + description " + Components requiring access to saved interrupt state via the + hal_saved_interrupt_state symbol should implement this + interface." + } + + cdl_option CYGPKG_HAL_GDB_FILEIO { + display "File I/O operations via GDB" + default_value 0 + active_if CYGSEM_REDBOOT_BSP_SYSCALLS + requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + compile gdb-fileio.c + description "This option enables support for various file I/O + operations using the GDB remote protocol to communicate + with GDB. The operations are then performed on the + debugging host by proxy. These operations are only + currently available by using a system call interface + to RedBoot. This may change in the future." + } + + define_proc { + puts $::cdl_header "/***** proc output start *****/" + puts $::cdl_header "#include <pkgconf/system.h>" + + puts $::cdl_header "#include CYGBLD_HAL_TARGET_H" + puts $::cdl_header "#ifdef CYGBLD_HAL_VARIANT_H" + puts $::cdl_header "#include CYGBLD_HAL_VARIANT_H" + puts $::cdl_header "#endif" + puts $::cdl_header "#include CYGBLD_HAL_PLATFORM_H" + + puts $::cdl_header "/****** proc output end ******/" + + } + + cdl_option CYGPKG_HAL_BUILD_COMPILER_TESTS { + display "Build Compiler sanity checking tests" + description " + Enabling this option causes compiler tests to be built." + } + + cdl_component CYGPKG_HAL_TESTS { + display "Common HAL tests" + flavor data + no_define + calculated { "tests/context tests/basic" + . ((!CYGINT_HAL_TESTS_NO_CACHES) ? " tests/cache" : "") + . ((CYGPKG_HAL_BUILD_COMPILER_TESTS) ? " tests/cpp1 tests/vaargs" : "") + . ((!CYGVAR_KERNEL_COUNTERS_CLOCK) ? " tests/intr" : "") } + description " + This option specifies the set of tests for the common HAL." + + + cdl_interface CYGINT_HAL_TESTS_NO_CACHES { + display "Interface for cache presence" + flavor booldata + description " + Some architectures and/or platforms do not have caches. By + implementing this interface, these can disable the various + cache-related tests." + } + + } +} diff --git a/ecos/packages/hal/common/current/cdl/interrupts.cdl b/ecos/packages/hal/common/current/cdl/interrupts.cdl new file mode 100644 index 0000000..e9bd1df --- /dev/null +++ b/ecos/packages/hal/common/current/cdl/interrupts.cdl @@ -0,0 +1,142 @@ +# ==================================================================== +# +# interrupts.cdl +# +# HAL interrupt configuration data +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later +## version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT +## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License +## along with eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: nickg,jskov,jlarmour +# Contributors: +# Date: 1999-07-02 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_option CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK { + display "Use separate stack for interrupts" + default_value 1 + description " + When an interrupt occurs this interrupt can be handled either + on the current stack or on a separate stack maintained by the + HAL. Using a separate stack requires a small number of extra + instructions in the interrupt handling code, but it has the + advantage that it is no longer necessary to allow extra space + in every thread stack for the interrupt handlers. The amount + of extra space required depends on the interrupt handlers + that are being used." +} + +# NOTE: various parts of the system such as device drivers should +# impose lower bounds on this. The actual lower bound depends on a +# platform-specific value for startup overheads, and the minimum +# sizes specified by the various device drivers. If interrupts are +# not handled on a separate stack then only the startup overheads +# are significant. If nested interrupts are disabled then the +# lower bound is the maximum of the individual sizes, otherwise +# it is the sum of these sizes. It is not currently possible to +# express a relationship like this. +cdl_option CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE { + display "Interrupt stack size" + flavor data + default_value { CYGPKG_KERNEL ? 4096 : 32768 } + legal_values 128 to 1048576 + description " + This configuration option specifies the stack size in bytes + for the interrupt stack. Typically this should be a multiple + of 16, but the exact requirements will vary from architecture + to architecture. The interrupt stack serves two separate + purposes. It is used as the stack during system + initialization. In addition, if the interrupt system is + configured to use a separate stack then all interrupts will + be processed on this stack. The exact memory requirements + will vary from application to application, and will depend + heavily on whether or not other interrupt-related options, + for example nested interrupts, are enabled. On most targets, + in a configuration with no kernel this stack will also be + the stack used to invoke the application, and must obviously + be appropriately large in that case." +} + +cdl_option CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING { + display "Allow nested interrupts" + default_value 0 + description " + When an interrupt occurs the HAL interrupt handling code can + either leave interrupts disabled for the duration of the + interrupt handling code, or by doing some extra work it can + reenable interrupts before invoking the interrupt handler and + thus allow nested interrupts to happen. If all the interrupt + handlers being used are small and do not involve any loops + then it is usually better to disallow nested interrupts. + However if any of the interrupt handlers are more complicated + than nested interrupts will usually be required." +} + +cdl_option CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT { + display "Save minimum context on interrupt" + default_value 1 + description " + The HAL interrupt handling code can exploit the calling conventions + defined for a given architecture to reduce the amount of state + that has to be saved. Generally this improves performance and + reduces code size. However it can make source-level debugging + more difficult." +} + +cdl_option CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN { + display "Chain all interrupts together" + default_value 0 + description " + Interrupts can be attached to vectors either singly, or be + chained together. The latter is necessary if there is no way + of discovering which device has interrupted without + inspecting the device itself. It can also reduce the amount + of RAM needed for interrupt decoding tables and code." +} + +cdl_option CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS { + display "Ignore spurious \[fleeting\] interrupts" + default_value 0 + description " + On some hardware, interrupt sources may not be de-bounced or + de-glitched. Rather than try to handle these interrupts (no + handling may be possible), this option allows the HAL to simply + ignore them. In most cases, if the interrupt is real it will + reoccur in a detectable form." +} diff --git a/ecos/packages/hal/common/current/doc/hal.sgml b/ecos/packages/hal/common/current/doc/hal.sgml new file mode 100644 index 0000000..f5caf8e --- /dev/null +++ b/ecos/packages/hal/common/current/doc/hal.sgml @@ -0,0 +1,3159 @@ +<!-- {{{ Banner --> + +<!-- =============================================================== --> +<!-- --> +<!-- HAL.sgml --> +<!-- --> +<!-- eCos common HAL documentation --> +<!-- --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTBEGIN#### --> +<!-- =============================================================== --> +<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<part id="the-ecos-hardware-abstraction-layer"> +<title>The eCos Hardware Abstraction Layer (HAL)</title> + +<!-- {{{ Intro --> + +<chapter id=hal-introduction> +<title>Introduction</title> +<PARA> +This is an initial specification of the <EMPHASIS>eCos</EMPHASIS> <!-- +<index></index> -->Hardware Abstraction Layer (HAL). The HAL abstracts +the underlying hardware of a processor architecture and/or the +platform to a level sufficient for the eCos kernel to be ported onto +that platform. +</PARA> + +<note> +<title>Caveat</title> +<PARA> +This document is an informal description of the HAL capabilities and +is not intended to be full documentation, although it may be used as a +source for such. It also describes the HAL as it is currently +implemented for the architectures targeted in this release. It most +closely describes the HALs for the MIPS, I386 and PowerPC HALs. Other +architectures are similar but may not be organized precisely as +described here. +</PARA> +</note> + +</chapter> + +<!-- }}} --> +<!-- {{{ Architecture, Variant and Platform --> + +<CHAPTER id="hal-architecture-variant-and-platform"> +<TITLE>Architecture, Variant and Platform</TITLE> + +<para> +We have identified three levels at which the HAL must operate. +</para> + +<itemizedlist> + <listitem> + <para> + The <!-- <index></index> --><firstterm>architecture + HAL</firstterm> abstracts the basic CPU architecture and includes + things like interrupt delivery, context switching, CPU startup + etc. + </para> + </listitem> + + <listitem> + <para> + The <!-- <index></index> --> <firstterm>variant HAL</firstterm> + encapsulates features of the CPU variant such as caches, MMU and + FPU features. It also deals with any on-chip peripherals such as + memory and interrupt controllers. For architectural variations, + the actual implementation of the variation is often in the + architectural HAL, and the variant HAL simply provides the correct + configuration definitions. + </para> + </listitem> + + <listitem> + <para> + The <!-- <index></index> --><firstterm>platform HAL</firstterm> + abstracts the properties of the current platform and includes + things like platform startup, timer devices, I/O register access + and interrupt controllers. + </para> + </listitem> + +</itemizedlist> + +<para> +The boundaries between these three HAL levels are necessarily blurred +since functionality shifts between levels on a target-by-target basis. +For example caches and MMU may be either an architecture feature or a +variant feature. Similarly, memory and interrupt controllers may be +on-chip and in the variant HAL, or off-chip and in the platform HAL. +</para> +<para> +Generally there is a separate package for each of the architecture, +variant and package HALs for a target. For some of the older targets, +or where it would be essentially empty, the variant HAL is omitted. +</para> +</CHAPTER> + +<!-- }}} --> +<!-- {{{ General Principles --> + +<CHAPTER id="hal-general-principles"> +<TITLE>General principles</TITLE> + +<PARA> +The HAL has been implemented according to the following general +principles: +</PARA> +<ORDEREDLIST> +<LISTITEM> +<PARA> The HAL is implemented in C and assembler, although the + eCos kernel is largely implemented in C++. + This is to permit the HAL the widest possible + applicability.</PARA> +</LISTITEM> +<LISTITEM> +<PARA>All interfaces to the HAL are implemented by + CPP macros. This allows them to be implemented as inline + C code, inline assembler or function calls to external C + or assembler code. This allows the most efficient + implementation to be selected without affecting the + interface. It also allows them to be redefined if the + platform or variant HAL needs to replace or enhance a definition + from the architecture HAL.</PARA> +</LISTITEM> +<LISTITEM> +<PARA>The HAL provides simple, portable mechanisms for dealing +with the hardware of a wide range of architectures and platforms. +It is always possible to bypass the HAL and program the hardware +directly, but this may lead to a loss of portability. </PARA> +</LISTITEM> +</ORDEREDLIST> +</CHAPTER> + +<!-- }}} --> +<!-- {{{ HAL Interfaces --> + +<CHAPTER id="hal-interfaces"> +<TITLE><!-- <index></index> --><!-- <xref> -->HAL Interfaces</TITLE> + +<para> +This section describes the main HAL interfaces. +</para> + +<!-- {{{ Base Definitions --> + +<SECTION id="hal-base-definitions"> +<TITLE>Base Definitions</TITLE> + +<para> +These are definitions that characterize the properties of the base +architecture that are used to compile the portable parts of the +kernel. They are concerned with such things a portable type +definitions, endianness, and labeling. +</para> + +<PARA> +These definitions are supplied by the +<filename>cyg/hal/basetype.h</filename> header file which is supplied +by the architecture HAL. It is included automatically by +<FILENAME>cyg/infra/cyg_type.h</FILENAME>. +</PARA> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Byte order</TITLE> +<VARIABLELIST> + <VARLISTENTRY> + <TERM><VARNAME>CYG_BYTEORDER</VARNAME></TERM> + <LISTITEM> + <PARA> + This defines the byte order of the target and must be set to either + <varname>CYG_LSBFIRST</varname> or <varname>CYG_MSBFIRST</varname>. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Label Translation</TITLE> + +<VARIABLELIST> + <VARLISTENTRY> + <TERM><FUNCTION>CYG_LABEL_NAME(name)</FUNCTION></TERM> + <LISTITEM> + + <PARA> + This is a wrapper used in some C and C++ files which + use labels defined in assembly code or the linker script. + It need only be defined if the default implementation in + <filename>cyg/infra/cyg_type.h</filename>, which passes the name + argument unaltered, is inadequate. It should be paired with + <function>CYG_LABEL_DEFN()</function>. + </PARA> + </LISTITEM> + </VARLISTENTRY> + <VARLISTENTRY> + <TERM><FUNCTION>CYG_LABEL_DEFN(name)</FUNCTION></TERM> + <LISTITEM> + + <PARA> + This is a wrapper used in assembler sources and linker scripts + which define labels. It need only be defined if the default + implementation in + <filename>cyg/infra/cyg_type.h</filename>, which passes the name + argument unaltered, is inadequate. The most usual alternative + definition of this macro prepends an underscore to the label + name. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> +</SECTION> + + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Base types</TITLE> +<PROGRAMLISTING> + cyg_halint8 + cyg_halint16 + cyg_halint32 + cyg_halint64 + cyg_halcount8 + cyg_halcount16 + cyg_halcount32 + cyg_halcount64 + cyg_halbool +</PROGRAMLISTING> +<PARA> +These macros define the C base types that should be used to define +variables of the given size. They only need to be defined if the +default types specified in <filename>cyg/infra/cyg_type.h</filename> +cannot be used. Note that these are only the base types, they will be +composed with <literal>signed</literal> and +<literal>unsigned</literal> to form full type specifications. +</PARA> +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Atomic types</TITLE> +<PROGRAMLISTING> + cyg_halatomic CYG_ATOMIC +</PROGRAMLISTING> +<PARA> +These types are guaranteed to be read or written in a single +uninterruptible operation. It is architecture defined what size this +type is, but it will be at least a byte. +</PARA> +</SECTION> + +</SECTION> + +<!-- }}} --> +<!-- {{{ Architecture Characterization --> + +<SECTION id="hal-architecture-characterization"> +<TITLE>Architecture Characterization</TITLE> + +<para> +These are definition that are related to the basic architecture of the +CPU. These include the CPU context save format, context switching, bit +twiddling, breakpoints, stack sizes and address translation. +</para> + +<PARA> +Most of these definition are found in +<filename>cyg/hal/hal_arch.h</filename>. This file is supplied by the +architecture HAL. If there are variant or platform specific +definitions then these will be found in +<filename>cyg/hal/var_arch.h</filename> or +<filename>cyg/hal/plf_arch.h</filename>. These files are include +automatically by this header, so need not be included explicitly. +</PARA> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Register Save Format</TITLE> +<PROGRAMLISTING> +typedef struct HAL_SavedRegisters +{ + /* architecture-dependent list of registers to be saved */ +} HAL_SavedRegisters; +</PROGRAMLISTING> +<PARA> +This structure describes the layout of a saved machine state on the +stack. Such states are saved during thread context switches, +interrupts and exceptions. Different quantities of state may be saved +during each of these, but usually a thread context state is a subset +of the interrupt state which is itself a subset of an exception state. +For debugging purposes, the same structure is used for all three +purposes, but where these states are significantly different, this +structure may contain a union of the three states. +</PARA> +</SECTION> + + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Thread Context Initialization</TITLE> + +<PROGRAMLISTING> +HAL_THREAD_INIT_CONTEXT( sp, arg, entry, id ) +</PROGRAMLISTING> + +<PARA> +This macro initializes a thread's context so that +it may be switched to by <FUNCTION>HAL_THREAD_SWITCH_CONTEXT()</FUNCTION>. +The arguments are: +</PARA> +<VARIABLELIST> + <VARLISTENTRY> + <TERM>sp</TERM> + <LISTITEM> + <PARA> + A location containing the current value of the thread's stack + pointer. This should be a variable or a structure field. The SP + value will be read out of here and an adjusted value written + back. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>arg</TERM> + <LISTITEM> + <PARA> + A value that is passed as the first argument to the entry + point function. + </PARA> + </LISTITEM> + </VARLISTENTRY> + <VARLISTENTRY> + <TERM>entry</TERM> + <LISTITEM> + <PARA> + The address of an entry point function. This will be called + according the C calling conventions, and the value of + <parameter>arg</parameter> will be passed as the first + argument. This function should have the following type signature + <function>void entry(CYG_ADDRWORD arg)</function>. + </PARA> + </LISTITEM> + </VARLISTENTRY> + <VARLISTENTRY> + <TERM>id</TERM> + <LISTITEM> + <PARA> + A thread id value. This is only used for debugging purposes, + it is ORed into the initialization pattern for unused registers + and may be used to help identify the thread from its register dump. + The least significant 16 bits of this value should be zero to allow + space for a register identifier. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> +</SECTION> + +<!-- =================================================================== --> + +<SECTION id="hal-context-switch"> +<TITLE>Thread Context Switching</TITLE> + +<PROGRAMLISTING> +HAL_THREAD_LOAD_CONTEXT( to ) +HAL_THREAD_SWITCH_CONTEXT( from, to ) +</PROGRAMLISTING> +<PARA> +These macros implement the thread switch code. The arguments are: +</PARA> + +<VARIABLELIST> + <VARLISTENTRY> + <TERM>from</TERM> + <LISTITEM> + <PARA> + A pointer to a location where the stack pointer of the current + thread will be stored. + </PARA> + </LISTITEM> + </VARLISTENTRY> + <VARLISTENTRY> + <TERM>to</TERM> + <LISTITEM> + <PARA> + A pointer to a location from where the stack pointer of the next + thread will be read. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> + +<para> +For <function>HAL_THREAD_LOAD_CONTEXT()</function> the current CPU +state is discarded and the state of the destination thread is +loaded. This is only used once, to load the first thread when the +scheduler is started. +</para> + +<PARA> +For <function>HAL_THREAD_SWITCH_CONTEXT()</function> the state of the +current thread is saved onto its stack, using the current value of the +stack pointer, and the address of the saved state placed in +<parameter>*from</parameter>. The value in +<parameter>*to</parameter> is then read and the state of the new +thread is loaded from it. +</PARA> + +<para> +While these two operations may be implemented with inline assembler, +they are normally implemented as calls to assembly code functions in +the HAL. There are two advantages to doing it this way. First, the +return link of the call provides a convenient PC value to be used in +the saved context. Second, the calling conventions mean that the +compiler will have already saved the caller-saved registers before the +call, so the HAL need only save the callee-saved registers. +</para> + +<para> +The implementation of <function>HAL_THREAD_SWITCH_CONTEXT()</function> +saves the current CPU state on the stack, including the current +interrupt state (or at least the register that contains it). For +debugging purposes it is useful to save the entire register set, but +for performance only the ABI-defined callee-saved registers need be +saved. If it is implemented, the option +<literal>CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM</literal> controls +how many registers are saved. +</para> + +<para> +The implementation of <function>HAL_THREAD_LOAD_CONTEXT()</function> +loads a thread context, destroying the current context. With a little +care this can be implemented by sharing code with +<function>HAL_THREAD_SWITCH_CONTEXT()</function>. To load a thread +context simply requires the saved registers to be restored from the +stack and a jump or return made back to the saved PC. +</para> + +<PARA> +Note that interrupts are not disabled during this process, any +interrupts that occur will be delivered onto the stack to which the +current CPU stack pointer points. Hence the stack pointer +should never be invalid, or loaded with a value that might cause the +saved state to become corrupted by an interrupt. However, the current +interrupt state is saved and restored as part of the thread +context. If a thread disables interrupts and does something to cause a +context switch, interrupts may be re-enabled on switching to another +thread. Interrupts will be disabled again when the original thread +regains control. +</PARA> + +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Bit indexing</TITLE> + +<PROGRAMLISTING> +HAL_LSBIT_INDEX( index, mask ) +HAL_MSBIT_INDEX( index, mask ) +</PROGRAMLISTING> + +<PARA> +These macros place in <parameter>index</parameter> the bit index of +the least significant bit in <parameter>mask</parameter>. Some +architectures have instruction level support for one or other of these +operations. If no architectural support is available, then these +macros may call C functions to do the job. +</PARA> +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Idle thread activity</TITLE> + +<PROGRAMLISTING> +HAL_IDLE_THREAD_ACTION( count ) +</PROGRAMLISTING> + +<PARA> +It may be necessary under some circumstances for the HAL to execute +code in the kernel idle thread's loop. An example might be to execute +a processor halt instruction. This macro provides a portable way of +doing this. The argument is a copy of the idle thread's loop counter, +and may be used to trigger actions at longer intervals than every +loop. +</PARA> +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Reorder barrier</TITLE> + +<PROGRAMLISTING> +HAL_REORDER_BARRIER() +</PROGRAMLISTING> + +<PARA> +When optimizing the compiler can reorder code. In some parts of +multi-threaded systems, where the order of actions is vital, this can +sometimes cause problems. This macro may be inserted into places where +reordering should not happen and prevents code being migrated across +it by the compiler optimizer. It should be placed between statements +that must be executed in the order written in the code. +</PARA> +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Breakpoint support</TITLE> + +<PROGRAMLISTING> +HAL_BREAKPOINT( label ) +HAL_BREAKINST +HAL_BREAKINST_SIZE +</PROGRAMLISTING> + +<PARA> +These macros provide support for breakpoints. +</PARA> + +<PARA> +<FUNCTION>HAL_BREAKPOINT()</FUNCTION> executes a breakpoint +instruction. The label is defined at the breakpoint instruction so +that exception code can detect which breakpoint was executed. +</PARA> + +<PARA> +<literal>HAL_BREAKINST</literal> contains the breakpoint instruction +code as an integer value. <literal>HAL_BREAKINST_SIZE</literal> is +the size of that breakpoint instruction in bytes. Together these +may be used to place a breakpoint in any code. +</PARA> +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>GDB support</TITLE> + +<PROGRAMLISTING> +HAL_THREAD_GET_SAVED_REGISTERS( sp, regs ) +HAL_GET_GDB_REGISTERS( regval, regs ) +HAL_SET_GDB_REGISTERS( regs, regval ) +</PROGRAMLISTING> + +<PARA> +These macros provide support for interfacing GDB to the HAL. +</PARA> + +<PARA> +<FUNCTION>HAL_THREAD_GET_SAVED_REGISTERS()</FUNCTION> extracts a +pointer to a <STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure +from a stack pointer value. The stack pointer passed in should be the +value saved by the thread context macros. The macro will assign a +pointer to the <STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure +to the variable passed as the second argument. +</PARA> + +<PARA> +<FUNCTION>HAL_GET_GDB_REGISTERS()</FUNCTION> translates a register +state as saved by the HAL and into a register dump in the format +expected by GDB. It takes a pointer to a +<STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure in the +<parameter>regs</parameter> argument and a pointer to the memory to +contain the GDB register dump in the <parameter>regval</parameter> +argument. +</PARA> + +<PARA> +<FUNCTION>HAL_SET_GDB_REGISTERS()</FUNCTION> translates a GDB format +register dump into a the format expected by the HAL. It takes a +pointer to the memory containing the GDB register dump in the +<parameter>regval</parameter> argument and a pointer to a +<STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure +in the <parameter>regs</parameter> argument. +</PARA> +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Setjmp and longjmp support</TITLE> + +<PROGRAMLISTING> +CYGARC_JMP_BUF_SIZE +hal_jmp_buf[CYGARC_JMP_BUF_SIZE] +hal_setjmp( hal_jmp_buf env ) +hal_longjmp( hal_jmp_buf env, int val ) +</PROGRAMLISTING> + +<PARA> +These functions provide support for the C +<FUNCTION>setjmp()</FUNCTION> and <FUNCTION>longjmp()</FUNCTION> +functions. Refer to the C library for further information. +</PARA> + +</SECTION> + +<!-- =================================================================== --> + +<section> +<title>Stack Sizes</title> +<programlisting> +CYGNUM_HAL_STACK_SIZE_MINIMUM +CYGNUM_HAL_STACK_SIZE_TYPICAL +</programlisting> + +<para> +The values of these macros define the minimum and typical sizes of +thread stacks. +</para> + +<para> +<literal>CYGNUM_HAL_STACK_SIZE_MINIMUM</literal> defines the minimum +size of a thread stack. This is enough for the thread to function +correctly within eCos and allows it to take interrupts and context +switches. There should also be enough space for a simple thread entry +function to execute and call basic kernel operations on objects like +mutexes and semaphores. However there will not be enough room for much +more than this. When creating stacks for their own threads, +applications should determine the stack usage needed for application +purposes and then add +<literal>CYGNUM_HAL_STACK_SIZE_MINIMUM</literal>. +</para> + +<para> +<literal>CYGNUM_HAL_STACK_SIZE_TYPICAL</literal> is a reasonable increment over +<literal>CYGNUM_HAL_STACK_SIZE_MINIMUM</literal>, usually about 1kB. This should be +adequate for most modest thread needs. Only threads that need to +define significant amounts of local data, or have very deep call trees +should need to use a larger stack size. +</para> + +</section> + + +<!-- =================================================================== --> + +<section> +<title>Address Translation</title> + +<programlisting> +CYGARC_CACHED_ADDRESS(addr) +CYGARC_UNCACHED_ADDRESS(addr) +CYGARC_PHYSICAL_ADDRESS(addr) +</programlisting> + +<para> +These macros provide address translation between different views of +memory. In many architectures a given memory location may be visible +at different addresses in both cached and uncached forms. It is also +possible that the MMU or some other address translation unit in the +CPU presents memory to the program at a different virtual address to +its physical address on the bus. +</para> + +<para> +<function>CYGARC_CACHED_ADDRESS()</function> translates the given +address to its location in cached memory. This is typically where the +application will access the memory. +</para> + +<para> +<function>CYGARC_UNCACHED_ADDRESS()</function> translates the given +address to its location in uncached memory. This is typically where +device drivers will access the memory to avoid cache problems. It may +additionally be necessary for the cache to be flushed before the +contents of this location is fully valid. +</para> + +<para> +<function>CYGARC_PHYSICAL_ADDRESS()</function> translates the given +address to its location in the physical address space. This is +typically the address that needs to be passed to device hardware such +as a DMA engine, ethernet device or PCI bus bridge. The physical +address may not be directly accessible to the program, it may be +re-mapped by address translation. +</para> + +</section> + + +<!-- =================================================================== --> + +<section> +<title>Global Pointer</title> + +<programlisting> +CYGARC_HAL_SAVE_GP() +CYGARC_HAL_RESTORE_GP() +</programlisting> + +<para> +These macros insert code to save and restore any global data pointer +that the ABI uses. These are necessary when switching context between +two eCos instances - for example between an eCos application and +RedBoot. +</para> + +</section> + +</SECTION> + +<!-- }}} --> +<!-- {{{ Interrupt Handling --> + +<SECTION id="hal-interrupt-handling"> +<TITLE>Interrupt Handling</TITLE> + +<para> +These interfaces contain definitions related to interrupt +handling. They include definitions of exception and interrupt numbers, +interrupt enabling and masking. +</para> + +<PARA> +These definitions are normally found in +<FILENAME>cyg/hal/hal_intr.h</FILENAME>. This file is supplied by the +architecture HAL. Any variant or platform specific definitions will +be found in <filename>cyg/hal/var_intr.h</filename>, +<filename>cyg/hal/plf_intr.h</filename> or +<filename>cyg/hal/hal_platform_ints.h</filename> in the variant or platform +HAL, depending on the exact target. These files are include +automatically by this header, so need not be included explicitly. +</PARA> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Vector numbers</TITLE> + +<PROGRAMLISTING> +CYGNUM_HAL_VECTOR_XXXX +CYGNUM_HAL_VSR_MIN +CYGNUM_HAL_VSR_MAX +CYGNUM_HAL_VSR_COUNT + +CYGNUM_HAL_INTERRUPT_XXXX +CYGNUM_HAL_ISR_MIN +CYGNUM_HAL_ISR_MAX +CYGNUM_HAL_ISR_COUNT + +CYGNUM_HAL_EXCEPTION_XXXX +CYGNUM_HAL_EXCEPTION_MIN +CYGNUM_HAL_EXCEPTION_MAX +CYGNUM_HAL_EXCEPTION_COUNT +</PROGRAMLISTING> + +<PARA> +All possible VSR, interrupt and exception vectors are specified here, +together with maximum and minimum values for range checking. While the +VSR and exception numbers will be defined in this file, the interrupt +numbers will normally be defined in the variant or platform HAL file +that is included by this header. +</PARA> + +<PARA> +There are two ranges of numbers, those for the vector service +routines and those for the interrupt service routines. The relationship +between these two ranges is undefined, and no equivalence should +be assumed if vectors from the two ranges coincide. +</PARA> + +<PARA> +The VSR vectors correspond to the set of exception vectors that can be +delivered by the CPU architecture, many of these will be internal +exception traps. The ISR vectors correspond to the set of external +interrupts that can be delivered and are usually determined by extra +decoding of the interrupt controller by the interrupt VSR. +</PARA> + +<PARA> +Where a CPU supports synchronous exceptions, the range of such +exceptions allowed are defined by <literal>CYGNUM_HAL_EXCEPTION_MIN</literal> and +<literal>CYGNUM_HAL_EXCEPTION_MAX</literal>. The +<literal>CYGNUM_HAL_EXCEPTION_XXXX</literal> definitions are +standard names used by target independent code to test for the +presence of particular exceptions in the architecture. The actual +exception numbers will normally correspond to the VSR exception +range. In future other exceptions generated by the system software +(such as stack overflow) may be added. +</PARA> + +<PARA> +<literal>CYGNUM_HAL_ISR_COUNT</literal>, <literal>CYGNUM_HAL_VSR_COUNT</literal> and +<literal>CYGNUM_HAL_EXCEPTION_COUNT</literal> define the number of +ISRs, VSRs and EXCEPTIONs respectively for the purposes of defining +arrays etc. There might be a translation from the supplied vector +numbers into array offsets. Hence +<literal>CYGNUM_HAL_XXX_COUNT</literal> may not simply be +<literal>CYGNUM_HAL_XXX_MAX</literal> - <literal>CYGNUM_HAL_XXX_MIN</literal> or <literal>CYGNUM_HAL_XXX_MAX</literal>+1. +</PARA> + +</SECTION> + + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Interrupt state control</TITLE> + +<PROGRAMLISTING> +CYG_INTERRUPT_STATE +HAL_DISABLE_INTERRUPTS( old ) +HAL_RESTORE_INTERRUPTS( old ) +HAL_ENABLE_INTERRUPTS() +HAL_QUERY_INTERRUPTS( state ) +</PROGRAMLISTING> + +<PARA> +These macros provide control over the state of the CPUs interrupt mask +mechanism. They should normally manipulate a CPU status register to +enable and disable interrupt delivery. They should not access an +interrupt controller. +</PARA> + + +<para> +<literal>CYG_INTERRUPT_STATE</literal> is a data type that should be +used to store the interrupt state returned by +<function>HAL_DISABLE_INTERRUPTS()</function> and +<function>HAL_QUERY_INTERRUPTS()</function> and passed to +<function>HAL_RESTORE_INTERRUPTS()</function>. +</para> + +<PARA> +<FUNCTION>HAL_DISABLE_INTERRUPTS()</FUNCTION> disables the delivery of +interrupts and stores the original state of the interrupt mask in the +variable passed in the <parameter>old</parameter> argument. +</PARA> + +<PARA> +<FUNCTION>HAL_RESTORE_INTERRUPTS()</FUNCTION> restores the state of +the interrupt mask to that recorded in <parameter>old</parameter>. +</PARA> + +<PARA> +<FUNCTION>HAL_ENABLE_INTERRUPTS()</FUNCTION> simply enables interrupts +regardless of the current state of the mask. +</PARA> + +<PARA> +<FUNCTION>HAL_QUERY_INTERRUPTS()</FUNCTION> stores the state of the +interrupt mask in the variable passed in the <parameter> +state</parameter> argument. The state stored here should also be +capable of being passed to +<function>HAL_RESTORE_INTERRUPTS()</function> at a later point. +</PARA> + +<PARA> +It is at the HAL implementer’s discretion exactly +which interrupts are masked by this mechanism. Where a CPU has more +than one interrupt type that may be masked separately (e.g. the +ARM's IRQ and FIQ) only those that can raise DSRs need +to be masked here. A separate architecture specific mechanism may +then be used to control the other interrupt types. +</PARA> + +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>ISR and VSR management</TITLE> + +<PROGRAMLISTING> +HAL_INTERRUPT_IN_USE( vector, state ) +HAL_INTERRUPT_ATTACH( vector, isr, data, object ) +HAL_INTERRUPT_DETACH( vector, isr ) +HAL_VSR_SET( vector, vsr, poldvsr ) +HAL_VSR_GET( vector, pvsr ) +HAL_VSR_SET_TO_ECOS_HANDLER( vector, poldvsr ) +</PROGRAMLISTING> + +<PARA> +These macros manage the attachment of interrupt and vector service +routines to interrupt and exception vectors respectively. +</PARA> + +<para> +<function>HAL_INTERRUPT_IN_USE()</function> tests the state of the +supplied interrupt vector and sets the value of the state parameter to +either 1 or 0 depending on whether there is already an ISR attached to +the vector. The HAL will only allow one ISR to be attached to each +vector, so it is a good idea to use this function before using +<function>HAL_INTERRUPT_ATTACH()</function>. +</para> + +<PARA> +<FUNCTION>HAL_INTERRUPT_ATTACH()</FUNCTION> attaches +the ISR, data pointer and object pointer to the given +<parameter>vector</parameter>. When an interrupt occurs on this +vector the ISR is called using the C calling convention and the vector +number and data pointer are passed to it as the first and second +arguments respectively. +</PARA> + +<PARA> +<FUNCTION>HAL_INTERRUPT_DETACH()</FUNCTION> detaches the ISR from the +vector. +</PARA> + +<PARA> +<FUNCTION>HAL_VSR_SET()</FUNCTION> replaces the VSR attached to the +<parameter>vector</parameter> with the replacement supplied in +<parameter>vsr</parameter>. The old VSR is returned in the location +pointed to by <parameter>pvsr</parameter>. +</PARA> + +<PARA> +<FUNCTION>HAL_VSR_GET()</FUNCTION> assigns +a copy of the VSR to the location pointed to by <parameter>pvsr</parameter>. +</PARA> + +<para> +<function>HAL_VSR_SET_TO_ECOS_HANDLER()</function> ensures that the +VSR for a specific exception is pointing at the eCos exception VSR and +not one for RedBoot or some other ROM monitor. The default when +running under RedBoot is for exceptions to be handled by RedBoot and +passed to GDB. This macro diverts the exception to eCos so that it may +be handled by application code. The arguments are the VSR vector to be +replaces, and a location in which to store the old VSR pointer, so +that it may be replaced at a later point. +</para> + +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Interrupt controller management</TITLE> + +<PROGRAMLISTING> +HAL_INTERRUPT_MASK( vector ) +HAL_INTERRUPT_UNMASK( vector ) +HAL_INTERRUPT_ACKNOWLEDGE( vector ) +HAL_INTERRUPT_CONFIGURE( vector, level, up ) +HAL_INTERRUPT_SET_LEVEL( vector, level ) +</PROGRAMLISTING> + +<PARA> +These macros exert control over any prioritized interrupt +controller that is present. If no priority controller exists, then +these macros should be empty. +</para> + +<note> + <para> + These macros may not be reentrant, so care should be taken to + prevent them being called while interrupts are enabled. This means + that they can be safely used in initialization code before + interrupts are enabled, and in ISRs. In DSRs, ASRs and thread code, + however, interrupts must be disabled before these macros are + called. Here is an example for use in a DSR where the interrupt + source is unmasked after data processing: + </para> +<PROGRAMLISTING> + ... + HAL_DISABLE_INTERRUPTS(old); + HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_ETH); + HAL_RESTORE_INTERRUPTS(old); + ... +</PROGRAMLISTING> +</note> + +<PARA> +<FUNCTION>HAL_INTERRUPT_MASK()</FUNCTION> causes the interrupt +associated with the given vector to be blocked. +</PARA> + +<PARA> +<FUNCTION>HAL_INTERRUPT_UNMASK()</FUNCTION> causes the interrupt +associated with the given vector to be unblocked. +</PARA> + +<PARA> +<FUNCTION>HAL_INTERRUPT_ACKNOWLEDGE()</FUNCTION> acknowledges the +current interrupt from the given vector. This is usually executed from +the ISR for this vector when it is prepared to allow further +interrupts. Most interrupt controllers need some form of acknowledge +action before the next interrupt is allowed through. Executing this +macro may cause another interrupt to be delivered. Whether this +interrupts the current code depends on the state of the CPU interrupt +mask. +</PARA> + +<PARA> +<FUNCTION>HAL_INTERRUPT_CONFIGURE()</FUNCTION> provides +control over how an interrupt signal is detected. The arguments +are: +</PARA> +<VARIABLELIST> + <VARLISTENTRY> + <TERM>vector</TERM> + <LISTITEM> + <PARA>The interrupt vector to be configured.</PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>level</TERM> + <LISTITEM> + <PARA> + Set to <varname>true</varname> if the interrupt is detected by + level, and <varname>false</varname> if it is edge triggered. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>up</TERM> + <LISTITEM> + <PARA> + If the interrupt is set to level detect, then if this is + <VARNAME>true</VARNAME> it is detected by a high signal level, + and if <VARNAME>false</VARNAME> by a low signal level. If the + interrupt is set to edge triggered, then if this is + <VARNAME>true</VARNAME> it is triggered by a rising edge and if + <VARNAME>false</VARNAME> by a falling edge. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> + +<PARA> +<FUNCTION>HAL_INTERRUPT_SET_LEVEL()</FUNCTION> provides control over +the hardware priority of the interrupt. The arguments are: +</PARA> + +<VARIABLELIST> + <VARLISTENTRY> + <TERM>vector</TERM> + <LISTITEM> + <PARA>The interrupt whose level is to be set.</PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>level</TERM> + <LISTITEM> + <PARA> + The priority level to which the interrupt is to set. In some + architectures the masking of an interrupt is achieved by + changing its priority level. Hence this function, + <FUNCTION>HAL_INTERRUPT_MASK()</FUNCTION> and + <FUNCTION>HAL_INTERRUPT_UNMASK()</FUNCTION> may interfere with + each other. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> + +</SECTION> + +</SECTION> + +<!-- }}} --> +<!-- {{{ Clocks and Timers --> + +<SECTION id="hal-clocks-and-timers"> +<TITLE>Clocks and Timers</TITLE> + +<para> +These interfaces contain definitions related to clock and timer +handling. They include interfaces to initialize and read a clock for +generating regular interrupts, definitions for setting the frequency of +the clock, and support for short timed delays. +</para> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Clock Control</TITLE> + +<PROGRAMLISTING> +HAL_CLOCK_INITIALIZE( period ) +HAL_CLOCK_RESET( vector, period ) +HAL_CLOCK_READ( pvalue ) +</PROGRAMLISTING> + +<PARA> +These macros provide control over a clock or timer device that may be +used by the kernel to provide time-out, delay and scheduling +services. The clock is assumed to be implemented by some form of +counter that is incremented or decremented by some external source and +which raises an interrupt when it reaches a predetermined value. +</PARA> + +<PARA> +<FUNCTION>HAL_CLOCK_INITIALIZE()</FUNCTION> initializes the timer +device to interrupt at the given period. The period is essentially the +value used to initialize the timer counter and must be calculated from +the timer frequency and the desired interrupt rate. The timer device +should generate an interrupt every <varname>period</varname> cycles. +</PARA> + +<PARA> +<FUNCTION>HAL_CLOCK_RESET()</FUNCTION> re-initializes the timer to +provoke the next interrupt. This macro is only really necessary when +the timer device needs to be reset in some way after each interrupt. +</PARA> + +<PARA> +<FUNCTION>HAL_CLOCK_READ()</FUNCTION> reads the current value of the +timer counter and puts the value in the location pointed to by +<parameter>pvalue</parameter>. The value stored will always be the +number of timer cycles since the last interrupt, and hence ranges +between zero and the initial period value. If this is a count-down +cyclic timer, some arithmetic may be necessary to generate this value. +</PARA> + +</SECTION> + +<!-- =================================================================== --> + +<section> +<title>Microsecond Delay</title> + +<programlisting width=72> +HAL_DELAY_US(us) +</programlisting> + +<para> +This macro provides a busy loop delay for the given number of +microseconds. It is intended mainly for controlling hardware that +needs short delays between operations. Code which needs longer delays, +of the order of milliseconds, should instead use higher-level +functions such as <function>cyg_thread_delay</function>. The macro +implementation should be thread-safe. It can also be used in ISRs or +DSRs, although such usage is undesirable because of the impact on +interrupt and dispatch latency. +</para> + +<para> +The macro should never delay for less than the specified amount of +time. It may delay for somewhat longer, although since the macro uses +a busy loop this is a waste of cpu cycles. Of course the code invoking +<function>HAL_DELAY_US</function> may get interrupted or timesliced, +in which case the delay may be much longer than intended. If this is +unacceptable then the calling code must take preventative action +such as disabling interrupts or locking the scheduler. +</para> + +<para> +There are three main ways of implementating the macro: +</para> + +<orderedlist> + <listitem><para> +a counting loop, typically written in inline assembler, using an outer +loop for the microseconds and an inner loop that consumes +approximately 1us. This implementation is automatically thread-safe +and does not impose any dependencies on the rest of the system, for +example it does not depend on the system clock having been started. +However it assumes that the cpu clock speed is known at compile-time +or can be easily determined at run-time. + </para></listitem> + <listitem><para> +monitor one of the hardware clocks, usually the system clock. Usually +this clock ticks at a rate independent of the cpu so calibration is +easier. However the implementation relies on the system clock having +been started, and assumes that no other code is manipulating the clock +hardware. There can also be complications when the system clock wraps +around. + </para></listitem> + <listitem><para> +a combination of the previous two. The system clock is used during +system initialization to determine the cpu clock speed, and the result +is then used to calibrate a counting loop. This has the disadvantage +of significantly increasing the system startup time, which may be +unacceptable to some applications. There are also complications if the +system startup code normally runs with the cache disabled because the +instruction cache will greatly affect any calibration loop. + </para></listitem> +</orderedlist> + +</section> + +<!-- =================================================================== --> + +<section> +<title>Clock Frequency Definition</title> + +<programlisting width=72> +CYGNUM_HAL_RTC_NUMERATOR +CYGNUM_HAL_RTC_DENOMINATOR +CYGNUM_HAL_RTC_PERIOD +</programlisting> + +<para> +These macros are defined in the CDL for each platform and supply the +necessary parameters to specify the frequency at which the clock +interrupts. These parameters are usually found in the CDL definitions +for the target platform, or in some cases the CPU variant. +</para> + +<para> +<literal>CYGNUM_HAL_RTC_NUMERATOR</literal> and +<literal>CYGNUM_HAL_RTC_DENOMINATOR</literal> specify the resolution +of the clock interrupt. This resolution involves two separate values, +the numerator and the denominator. The result of dividing the +numerator by the denominator should correspond to the number of +nanoseconds between clock interrupts. For example a numerator of +1000000000 and a denominator of 100 means that there are 10000000 +nanoseconds (or 10 milliseconds) between clock interrupts. Expressing +the resolution as a fraction minimizes clock drift even for +frequencies that cannot be expressed as a simple integer. For example +a frequency of 60Hz corresponds to a clock resolution of +16666666.66... nanoseconds. This can be expressed accurately as +1000000000 over 60. +</para> + +<para> +<literal>CYGNUM_HAL_RTC_PERIOD</literal> specifies the exact value +used to initialize the clock hardware, it is the value passed as a +parameter to <literal>HAL_CLOCK_INITIALIZE()</literal> and +<literal>HAL_CLOCK_RESET()</literal>. The exact meaning of the value +and the range of legal values therefore depends on the target +hardware, and the hardware documentation should be consulted for +further details. +</para> + +<para> +The default values for these macros in all HALs are calculated to give +a clock interrupt frequency of 100Hz, or 10ms between interrupts. To +change the clock frequency, the period needs to be changed, and the +resolution needs to be adjusted accordingly. As an example consider +the i386 PC target. The default values for these macros are: +</para> + +<programlisting width=72> +CYGNUM_HAL_RTC_NUMERATOR 1000000000 +CYGNUM_HAL_RTC_DENOMINATOR 100 +CYGNUM_HAL_RTC_PERIOD 11932 +</programlisting> + +<para> +To change to, say, a 200Hz clock the period needs to be halved to +5966, and to compensate the denominator needs to be doubled to 200. To +change to a 1KHz interrupt rate change the period to 1193 and the +denominator to 1000. +</para> + +<para> +Some HALs make this process a little easier by deriving the period +arithmetically from the denominator. This calculation may also involve +the CPU clock frequency and possibly other factors. For example in the +ARM AT91 variant HAL the period is defined by the following +expression: +</para> + +<programlisting width=72> +((CYGNUM_HAL_ARM_AT91_CLOCK_SPEED/32) / CYGNUM_HAL_RTC_DENOMINATOR) +</programlisting> + +<para> +In this case it is not necessary to change the period at all, just +change the denominator to select the desired clock frequency. However, +note that for certain choices of frequency, rounding errors in this +calculation may result in a small clock drift over time. This is +usually negligible, but if perfect accuracy is required, it may be +necessary to adjust the frequency or period by hand. +</para> + +</section> + + +</section> + +<!-- }}} --> +<!-- {{{ Input and Output --> + +<SECTION id="hal-input-and-output"> +<TITLE>HAL I/O</TITLE> + +<PARA> +This section contains definitions for supporting access +to device control registers in an architecture neutral +fashion. +</PARA> + +<para> +These definitions are normally found in the header file +<FILENAME>cyg/hal/hal_io.h</FILENAME>. This file itself contains +macros that are generic to the architecture. If there are variant or +platform specific IO access macros then these will be found in +<filename>cyg/hal/var_io.h</filename> and +<filename>cyg/hal/plf_io.h</filename> in the variant or platform HALs +respectively. These files are include automatically by this header, so +need not be included explicitly. +</para> + +<para> +This header (or more likely <filename>cyg/hal/plf_io.h</filename>) also +defines the PCI access macros. For more information on these see <xref +linkend="pci-library-reference">. +</para> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Register address</TITLE> + +<PROGRAMLISTING> +HAL_IO_REGISTER +</PROGRAMLISTING> + +<PARA> +This type is used to store the address of an I/O register. It will +normally be a memory address, an integer port address or an offset +into an I/O space. More complex architectures may need to code an +address space plus offset pair into a single word, or may represent it +as a structure. +</PARA> + +<PARA> +Values of variables and constants of this type will usually be +supplied by configuration mechanisms or in target specific headers. +</PARA> + +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Register read</TITLE> + +<PROGRAMLISTING> +HAL_READ_XXX( register, value ) +HAL_READ_XXX_VECTOR( register, buffer, count, stride ) +</PROGRAMLISTING> + +<PARA> +These macros support the reading of I/O registers in various +sizes. The <replaceable>XXX</replaceable> component of the name may be +<literal>UINT8</literal>, <literal>UINT16</literal>, +<literal>UINT32</literal>. +</PARA> + +<PARA> +<FUNCTION>HAL_READ_XXX()</FUNCTION> reads the appropriately sized +value from the register and stores it in the variable passed as the +second argument. +</PARA> + +<PARA> +<FUNCTION>HAL_READ_XXX_VECTOR()</FUNCTION> reads +<parameter>count</parameter> values of the appropriate size into +<parameter>buffer</parameter>. The <parameter>stride</parameter> +controls how the pointer advances through the register space. A stride +of zero will read the same register repeatedly, and a stride of one +will read adjacent registers of the given size. Greater strides will +step by larger amounts, to allow for sparsely mapped registers for +example.</PARA> +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Register write</TITLE> + +<PROGRAMLISTING> +HAL_WRITE_XXX( register, value ) +HAL_WRITE_XXX_VECTOR( register, buffer,count, stride ) +</PROGRAMLISTING> + +<PARA> +These macros support the writing of I/O registers in various +sizes. The <replaceable>XXX</replaceable> component of the name may be +<LITERAL>UINT8</LITERAL>, <LITERAL>UINT16</LITERAL>, +<LITERAL>UINT32</LITERAL>. +</PARA> + +<PARA> +<FUNCTION>HAL_WRITE_XXX()</FUNCTION> writes +the appropriately sized value from the variable passed as the second argument +stored it in the register.</PARA> +<PARA><FUNCTION>HAL_WRITE_XXX_VECTOR()</FUNCTION> writes +<parameter>count</parameter> values of the appropriate size from <parameter> +buffer</parameter>. The <parameter>stride</parameter> controls +how the pointer advances through the register space. A stride of +zero will write the same register repeatedly, and a stride of one +will write adjacent registers of the given size. Greater strides +will step by larger amounts, to allow for sparsely mapped registers +for example.</PARA> +</SECTION> +</SECTION> + +<!-- }}} --> +<!-- {{{ Cache Control --> + +<SECTION id="hal-cache-control"> +<TITLE>Cache Control</TITLE> + +<PARA>This section contains definitions for supporting control +of the caches on the CPU. +</PARA> + +<para> +These definitions are usually found in the header file +<FILENAME>cyg/hal/hal_cache.h</FILENAME>. This file may be defined in +the architecture, variant or platform HAL, depending on where the +caches are implemented for the target. Often there will be a generic +implementation of the cache control macros in the architecture HAL +with the ability to override or undefine them in the variant or +platform HAL. Even when the implementation of the cache macros is in +the architecture HAL, the cache dimensions will be defined in the +variant or platform HAL. As with other files, the variant or platform +specific definitions are usually found in +<filename>cyg/hal/var_cache.h</filename> and +<filename>cyg/hal/plf_cache.h</filename> respectively. These files +are include automatically by this header, so need not be included +explicitly. +</para> + +<PARA> +There are versions of the macros defined here for both the Data and +Instruction caches. these are distinguished by the use of either +<literal>DCACHE</literal> or <literal>ICACHE</literal> in the macro +names. Some architectures have a unified cache, where both data and +instruction share the same cache. In these cases the control macros +use <literal>UCACHE</literal> and the <literal>DCACHE</literal> and +<literal>ICACHE</literal> macros will just be calls to the +<literal>UCACHE</literal> version. In the following descriptions, +<literal>XCACHE</literal> is used to stand for any of these. Where +there are issues specific to a particular cache, this will be +explained in the text. +</PARA> + +<PARA> +There might be target specific restrictions on the use of some of the +macros which it is the user's responsibility to comply with. Such +restrictions are documented in the header file with the macro +definition. +</PARA> + +<PARA> +Note that destructive cache macros should be used with caution. +Preceding a cache invalidation with a cache synchronization is not +safe in itself since an interrupt may happen after the synchronization +but before the invalidation. This might cause the state of dirty data +lines created during the interrupt to be lost. +</PARA> + +<PARA> +Depending on the architecture's capabilities, it may be possible to +temporarily disable the cache while doing the synchronization and +invalidation which solves the problem (no new data would be cached +during an interrupt). Otherwise it is necessary to disable interrupts +while manipulating the cache which may take a long time. +</PARA> + +<PARA> +Some platform HALs now support a pair of cache state query +macros: <function>HAL_ICACHE_IS_ENABLED( x )</function> and +<function>HAL_DCACHE_IS_ENABLED( x )</function> which set the argument +to true if the instruction or data cache is enabled, +respectively. Like most cache control macros, these are optional, +because the capabilities of different targets and boards can vary +considerably. Code which uses them, if it is to be considered +portable, should test for their existence first by means of +<literal>#ifdef</literal>. Be sure to include +<filename><cyg/hal/hal_cache.h></filename> in order to do this +test and (maybe) use the macros. +</PARA> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Cache Dimensions</TITLE> + +<PROGRAMLISTING> +HAL_XCACHE_SIZE +HAL_XCACHE_LINE_SIZE +HAL_XCACHE_WAYS +HAL_XCACHE_SETS +</PROGRAMLISTING> +<PARA> +These macros define the size and dimensions of the Instruction +and Data caches. +</PARA> + +<VARIABLELIST> + <VARLISTENTRY> + <TERM>HAL_XCACHE_SIZE </TERM> + <LISTITEM> + <PARA>Defines the total size of the cache in bytes.</PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_LINE_SIZE </TERM> + <LISTITEM> + <PARA>Defines the cache line size in bytes.</PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_WAYS </TERM> + <LISTITEM> + <PARA> + Defines the number of ways in each set and defines its level + of associativity. This would be 1 for a direct mapped + cache, 2 for a 2-way cache, 4 for 4-way and so on. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_SETS </TERM> + <LISTITEM> + <PARA> + Defines the number of sets in the cache, and is calculated from + the previous values. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> + +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Global Cache Control</TITLE> + +<PROGRAMLISTING> +HAL_XCACHE_ENABLE() +HAL_XCACHE_DISABLE() +HAL_XCACHE_INVALIDATE_ALL() +HAL_XCACHE_SYNC() +HAL_XCACHE_BURST_SIZE( size ) +HAL_DCACHE_WRITE_MODE( mode ) +HAL_XCACHE_LOCK( base, size ) +HAL_XCACHE_UNLOCK( base, size ) +HAL_XCACHE_UNLOCK_ALL() +</PROGRAMLISTING> + +<PARA> +These macros affect the state of the entire cache, or a large part of +it. +</PARA> + +<VARIABLELIST> + <VARLISTENTRY> + <TERM>HAL_XCACHE_ENABLE() and HAL_XCACHE_DISABLE()</TERM> + <LISTITEM> + <PARA>Enable and disable the cache.</PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_INVALIDATE_ALL()</TERM> + <LISTITEM> + <PARA> + Causes the entire contents of the cache to be invalidated. + Depending on the hardware, this may require the cache to be disabled + during the invalidation process. If so, the implementation must + use <function>HAL_XCACHE_IS_ENABLED()</function> to save and + restore the previous state. + </PARA> + <note> + <para> + If this macro is called after + <function>HAL_XCACHE_SYNC()</function> with the intention of clearing + the cache (invalidating the cache after writing dirty data back to + memory), you must prevent interrupts from happening between the two + calls: + </para> +<PROGRAMLISTING> + ... + HAL_DISABLE_INTERRUPTS(old); + HAL_XCACHE_SYNC(); + HAL_XCACHE_INVALIDATE_ALL(); + HAL_RESTORE_INTERRUPTS(old); + ... +</PROGRAMLISTING> + <para> + Since the operation may take a very long time, real-time + responsiveness could be affected, so only do this when it is + absolutely required and you know the delay will not interfere + with the operation of drivers or the application. + </para> + </note> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_SYNC()</TERM> + <LISTITEM> + <PARA> + Causes the contents of the cache to be brought into synchronization + with the contents of memory. In some implementations this may be + equivalent to <function>HAL_XCACHE_INVALIDATE_ALL()</function>. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_BURST_SIZE()</TERM> + <LISTITEM> + <PARA> + Allows the size of cache to/from memory bursts to + be controlled. This macro will only be defined if this functionality + is available. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_DCACHE_WRITE_MODE()</TERM> + <LISTITEM> + <PARA> + Controls the way in which data cache lines are written back to + memory. There will be definitions for the possible + modes. Typical definitions are + <literal>HAL_DCACHE_WRITEBACK_MODE</literal> and + <literal>HAL_DCACHE_WRITETHRU_MODE</literal>. This macro will + only be defined if this functionality is available. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_LOCK()</TERM> + <LISTITEM> + <PARA> + Causes data to be locked into the cache. The base and size + arguments define the memory region that will be locked into the + cache. It is architecture dependent whether more than one locked + region is allowed at any one time, and whether this operation + causes the cache to cease acting as a cache for addresses + outside the region during the duration of the lock. This macro + will only be defined if this functionality is available. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_UNLOCK()</TERM> + <LISTITEM> + <PARA> + Cancels the locking of the memory region given. This should + normally correspond to a region supplied in a matching lock + call. This macro will only be defined if this functionality is + available. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_UNLOCK_ALL()</TERM> + <LISTITEM> + <PARA> + Cancels all existing locked memory regions. This may be required + as part of the cache initialization on some architectures. This + macro will only be defined if this functionality is available. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> + +</SECTION> + +<!-- =================================================================== --> + +<SECTION> +<TITLE>Cache Line Control</TITLE> + +<PROGRAMLISTING> +HAL_DCACHE_ALLOCATE( base , size ) +HAL_DCACHE_FLUSH( base , size ) +HAL_XCACHE_INVALIDATE( base , size ) +HAL_DCACHE_STORE( base , size ) +HAL_DCACHE_READ_HINT( base , size ) +HAL_DCACHE_WRITE_HINT( base , size ) +HAL_DCACHE_ZERO( base , size ) +</PROGRAMLISTING> + +<PARA> +All of these macros apply a cache operation to all cache lines that +match the memory address region defined by the base and size +arguments. These macros will only be defined if the described +functionality is available. Also, it is not guaranteed that the cache +function will only be applied to just the described regions, in some +architectures it may be applied to the whole cache. +</PARA> + +<VARIABLELIST> + <VARLISTENTRY> + <TERM>HAL_DCACHE_ALLOCATE()</TERM> + <LISTITEM> + <PARA> + Allocates lines in the cache for the given region without + reading their contents from memory, hence the contents of the lines + is undefined. This is useful for preallocating lines which are to + be completely overwritten, for example in a block copy + operation. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_DCACHE_FLUSH()</TERM> + <LISTITEM> + <PARA> + Invalidates all cache lines in the region after writing any + dirty lines to memory. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_XCACHE_INVALIDATE() </TERM> + <LISTITEM> + <PARA> + Invalidates all cache lines in the region. Any dirty lines + are invalidated without being written to memory. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_DCACHE_STORE() </TERM> + <LISTITEM> + <PARA> + Writes all dirty lines in the region to memory, but does not + invalidate any lines. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_DCACHE_READ_HINT() </TERM> + <LISTITEM> + <PARA> + Hints to the cache that the region is going to be read from + in the near future. This may cause the region to be speculatively + read into the cache. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_DCACHE_WRITE_HINT() </TERM> + <LISTITEM> + <PARA> + Hints to the cache that the region is going to be written + to in the near future. This may have the identical behavior to + HAL_DCACHE_READ_HINT(). + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>HAL_DCACHE_ZERO()</TERM> + <LISTITEM> + <PARA> + Allocates and zeroes lines in the cache for the given + region without reading memory. This is useful if a large area of + memory is to be cleared. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> + +</SECTION> +</SECTION> + +<!-- }}} --> +<!-- {{{ Linker Scripts --> + +<SECTION id="hal-linker-scripts"> +<TITLE><!-- <xref> -->Linker Scripts</TITLE> + +<para> +When an eCos application is linked it must be done under the control +of a linker script. This script defines the memory areas, addresses +and sized, into which the code and data are to be put, and allocates +the various sections generated by the compiler to these. +</para> + +<para> +The linker script actually used is in +<filename>lib/target.ld</filename> in the install directory. This is +actually manufactured out of two other files: a base linker script and +an <literal>.ldi</literal> file that was generated by the memory +layout tool. +</para> + +<para> +The base linker script is usually supplied either by the architecture +HAL or the variant HAL. It consists of a set of linker script +fragments, in the form of C preprocessor macros, that define the major +output sections to be generated by the link operation. The +<literal>.ldi</literal> file, which is <literal>#include'ed</literal> +by the base linker script, uses these macro definitions to assign the +output sections to the required memory areas and link addresses. +</para> + +<para> +The <literal>.ldi</literal> file is supplied by the platform HAL, and +contains knowledge of the memory layout of the target platform. These +files generally conform to a standard naming convention, each file +being of the form: +</para> +<para> +<filename>pkgconf/mlt_<architecture>_<variant>_<platform>_<startup>.ldi</filename> +</para> +<para> +where <literal><architecture></literal>, +<literal><variant></literal> and +<literal><platform></literal> are the respective HAL package +names and <literal><startup></literal> is the startup type which +is usually one of <literal>ROM</literal>, <literal>RAM</literal> or +<literal>ROMRAM</literal>. +</para> + +<para> +In addition to the <literal>.ldi</literal> file, there is also a +congruously name <literal>.h</literal> file. This may be used by the +application to access information defined in the +<literal>.ldi</literal> file. Specifically it contains the memory +layout defined there, together with any additional section names +defined by the user. Examples of the latter are heap areas or PCI bus +memory access windows. +</para> + +<para> +The <literal>.ldi</literal> is manufactured by the <application>Memory +Layout Tool</application> (MLT). The <application>MLT</application> saves the memory +configuration into a file named +</para> +<para> +<filename>include/pkgconf/mlt_<architecture>_<variant>_<platform>_<startup>.mlt</filename> +</para> +<para> +in the platform HAL. This file is used by the +<application>MLT</application> to manufacture both the +<literal>.ldi</literal> and <literal>.h</literal> files. Users should +beware that direct edits the either of these files may be overwritten +if the <application>MLT</application> is run and regenerates them from the +<literal>.mlt</literal> file. +</para> + +<para> +The names of the <literal>.ldi</literal> and <literal>.h</literal> +files are defined by macro definitions in +<FILENAME>pkgconf/system.h</FILENAME>. These are +<literal>CYGHWR_MEMORY_LAYOUT_LDI</literal> and +<literal>CYGHWR_MEMORY_LAYOUT_H</literal> respectively. While there +will be little need for the application to refer to the +<literal>.ldi</literal> file directly, it may include the +<literal>.h</literal> file as follows: +</para> + +<programlisting> +#include CYGHWR_MEMORY_LAYOUT_H +</programlisting> + +</SECTION> + +<!-- }}} --> +<!-- {{{ Diagnostic Support --> + +<SECTION id="hal-diagnostic-support"> +<TITLE>Diagnostic Support</TITLE> + +<para> +The HAL provides support for low level diagnostic IO. This is +particularly useful during early development as an aid to bringing up +a new platform. Usually this diagnostic channel is a UART or some +other serial IO device, but it may equally be a a memory +buffer, a simulator supported output channel, a ROM emulator virtual +UART, and LCD panel, a memory mapped video buffer or any other output +device. +</para> + +<PARA> +<FUNCTION>HAL_DIAG_INIT()</FUNCTION> performs any initialization +required on the device being used to generate diagnostic output. This +may include, for a UART, setting baud rate, and stop, parity and +character bits. For other devices it may include initializing a +controller or establishing contact with a remote device. +</PARA> + +<PARA> +<FUNCTION>HAL_DIAG_WRITE_CHAR(c)</FUNCTION> writes +the character supplied to the diagnostic output device. +</PARA> + +<PARA> +<FUNCTION>HAL_DIAG_READ_CHAR(c)</FUNCTION> reads a character from the +diagnostic device into the supplied variable. This is not supported +for all diagnostic devices. +</PARA> + +<para> +These macros are defined in the header file +<filename>cyg/hal/hal_diag.h</filename>. This file is usually supplied +by the variant or platform HAL, depending on where the IO device being +used is located. For example for on-chip UARTs it would be in the +variant HAL, but for a board-level LCD panel it would be in the +platform HAL. +</para> + +</section> + +<!-- }}} --> +<!-- {{{ SMP Support --> + +<section id="hal-smp-support"> +<TITLE>SMP Support</TITLE> + +<para> +eCos contains support for limited Symmetric Multi-Processing +(SMP). This is only available on selected architectures and platforms. +</para> + +<section> +<title>Target Hardware Limitations</title> + +<para> +To allow a reasonable implementation of SMP, and to reduce the +disruption to the existing source base, a number of assumptions have +been made about the features of the target hardware. +</para> + +<itemizedlist> +<listitem> +<para> +Modest multiprocessing. The typical number of CPUs supported is two +to four, with an upper limit around eight. While there are no +inherent limits in the code, hardware and algorithmic limitations +will probably become significant beyond this point. +</para> +</listitem> + +<listitem> +<para> +SMP synchronization support. The hardware must supply a mechanism to +allow software on two CPUs to synchronize. This is normally provided +as part of the instruction set in the form of test-and-set, +compare-and-swap or load-link/store-conditional instructions. An +alternative approach is the provision of hardware semaphore +registers which can be used to serialize implementations of these +operations. Whatever hardware facilities are available, they are +used in eCos to implement spinlocks. +</para> +</listitem> + +<listitem> +<para> +Coherent caches. It is assumed that no extra effort will be required +to access shared memory from any processor. This means that either +there are no caches, they are shared by all processors, or are +maintained in a coherent state by the hardware. It would be too +disruptive to the eCos sources if every memory access had to be +bracketed by cache load/flush operations. Any hardware that requires +this is not supported. +</para> +</listitem> + +<listitem> +<para> +Uniform addressing. It is assumed that all memory that is +shared between CPUs is addressed at the same location from all +CPUs. Like non-coherent caches, dealing with CPU-specific address +translation is considered too disruptive to the eCos source +base. This does not, however, preclude systems with non-uniform +access costs for different CPUs. +</para> +</listitem> + +<listitem> +<para> +Uniform device addressing. As with access to memory, it is assumed +that all devices are equally accessible to all CPUs. Since device +access is often made from thread contexts, it is not possible to +restrict access to device control registers to certain CPUs, since +there is currently no support for binding or migrating threads to CPUs. +</para> +</listitem> + +<listitem> +<para> +Interrupt routing. The target hardware must have an interrupt +controller that can route interrupts to specific CPUs. It is +acceptable for all interrupts to be delivered to just one CPU, or +for some interrupts to be bound to specific CPUs, or for some +interrupts to be local to each CPU. At present dynamic routing, +where a different CPU may be chosen each time an interrupt is +delivered, is not supported. ECos cannot support hardware where all +interrupts are delivered to all CPUs simultaneously with the +expectation that software will resolve any conflicts. +</para> +</listitem> + +<listitem> +<para> +Inter-CPU interrupts. A mechanism to allow one CPU to interrupt +another is needed. This is necessary so that events on one CPU can +cause rescheduling on other CPUs. +</para> +</listitem> + +<listitem> +<para> +CPU Identifiers. Code running on a CPU must be able to determine +which CPU it is running on. The CPU Id is usually provided either in +a CPU status register, or in a register associated with the +inter-CPU interrupt delivery subsystem. ECos expects CPU Ids to be +small positive integers, although alternative representations, such +as bitmaps, can be converted relatively easily. Complex mechanisms +for getting the CPU Id cannot be supported. Getting the CPU Id must +be a cheap operation, since it is done often, and in performance +critical places such as interrupt handlers and the scheduler. +</para> +</listitem> +</itemizedlist> + +</section> + +<section> +<title>HAL Support</title> + +<para> +SMP support in any platform depends on the HAL supplying the +appropriate operations. All HAL SMP support is defined in the +<filename>cyg/hal/hal_smp.h</filename> header. Variant and platform +specific definitions will be in <filename>cyg/hal/var_smp.h</filename> +and <filename>cyg/hal/plf_smp.h</filename> respectively. These files +are include automatically by this header, so need not be included +explicitly. +</para> + +<para> +SMP support falls into a number of functional groups. +</para> + +<section> +<title>CPU Control</title> + +<para> +This group consists of descriptive and control macros for managing the +CPUs in an SMP system. +</para> + +<variablelist> +<varlistentry> +<term><literal>HAL_SMP_CPU_TYPE</literal></term> +<listitem> +<para> +A type that can contain a CPU id. A CPU id is +usually a small integer that is used to index +arrays of variables that are managed on an +per-CPU basis. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_CPU_MAX</literal></term> +<listitem> +<para> +The maximum number of CPUs that can be +supported. This is used to provide the size of +any arrays that have an element per CPU. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_CPU_COUNT()</literal></term> +<listitem> +<para> +Returns the number of CPUs currently +operational. This may differ from +HAL_SMP_CPU_MAX depending on the runtime +environment. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_CPU_THIS()</literal></term> +<listitem> +<para> +Returns the CPU id of the current CPU. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_CPU_NONE</literal></term> +<listitem> +<para> +A value that does not match any real CPU +id. This is uses where a CPU type variable +must be set to a null value. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_CPU_START( cpu )</literal></term> +<listitem> +<para> +Starts the given CPU executing at a defined +HAL entry point. After performing any HAL +level initialization, the CPU calls up into +the kernel at <function>cyg_kernel_cpu_startup()</function>. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_CPU_RESCHEDULE_INTERRUPT( cpu, wait )</literal></term> +<listitem> +<para> +Sends the CPU a reschedule interrupt, and if +<parameter>wait</parameter> is non-zero, waits for an +acknowledgment. The interrupted CPU should call +<function>cyg_scheduler_set_need_reschedule()</function> in its DSR to +cause the reschedule to occur. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_CPU_TIMESLICE_INTERRUPT( cpu, wait )</literal></term> +<listitem> +<para> +Sends the CPU a timeslice interrupt, and if +<parameter>wait</parameter> is non-zero, waits for an +acknowledgment. The interrupted CPU should call +<function>cyg_scheduler_timeslice_cpu()</function> to cause the +timeslice event to be processed. +</para> +</listitem> +</varlistentry> +</variablelist> +</section> + + +<section> +<title>Test-and-set Support</title> + +<para> +Test-and-set is the foundation of the SMP synchronization +mechanisms. +</para> + +<variablelist> +<varlistentry> +<term><literal>HAL_TAS_TYPE</literal></term> +<listitem> +<para> +The type for all test-and-set variables. The +test-and-set macros only support operations on +a single bit (usually the least significant +bit) of this location. This allows for maximum +flexibility in the implementation. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_TAS_SET( tas, oldb )</literal></term> +<listitem> +<para> +Performs a test and set operation on the +location <parameter>tas</parameter>. <parameter>oldb</parameter> will contain <literal>true</literal> if +the location was already set, and <literal>false</literal> if +it was clear. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_TAS_CLEAR( tas, oldb )</literal></term> +<listitem> +<para> +Performs a test and clear operation on the +location <parameter>tas</parameter>. <parameter>oldb</parameter> will contain <literal>true</literal> if +the location was already set, and <literal>false</literal> if +it was clear. +</para> +</listitem> +</varlistentry> +</variablelist> +</section> +<section> + +<title>Spinlocks</title> + +<para> +Spinlocks provide inter-CPU locking. Normally they will be implemented +on top of the test-and-set mechanism above, but may also be +implemented by other means if, for example, the hardware has more +direct support for spinlocks. +</para> + +<variablelist> +<varlistentry> +<term><literal>HAL_SPINLOCK_TYPE</literal></term> +<listitem> +<para> +The type for all spinlock variables. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SPINLOCK_INIT_CLEAR</literal></term> +<listitem> +<para> +A value that may be assigned to a spinlock +variable to initialize it to clear. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SPINLOCK_INIT_SET</literal></term> +<listitem> +<para> +A value that may be assigned to a spinlock +variable to initialize it to set. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SPINLOCK_SPIN( lock )</literal></term> +<listitem> +<para> +The caller spins in a busy loop waiting for +the lock to become clear. It then sets it and +continues. This is all handled atomically, so +that there are no race conditions between CPUs. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SPINLOCK_CLEAR( lock )</literal></term> +<listitem> +<para> +The caller clears the lock. One of any waiting +spinners will then be able to proceed. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SPINLOCK_TRY( lock, val )</literal></term> +<listitem> +<para> +Attempts to set the lock. The value put in +<parameter>val</parameter> will be <literal>true</literal> if the lock was +claimed successfully, and <literal>false</literal> if it was +not. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SPINLOCK_TEST( lock, val )</literal></term> +<listitem> +<para> +Tests the current value of the lock. The value +put in <parameter>val</parameter> will be <literal>true</literal> if the lock is +claimed and <literal>false</literal> of it is clear. +</para> +</listitem> +</varlistentry> +</variablelist> +</section> +<section> + +<title>Scheduler Lock</title> + +<para> +The scheduler lock is the main protection for all kernel data +structures. By default the kernel implements the scheduler lock itself +using a spinlock. However, if spinlocks cannot be supported by the +hardware, or there is a more efficient implementation available, the +HAL may provide macros to implement the scheduler lock. +</para> + +<variablelist> +<varlistentry> +<term><literal>HAL_SMP_SCHEDLOCK_DATA_TYPE</literal></term> +<listitem> +<para> +A data type, possibly a structure, that +contains any data items needed by the +scheduler lock implementation. A variable of +this type will be instantiated as a static +member of the Cyg_Scheduler_SchedLock class +and passed to all the following macros. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_SCHEDLOCK_INIT( lock, data )</literal></term> +<listitem> +<para> +Initialize the scheduler lock. The <parameter>lock</parameter> +argument is the scheduler lock counter and the +<parameter>data</parameter> argument is a variable of +HAL_SMP_SCHEDLOCK_DATA_TYPE type. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_SCHEDLOCK_INC( lock, data )</literal></term> +<listitem> +<para> +Increment the scheduler lock. The first +increment of the lock from zero to one for any +CPU may cause it to wait until the lock is +zeroed by another CPU. Subsequent increments +should be less expensive since this CPU +already holds the lock. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_SCHEDLOCK_ZERO( lock, data )</literal></term> +<listitem> +<para> +Zero the scheduler lock. This operation will +also clear the lock so that other CPUs may +claim it. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_SMP_SCHEDLOCK_SET( lock, data, new )</literal></term> +<listitem> +<para> +Set the lock to a different value, in +<parameter>new</parameter>. This is only called when the lock is +already known to be owned by the current CPU. It is never called to +zero the lock, or to increment it from zero. +</para> +</listitem> +</varlistentry> + +</variablelist> +</section> +<section> + +<title>Interrupt Routing</title> + +<para> +The routing of interrupts to different CPUs is supported by two new +interfaces in hal_intr.h. +</para> + +<para> +Once an interrupt has been routed to a new CPU, the existing vector +masking and configuration operations should take account of the CPU +routing. For example, if the operation is not invoked on the +destination CPU itself, then the HAL may need to arrange to transfer +the operation to the destination CPU for correct application. +</para> + +<variablelist> +<varlistentry> +<term><literal>HAL_INTERRUPT_SET_CPU( vector, cpu )</literal></term> +<listitem> +<para> +Route the interrupt for the given <parameter>vector</parameter> to +the given <parameter>cpu</parameter>. +</para> +</listitem> +</varlistentry> + +<varlistentry> +<term><literal>HAL_INTERRUPT_GET_CPU( vector, cpu )</literal></term> +<listitem> +<para> +Set <parameter>cpu</parameter> to the id of the CPU to which this +vector is routed. +</para> +</listitem> +</varlistentry> +</variablelist> + +</section> + +</section> + + +</section> + +<!-- }}} --> + +</CHAPTER> + +<!-- }}} --> +<!-- {{{ Exception Handling --> + +<CHAPTER id="hal-exception-handling"> +<TITLE>Exception Handling</TITLE> + +<!-- {{{ Intro --> + +<para> +Most of the HAL consists of simple macros or functions that are +called via the interfaces described in the previous section. These +just perform whatever operation is required by accessing the hardware +and then return. The exception to this is the handling of exceptions: +either synchronous hardware traps or asynchronous device +interrupts. Here control is passed first to the HAL, which then passed +it on to eCos or the application. After eCos has finished with it, +control is then passed back to the HAL for it to tidy up the CPU state +and resume processing from the point at which the exception occurred. +</para> + +<PARA> +The HAL exceptions handling code is usually found in the file +<FILENAME>vectors.S</FILENAME> in the architecture HAL. Since the +reset entry point is usually implemented as one of these it also deals +with system startup. +</PARA> + +<PARA> +The exact implementation of this code is under the control of the HAL +implementer. So long as it interacts correctly with the interfaces +defined previously it may take any form. However, all current +implementation follow the same pattern, and there should be a very +good reason to break with this. The rest of this section describes +these operate. +</PARA> + +<para> +Exception handling normally deals with the following broad areas of +functionality: +</para> + +<ITEMIZEDLIST> + <LISTITEM> + <PARA>Startup and initialization.</PARA> + </LISTITEM> + + <LISTITEM> + <PARA>Hardware exception delivery.</PARA> + </LISTITEM> + + <LISTITEM> + <PARA>Default handling of synchronous exceptions.</PARA> + </LISTITEM> + + <LISTITEM> + <PARA>Default handling of asynchronous interrupts.</PARA> + </LISTITEM> +</ITEMIZEDLIST> + +<!-- }}} --> +<!-- {{{ HAL Startup --> + +<SECTION id="hal-startup"> +<TITLE><!-- <index></index> --><!-- <xref> -->HAL Startup</TITLE> + +<PARA> +Execution normally begins at the reset vector with +the machine in a minimal startup state. From here the HAL needs to get +the machine running, set up the execution environment for the +application, and finally invoke its entry point. +</PARA> + +<PARA> +The following is a list of the jobs that need to be done in +approximately the order in which they should be accomplished. Many +of these will not be needed in some configurations. +</PARA> + +<ITEMIZEDLIST> + <listitem> + <para> + Initialize the hardware. This may involve initializing several + subsystems in both the architecture, variant and platform + HALs. These include: + </para> + <itemizedlist> + <LISTITEM> + <PARA> + Initialize various CPU status registers. Most importantly, the CPU + interrupt mask should be set to disable interrupts. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Initialize the MMU, if it is used. On many platforms it is + only possible to control the cacheability of address ranges + via the MMU. Also, it may be necessary to remap RAM and device + registers to locations other than their defaults. However, for + simplicity, the mapping should be kept as close to one-to-one + physical-to-virtual as possible. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Set up the memory controller to access RAM, ROM and I/O devices + correctly. Until this is done it may not be possible to access + RAM. If this is a ROMRAM startup then the program code can + now be copied to its RAM address and control transferred to it. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Set up any bus bridges and support chips. Often access to + device registers needs to go through various bus bridges and + other intermediary devices. In many systems these are combined + with the memory controller, so it makes sense to set these up + together. This is particularly important if early diagnostic + output needs to go through one of these devices. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Set up diagnostic mechanisms. If the platform includes an LED or + LCD output device, it often makes sense to output progress + indications on this during startup. This helps with diagnosing + hardware and software errors. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Initialize floating point and other extensions such as SIMD + and multimedia engines. It is usually necessary to enable + these and maybe initialize control and exception registers for + these extensions. + </PARA> + </LISTITEM> + + + <LISTITEM> + <PARA> + Initialize interrupt controller. At the very least, it should + be configured to mask all interrupts. It may also be necessary + to set up the mapping from the interrupt controller's vector + number space to the CPU's exception number space. Similar + mappings may need to be set up between primary and secondary + interrupt controllers. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Disable and initialize the caches. The caches should not + normally be enabled at this point, but it may be necessary to + clear or initialize them so that they can be enabled + later. Some architectures require that the caches be + explicitly reinitialized after a power-on reset. + </PARA> + </LISTITEM> + + + <LISTITEM> + <PARA> + Initialize the timer, clock etc. While the timer used for RTC + interrupts will be initialized later, it may be necessary to + set up the clocks that drive it here. + </PARA> + </LISTITEM> + + </itemizedlist> + <para> + The exact order in which these initializations is done is + architecture or variant specific. It is also often not necessary + to do anything at all for some of these options. These fragments + of code should concentrate on getting the target up and running so + that C function calls can be made and code can be run. More + complex initializations that cannot be done in assembly code may + be postponed until calls to + <function>hal_variant_init()</function> or + <function>hal_platform_init()</function> are made. + </para> + + <para> + Not all of these initializations need to be done for all startup + types. In particular, RAM startups can reasonably assume that the + ROM monitor or loader has already done most of this work. + </para> + + </listitem> + + <LISTITEM> + <PARA> + Set up the stack pointer, this allows subsequent initialization + code to make proper procedure calls. Usually the interrupt stack + is used for this purpose since it is available, large enough, and + will be reused for other purposes later. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Initialize any global pointer register needed for access to + globally defined variables. This allows subsequent initialization + code to access global variables. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + If the system is starting from ROM, copy the ROM template of the + <filename>.data</filename> section out to its correct position in + RAM. (<xref linkend="hal-linker-scripts">). + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Zero the <filename>.bss</filename> section. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Create a suitable C call stack frame. This may involve making + stack space for call frames, and arguments, and initializing the + back pointers to halt a GDB backtrace operation. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Call <function>hal_variant_init()</function> and + <function>hal_platform_init()</function>. These will perform any + additional initialization needed by the variant and platform. This + typically includes further initialization of the interrupt + controller, PCI bus bridges, basic IO devices and enabling the + caches. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Call <FUNCTION>cyg_hal_invoke_constructors()</FUNCTION> to run any + static constructors. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Call <FUNCTION>cyg_start()</FUNCTION>. If + <FUNCTION>cyg_start()</FUNCTION> returns, drop into an infinite + loop. + </PARA> + </LISTITEM> +</ITEMIZEDLIST> + +</SECTION> + +<!-- }}} --> +<!-- {{{ Vectors and VSRs --> + +<SECTION id="hal-vectors-and-vsrs"><!-- <index></index> --> +<TITLE>Vectors and VSRs</TITLE> + +<PARA> +The CPU delivers all <!-- <index></index> --> exceptions, whether +synchronous faults or asynchronous interrupts, to a set of hardware +defined vectors. Depending on the architecture, these may be +implemented in a number of different ways. Examples of existing +mechanisms are: +</PARA> + +<VARIABLELIST> + <VARLISTENTRY> + <TERM>PowerPC</TERM> + <LISTITEM> + <PARA> + Exceptions are vectored to locations 256 bytes apart starting at + either zero or <literal>0xFFF00000</literal>. There are 16 such + vectors defined by the basic architecture and extra vectors may + be defined by specific variants. One of the base vectors is for + all external interrupts, and another is for the architecture + defined timer. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>MIPS</TERM> + <LISTITEM> + <PARA> + Most exceptions and all interrupts are vectored to a single + address at either <literal>0x80000000</literal> or + <literal>0xBFC00180</literal>. Software is responsible for + reading the exception code from the CPU <literal>cause</literal> + register to discover its true source. Some TLB and debug + exceptions are delivered to different vector addresses, but + these are not used currently by eCos. One of the exception codes + in the <literal>cause</literal> register indicates an external + interrupt. Additional bits in the <literal>cause</literal> + register provide a first-level decode for the interrupt source, + one of which represents an architecture defined timer. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>IA32</TERM> + <LISTITEM> + <PARA> + Exceptions are delivered via an Interrupt Descriptor Table (IDT) + which is essentially an indirection table indexed by exception + number. The IDT may be placed anywhere in memory. In PC hardware + the standard interrupt controller can be programmed to deliver + the external interrupts to a block of 16 vectors at any offset + in the IDT. There is no hardware supplied mechanism for + determining the vector taken, other than from the address jumped + to. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>ARM</TERM> + <LISTITEM> + <PARA> + All exceptions, including the FIQ and IRQ interrupts, are + vectored to locations four bytes apart starting at zero. There + is only room for one instruction here, which must immediately + jump out to handling code higher in memory. Interrupt sources + have to be decoded entirely from the interrupt controller. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> + + +<para> +With such a wide variety of hardware approaches, it is not possible to +provide a generic mechanism for the substitution of exception vectors +directly. Therefore, eCos translates all of these mechanisms in to a +common approach that can be used by portable code on all platforms. +</para> + +<para> +The mechanism implemented is to attach to each hardware vector a short +piece of trampoline code that makes an indirect jump via a table to +the actual handler for the exception. This handler is called the +Vector Service Routine (VSR) and the table is called the VSR table. +</para> + +<para> +The trampoline code performs the absolute minimum processing necessary +to identify the exception source, and jump to the VSR. The VSR is then +responsible for saving the CPU state and taking the necessary actions +to handle the exception or interrupt. The entry conditions for the VSR +are as close to the raw hardware exception entry state as possible - +although on some platforms the trampoline will have had to move or +reorganize some registers to do its job. +</para> + +<para> +To make this more concrete, consider how the trampoline code operates +in each of the architectures described above: +</para> + + +<VARIABLELIST> + <VARLISTENTRY> + <TERM>PowerPC</TERM> + <LISTITEM> + <PARA> + A separate trampoline is contained in each of the vector + locations. This code saves a few work registers away to the + special purposes registers available, loads the exception number + into a register and then uses that to index the VSR table and + jump to the VSR. The VSR is entered with some registers move to + the SPRs, and one of the data register containing the number of + the vector taken. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>MIPS</TERM> + <LISTITEM> + <PARA> + A single trampoline routine attached to the common vector reads + the exception code out of the <literal>cause</literal> register + and uses that value to index the VSR table and jump to the VSR. + The trampoline uses the two registers defined in the ABI for + kernel use to do this, one of these will contain the exception + vector number for the VSR. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>IA32</TERM> + <LISTITEM> + <PARA> + There is a separate 3 or 4 instruction trampoline pointed to by + each active IDT table entry. The trampoline for exceptions that + also have an error code pop it from the stack and put it into a + memory location. Trampolines for non-error-code exceptions just + zero the memory location. Then all trampolines push an + interrupt/exception number onto the stack, and take an indirect + jump through a precalculated offset in the VSR table. This is + all done without saving any registers, using memory-only + operations. The VSR is entered with the vector number pushed + onto the stack on top of the standard hardware saved state. + </PARA> + </LISTITEM> + </VARLISTENTRY> + + <VARLISTENTRY> + <TERM>ARM</TERM> + <LISTITEM> + <PARA> + The trampoline consists solely of the single instruction at the + exception entry point. This is an indirect jump via a location + 32 bytes higher in memory. These locations, from + <literal>0x20</literal> up, form the VSR table. Since each VSR + is entered in a different CPU mode + (<literal>SVC,UNDEF,ABORT,IRQ or FIQ</literal>) there has to be a + different VSR for each exception that knows how to save the CPU + state correctly. + </PARA> + </LISTITEM> + </VARLISTENTRY> +</VARIABLELIST> + +</section> + +<!-- }}} --> +<!-- {{{ Synchronous Exception Handling --> + +<SECTION id="hal-default-synchronous-exception-handling"> +<TITLE><!-- <index></index> -->Default Synchronous Exception Handling</TITLE> + +<PARA> +Most synchronous exception VSR table entries will point to a default +exception VSR which is responsible for handling all exceptions in a +generic manner. The default VSR simply saves the CPU state, makes any +adjustments to the CPU state that is necessary, and calls +<function>cyg_hal_exception_handler()</function>. +</PARA> + +<PARA> +<function>cyg_hal_exception_handler()</function> needs to pass the +exception on to some handling code. There are two basic destinations: +enter GDB or pass the exception up to eCos. Exactly which +destination is taken depends on the configuration. When the GDB stubs are +included then the exception is passed to them, otherwise it is passed +to eCos. +</PARA> + +<para> +If an eCos application has been loaded by RedBoot then the VSR table +entries will all point into RedBoot's exception VSR, and will +therefore enter GDB if an exception occurs. If the eCos application +wants to handle an exception itself, it needs to replace the the VSR +table entry with one pointing to its own VSR. It can do this with the +<function>HAL_VSR_SET_TO_ECOS_HANDLER()</function> macro. +</para> + +</SECTION> + +<!-- }}} --> +<!-- {{{ Interrupt Handling --> + +<SECTION id="hal-default-interrupt-handling"> +<TITLE><!-- <index></index> -->Default Interrupt Handling</TITLE> + +<PARA> +Most asynchronous external interrupt vectors will point to a default +interrupt VSR which decodes the actual interrupt being delivered from +the interrupt controller and invokes the appropriate ISR. +</PARA> + +<PARA> +The default interrupt VSR has a number of responsibilities if it is +going to interact with the Kernel cleanly and allow interrupts to +cause thread preemption. +</PARA> + +<PARA> +To support this VSR an ISR vector table is needed. For each valid +vector three pointers need to be stored: the ISR, its data pointer and +an opaque (to the HAL) interrupt object pointer needed by the +kernel. It is implementation defined whether these are stored in a +single table of triples, or in three separate tables. +</PARA> + +<PARA> +The VSR follows the following approximate plan: +</PARA> + +<ORDEREDLIST> + <LISTITEM> + <PARA> + Save the CPU state. In non-debug configurations, it may be + possible to get away with saving less than the entire machine + state. The option + <literal>CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT</literal> + is supported in some targets to do this. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Increment the kernel scheduler lock. This is a static member of + the Cyg_Scheduler class, however it has also been aliased to + <literal>cyg_scheduler_sched_lock</literal> so that it can be + accessed from assembly code. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + (Optional) Switch to an interrupt stack if not already running on + it. This allows nested interrupts to be delivered without needing + every thread to have a stack large enough to take the maximum + possible nesting. It is implementation defined how to detect + whether this is a nested interrupt but there are two basic + techniques. The first is to inspect the stack pointer and switch + only if it is not currently within the interrupt stack range; the + second is to maintain a counter of the interrupt nesting level and + switch only if it is zero. The option + <literal>CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK</literal> + controls whether this happens. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Decode the actual external interrupt being delivered from + the interrupt controller. This will yield the ISR vector + number. The code to do this usually needs to come from the + variant or platform HAL, so is usually present in the form of a + macro or procedure callout. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + (Optional) Re-enable interrupts to permit nesting. At this point + we can potentially allow higher priority interrupts to occur. It + depends on the interrupt architecture of the CPU and platform + whether more interrupts will occur at this point, or whether they + will only be delivered after the current interrupt has been + acknowledged (by a call to + <function>HAL_INTERRUPT_ACKNOWLEDGE()</function> in the ISR). + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Using the ISR vector number as an index, retrieve the + ISR pointer and its data pointer from the ISR vector table. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Construct a C call stack frame. This may involve making stack + space for call frames, and arguments, and initializing the back + pointers to halt a GDB backtrace operation. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Call the ISR, passing the vector number and data pointer. The + vector number and a pointer to the saved state should be preserved + across this call, preferably by storing them in registers that are + defined to be callee-saved by the calling conventions. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + If this is an un-nested interrupt and a separate interrupt + stack is being used, switch back to the interrupted thread's + own stack. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Use the saved ISR vector number to get the interrupt object + pointer from the ISR vector table. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + Call <FUNCTION>interrupt_end()</FUNCTION> passing it the return + value from the ISR, the interrupt object pointer and a pointer to + the saved CPU state. This function is implemented by the Kernel + and is responsible for finishing off the interrupt + handling. Specifically, it may post a DSR depending on the ISR + return value, and will decrement the scheduler lock. If the lock + is zeroed by this operation then any posted DSRs may be called and + may in turn result in a thread context switch. + </PARA> + </LISTITEM> + + <LISTITEM> + <PARA> + The return from <FUNCTION>interrupt_end()</FUNCTION> may occur + some time after the call. Many other threads may have executed in + the meantime. So here all we may do is restore the machine state + and resume execution of the interrupted thread. Depending on the + architecture, it may be necessary to disable interrupts again for + part of this. + </PARA> + </LISTITEM> + +</ORDEREDLIST> + +<PARA> +The detailed order of these steps may vary slightly depending on the +architecture, in particular where interrupts are enabled and disabled. +</PARA> + +</SECTION> + +<!-- }}} --> + +</CHAPTER> + +<!-- }}} --> +<!-- {{{ Porting Guide --> + +&hal-common-porting-sgml; + +<!-- }}} --> +<!-- {{{ Future Developments --> + +<CHAPTER id="hal-future-developments"> +<TITLE><!-- <index></index> --><!-- <xref> -->Future developments</TITLE> + +<PARA> +The HAL is not complete, and will evolve and increase over +time. Among the intended developments are: +</PARA> +<ITEMIZEDLIST> +<LISTITEM> +<PARA>Common macros for interpreting the contents of a saved +machine context. These would allow portable code, such as debug +stubs, to extract such values as the program counter and stack pointer +from a state without having to interpret a <STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure +directly.</PARA> +</LISTITEM> +<LISTITEM> +<PARA>Debugging support. Macros to set and clear hardware and +software breakpoints. Access to other areas of machine state may +also be supported.</PARA> +</LISTITEM> +<LISTITEM> +<PARA>Static initialization support. The current HAL provides a +dynamic interface to things like thread context initialization and ISR +attachment. We also need to be able to define the system entirely +statically so that it is ready to go on restart, without needing to +run code. This will require extra macros to define these +initializations. Such support may have a consequential effect on the +current HAL specification.</PARA> +</LISTITEM> +<LISTITEM> +<PARA>CPU state control. Many CPUs have both kernel and user +states. Although it is not intended to run any code in user state +for the foreseeable future, it is possible that this may happen +eventually. If this is the case, then some minor changes may be needed +to the current HAL API to accommodate this. These should mostly +be extensions, but minor changes in semantics may also be required.</PARA> +</LISTITEM> +<LISTITEM> +<PARA>Physical memory management. Many embedded systems have +multiple memory areas with varying properties such as base address, +size, speed, bus width, cacheability and persistence. An API is +needed to support the discovery of this information about the machine's +physical memory map.</PARA> +</LISTITEM> +<LISTITEM> +<PARA>Memory management control. Some embedded processors have +a memory management unit. In some cases this must be enabled to +allow the cache to be controlled, particularly if different regions +of memory must have different caching properties. For some purposes, +in some systems, it will be useful to manipulate the MMU settings +dynamically.</PARA> +</LISTITEM> +<LISTITEM> +<PARA>Power management. Macros to access and control any power +management mechanisms available on the CPU implementation. These +would provide a substrate for a more general power management system +that also involved device drivers and other hardware components.</PARA> +</LISTITEM> +<LISTITEM> +<PARA>Generic serial line macros. Most serial line devices operate +in the same way, the only real differences being exactly which bits +in which registers perform the standard functions. It should be +possible to develop a set of HAL macros that provide basic serial +line services such as baud rate setting, enabling interrupts, polling +for transmit or receive ready, transmitting and receiving data etc. +Given these it should be possible to create a generic serial line +device driver that will allow rapid bootstrapping on any new platform. +It may be possible to extend this mechanism to other device types.</PARA> +</LISTITEM> +</ITEMIZEDLIST> +</CHAPTER> + +<!-- }}} --> + +</part> diff --git a/ecos/packages/hal/common/current/doc/porting.sgml b/ecos/packages/hal/common/current/doc/porting.sgml new file mode 100644 index 0000000..792150f --- /dev/null +++ b/ecos/packages/hal/common/current/doc/porting.sgml @@ -0,0 +1,4391 @@ +<!-- {{{ Banner --> + +<!-- =============================================================== --> +<!-- --> +<!-- porting.sgml --> +<!-- --> +<!-- eCos common HAL documentation --> +<!-- --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTBEGIN#### --> +<!-- =============================================================== --> +<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2010 Free Software Foundation, Inc. --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<CHAPTER id="hal-porting-guide"> +<TITLE><!-- <index></index> --> Porting Guide</TITLE> + +<!-- {{{ Intro --> + +<section id="hal-porting-intro"> +<title>Introduction</title> + +<para> +eCos has been designed to be fairly easy to port to new targets. A +target is a specific platform (board) using a given architecture (CPU +type). The porting is facilitated by the hierarchical layering of the +eCos sources - all architecture and platform specific code is +implemented in a HAL (hardware abstraction layer). +</para> + +<para> +By porting the eCos HAL to a new target the core functionality of eCos +(infra, kernel, uITRON, etc) will be able to run on the target. It may +be necessary to add further platform specific code such as serial +drivers, display drivers, ethernet drivers, etc. to get a fully +capable system. +</para> + +<para> +This document is intended as a help to the HAL porting process. Due to +the nature of a porting job, it is impossible to give a complete +description of what has to be done for each and every potential +target. This should not be considered a clear-cut recipe - you will +probably need to make some implementation decisions, tweak a few +things, and just plain have to rely on common sense. +</para> + +<para> +However, what is covered here should be a large part of the +process. If you get stuck, you are advised to read the +<ulink url="http://ecos.sourceware.org/ml/ecos-discuss/"> +ecos-discuss archive +</ulink> +where you may find discussions which apply to the problem at +hand. You are also invited to ask questions on the +<ulink url="http://ecos.sourceware.org/intouch.html"> +ecos-discuss mailing list +</ulink> +to help you resolve problems - but as is always the case +with community lists, do not consider it an oracle for any and all +questions. Use common sense - if you ask too many questions which +could have been answered by reading the +<ulink +url="http://ecos.sourceware.org/ecos/docs-latest/">documentation</ulink>, +<ulink url="http://ecos.sourceware.org/fom/ecos">FAQ</ulink> or +<ulink url="http://ecos.sourceware.org/cgi-bin/cvsweb.cgi/ecos/packages/?cvsroot=ecos"> +source code +</ulink>, you are likely to be ignored. +</para> + +<para> +This document will be continually improved by Red Hat engineers as +time allows. Feedback and help with improving the document is sought, +so if you have any comments at all, please do not hesitate to post +them on +<ulink url="mailto:ecos-discuss@ecos.sourceware.org?subject=[porting]<subject>"> +ecos-discuss +</ulink> +(please prefix the subject with [porting]). +</para> + +<para> +At the moment this document is mostly an outline. There are many +details to fill in before it becomes complete. Many places you'll just +find a list of keywords / concepts that should be described (please +post on ecos-discuss if there are areas you think are not covered). +</para> + +<para> +All pages or sections where the caption ends in [TBD] contain little +more than key words and/or random thoughts - there has been no work +done as such on the content. The word FIXME may appear in the text to +highlight places where information is missing. +</para> + +</section> + +<!-- }}} --> +<!-- {{{ HAL Structure --> + +<section id="hal-porting-structure"> +<title>HAL Structure</title> + +<para> +In order to write an eCos HAL it's a good idea to have at least a +passing understanding of how the HAL interacts with the rest of the +system. +</para> + +<!-- {{{ HAL Classes --> + +<section> +<title>HAL Classes</title> + +<para> +The eCos HAL consists of four HAL sub-classes. This table gives a +brief description of each class and partly reiterates the description +in <xref linkend="hal-architecture-variant-and-platform">. The links +refer to the on-line CVS tree (specifically to the sub-HALs used by +the PowerPC MBX target). +</para> + +<informaltable frame=all> +<tgroup cols=3 align=left colsep=1 rowsep=1> +<thead> +<row> +<entry>HAL type</entry> +<entry>Description</entry> +<entry>Functionality Overview</entry> +</row> +</thead> +<tbody> +<row> +<entry> +Common HAL <ulink url="http://ecos.sourceware.org/cgi-bin/cvsweb.cgi/ecos/packages/hal/common/current?cvsroot=ecos">(hal/common)</ulink> +</entry> +<entry>Configuration options and functionality shared by all HALs.</entry> +<entry>Generic debugging functionality, driver API, eCos/ROM monitor + calling interface, and tests.</entry> +</row> +<row> + <entry>Architecture HAL <ulink url="http://ecos.sourceware.org/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/arch/current?cvsroot=ecos">(hal/<architecture>/arch)</ulink></entry> + <entry>Functionality specific to the given architecture. Also default + implementations of some functionality which can be overridden by + variant or platform HALs.</entry> + <entry>Architecture specific debugger functionality (handles single + stepping, exception-to-signal conversion, etc.), + exception/interrupt vector definitions and handlers, cache + definition and control macros, context switching code, assembler + functions for early system initialization, configuration options, + and possibly tests. </entry> +</row> +<row> + <entry>Variant HAL <ulink url="http://ecos.sourceware.org/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/mpc8xx/current?cvsroot=ecos">(hal/<architecture>/<variant>)</ulink></entry> + <entry>Some CPU architectures consist of a number variants, for example + MIPS CPUs come in both 32 and 64 bit versions, and some variants + have embedded features additional to the CPU core. +</entry> + <entry>Variant extensions to the architecture code (cache, + exception/interrupt), configuration options, possibly drivers for + variant on-core devices, and possibly tests.</entry> +</row> +<row> + <entry>Platform HAL <ulink url="http://ecos.sourceware.org/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/mbx/current?cvsroot=ecos">(hal/<architecture>/<platform>)</ulink></entry> + <entry>Contains functionality and configuration options specific to the + platform. +</entry> + <entry>Early platform initialization code, platform memory layout + specification, configuration options (processor speed, compiler + options), diagnostic IO functions, debugger IO functions, + platform specific extensions to architecture or variant code + (off-core interrupt controller), and possibly tests.</entry> +</row> +<row> + <entry>Auxiliary HAL <ulink url="http://ecos.sourceware.org/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/quicc/current?cvsroot=ecos">(hal/<architecture>/<module>)</ulink></entry> + <entry>Some variants share common modules on the core. Motorola's PowerPC + QUICC is an example of such a module. +</entry> + <entry>Module specific functionality (interrupt controller, simple + device drivers), possibly tests. +</entry> +</row> +</tbody> +</tgroup> +</informaltable> + +</section> + +<!-- }}} --> +<!-- {{{ File Descriptions --> + +<section> +<title>File Descriptions</title> + +<para> +Listed below are the files found in various HALs, with a short +description of what each file contains. When looking in existing HALs +beware that they do not necessarily follow this naming scheme. +If you are writing a new HAL, please try to follow it as +closely as possible. Still, no two targets are the same, so sometimes +it makes sense to use additional files. +</para> + +<!-- {{{ Common HAL --> + +<section> +<title>Common HAL</title> + +<informaltable frame=all> +<tgroup cols=2 align=left colsep=1 rowsep=1> +<thead> +<row> +<entry>File</entry> +<entry>Description</entry> +</row> +</thead> +<tbody> + +<row> +<entry><filename>include/dbg-thread-syscall.h</filename></entry> + <entry>Defines the thread debugging syscall function. This is used by + the ROM monitor to access the thread debugging API in the RAM + application. <!-- FIXME: link thread debug description -->.</entry> +</row> +<row> +<entry><filename>include/dbg-threads-api.h</filename></entry> + <entry>Defines the thread debugging API. <!-- FIXME: link thread + debug description -->.</entry> +</row> +<row> +<entry><filename>include/drv_api.h</filename></entry> + <entry>Defines the driver API.</entry> +</row> +<row> +<entry><filename>include/generic-stub.h</filename></entry> + <entry>Defines the generic stub features.</entry> +</row> +<row> +<entry><filename>include/hal_if.h</filename></entry> + <entry>Defines the ROM/RAM calling interface API.</entry> +</row> +<row> +<entry><filename>include/hal_misc.h</filename></entry> + <entry>Defines miscellaneous helper functions shared by all HALs.</entry> +</row> +<row> +<entry><filename>include/hal_stub.h</filename></entry> + <entry>Defines eCos mappings of GDB stub features.</entry> +</row> +<row> +<entry><filename>src/dbg-threads-syscall.c</filename></entry> + <entry>Thread debugging implementation.</entry> +</row> +<row> +<entry><filename>src/drv_api.c</filename></entry> + <entry>Driver API implementation. Depending on configuration this + provides either wrappers for the kernel API, or a minimal + implementation of these features. This allows drivers to be written + relying only on HAL features.</entry> +</row> +<row> +<entry><filename>src/dummy.c</filename></entry> + <entry>Empty dummy file ensuring creation of libtarget.a.</entry> +</row> +<row> +<entry><filename>src/generic-stub.c</filename></entry> + <entry>Generic GDB stub implementation. This provides the + communication protocol used to communicate with GDB over a serial + device or via the network.</entry> +</row> +<row> +<entry><filename>src/hal_if.c</filename></entry> + <entry>ROM/RAM calling interface implementation. Provides wrappers from + the calling interface API to the eCos features used for the + implementation.</entry> +</row> +<row> +<entry><filename>src/hal_misc.c</filename></entry> + <entry>Various helper functions shared by all platforms and + architectures.</entry> +</row> +<row> +<entry><filename>src/hal_stub.c</filename></entry> + <entry>Wrappers from eCos HAL features to the features required by the + generic GDB stub.</entry> +</row> +<row> +<entry><filename>src/stubrom/stubrom.c</filename></entry> + <entry>The file used to build eCos GDB stub images. Basically a + cyg_start function with a hard coded breakpoint.</entry> +</row> +<row> +<entry><filename>src/thread-packets.c</filename></entry> + <entry>More thread debugging related functions.</entry> +</row> +<row> +<entry><filename>src/thread-pkts.h</filename></entry> + <entry>Defines more thread debugging related function.</entry> +</row> +</tbody> +</tgroup> +</informaltable> + +</section> + +<!-- }}} --> +<!-- {{{ Architecture HAL --> + +<section> +<title>Architecture HAL</title> + +<para>Some architecture HALs may add extra files for architecture +specific serial drivers, or for handling interrupts and exceptions if it +makes sense.</para> + +<para>Note that many of the definitions in these files are only +conditionally defined - if the equivalent variant or platform headers +provide the definitions, those override the generic architecture +definitions.</para> + +<informaltable frame=all> +<tgroup cols=2 align=left colsep=1 rowsep=1> +<thead> +<row> +<entry>File</entry> +<entry>Description</entry> +</row> +</thead> +<tbody> + +<row> +<entry><filename>include/arch.inc</filename></entry> + <entry>Various assembly macros used during system initialization.</entry> +</row> +<row> +<entry><filename>include/basetype.h</filename></entry> + <entry>Endian, label, alignment, and type size definitions. These + override common defaults in CYGPKG_INFRA.</entry> +</row> +<row> +<entry><filename>include/hal_arch.h</filename></entry> + <entry>Saved register frame format, various thread, register and stack + related macros.</entry> +</row> +<row> +<entry><filename>include/hal_cache.h</filename></entry> + <entry>Cache definitions and cache control macros.</entry> +</row> +<row> +<entry><filename>include/hal_intr.h</filename></entry> + <entry>Exception and interrupt definitions. Macros for configuring and + controlling interrupts. eCos real-time clock control macros.</entry> +</row> +<row> +<entry><filename>include/hal_io.h</filename></entry> + <entry>Macros for accessing IO devices.</entry> +</row> +<row> +<entry><filename>include/<arch>_regs.h</filename></entry> + <entry>Architecture register definitions.</entry> +</row> +<row> +<entry><filename>include/<arch>_stub.h</filename></entry> + <entry>Architecture stub definitions. In particular the register frame + layout used by GDB. This may differ from the one used by eCos.</entry> +</row> +<row> +<entry><filename>include/<arch>.inc</filename></entry> + <entry>Architecture convenience assembly macros.</entry> +</row> +<row> +<entry><filename>src/<arch>.ld</filename></entry> + <entry>Linker macros.</entry> +</row> +<row> +<entry><filename>src/context.S</filename></entry> + <entry>Functions handling context switching and setjmp/longjmp.</entry> +</row> +<row> +<entry><filename>src/hal_misc.c</filename></entry> + <entry>Exception and interrupt handlers in C. Various other utility + functions.</entry> +</row> +<row> +<entry><filename>src/hal_mk_defs.c</filename></entry> + <entry>Used to export definitions from C header files to assembler + header files.</entry> +</row> +<row> +<entry><filename>src/hal_intr.c</filename></entry> + <entry>Any necessary interrupt handling functions.</entry> +</row> +<row> +<entry><filename>src/<arch>stub.c</filename></entry> + <entry>Architecture stub code. Contains functions for translating eCos + exceptions to UNIX signals and functions for single-stepping.</entry> +</row> +<row> +<entry><filename>src/vectors.S</filename></entry> + <entry>Exception, interrupt and early initialization code.</entry> +</row> +</tbody> +</tgroup> +</informaltable> + + +</section> + +<!-- }}} --> +<!-- {{{ Variant HAL --> + +<section> +<title>Variant HAL</title> + +<para>Some variant HALs may add extra files for variant specific serial +drivers, or for handling interrupts/exceptions if it makes sense.</para> + +<para>Note that these files may be mostly empty if the CPU variant can be +controlled by the generic architecture macros. The definitions present +are only conditionally defined - if the equivalent platform headers +provide the definitions, those override the variant definitions.</para> + +<informaltable frame=all> +<tgroup cols=2 align=left colsep=1 rowsep=1> +<thead> +<row> +<entry>File</entry> +<entry>Description</entry> +</row> +</thead> +<tbody> + +<row> +<entry><filename>include/var_arch.h</filename></entry> + <entry>Saved register frame format, various thread, register and stack + related macros.</entry> +</row> +<row> +<entry><filename>include/var_cache.h</filename></entry> + <entry>Cache related macros.</entry> +</row> +<row> +<entry><filename>include/var_intr.h</filename></entry> + <entry>Interrupt related macros.</entry> +</row> +<row> +<entry><filename>include/var_regs.h</filename></entry> + <entry>Extra register definitions for the CPU variant.</entry> +</row> +<row> +<entry><filename>include/variant.inc</filename></entry> + <entry>Various assembly macros used during system initialization.</entry> +</row> +<row> +<entry><filename>src/var_intr.c</filename></entry> + <entry>Interrupt functions if necessary.</entry> +</row> +<row> +<entry><filename>src/var_misc.c</filename></entry> + <entry>hal_variant_init function and any necessary extra functions.</entry> +</row> +<row> +<entry><filename>src/variant.S</filename></entry> + <entry>Interrupt handler table definition.</entry> +</row> +<row> +<entry><filename>src/<arch>_<variant>.ld</filename></entry> + <entry>Linker macros.</entry> +</row> +</tbody> +</tgroup> +</informaltable> + +</section> + +<!-- }}} --> +<!-- {{{ Platform HAL --> + +<section> +<title>Platform HAL</title> + +<para>Extras files may be added for platform specific serial +drivers. Extra files for handling interrupts and exceptions will be +present if it makes sense.</para> + +<informaltable frame=all> +<tgroup cols=2 align=left colsep=1 rowsep=1> +<thead> +<row> +<entry>File</entry> +<entry>Description</entry> +</row> +</thead> +<tbody> + +<row> +<entry><filename>include/hal_diag.h</filename></entry> + <entry>Defines functions used for HAL diagnostics output. This would + normally be the ROM calling interface wrappers, but may also be the + low-level IO functions themselves, saving a little overhead.</entry> +</row> +<row> +<entry><filename>include/platform.inc</filename></entry> + + <entry>Platform initialization code. This includes memory controller, + vectors, and monitor initialization. Depending on the architecture, + other things may need defining here as well: interrupt decoding, + status register initialization value, etc.</entry> + +</row> +<row> +<entry><filename>include/plf_cache.h</filename></entry> + <entry>Platform specific cache handling.</entry> +</row> +<row> +<entry><filename>include/plf_intr.h</filename></entry> + <entry>Platform specific interrupt handling.</entry> +</row> +<row> +<entry><filename>include/plf_io.h</filename></entry> + <entry>PCI IO definitions and macros. May also be used to override + generic HAL IO macros if the platform endianness differs from that of + the CPU.</entry> +</row> +<row> +<entry><filename>include/plf_stub.h</filename></entry> + <entry>Defines stub initializer and board reset details.</entry> +</row> +<row> +<entry><filename>src/hal_diag.c</filename></entry> + <entry>May contain the low-level device drivers. But these may also + reside in plf_stub.c</entry> +</row> +<row> +<entry><filename>src/platform.S</filename></entry> + <entry>Memory controller setup macro, and if necessary interrupt + springboard code.</entry> +</row> +<row> +<entry><filename>src/plf_misc.c</filename></entry> + <entry>Platform initialization code.</entry> +</row> +<row> +<entry><filename>src/plf_mk_defs.c</filename></entry> + <entry>Used to export definitions from C header files to assembler + header files.</entry> +</row> +<row> +<entry><filename>src/plf_stub.c</filename></entry> + <entry>Platform specific stub initialization and possibly the low-level + device driver.</entry> +</row> +</tbody> +</tgroup> +</informaltable> + +<para>The platform HAL also contains files specifying the platform's +memory layout. These files are located in +<filename>include/pkgconf</filename>.</para> + +</section> + +<!-- }}} --> +<!-- {{{ Auxiliary HAL --> + +<section> +<title>Auxiliary HAL</title> + +<para>Auxiliary HALs contain whatever files are necessary to provide the +required functionality. There are no predefined set of files required +in an auxiliary HAL.</para> + +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> +<!-- {{{ ROM Monitor Calling Interface --> + +<section id="hal-calling-if"> +<TITLE>Virtual Vectors (eCos/ROM Monitor Calling Interface)</TITLE> + +<para> +Virtually all eCos platforms provide full debugging capabilities +via RedBoot. This enviroment contains not only debug stubs based +on GDB, but also rich I/O support which can be exported to loaded +programs. Such programs can take advantage of the I/O capabilities +using a special ROM/RAM calling interface +(also referred to as virtual vector table). +eCos programs make use of the virtual vector mechanism implicitly. +Non-eCos programs can access these functions using the support from +the <emphasis>newlib</emphasis> library. +</para> + +<!-- {{{ Virtual Vectors --> + +<section id="hal-porting-virtual-vectors"> +<title>Virtual Vectors</title> + +<para>What are virtual vectors, what do they do, and why are they +needed? +</para> + +<para> +"Virtual vectors" is the name of a table located at a static +location in the target address space. This table contains 64 vectors +that point to <emphasis>service</emphasis> functions or data. +</para> + +<para>The fact that the vectors are always placed at the same location in +the address space means that both ROM and RAM startup configurations +can access these and thus the services pointed to.</para> + +<para>The primary goal is to allow services to be provided by ROM +configurations (ROM monitors such as RedBoot in particular) with +<emphasis>clients</emphasis> in RAM configurations being able to use these +services.</para> + +<para>Without the table of pointers this would be impossible since the +ROM and RAM applications would be linked separately - in effect having +separate name spaces - preventing direct references from one to the +other.</para> + +<para>This decoupling of service from client is needed by RedBoot, +allowing among other things debugging of applications which do not +contain debugging client code (stubs).</para> + +<!-- {{{ Initialization --> + +<section> +<title>Initialization (or Mechanism vs. Policy)</title> + +<para>Virtual vectors are a <emphasis>mechanism</emphasis> for decoupling services +from clients in the address space.</para> + +<para>The mechanism allows services to be implemented by a ROM +monitor, a RAM application, to be switched out at run-time, to be +disabled by installing pointers to dummy functions, etc.</para> + +<para>The appropriate use of the mechanism is specified loosely by a +<emphasis>policy</emphasis>. The general policy dictates that the vectors are +initialized in whole by ROM monitors (built for ROM or RAM), or by +stand-alone applications.</para> + +<para>For configurations relying on a ROM monitor environment, the policy +is to allow initialization on a service by service basis. The default +is to initialize all services, except COMMS services since these are +presumed to already be carrying a communication session to the +debugger / console which was used for launching the application. This +means that the bulk of the code gets tested in normal builds, and not +just once in a blue moon when building new stubs or a ROM +configuration.</para> + +<para>The configuration options are written to comply with this policy by +default, but can be overridden by the user if desired. Defaults +are:</para> + +<itemizedlist> +<listitem><para>For application development: the ROM monitor provides +debugging and diagnostic IO services, the RAM application relies +on these by default.</para> +</listitem> +<listitem> +<para>For production systems: the application contains all the +necessary services.</para> +</listitem> + +</itemizedlist> + +</section> + +<!-- }}} --> +<!-- {{{ Pros and Cons --> + +<section> +<title>Pros and Cons of Virtual Vectors</title> + +<para> +There are pros and cons associated with the use of virtual +vectors. We do believe that the pros generally outweigh the cons by a +great margin, but there may be situations where the opposite is +true. +</para> + +<para> +The use of the services are implemented by way of macros, meaning +that it is possible to circumvent the virtual vectors if +desired. There is (as yet) no implementation for doing this, but it is +possible. +</para> + +<para>Here is a list of pros and cons:</para> + +<variablelist> +<varlistentry><term>Pro: Allows debugging without including stubs</term> + + <listitem><para>This is the primary reason for using virtual vectors. It + allows the ROM monitor to provide most of the debugging + infrastructure, requiring only the application to provide + hooks for asynchronous debugger interrupts and for accessing + kernel thread information.</para></listitem></varlistentry> + +<varlistentry><term>Pro: Allows debugging to be initiated from arbitrary + channel</term> + + <listitem><para> While this is only true where the application does not + actively override the debugging channel setup, it is a very + nice feature during development. In particular it makes it + possible to launch (and/or debug) applications via Ethernet + even though the application configuration does not contain + networking support.</para></listitem></varlistentry> + +<varlistentry><term>Pro: Image smaller due to services being provided by ROM + monitor</term> + + <listitem><para>All service functions except HAL IO are included in the + default configuration. But if these are all disabled the + image for download will be a little smaller. Probably + doesn't matter much for regular development, but it is a + worthwhile saving for the 20000 daily tests run in the Red + Hat eCos test farm.</para></listitem></varlistentry> + +<varlistentry><term>Con: The vectors add a layer of indirection, increasing application + size and reducing performance.</term> + + <listitem><para>The size increase is a fraction of what is required to + implement the services. So for RAM configurations there is + a net saving, while for ROM configurations there is a small + overhead.</para> + + <para>The performance loss means little for most of the + services (of which the most commonly used is diagnostic IO + which happens via polled routines + anyway).</para></listitem> +</varlistentry> + +<varlistentry><term>Con: The layer of indirection is another point of + failure.</term> + + <listitem><para> The concern primarily being that of vectors being + trashed by rogue writes from bad code, causing a complete + loss of the service and possibly a crash. But this does + not differ much from a rogue write to anywhere else in the + address space which could cause the same amount of + mayhem. But it is arguably an additional point of failure + for the service in question.</para></listitem></varlistentry> + +<varlistentry><term>Con: All the indirection stuff makes it harder to bring a HAL + up</term> + + <listitem><para> This is a valid concern. However, seeing as most of the + code in question is shared between all HALs and should + remain unchanged over time, the risk of it being broken + when a new HAL is being worked on should be + minimal.</para> + + <para> When starting a new port, be sure to implement the HAL + IO drivers according to the scheme used in other drivers, + and there should be no problem.</para> + + <para> However, it is still possible to circumvent the vectors + if they are suspect of causing problems: simply change the + HAL_DIAG_INIT and HAL_DIAG_WRITE_CHAR macros to use the raw + IO functions.</para></listitem></varlistentry> +</variablelist> + +</section> + +<!-- }}} --> +<!-- {{{ Available Services --> + +<section> +<title>Available services</title> + +<para> +The <filename>hal_if.h</filename> file in the common HAL defines the +complete list of available services. A few worth mentioning in +particular:</para> + +<itemizedlist> +<listitem> <para>COMMS services. All HAL IO happens via the communication + channels.</para> +</listitem> +<listitem> <para>uS delay. Fine granularity (busy wait) delay function.</para> +</listitem> +<listitem> <para>Reset. Allows a software initiated reset of the board.</para> +</listitem> +</itemizedlist> + +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> +<!-- {{{ The COMMS Channels --> + +<section> +<title>The COMMS channels</title> + +<para>As all HAL IO happens via the COMMS channels these deserve to be +described in a little more detail. In particular the controls of where +diagnostic output is routed and how it is treated to allow for display +in debuggers.</para> + +<!-- {{{ Console and Debuggers Channels --> + +<section> +<title>Console and Debugging Channels</title> + +<para>There are two COMMS channels - one for console IO and one for +debugging IO. They can be individually configured to use any of the +actual IO ports (serial or Ethernet) available on the platform.</para> + +<para>The console channel is used for any IO initiated by calling the +<function>diag_*()</function> functions. Note that these should only be used during +development for debugging, assertion and possibly tracing +messages. All proper IO should happen via proper devices. This means +it should be possible to remove the HAL device drivers from production +configurations where assertions are disabled.</para> + +<para>The debugging channel is used for communication between the +debugger and the stub which remotely controls the target for the +debugger (the stub runs on the target). This usually happens via some +protocol, encoding commands and replies in some suitable form.</para> + +<para>Having two separate channels allows, e.g., for simple logging +without conflicts with the debugger or interactive IO which some +debuggers do not allow.</para> + +</section> + +<!-- }}} --> +<!-- {{{ Mangling --> + +<section> +<title>Mangling</title> + +<para>As debuggers usually have a protocol using specialized commands +when communicating with the stub on the target, sending out text as +raw ASCII from the target on the same channel will either result in +protocol errors (with loss of control over the target) or the text may +just be ignored as junk by the debugger.</para> + +<para>To get around this, some debuggers have a special command for text +output. Mangling is the process of encoding diagnostic ASCII text +output in the form specified by the debugger protocol.</para> + +<para>When it is necessary to use mangling, i.e. when writing console +output to the same port used for debugging, a mangler function is +installed on the console channel which mangles the text and passes it +on to the debugger channel.</para> + +</section> + +<!-- }}} --> +<!-- {{{ Controlling the Console Channel --> + +<section> +<title>Controlling the Console Channel</title> + +<para>Console output configuration is either inherited from the ROM +monitor launching the application, or it is specified by the +application. This is controlled by the new option +<literal>CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE</literal> which +defaults to enabled when the configuration is set to use a ROM +monitor.</para> + +<para>If the user wants to specify the console configuration in the +application image, there are two new options that are used for +this.</para> + +<para>Defaults are to direct diagnostic output via a mangler to the +debugging channel (<literal>CYGDBG_HAL_DIAG_TO_DEBUG_CHAN</literal> +enabled). The mangler type is controlled by the option +<literal>CYGSEM_HAL_DIAG_MANGLER</literal>. At present there are only +two mangler types:</para> + +<variablelist> +<varlistentry><term><acronym>GDB</acronym></term> + + <listitem><para> This causes a mangler appropriate for debugging with GDB to be + installed on the console channel.</para></listitem></varlistentry> + +<varlistentry><term>None</term> + + <listitem><para> This causes a NULL mangler to be installed on the console + channel. It will redirect the IO to/from the debug channel + without mangling of the data. This option differs from setting + the console channel to the same IO port as the debugging + channel in that it will keep redirecting data to the debugging + channel even if that is changed to some other port.</para></listitem></varlistentry> + +</variablelist> + +<para>Finally, by disabling <literal>CYGDBG_HAL_DIAG_TO_DEBUG_CHAN</literal>, the diagnostic +output is directed in raw form to the specified console IO port.</para> + +<para>In summary this results in the following common configuration +scenarios for RAM startup configurations:</para> + +<itemizedlist> +<listitem><para> For regular debugging with diagnostic output appearing in the + debugger, mangling is enabled and stubs disabled.</para> + + <para>Diagnostic output appears via the debugging channel as + initiated by the ROM monitor, allowing for correct behavior + whether the application was launched via serial or Ethernet, from + the RedBoot command line or from a debugger.</para> +</listitem> + +<listitem><para> For debugging with raw diagnostic output, mangling is + disabled.</para> + + <para> Debugging session continues as initiated by the ROM monitor, + whether the application was launched via serial or + Ethernet. Diagnostic output is directed at the IO port configured + in the application configuration.</para> + + <note> + <title>Note:</title> + <para> There is one caveat to be aware of. If the + application uses proper devices (be it serial or Ethernet) on + the same ports as those used by the ROM monitor, the + connections initiated by the ROM monitor will be + terminated.</para> + </note> +</listitem> + +</itemizedlist> + +<para>And for ROM startup configurations:</para> + +<itemizedlist> +<listitem><para> Production configuration with raw output and no debugging + features (configured for RAM or ROM), mangling is disabled, no + stubs are included.</para> + + <para>Diagnostic output appears (in unmangled form) on the specified + IO port.</para> +</listitem> + +<listitem><para> RedBoot configuration, includes debugging features and necessary + mangling.</para> + + <para>Diagnostic and debugging output port is auto-selected by the + first connection to any of the supported IO ports. Can change + from interactive mode to debugging mode when a debugger is + detected - when this happens a mangler will be installed as + required.</para> +</listitem> + +<listitem><para> GDB stubs configuration (obsoleted by RedBoot configuration), + includes debugging features, mangling is hardwired to GDB + protocol.</para> + + <para>Diagnostic and debugging output is hardwired to configured IO + ports, mangling is hardwired.</para> +</listitem> + +</itemizedlist> +</section> + +<!-- }}} --> +<!-- {{{ Footnote: Design Reasoning --> + +<section> +<title>Footnote: Design Reasoning for Control of Console Channel</title> + +<para>The current code for controlling the console channel is a +replacement for an older implementation which had some shortcomings +which addressed by the new implementation.</para> + +<para>This is what the old implementation did: on initialization it would +check if the CDL configured console channel differed from the active +debug channel - and if so, set the console channel, thereby disabling +mangling.</para> + +<para>The idea was that whatever channel was configured to be used for +console (i.e., diagnostic output) in the application was what should +be used. Also, it meant that if debug and console channels were +normally the same, a changed console channel would imply a request for +unmangled output.</para> + +<para>But this prevented at least two things:</para> + +<itemizedlist> +<listitem><para> It was impossible to inherit the existing connection by which + the application was launched (either by RedBoot commands via + telnet, or by via a debugger).</para> + + <para>This was mostly a problem on targets supporting Ethernet + access since the diagnostic output would not be returned via the + Ethernet connection, but on the configured serial port.</para> + + <para>The problem also occurred on any targets with multiple serial + ports where the ROM monitor was configured to use a different + port than the CDL defaults.</para> +</listitem> + +<listitem><para> Proper control of when to mangle or just write out raw ASCII + text.</para> + + <para>Sometimes it's desirable to disable mangling, even if the + channel specified is the same as that used for debugging. This + usually happens if GDB is used to download the application, but + direct interaction with the application on the same channel is + desired (GDB protocol only allows output from the target, no + input).</para> +</listitem> +</itemizedlist> + +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> +<!-- {{{ The Calling Interface API --> + +<section> +<title>The calling Interface API</title> + +<para>The calling interface API is defined by hal_if.h and hal_if.c in +hal/common.</para> + +<para>The API provides a set of services. Different platforms, or +different versions of the ROM monitor for a single platform, may +implement fewer or extra service. The table has room for growth, and +any entries which are not supported map to a NOP-service (when called +it returns 0 (<literal>false</literal>)). +</para> + +<para>A client of a service should either be selected by configuration, +or have suitable fall back alternatives in case the feature is not +implemented by the ROM monitor. +</para> + +<note> +<title>Note:</title> +<para> +Checking for unimplemented service when this may be a data +field/pointer instead of a function: suggest reserving the last entry +in the table as the NOP-service pointer. Then clients can compare a +service entry with this pointer to determine whether it's initialized +or not. +</para> +</note> + +<para>The header file <filename>cyg/hal/hal_if.h</filename> defines + the table layout and accessor macros (allowing primitive type + checking and alternative implementations should it become necessary). +</para> + +<para>The source file <filename>hal_if.c</filename> defines the table + initialization function. All HALs should call this during platform + initialization - the table will get initialized according to + configuration. Also defined here are wrapper functions which map + between the calling interface API and the API of the used eCos + functions. +</para> + +<!-- {{{ Implemented Services --> + +<section> +<title>Implemented Services</title> + +<para>This is a brief description of the services, some of which are +described in further detail below.</para> + +<variablelist> +<varlistentry><term><literal>VERSION</literal></term> + <listitem><para>Version of table. Serves as a way to check for how many + features are available in the table. This is the index of the + last service in the table.</para></listitem></varlistentry> +<varlistentry><term><literal>KILL_VECTOR</literal></term> + <listitem><para>[Presently unused by the stub code, but initialized] This + vector defines a function to execute when the system receives + a kill signal from the debugger. It is initialized with the + reset function (see below), but the application (or eCos) can + override it if necessary.</para></listitem></varlistentry> +<varlistentry><term><literal>CONSOLE_PROCS</literal></term> + <listitem><para>The communication procedure table used for console IO + (see <xref linkend="hal-porting-io-channels">.</para></listitem></varlistentry> +<varlistentry><term><literal>DEBUG_PROCS</literal></term> + <listitem><para>The communication procedure table used for debugger IO + (see <xref linkend="hal-porting-io-channels">).</para></listitem></varlistentry> +<varlistentry><term><literal>FLUSH_DCACHE</literal></term> + <listitem><para>Flushes the data cache for the specified + region. Some implementations may flush the entire data cache.</para></listitem></varlistentry> +<varlistentry><term><literal>FLUSH_ICACHE</literal></term> + <listitem><para>Flushes (invalidates) the instruction cache + for the specified region. Some implementations may flush the + entire instruction cache.</para></listitem></varlistentry> +<varlistentry><term><literal>SET_DEBUG_COMM</literal></term> + <listitem><para>Change debugging communication channel.</para></listitem></varlistentry> +<varlistentry><term><literal>SET_CONSOLE_COMM</literal></term> + <listitem><para>Change console communication channel.</para></listitem></varlistentry> +<varlistentry><term><literal>DBG_SYSCALL</literal></term> + <listitem><para>Vector used to communication between debugger functions in + ROM and in RAM. RAM eCos configurations may install a function + pointer here which the ROM monitor uses to get thread + information from the kernel running in RAM.</para></listitem></varlistentry> +<varlistentry><term><literal>RESET</literal></term> + <listitem><para>Resets the board on call. If it is not possible to reset + the board from software, it will jump to the ROM entry point + which will perform a "software" reset of the board.</para></listitem></varlistentry> +<varlistentry><term><literal>CONSOLE_INTERRUPT_FLAG</literal></term> + <listitem><para>Set if a debugger interrupt request was detected while + processing console IO. Allows the actual breakpoint action to + be handled after return to RAM, ensuring proper backtraces + etc.</para></listitem></varlistentry> +<varlistentry><term><literal>DELAY_US</literal></term> + <listitem><para>Will delay the specified number of microseconds. The + precision is platform dependent to some extend - a small value + (<100us) is likely to cause bigger delays than requested.</para></listitem></varlistentry> +<varlistentry><term><literal>FLASH_CFG_OP</literal></term> + <listitem><para>For accessing configuration settings kept in flash memory.</para></listitem></varlistentry> +<varlistentry><term><literal>INSTALL_BPT_FN</literal></term> + <listitem><para>Installs a breakpoint at the specified address. This is + used by the asynchronous breakpoint support + (see <!-- <xref linkend="hal-stubs-async-bps"> -->).</para></listitem></varlistentry> +</variablelist> +</section> + +<!-- }}} --> +<!-- {{{ Compatibility --> + +<section> +<title>Compatibility</title> + +<para>When a platform is changed to support the calling interface, +applications will use it if so configured. That means that if an +application is run on a platform with an older ROM monitor, the +service is almost guaranteed to fail. +</para> + +<para>For this reason, applications should only use Console Comm for HAL +diagnostics output if explicitly configured to do so +(<literal>CYGSEM_HAL_VIRTUAL_VECTOR_DIAG</literal>). +</para> + +<para>As for asynchronous GDB interrupts, the service will always be +used. This is likely to cause a crash under older ROM monitors, but +this crash may be caught by the debugger. The old workaround still +applies: if you need asynchronous breakpoints or thread debugging +under older ROM monitors, you may have to include the debugging +support when configuring eCos. +</para> + +</section> + +<!-- }}} --> +<!-- {{{ Implementation Details --> + +<section> +<title>Implementation details</title> + +<para>During the startup of a ROM monitor, the calling table will be +initialized. This also happens if eCos is configured <emphasis>not</emphasis> to rely on +a ROM monitor. +</para> + +<note> +<title>Note:</title> +<para> There is reserved space (256 bytes) for the vector +table whether it gets used or not. This may be something that we want +to change if we ever have to shave off every last byte for a given +target. +</para> +</note> + +<para>If thread debugging features are enabled, the function for accessing +the thread information gets registered in the table during startup of +a RAM startup configuration. +</para> + +<para>Further implementation details are described where the service itself +is described.</para> + +<!-- +FIXME: Need to describe the CYGARC_HAL_SAVE_GP() and +CYGARC_HAL_RESTORE_GP() macros. +--> + +</section> + +<!-- }}} --> +<!-- {{{ New Platform Ports --> + +<section> +<title>New Platform Ports</title> + +<para>The <function>hal_platform_init()</function> function must call +<function>hal_if_init()</function>. +</para> + +<para>The HAL serial driver must, when called via +<function>cyg_hal_plf_comms_init()</function> must initialize the +communication channels. +</para> + +<para>The <function>reset()</function> function defined in +<filename>hal_if.c</filename> will attempt to do a hardware reset, but +if this fails it will fall back to simply jumping to the reset +entry-point. On most platforms the startup initialization will go a +long way to reset the target to a sane state (there will be +exceptions, of course). For this reason, make sure to define +<literal>HAL_STUB_PLATFORM_RESET_ENTRY</literal> in plf_stub.h. +</para> + +<para>All debugging features must be in place in order for the debugging +services to be functional. See general platform porting notes. +</para> + +</section> + +<!-- }}} --> +<!-- {{{ New Architecture Ports --> + +<section> +<title>New architecture ports</title> + +<para>There are no specific requirements for a new architecture port in +order to support the calling interface, but the basic debugging +features must be in place. See general architecture porting notes. +</para> +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> +<!-- {{{ IO Channels --> + +<section id="hal-porting-io-channels"> +<title>IO channels</title> + + +<para>The calling interface provides procedure tables for all IO channels on +the platform. These are used for console (diagnostic) and debugger IO, +allowing a ROM monitor to provided all the needed IO routines. At +the same time, this makes it easy to switch console/debugger channels +at run-time (the old implementation had hardwired drivers for console +and debugger IO, preventing these to change at run-time). +</para> + +<para>The hal_if provides wrappers which interface these services to the +eCos infrastructure diagnostics routines. This is done in a way which +ensures proper string mangling of the diagnostics output when required +(e.g. O-packetization when using a GDB compatible ROM monitor). +</para> + +<!-- {{{ Available Procedures --> + +<section> +<title>Available Procedures</title> + +<para>This is a brief description of the procedures</para> + +<variablelist> +<varlistentry><term><literal>CH_DATA</literal></term> +<listitem><para>Pointer to the controller IO base (or a pointer to a per-device + structure if more data than the IO base is required). All the + procedures below are called with this data item as the first + argument.</para></listitem></varlistentry> + +<varlistentry><term><literal>WRITE</literal></term> + <listitem><para>Writes the buffer to the device.</para></listitem></varlistentry> +<varlistentry><term><literal>READ</literal></term> + <listitem><para>Fills a buffer from the device.</para></listitem></varlistentry> +<varlistentry><term><literal>PUTC</literal></term> + <listitem><para>Write a character to the device.</para></listitem></varlistentry> +<varlistentry><term><literal>GETC</literal></term> + <listitem><para>Read a character from the device.</para></listitem></varlistentry> +<varlistentry><term><literal>CONTROL</literal></term> + <listitem><para>Device feature control. Second argument specifies function:</para> + <variablelist> + <varlistentry><term><literal>SETBAUD</literal></term> + <listitem><para>Changes baud rate.</para></listitem></varlistentry> + <varlistentry><term><literal>GETBAUD</literal></term> + <listitem><para>Returns the current baud rate.</para></listitem></varlistentry> + <varlistentry><term><literal>INSTALL_DBG_ISR</literal></term> + <listitem><para>[Unused]</para></listitem></varlistentry> + <varlistentry><term><literal>REMOVE_DBG_ISR</literal></term> + <listitem><para>[Unused]</para></listitem></varlistentry> + <varlistentry><term><literal>IRQ_DISABLE</literal></term> + <listitem><para>Disable debugging receive interrupts on the device.</para></listitem></varlistentry> + <varlistentry><term><literal>IRQ_ENABLE</literal></term> + <listitem><para>Enable debugging receive interrupts on the device.</para></listitem></varlistentry> + <varlistentry><term><literal>DBG_ISR_VECTOR</literal></term> + <listitem><para>Returns the ISR vector used by the device for debugging + receive interrupts.</para></listitem></varlistentry> + <varlistentry><term><literal>SET_TIMEOUT</literal></term> + <listitem><para>Set GETC timeout in milliseconds.</para></listitem></varlistentry> + <varlistentry><term><literal>FLUSH_OUTPUT</literal></term> + <listitem><para>Forces driver to flush data in its buffers. Note + that this may not affect hardware buffers + (e.g. FIFOs).</para></listitem></varlistentry> + </variablelist> + </listitem></varlistentry> + +<varlistentry><term><literal>DBG_ISR</literal></term> + <listitem><para>ISR used to handle receive interrupts from the + device (see <!-- <xref linkend="hal-stubs-async-bps"> -->).</para></listitem></varlistentry> +<varlistentry><term><literal>GETC_TIMEOUT</literal></term> + <listitem><para>Read a character from the device with timeout.</para></listitem></varlistentry> +</variablelist> + +</section> + +<!-- }}} --> +<!-- {{{ Usage --> + +<section><title>Usage</title> + +<para>The standard eCos diagnostics IO functions use the channel +procedure table when <literal>CYGSEM_HAL_VIRTUAL_VECTOR_DIAG</literal> is enabled. That +means that when you use diag_printf (or the libc printf function) the +stream goes through the selected console procedure table. If you use +the virtual vector function SET_CONSOLE_COMM you can change the device +which the diagnostics output goes to at run-time.</para> + +<para>You can also use the table functions directly if desired +(regardless of the <literal>CYGSEM_HAL_VIRTUAL_VECTOR_DIAG</literal> setting - assuming +the ROM monitor provides the services). Here is a small example which +changes the console to use channel 2, fetches the comm procs pointer +and calls the write function from that table, then restores the +console to the original channel:</para> + +<programlisting> +#define T "Hello World!\n" + +int +main(void) +{ + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + CYGACC_CALL_IF_SET_CONSOLE_COMM(2); + + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_WRITE(*comm, T, strlen(T)); + + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} +</programlisting> + +<para>Beware that if doing something like the above, you should only do +it to a channel which does not have GDB at the other end: GDB ignores +raw data, so you would not see the output.</para> + +</section> + +<!-- }}} --> +<!-- {{{ Compatibility --> + +<section> +<title>Compatibility</title> + +<para>The use of this service is controlled by the option +<literal>CYGSEM_HAL_VIRTUAL_VECTOR_DIAG</literal> which is disabled per default on most +older platforms (thus preserving backwards compatibility with older +stubs). On newer ports, this option should always be set. +</para> +</section> + +<!-- }}} --> +<!-- {{{ Implementation Details --> + +<section><title>Implementation Details</title> + +<para>There is an array of procedure tables (raw comm channels) for each +IO device of the platform which get initialized by the ROM monitor, or +optionally by a RAM startup configuration (allowing the RAM +configuration to take full control of the target). In addition to +this, there's a special table which is used to hold mangler +procedures.</para> + +<para>The vector table defines which of these channels are selected for +console and debugging IO respectively: console entry can be empty, +point to mangler channel, or point to a raw channel. The debugger +entry should always point to a raw channel.</para> + +<para>During normal console output (i.e., diagnostic output) the console +table will be used to handle IO if defined. If not defined, the debug +table will be used.</para> + +<para>This means that debuggers (such as GDB) which require text streams +to be mangled (O-packetized in the case of GDB), can rely on the ROM +monitor install mangling IO routines in the special mangler table and +select this for console output. The mangler will pass the mangled data +on to the selected debugging channel.</para> + +<para>If the eCos configuration specifies a different console channel +from that used by the debugger, the console entry will point to the +selected raw channel, thus overriding any mangler provided by the ROM +monitor.</para> + +<para>See hal_if_diag_* routines in hal_if.c for more details of the stream +path of diagnostic output. See <function>cyg_hal_gdb_diag_*()</function> routines in +<filename>hal_stub.c</filename> for the mangler used for GDB communication.</para> + +<!-- +FIXME: Other special channels are reserved for ethernet communication. +--> + +</section> + +<!-- }}} --> +<!-- {{{ New Platform Ports --> + +<section> +<title>New Platform Ports</title> + +<para>Define CDL options <literal>CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS</literal>, +<literal>CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL</literal>, and +<literal>CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL</literal>. +</para> + +<para>If <literal>CYGSEM_HAL_VIRTUAL_VECTOR_DIAG</literal> is set, make sure the infra diag +code uses the hal_if diag functions:</para> + +<programlisting> + #define HAL_DIAG_INIT() hal_if_diag_init() + #define HAL_DIAG_WRITE_CHAR(_c_) hal_if_diag_write_char(_c_) + #define HAL_DIAG_READ_CHAR(_c_) hal_if_diag_read_char(&_c_) +</programlisting> + +<para>In addition to the above functions, the platform HAL must also +provide a function cyg_hal_plf_comms_init which initializes the +drivers and the channel procedure tables. +</para> + +<para>Most of the other functionality in the table is more or less +possible to copy unchanged from existing ports. Some care is necessary +though to ensure the proper handling of interrupt vectors and timeouts +for various devices handled by the same driver. See PowerPC/Cogent +platform HAL for an example implementation.</para> + +<note> +<title>Note:</title> +<para> When vector table console code is <emphasis>not</emphasis> used, +the platform HAL must map the HAL_DIAG_INIT, HAL_DIAG_WRITE_CHAR and +HAL_DIAG_READ_CHAR macros directly to the low-level IO functions, +hardwired to use a compile-time configured channel.</para> +</note> + +<note> +<title>Note:</title> +<para> On old ports the hardwired <literal>HAL_DIAG_INIT</literal>, +<literal>HAL_DIAG_WRITE_CHAR</literal> and +<literal>HAL_DIAG_READ_CHAR</literal> implementations will also +contain code to O-packetize the output for GDB. This should +<emphasis>not</emphasis> be adopted for new ports! On new ports the +ROM monitor is guaranteed to provide the necessary mangling via the +vector table. The hardwired configuration should be reserved for ROM +startups where achieving minimal image size is crucial. +</para> +</note> + +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> + + +</section> + +<!-- }}} --> +<!-- {{{ Coding Conventions --> + +<section id="hal-porting-coding-conventions"> +<TITLE>HAL Coding Conventions</TITLE> + + +<para> +To get changes and larger submissions included into the eCos source +repository, we ask that you adhere to a set of coding conventions. +The conventions are defined as an attempt to make a consistent +tree. Consistency makes it easier for people to read, understand and +maintain the code, which is important when many people work on the +same project. +</para> + +<para> +The below is only a brief, and probably incomplete, summary of the +rules. Please look through files in the area where you are making +changes to get a feel for any additional conventions. Also feel free +to ask on the list if you have specific questions. +</para> + + +<section> +<title>Implementation issues</title> + +<para> +There are a few implementation issues that should be kept in mind: +</para> + +<variablelist> +<varlistentry><term>HALs</term> + <listitem><para>HALs must be written in C and assembly only. C++ must not + be used. This is in part to keep the HALs simple since this is + usually the first part of eCos a newcomer will see, and in + part to maintain the existing de facto standard.</para></listitem></varlistentry> + +<varlistentry><term>IO access</term> + <listitem><para>Use HAL IO access macros for code that might be reused on + different platforms than the one you are writing it for.</para></listitem></varlistentry> + +<varlistentry><term>MMU</term> + <listitem><para>If it is necessary to use the MMU (e.g., to prevent + caching of IO areas), use a simple 1-1 mapping of memory if + possible. On most platforms where using the MMU is necessary, + it will be possible to achieve the 1-1 mapping using the MMU's + provision for mapping large continuous areas (hardwired TLBs or + BATs). This reduces the footprint (no MMU table) and avoids + execution overhead (no MMU-related exceptions).</para></listitem></varlistentry> + +<varlistentry><term>Assertions</term> + <listitem><para>The code should contain assertions to validate argument + values, state information and any assumptions the code may be + making. Assertions are not enabled in production builds, so + liberally sprinkling assertions throughout the code is + good.</para></listitem></varlistentry> + +<varlistentry><term>Testing</term> + <listitem><para>The ability to test your code is very important. In + general, do not add new code to the eCos runtime unless you + also add a new test to exercise that code. The test also + serves as an example of how to use the new code.</para></listitem></varlistentry> + +</variablelist> + +</section> + +<section> +<title>Source code details</title> + +<variablelist> +<varlistentry><term>Line length</term> + <listitem><para>Keep line length below 78 columns whenever possible.</para></listitem></varlistentry> + +<varlistentry><term>Comments</term> + <listitem><para>Whenever possible, use // comments instead of /**/.</para></listitem></varlistentry> + +<varlistentry><term>Indentation</term> + <listitem><para>Use spaces instead of TABs. Indentation level is 4. Braces + start on the same line as the expression. See below for emacs + mode details.</para> + +<programlisting> +;;================================================================= +;; eCos C/C++ mode Setup. +;; +;; bsd mode: indent = 4 +;; tail comments are at col 40. +;; uses spaces not tabs in C + +(defun ecos-c-mode () + "C mode with adjusted defaults for use with the eCos sources." + (interactive) + (c++-mode) + (c-set-style "bsd") + (setq comment-column 40) + (setq indent-tabs-mode nil) + (show-paren-mode 1) + (setq c-basic-offset 4) + + (set-variable 'add-log-full-name "Your Name") + (set-variable 'add-log-mailing-address "Your email address")) + +(defun ecos-asm-mode () + "ASM mode with adjusted defaults for use with the eCos sources." + (interactive) + (setq comment-column 40) + (setq indent-tabs-mode nil) + (asm-mode) + (setq c-basic-offset 4) + + (set-variable 'add-log-full-name "Your Name") + (set-variable 'add-log-mailing-address "Your email address")) + +(setq auto-mode-alist + (append '(("/local/ecc/.*\\.C$" . ecos-c-mode) + ("/local/ecc/.*\\.cc$" . ecos-c-mode) + ("/local/ecc/.*\\.cpp$" . ecos-c-mode) + ("/local/ecc/.*\\.inl$" . ecos-c-mode) + ("/local/ecc/.*\\.c$" . ecos-c-mode) + ("/local/ecc/.*\\.h$" . ecos-c-mode) + ("/local/ecc/.*\\.S$" . ecos-asm-mode) + ("/local/ecc/.*\\.inc$" . ecos-asm-mode) + ("/local/ecc/.*\\.cdl$" . tcl-mode) + ) auto-mode-alist)) +</programlisting> +</listitem> +</varlistentry> +</variablelist> +</section> + +<section> + +<title>Nested Headers</title> + +<para>In order to allow platforms to define all necessary details, while +still maintaining the ability to share code between common platforms, +all HAL headers are included in a nested fashion.</para> + +<para>The architecture header (usually <filename>hal_XXX.h</filename>) includes the +variant equivalent of the header (<filename>var_XXX.h</filename>) which in turn +includes the platform equivalent of the header +(<filename>plf_XXX.h</filename>).</para> + +<para>All definitions that may need to be overridden by a platform are +then only conditionally defined, depending on whether a lower layer +has already made the definition:</para> + +<programlisting> +hal_intr.h: #include <var_intr.h> + + #ifndef MACRO_DEFINED + # define MACRO ... + # define MACRO_DEFINED + #endif + + + +var_intr.h: #include <plf_intr.h> + + #ifndef MACRO_DEFINED + # define MACRO ... + # define MACRO_DEFINED + #endif + + +plf_intr.h: + + # define MACRO ... + # define MACRO_DEFINED +</programlisting> + +<para>This means a platform can opt to rely on the variant or +architecture implementation of a feature, or implement it itself.</para> + +</section> + +</section> + +<!-- }}} --> +<!-- {{{ Platform HAL Porting --> + +<section id="hal-porting-platform"> +<title>Platform HAL Porting</title> + +<para> +This is the type of port that takes the least effort. It basically +consists of describing the platform (board) for the HAL: memory +layout, early platform initialization, interrupt controllers, and a +simple serial device driver. +</para> + +<para> +Doing a platform port requires a preexisting architecture and +possibly a variant HAL port. +</para> + +<!-- {{{ Porting Process --> + +<section> +<TITLE>HAL Platform Porting Process</TITLE> + +<!-- {{{ Brief Overview --> + +<section> +<title>Brief overview</title> + +<para>The easiest way to make a new platform HAL is simply to copy an +existing platform HAL of the same architecture/variant and change all +the files to match the new one. In case this is the first platform for +the architecture/variant, a platform HAL from another architecture +should be used as a template. +</para> + +<para> +The best way to start a platform port is to concentrate on getting +RedBoot to run. RedBoot is a simpler environment than full eCos, it +does not use interrupts or threads, but covers most of the +basic startup requirements. +</para> + +<para> +RedBoot normally runs out of FLASH or ROM and provides program loading +and debugging facilities. This allows further HAL development to +happen using RAM startup configurations, which is desirable for the +simple reason that downloading an image which you need to test is +often many times faster than either updating a flash part, or indeed, +erasing and reprogramming an EPROM. +</para> + +<para>There are two approaches to getting to this first goal: +</para> + +<orderedlist> +<listitem> +<para> +The board is equipped with a ROM monitor which allows "load and go" of +ELF, binary, S-record or some other image type which can be created +using <application>objcopy</application>. This allows you to develop +RedBoot by downloading and running the code (saving time). +</para> + +<para> +When the stub is running it is a good idea to examine the various +hardware registers to help you write the platform initialization code. +</para> + +<para> +Then you may have to fiddle a bit going through step two (getting it +to run from ROM startup). If at all possible, preserve the original +ROM monitor so you can revert to it if necessary. +</para> +</listitem> + +<listitem> +<para> +The board has no ROM monitor. You need to get the platform +initialization and stub working by repeatedly making changes, updating +flash or EPROM and testing the changes. If you are lucky, you have a +JTAG or similar CPU debugger to help you. If not, you will probably +learn to appreciate LEDs. This approach may also be needed during the +initial phase of moving RedBoot from RAM startup to ROM, since it is +very unlikely to work first time. +</para> +</listitem> +</orderedlist> + +</section> + +<!-- }}} --> +<!-- {{{ Step-by-step --> + +<section> +<title>Step-by-step</title> + +<para>Given that no two platforms are exactly the same, you may have to +deviate from the below. Also, you should expect a fair amount of +fiddling - things almost never go right the first time. See the hints +section below for some suggestions that might help debugging. +</para> + +<para>The description below is based on the HAL layout used in the MIPS, +PC and MN10300 HALs. Eventually all HALs should be converted to look like +these - but in a transition period there will be other HALs which look +substantially different. Please try to adhere to the following as much is +possible without causing yourself too much grief integrating with a +HAL which does not follow this layout. +</para> + +<!-- ====================================================================== --> + +<section> +<title>Minimal requirements</title> + +<para> +These are the changes you must make before you attempt to build +RedBoot. You are advised to read all the sources though. +</para> + +<orderedlist> +<listitem><para>Copy an existing platform HAL from the same or another + architecture. Rename the files as necessary to follow the + standard: CDL and memory layout related files should contain the + <arch>_<variant>_<platform> triplet.</para> +</listitem> + +<listitem><para>Adjust CDL options. Primarily option naming, real-time + clock/counter, and CYGHWR_MEMORY_LAYOUT variables, but also other + options may need editing. Look through the architecture/variant + CDL files to see if there are any requirements/features which + where not used on the platform you copied. If so, add appropriate + ones. See <xref linkend="hal-porting-cdl-requirements"> for more + details.</para> +</listitem> + +<listitem><para>Add the necessary packages and target descriptions to the + top-level <filename>ecos.db</filename> file. See <xref + linkend="hal-porting-ecos-database">. Initially, the target entry + should only contain the HAL packages. Other hardware support + packages will be added later.</para> +</listitem> + +<listitem><para>Adjust the memory layout files in + <filename>include/pkgconf</filename> to match the memory layout on + the platform. <!-- For initial testing it should be enough to just hand + edit .h and .ldi files, but eventually you should generate all + files using the memory layout editor in the configuration + tool. --> See <xref linkend="hal-porting-platform-memory-layout"> for + more details.</para> +</listitem> + +<listitem> + <para> + Edit the <filename>misc/redboot_<STARTUP>.ecm</filename> for + the startup type you have chosen to begin with. Rename any + platform specific options and remove any that do not apply. In the + <literal>cdl_configuration</literal> section, comment out any + extra packages that are added, particularly packages such as + <literal>CYGPKG_IO_FLASH</literal> and + <literal>CYGPKG_IO_ETH_DRIVERS</literal>. These are not needed for + initial porting and will be added back later. + </para> +</listitem> + +<listitem><para>If the default IO macros are not correct, override them in + plf_io.h. This may be necessary if the platform uses a different + endianness from the default for the CPU.</para> +</listitem> + +<listitem><para>Leave out/comment out code that enables caches and/or MMU if + possible. Execution speed will not be a concern until the port is + feature complete.</para> +</listitem> + +<listitem><para>Implement a simple serial driver (polled mode only). Make sure the + initialization function properly hooks the procedures up in the + virtual vector IO channel tables. RedBoot will call the serial + driver via these tables.</para> + <para> + By copying an existing platform HAL most of this code will be + already done, and will only need the platform specific hardware + access code to be written. + </para> +</listitem> + +<listitem><para>Adjust/implement necessary platform + initialization. This can be found in + <filename>platform.inc</filename> and + <filename>platform.S</filename> files (ARM: + <filename>hal_platform_setup.h</filename> and + <filename><platform>_misc.c</filename>, PowerPC: + <filename><platform>.S</filename>). This step can be + postponed if you are doing a RAM startup RedBoot first and the + existing ROM monitor handles board initialization.</para> +</listitem> + +<listitem><para>Define <literal>HAL_STUB_PLATFORM_RESET</literal> + (optionally empty) and + <literal>HAL_STUB_PLATFORM_RESET_ENTRY</literal> so that RedBoot + can reset-on-detach - this is very handy, often removing the need + for physically resetting the board between downloads.</para> +</listitem> + +</orderedlist> + +<para>You should now be able to build RedBoot. For ROM startup: +</para> + +<programlisting width=72> +% ecosconfig new <target_name> redboot +% ecosconfig import $(ECOS_REPOSITORY)/hal/<architecture>/<platform>/<version>/misc/redboot_ROM.ecm +% ecosconfig tree +% make +</programlisting> + +<para>You may have to make further changes than suggested above to get +the make command to succeed. But when it does, you should find a +RedBoot image in install/bin. To program this image into flash or +EPROM, you may need to convert to some other file type, and possibly +adjust the start address. When you have the correct +<application>objcopy</application> command to do this, add it to the +<literal>CYGBLD_BUILD_GDB_STUBS</literal> custom build rule in the +platform CDL file. +</para> + +<para>Having updated the flash/EPROM on the board, you should see output +on the serial port looking like this when powering on the board: +</para> + +<programlisting> +RedBoot(tm) bootstrap and debug environment [ROMRAM] +Non-certified release, version UNKNOWN - built 15:42:24, Mar 14 2002 + +Platform: <PLATFORM> (<ARCHITECTURE> <VARIANT>) +Copyright (C) 2000, 2001, 2002, Free Software Foundation, Inc. + +RAM: 0x00000000-0x01000000, 0x000293e8-0x00ed1000 available +FLASH: 0x24000000 - 0x26000000, 256 blocks of 0x00020000 bytes each. +RedBoot> +</programlisting> + +<para>If you do not see this output, you need to go through all your +changes and figure out what's wrong. If there's a user programmable +LED or LCD on the board it may help you figure out how far RedBoot +gets before it hangs. Unfortunately there's no good way to describe +what to do in this situation - other than that you have to play with +the code and the board. +</para> + +</section> + +<!-- ====================================================================== --> + +<section> +<title>Adding features</title> + +<para>Now you should have a basic RedBoot running on the board. This +means you have a the correct board initialization and a working serial +driver. It's time to flesh out the remaining HAL features. +</para> + +<orderedlist> +<listitem><para>Reset. As mentioned above it is desirable to get the board to +reset when GDB disconnects. When GDB disconnects it sends RedBoot +a kill-packet, and RedBoot first calls <literal>HAL_STUB_PLATFORM_RESET()</literal>, +attempting to perform a software-invoked reset. Most embedded +CPUs/boards have a watchdog which is capable of triggering a reset. +If your target does not have a watchdog, leave +<literal>HAL_STUB_PLATFORM_RESET()</literal> empty and rely on the fallback approach. +</para> + +<para>If <literal>HAL_STUB_PLATFORM_RESET()</literal> did not cause a reset, RedBoot will +jump to <literal>HAL_STUB_PLATFORM_RESET_ENTRY</literal> - this should be the address +where the CPU will start execution after a reset. Re-initializing the +board and drivers will <emphasis>usually</emphasis> be good enough to make a +hardware reset unnecessary. +</para> + +<para>After the reset caused by the kill-packet, the target will be ready +for GDB to connect again. During a days work, this will save you from +pressing the reset button many times. +</para> + +<para>Note that it is possible to disconnect from the board without +causing it to reset by using the GDB command "detach".</para> +</listitem> + +<listitem> +<para>Single-stepping is necessary for both instruction-level debugging +and for breakpoint support. Single-stepping support should already be +in place as part of the architecture/variant HAL, but you want to give +it a quick test since you will come to rely on it.</para> +</listitem> + +<listitem> +<para>Real-time clock interrupts drive the eCos scheduler clock. Many +embedded CPUs have an on-core timer (e.g. SH) or decrementer +(e.g. MIPS, PPC) that can be used, and in this case it will already be +supported by the architecture/variant HAL. You only have to calculate +and enter the proper <literal>CYGNUM_HAL_RTC_CONSTANTS</literal> +definitions in the platform CDL file. +</para> + +<para>On some targets it may be necessary to use a platform-specific +timer source for driving the real-time clock. In this case you also +have to enter the proper CDL definitions, but must also define +suitable versions of the <literal>HAL_CLOCK_XXXX</literal> macros.</para> +</listitem> + +<listitem> +<para>Interrupt decoding usually differs between platforms because the +number and type of devices on the board differ. In +<filename>plf_intr.h</filename> (ARM: +<filename>hal_platform_ints.h</filename>) you must either extend or +replace the default vector definitions provided by the architecture +or variant interrupt headers. You may also have to define +<literal>HAL_INTERRUPT_XXXX</literal> control macros.</para> +</listitem> + +<listitem> +<para>Caching may also differ from architecture/variant definitions. +This maybe just the cache sizes, but there can also be bigger +differences for example if the platform supports 2nd level caches. +</para> + +<para>When cache definitions are in place, enable the caches on +startup. First verify that the system is stable for RAM startups, then +build a new RedBoot and install it. This will test if caching, and in +particular the cache sync/flush operations, also work for ROM startup.</para> +</listitem> + +<listitem> +<para>Asynchronous breakpoints allow you to stop application execution +and enter the debugger. Asynchronous breakpoint details are described +in <!-- <xref linkend="hal-stubs-async-bps"> -->.</para> +</listitem> + +</orderedlist> + +<para>You should now have a completed platform HAL port. Verify its +stability and completeness by running all the eCos tests and fix any +problems that show up (you have a working RedBoot now, remember! That +means you can debug the code to see why it fails). +</para> + +<para>Given the many configuration options in eCos, there may be hidden +bugs or missing features that do not show up even if you run all the +tests successfully with a default configuration. A comprehensive test +of the entire system will take many configuration permutations and +many many thousands of tests executed. +</para> + +</section> + +</section> + +<!-- }}} --> +<!-- {{{ Hints --> + +<section> +<title>Hints</title> + +<itemizedlist> + +<listitem> + <para>JTAG or similar CPU debugging hardware can greatly reduce the time + it takes to write a HAL port since you always have full visibility + of what the CPU is doing. + </para> +</listitem> + +<listitem> + <para>LEDs can be your friends if you don't have a JTAG + device. Especially in the start of the porting effort if you don't + already have a working ROM monitor on the target. Then you have to + get a basic RedBoot working while basically being blindfolded. The + LED can make it little easier, as you'll be able to do limited + tracking of program flow and behavior by switching the LED on and + off. If the board has multiple LEDs you can show a number (using + binary notation with the LEDs) and sprinkle code which sets + different numbers throughout the code.</para> +</listitem> + +<listitem> + <para>Debugging the interrupt processing is possible if you are + careful with the way you program the very early interrupt entry + handling. Write it so that as soon as possible in the interrupt + path, taking a trap (exception) does not harm execution. See the + SH vectors.S code for an example. Look for + <literal>cyg_hal_default_interrupt_vsr</literal> and the label + <literal>cyg_hal_default_interrupt_vsr_bp_safe</literal>, which + marks the point after which traps/single-stepping is safe. + </para> + + <para>Being able to display memory content, CPU registers, + interrupt controller details at the time of an interrupt can save + a lot of time.</para> +</listitem> + +<listitem> + <para>Using assertions is a good idea. They can sometimes reveal subtle + bugs or missing features long before you would otherwise have + found them, let alone notice them. + </para> + + <para>The default eCos configuration does not use assertions, so you + have to enable them by switching on the option <literal>CYGPKG_INFRA_DEBUG</literal> + in the infra package.</para> +</listitem> + +<listitem> + <para>The idle loop can be used to help debug the system. + </para> + + <para>Triggering clock from the idle loop is a neat trick for + examining system behavior either before interrupts are fully + working, or to speed up "the clock". + </para> + + <para>Use the idle loop to monitor and/or print out variables or + hardware registers.</para> +</listitem> + +<listitem> +<para><application>hal_mk_defs</application> is used in some of the +HALs (ARM, SH) as a way to generate assembler symbol definitions from +C header files without imposing an assembler/C syntax separation in +the C header files.</para> +</listitem> + +<!-- +<listitem><para>Tracing using buffers [FIXME:TBD]</para> +</listitem> +--> + +</itemizedlist> + +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> +<!-- {{{ CDL Requirements --> + +<section id="hal-porting-cdl-requirements"> +<TITLE>HAL Platform CDL</TITLE> + +<para>The platform CDL both contains details necessary for the building +of eCos, and platform-specific configuration options. For this reason +the options differ between platforms, and the below is just a brief +description of the most common options.</para> + +<para> See <!-- <xref linkend="???"> --> Components Writers Guide +for more details on CDL. Also have a quick look around in +existing platform CDL files to get an idea of what is possible and how +various configuration issues can be represented with CDL.</para> + +<!-- {{{ eCos Database --> + +<section id="hal-porting-ecos-database"> +<title>eCos Database</title> + +<para> +The eCos configuration system is made aware of a package by +adding a package description in <filename>ecos.db</filename>. As an +example we use the <literal>TX39/JMR3904</literal> platform: +</para> + +<programlisting> +package CYGPKG_HAL_MIPS_TX39_JMR3904 { + alias { "Toshiba JMR-TX3904 board" hal_tx39_jmr3904 tx39_jmr3904_hal } + directory hal/mips/jmr3904 + script hal_mips_tx39_jmr3904.cdl + hardware + description " + The JMR3904 HAL package should be used when targeting the + actual hardware. The same package can also be used when + running on the full simulator, since this provides an + accurate simulation of the hardware including I/O devices. + To use the simulator in this mode the command + `target sim --board=jmr3904' should be used from inside gdb." +} +</programlisting> + +<para>This contains the title and description presented in the +Configuration Tool when the package is selected. It also specifies +where in the tree the package files can be found (<literal>directory</literal>) +and the name of the CDL file which contains the package details +(<literal>script</literal>). +</para> + +<para> +To be able to build and test a configuration for the new target, there +also needs to be a <literal>target</literal> entry in the +<filename>ecos.db</filename> file. +</para> + +<programlisting> +target jmr3904 { + alias { "Toshiba JMR-TX3904 board" jmr tx39 } + packages { CYGPKG_HAL_MIPS + CYGPKG_HAL_MIPS_TX39 + CYGPKG_HAL_MIPS_TX39_JMR3904 + } + description " + The jmr3904 target provides the packages needed to run + eCos on a Toshiba JMR-TX3904 board. This target can also + be used when running in the full simulator, since the simulator provides an + accurate simulation of the hardware including I/O devices. + To use the simulator in this mode the command + `target sim --board=jmr3904' should be used from inside gdb." +} +</programlisting> + + +<para> +The important part here is the <literal>packages</literal> section +which defines the various hardware specific packages that contribute +to support for this target. In this case the MIPS architecture +package, the TX39 variant package, and the JMR-TX3904 platform +packages are selected. Other packages, for serial drivers, ethernet +drivers and FLASH memory drivers may also appear here. +</para> + +</section> + +<!-- }}} --> +<!-- {{{ CDL File Layout --> + +<section> +<title>CDL File Layout</title> + +<para> +All the platform options are contained in a CDL package named +<literal>CYGPKG_HAL_<architecture>_<variant>_<platform></literal>. +They all share more or less the same <literal>cdl_package</literal> +details: +</para> + +<programlisting> +cdl_package CYGPKG_HAL_MIPS_TX39_JMR3904 { + display "JMR3904 evaluation board" + parent CYGPKG_HAL_MIPS + requires CYGPKG_HAL_MIPS_TX39 + define_header hal_mips_tx39_jmr3904.h + include_dir cyg/hal + description " + The JMR3904 HAL package should be used when targeting the + actual hardware. The same package can also be used when + running on the full simulator, since this provides an + accurate simulation of the hardware including I/O devices. + To use the simulator in this mode the command + `target sim --board=jmr3904' should be used from inside gdb." + + compile platform.S plf_misc.c plf_stub.c + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H <pkgconf/hal_mips_tx39.h>" + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H <pkgconf/hal_mips_tx39_jmr3904.h>" + } + + ... +} +</programlisting> + +<para>This specifies that the platform package should be parented under +the MIPS packages, requires the TX39 variant HAL and all configuration +settings should be saved in +<filename>cyg/hal/hal_mips_tx39_jmt3904.h</filename>. +</para> + +<para>The <literal>compile</literal> line specifies which files should be built +when this package is enabled, and the <literal>define_proc</literal> defines +some macros that are used to access the variant or architecture (the +<literal>_TARGET_</literal> name is a bit of a misnomer) and platform +configuration options. </para> + +</section> + +<!-- }}} --> +<!-- {{{ Startup Type --> + +<section> +<title>Startup Type</title> + +<para>eCos uses an option to select between a set of valid startup +configurations. These are normally RAM, ROM and possibly ROMRAM. This +setting is used to select which linker map to use (i.e., where to link +eCos and the application in the memory space), and how the startup +code should behave.</para> + +<programlisting> +cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + legal_values {"RAM" "ROM"} + default_value {"RAM"} + no_define + define -file system.h CYG_HAL_STARTUP + description " + When targeting the JMR3904 board it is possible to build + the system for either RAM bootstrap, ROM bootstrap, or STUB + bootstrap. RAM bootstrap generally requires that the board + is equipped with ROMs containing a suitable ROM monitor or + equivalent software that allows GDB to download the eCos + application on to the board. The ROM bootstrap typically + requires that the eCos application be blown into EPROMs or + equivalent technology." +} +</programlisting> + +<para>The <literal>no_define</literal> and <literal>define</literal> +pair is used to make the setting of this option appear in the file +<filename>system.h</filename> instead of the default specified in the +header.</para> + +</section> + +<!-- }}} --> +<!-- {{{ Build Options --> + +<section> +<title>Build options</title> + +<para> +A set of options under the components +<literal>CYGBLD_GLOBAL_OPTIONS</literal> and +<literal>CYGHWR_MEMORY_LAYOUT</literal> specify how eCos should be +built: what tools and compiler options should be used, and which +linker fragments should be used. +</para> + +<programlisting> + +cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + parent CYGPKG_NONE + description " + Global build options including control over + compiler flags, linker flags and choice of toolchain." + + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "mips-tx39-elf" } + description " + This option specifies the command prefix used when + invoking the build tools." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Global compiler flags" + flavor data + no_define + default_value { "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } + description " + This option controls the global compiler flags which + are used to compile all packages by + default. Individual packages may define + options which override these global flags." + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Global linker flags" + flavor data + no_define + default_value { "-g -nostdlib -Wl,--gc-sections -Wl,-static" } + description " + This option controls the global linker flags. Individual + packages may define options which override these global flags." + } +} + +cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { CYG_HAL_STARTUP == "RAM" ? "mips_tx39_jmr3904_ram" : \ + "mips_tx39_jmr3904_rom" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { CYG_HAL_STARTUP == "RAM" ? "<pkgconf/mlt_mips_tx39_jmr3904_ram.ldi>" : \ + "<pkgconf/mlt_mips_tx39_jmr3904_rom.ldi>" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { CYG_HAL_STARTUP == "RAM" ? "<pkgconf/mlt_mips_tx39_jmr3904_ram.h>" : \ + "<pkgconf/mlt_mips_tx39_jmr3904_rom.h>" } + } +} + +</programlisting> + +</section> + +<!-- }}} --> +<!-- {{{ Common Target Options --> + +<section> +<title>Common Target Options</title> + +<para>All platforms also specify real-time clock details:</para> + +<programlisting> +# Real-time clock/counter specifics +cdl_component CYGNUM_HAL_RTC_CONSTANTS { + display "Real-time clock constants." + flavor none + + cdl_option CYGNUM_HAL_RTC_NUMERATOR { + display "Real-time clock numerator" + flavor data + calculated 1000000000 + } + cdl_option CYGNUM_HAL_RTC_DENOMINATOR { + display "Real-time clock denominator" + flavor data + calculated 100 + } + # Isn't a nice way to handle freq requirement! + cdl_option CYGNUM_HAL_RTC_PERIOD { + display "Real-time clock period" + flavor data + legal_values { 15360 20736 } + calculated { CYGHWR_HAL_MIPS_CPU_FREQ == 50 ? 15360 : \ + CYGHWR_HAL_MIPS_CPU_FREQ == 66 ? 20736 : 0 } + } +} +</programlisting> + +<para> The <literal>NUMERATOR</literal> divided by the +<literal>DENOMINATOR</literal> gives the number of nanoseconds per +tick. The <literal>PERIOD</literal> is the divider to be programmed +into a hardware timer that is driven from an appropriate hardware +clock, such that the timer overflows once per tick (normally +generating a CPU interrupt to mark the end of a tick). The tick +default rate is typically 100Hz.</para> + + +<para>Platforms that make use of the virtual vector +ROM calling interface (see <xref linkend="hal-calling-if">) will also +specify details necessary to define configuration channels (these +options are from the SH/EDK7707 HAL) :</para> + +<programlisting> +cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { + display "Number of communication channels on the board" + flavor data + calculated 1 +} + +cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { + display "Debug serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The EDK/7708 board has only one serial port. This option + chooses which port will be used to connect to a host + running GDB." +} + +cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { + display "Diagnostic serial port" + flavor data + legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 + default_value 0 + description " + The EDK/7708 board has only one serial port. This option + chooses which port will be used for diagnostic output." +} +</programlisting> + +<para>The platform usually also specify an option controlling the ability + to co-exist with a ROM monitor:</para> + +<programlisting> +cdl_option CYGSEM_HAL_USE_ROM_MONITOR { + display "Work with a ROM monitor" + flavor booldata + legal_values { "Generic" "CygMon" "GDB_stubs" } + default_value { CYG_HAL_STARTUP == "RAM" ? "CygMon" : 0 } + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "RAM" } + description " + Support can be enabled for three different varieties of ROM monitor. + This support changes various eCos semantics such as the encoding + of diagnostic output, or the overriding of hardware interrupt + vectors. + Firstly there is \"Generic\" support which prevents the HAL + from overriding the hardware vectors that it does not use, to + instead allow an installed ROM monitor to handle them. This is + the most basic support which is likely to be common to most + implementations of ROM monitor. + \"CygMon\" provides support for the Cygnus ROM Monitor. + And finally, \"GDB_stubs\" provides support when GDB stubs are + included in the ROM monitor or boot ROM." +} +</programlisting> + +<para>Or the ability to be configured as a ROM monitor:</para> + +<programlisting> +cdl_option CYGSEM_HAL_ROM_MONITOR { + display "Behave as a ROM monitor" + flavor bool + default_value 0 + parent CYGPKG_HAL_ROM_MONITOR + requires { CYG_HAL_STARTUP == "ROM" } + description " + Enable this option if this program is to be used as a ROM monitor, + i.e. applications will be loaded into RAM on the board, and this + ROM monitor may process exceptions or interrupts generated from the + application. This enables features such as utilizing a separate + interrupt stack when exceptions are generated." +} +</programlisting> + +<para>The latter option is accompanied by a special build rule that +extends the generic ROM monitor build rule in the common HAL:</para> + +<programlisting> +cdl_option CYGBLD_BUILD_GDB_STUBS { + display "Build GDB stub ROM image" + default_value 0 + requires { CYG_HAL_STARTUP == "ROM" } + requires CYGSEM_HAL_ROM_MONITOR + requires CYGBLD_BUILD_COMMON_GDB_STUBS + requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + requires ! CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + requires ! CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT + requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM + no_define + description " + This option enables the building of the GDB stubs for the + board. The common HAL controls takes care of most of the + build process, but the final conversion from ELF image to + binary data is handled by the platform CDL, allowing + relocation of the data if necessary." + + make -priority 320 { + <PREFIX>/bin/gdb_module.bin : <PREFIX>/bin/gdb_module.img + $(OBJCOPY) -O binary $< $@ + } +} +</programlisting> + +<para> +Most platforms support RedBoot, and some options are needed to +configure for RedBoot. +</para> + +<programlisting width=72> + cdl_component CYGPKG_REDBOOT_HAL_OPTIONS { + display "Redboot HAL options" + flavor none + no_define + parent CYGPKG_REDBOOT + active_if CYGPKG_REDBOOT + description " + This option lists the target's requirements for a valid Redboot + configuration." + + cdl_option CYGBLD_BUILD_REDBOOT_BIN { + display "Build Redboot ROM binary image" + active_if CYGBLD_BUILD_REDBOOT + default_value 1 + no_define + description "This option enables the conversion of the Redboot ELF + image to a binary image suitable for ROM programming." + + make -priority 325 { + <PREFIX>/bin/redboot.bin : <PREFIX>/bin/redboot.elf + $(OBJCOPY) --strip-debug $< $(@:.bin=.img) + $(OBJCOPY) -O srec $< $(@:.bin=.srec) + $(OBJCOPY) -O binary $< $@ + } + } + } +</programlisting> + +<para> +The important part here is the <literal>make</literal> command in the +<literal>CYGBLD_BUILD_REDBOOT_BIN</literal> option which emits +makefile commands to translate the <filename>.elf</filename> file +generated by the link phase into both a binary file and an S-Record +file. If a different format is required by a PROM programmer or ROM +monitor, then different output formats would need to be generated here. +</para> + +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> +<!-- {{{ Platform Memory Layout --> + +<section id="hal-porting-platform-memory-layout"> +<TITLE>Platform Memory Layout</TITLE> + +<para>Historically, the platform memory layout was defined using a Memory +Configuration window in the eCos Configuration Tool (version 1.x). +However, the memory layout feature was not ported to the wxWidgets version +of the tool (version 2.0 and later). Memory layouts are currently manipulated +using a text editor.</para> + +<!-- +<note> +<para>If you do not have access to a Windows machine, you can +hand edit the <filename>.h</filename> and <filename>.ldi</filename> files to match the +properties of your platform. If you want to contribute your port back +to the eCos community, ask someone on the list to make proper memory +map files for you.</para> +</note> +--> + +<section> +<title>Layout Files</title> + +<para>The memory configuration details are specified in two files:</para> + +<variablelist> +<!-- +<varlistentry> +<term><filename>.mlt</filename></term> + <listitem><para>This is the Configuration Tool save-file. It is only used + by the Configuration Tool.</para></listitem> +</varlistentry> +--> +<varlistentry> +<term><filename>.ldi</filename></term> + <listitem><para>This is the linker script fragment. It defines the memory + and location of sections by way of macros defined in the + architecture or variant linker script.</para></listitem> +</varlistentry> +<varlistentry> +<term><filename>.h</filename></term> + <listitem><para>This file describes some of the memory region details as C + macros, allowing eCos or the application adapt the memory + layout of a specific configuration.</para></listitem> +</varlistentry> +</variablelist> + +<para>These files are generated for each startup-type, since the +memory details usually differ. The layout and structure of new files +should match those of existing memory layout files to allow for the +introduction of a new memory layout editor in the future. +</para> + +</section> + +<section> +<title>Reserved Regions</title> + +<para>Some areas of the memory space are reserved for specific +purposes, making room for exception vectors and various tables. RAM +startup configurations also need to reserve some space at the bottom +of the memory map for the ROM monitor.</para> + +<para>These reserved areas are named with the prefix "reserved_" <!-- which is +handled specially by the Configuration Tool: --> instead of referring to a +linker macro, the start of the area is labeled and a gap left in the +memory map.</para> + +</section> + + +</section> + +<!-- }}} --> +<!-- {{{ Platform Serial Device Support --> + +<section> +<title>Platform Serial Device Support</title> + +<para> +The first step is to set up the CDL definitions. The configuration +options that need to be set are the following: +</para> + +<variablelist> + <varlistentry> + <term><literal>CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS</literal></term> + <listitem><para>The number of channels, usually 0, 1 or 2.</para></listitem> + </varlistentry> + + <varlistentry> + <term><literal>CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL</literal></term> + <listitem><para>The channel to use for GDB.</para></listitem> + </varlistentry> + + <varlistentry> + <term><literal>CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD</literal></term> + <listitem><para>Initial baud rate for debug channel.</para></listitem> + </varlistentry> + + <varlistentry> + <term><literal>CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL</literal></term> + <listitem><para>The channel to use for the + console.</para></listitem> + </varlistentry> + + <varlistentry> + <term><literal>CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD</literal></term> + <listitem><para>The initial baud rate for the console + channel.</para></listitem> + </varlistentry> + + <varlistentry> + <term><literal>CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT</literal></term> + <listitem><para>The default console channel.</para></listitem> + </varlistentry> +</variablelist> + +<para> +The code in <filename>hal_diag.c</filename> need to be converted to +support the new serial device. +If this the same as a device already supported, copy that. +</para> + +<para> +The following functions and types need to be rewritten to support a new serial +device. +</para> + +<variablelist> + <varlistentry> + <term><literal>struct channel_data_t;</literal></term> + <listitem> + <para> + Structure containing base address, timeout and ISR vector number + for each serial device supported. Extra fields my be added if + necessary for the device. For example some devices have + write-only control registers, so keeping a shadow of the last + value written here can be useful. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>xxxx_ser_channels[];</literal></term> + <listitem> + <para> + Array of <literal>channel_data_t</literal>, initialized with parameters of each + channel. The index into this array is the channel number used + in the CDL options above and is used by the virtual vector + mechanism to refer to each channel. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>void cyg_hal_plf_serial_init_channel(void + *__ch_data)</literal></term> + <listitem> + <para> + Initialize the serial device. The parameter is actually a pointer to a + <literal>channel_data_t</literal> and should be cast back to + this type before use. This function should use the CDL + definition for the baud rate for the channel it is initializing. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>void cyg_hal_plf_serial_putc(void * __ch_data, + char *c)</literal></term> + <listitem> + <para> + Send a character to the serial device. This function should + poll for the device being ready to send and then write the character. + Since this is intended to be a diagnostic/debug channel, it is + often also a good idea to poll for end of transmission + too. This ensures that as much data gets out of the system as + possible. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>bool cyg_hal_plf_serial_getc_nonblock(void* + __ch_data, cyg_uint8* ch)</literal></term> + <listitem> + <para> + This function tests the device and if a character is + available, places it in <parameter>*ch</parameter> and returns + <literal>TRUE</literal>. If no character is available, then + the function returns <literal>FALSE</literal> immediately. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int cyg_hal_plf_serial_control(void *__ch_data, + __comm_control_cmd_t __func, + ...)</literal></term> + <listitem> + <para> + This is an IOCTL-like function for controlling various aspects + of the serial device. The only part in which you may need to + do some work initially is in the + <literal>__COMMCTL_IRQ_ENABLE</literal> and + <literal>__COMMCTL_IRQ_DISABLE</literal> cases to + enable/disable interrupts. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>int cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD + __data)</literal></term> + <listitem> + <para> + This interrupt handler, called from the spurious interrupt + vector, is specifically for dealing with + <literal>Ctrl-C</literal> interrupts from GDB. When called + this function should do the following: + <orderedlist> + <listitem> + <para>Check for an incoming character. The code here is very + similar to that in + <function>cyg_hal_plf_serial_getc_nonblock()</function>. + </para> + </listitem> + <listitem> + <para> + Read the character and call + <function>cyg_hal_is_break()</function>. + </para> + </listitem> + <listitem> + <para> + If result is true, set <parameter>*__ctrlc</parameter> to + <literal>1</literal>. + </para> + </listitem> + <listitem> + <para> + Return <literal>CYG_ISR_HANDLED</literal>. + </para> + </listitem> + </orderedlist> + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>void cyg_hal_plf_serial_init()</literal></term> + <listitem> + <para> + Initialize each of the serial channels. + First call <function>cyg_hal_plf_serial_init_channel()</function> for each channel. + Then call the <literal>CYGACC_COMM_IF_*</literal> macros for + each channel. This latter set of calls are identical for all + channels, so the best way to do this is to copy and edit an + existing example. + </para> + </listitem> + </varlistentry> +</variablelist> + +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> +<!-- {{{ Variant HAL Porting --> + +<section id="hal-porting-variant"> +<title>Variant HAL Porting</title> + +<para> +A variant port can be a fairly limited job, but can also +require quite a lot of work. A variant HAL describes how a specific +CPU variant differs from the generic CPU architecture. The variant HAL +can re-define cache, MMU, interrupt, and other features which override +the default implementation provided by the architecture HAL. +</para> + +<para> +Doing a variant port requires a preexisting architecture HAL port. It +is also likely that a platform port will have to be done at the same +time if it is to be tested. +</para> + +<!-- {{{ Porting Process --> + +<section> +<TITLE>HAL Variant Porting Process</TITLE> + +<para>The easiest way to make a new variant HAL is simply to copy an +existing variant HAL and change all the files to match the new +variant. If this is the first variant for an architecture, it may be +hard to decide which parts should be put in the variant - knowledge of +other variants of the architecture is required.</para> + +<para>Looking at existing variant HALs (e.g., MIPS tx39, tx49) may be a +help - usually things such as caching, interrupt and exception +handling differ between variants. Initialization code, and code for +handling various core components (FPU, DSP, MMU, etc.) may also differ +or be missing altogether on some variants. Linker scripts may also require +specific variant versions.</para> + +<note> +<title>Note</title> +<para>Some CPU variants may require specific compiler +support. That support must be in place before you can undertake the +eCos variant port.</para> +</note> + + + +</section> + +<!-- }}} --> +<!-- {{{ CDL Requirements --> + +<section> +<TITLE>HAL Variant CDL</TITLE> + +<para> +The CDL in a variant HAL tends to depend on the exact functionality +supported by the variant. If it implements some of the devices +described in the platform HAL, then the CDL for those will be here +rather than there (for example the real-time clock). +</para> + +<para> +There may also be CDL to select options in the architecture HAL to +configure it to a particular architectural variant. +</para> + +<para> +Each variant needs an entry in the <filename>ecos.db</filename> +file. This is the one for the SH3: +</para> + +<programlisting width=72> +package CYGPKG_HAL_SH_SH3 { + alias { "SH3 architecture" hal_sh_sh3 } + directory hal/sh/sh3 + script hal_sh_sh3.cdl + hardware + description " + The SH3 (SuperH 3) variant HAL package provides generic + support for SH3 variant CPUs." +} +</programlisting> + +<para> +As you can see, it is very similar to the platform entry. +</para> + +<para> +The variant CDL file will contain a package entry named for the +architecture and variant, matching the package name in the +<filename>ecos.db</filename> file. Here is the initial part of the +MIPS VR4300 CDL file: +</para> + +<programlisting width=72> +cdl_package CYGPKG_HAL_MIPS_VR4300 { + display "VR4300 variant" + parent CYGPKG_HAL_MIPS + implements CYGINT_HAL_MIPS_VARIANT + hardware + include_dir cyg/hal + define_header hal_mips_vr4300.h + description " + The VR4300 variant HAL package provides generic support + for this processor architecture. It is also necessary to + select a specific target platform HAL package." +</programlisting> + +<para> +This defines the package, placing it under the MIPS architecture +package in the hierarchy. The <literal>implements</literal> line +indicates that this is a MIPS variant. The architecture package uses +this to check that exactly one variant is configured in. +</para> + +<para> +The variant defines some options that cause the architecture HAL to +configure itself to support this variant. +</para> + +<programlisting width=72> + cdl_option CYGHWR_HAL_MIPS_64BIT { + display "Variant 64 bit architecture support" + calculated 1 + } + + cdl_option CYGHWR_HAL_MIPS_FPU { + display "Variant FPU support" + calculated 1 + } + + cdl_option CYGHWR_HAL_MIPS_FPU_64BIT { + display "Variant 64 bit FPU support" + calculated 1 + } +</programlisting> + +<para> +These tell the architecture that this is a 64 bit MIPS architecture, +that it has a floating point unit, and that we are going to use it in +64 bit mode rather than 32 bit mode. +</para> + +<para> +The CDL file finishes off with some build options. +</para> + +<programlisting width=72> + define_proc { + puts $::cdl_header "#include <pkgconf/hal_mips.h>" + } + + compile var_misc.c + + make { + <PREFIX>/lib/target.ld: <PACKAGE>/src/mips_vr4300.ld + $(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(CFLAGS) -o $@ $< + @echo $@ ": \\" > $(notdir $@).deps + @tail +2 target.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm target.tmp + } + + cdl_option CYGBLD_LINKER_SCRIPT { + display "Linker script" + flavor data + no_define + calculated { "src/mips_vr4300.ld" } + } + +} +</programlisting> + +<para> +The <literal>define_proc</literal> causes the architecture +configuration file to be included into the configuration file for the +variant. The <literal>compile</literal> causes the single source file +for this variant, <filename>var_misc.c</filename> to be compiled. The +<literal>make</literal> command emits makefile rules to combine the +linker script with the <filename>.ldi</filename> file to generate +<literal>target.ld</literal>. Finally, in the MIPS HALs, the main +linker script is defined in the variant, rather than the architecture, +so <literal>CYGBLD_LINKER_SCRIPT</literal> is defined here. +</para> + +</section> + +<!-- }}} --> +<!-- {{{ Cache Support --> + +<section> +<title>Cache Support</title> + +<para> +The main area where the variant is likely to be involved is in cache +support. Often the only thing that distinguishes one CPU variant from +another is the size of its caches. +</para> + +<para> +In architectures such as the MIPS and PowerPC where cache instructions +are part of the ISA, most of the actual cache operations are +implemented in the architecture HAL. In this case the variant HAL only +needs to define the cache dimensions. The following are the cache +dimensions defined in the MIPS VR4300 variant +<filename>var_cache.h</filename>. +</para> + +<programlisting width=72> +// Data cache +#define HAL_DCACHE_SIZE (8*1024) // Size of data cache in bytes +#define HAL_DCACHE_LINE_SIZE 16 // Size of a data cache line +#define HAL_DCACHE_WAYS 1 // Associativity of the cache + +// Instruction cache +#define HAL_ICACHE_SIZE (16*1024) // Size of cache in bytes +#define HAL_ICACHE_LINE_SIZE 32 // Size of a cache line +#define HAL_ICACHE_WAYS 1 // Associativity of the cache + +#define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS)) +#define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS)) +</programlisting> + +<para> +Additional cache macros, or overrides for the defaults, may also +appear in here. While some architectures have instructions for +managing cache lines, overall enable/disable operations may be handled +via variant specific registers. If so then +<filename>var_cache.h</filename> should also define the +<literal>HAL_XCACHE_ENABLE()</literal> and +<literal>HAL_XCACHE_DISABLE()</literal> macros. +</para> + +<para> +If there are any generic features that the variant does not support +(cache locking is a typical example) then +<literal>var_cache.h</literal> may need to disable definitions of +certain operations. It is architecture dependent exactly how this is +done. +</para> + + +</section> + +<!-- }}} --> + +</section> + +<!-- }}} --> +<!-- {{{ Architecture HAL Porting --> + +<section id="hal-porting-architecture"> + +<title>Architecture HAL Porting</title> + +<para> +A new architecture HAL is the most complex HAL to write, and it the +least easily described. Hence this section is presently nothing more +than a place holder for the future. +</para> + +<!-- {{{ Porting Process --> + +<section> +<TITLE>HAL Architecture Porting Process</TITLE> + +<para>The easiest way to make a new architecture HAL is simply to copy an +existing architecture HAL of an, if possible, closely matching +architecture and change all the files to match the new +architecture. The MIPS architecture HAL should be used if possible, as +it has the appropriate layout and coding conventions. Other HALs +may deviate from that norm in various ways.</para> + +<note> +<title>Note</title> +<para> eCos is written for GCC. It requires C and C++ +compiler support as well as a few compiler features introduced during +eCos development - so compilers older than eCos may not provide these +features. Note that there is no C++ support for any 8 or 16 bit +CPUs. Before you can undertake an eCos port, you need the required +compiler support. +</para> +</note> + +<para> +The following gives a rough outline of the steps needed to create a +new architecture HAL. The exact order and set of steps needed will +vary greatly from architecture to architecture, so a lot of +flexibility is required. And of course, if the architecture HAL is to +be tested, it is necessary to do variant and platform ports for the +initial target simultaneously. +</para> + +<orderedlist> + +<listitem> +<para> +Make a new directory for the new architecture under the +<filename>hal</filename> directory in the source repository. Make an +<filename>arch</filename> directory under this and populate this with +the standard set of package directories. +</para> +</listitem> + +<listitem> +<para> +Copy the CDL file from an example HAL changing its name to match the +new HAL. Edit the file, changing option names as appropriate. Delete +any options that are specific to the original HAL, and and any new +options that are necessary for the new architecture. This is likely to +be a continuing process during the development of the HAL. See <xref +linkend="hal-porting-architecture-cdl"> for more details. +</para> +</listitem> + +<listitem> +<para> +Copy the <filename>hal_arch.h</filename> file from an example +HAL. Within this file you need to change or define the following: +</para> +<itemizedlist> + +<listitem> +<para> +Define the <structname>HAL_SavedRegisters</structname> structure. This +may need to reflect the save order of any group register save/restore +instructions, the interrupt and exception save and restore formats, +and the procedure calling conventions. It may also need to cater for +optional FPUs and other functional units. It can be quite difficult to +develop a layout that copes with all requirements. +</para> +</listitem> + +<listitem> +<para> +Define the bit manipulation routines, +<literal>HAL_LSBIT_INDEX()</literal> and +<literal>HAL_MSBIT_INDEX()</literal>. If the architecture contains +instructions to perform these, or related, operations, then these +should be defined as inline assembler fragments. Otherwise make them +calls to functions. +</para> +</listitem> + +<listitem> +<para> +Define <literal>HAL_THREAD_INIT_CONTEXT()</literal>. This initializes +a restorable CPU context onto a stack pointer so that a later call to +<literal>HAL_THREAD_LOAD_CONTEXT()</literal> or +<literal>HAL_THREAD_SWITCH_CONTEXT()</literal> will execute it +correctly. This macro needs to take account of the same optional +features of the architecture as the definition of +<structname>HAL_SavedRegisters</structname>. +</para> +</listitem> + +<listitem> +<para> +Define <literal>HAL_THREAD_LOAD_CONTEXT()</literal> and +<literal>HAL_THREAD_SWITCH_CONTEXT()</literal>. These should just be +calls to functions in <filename>context.S</filename>. +</para> +</listitem> + +<listitem> +<para> +Define <literal>HAL_REORDER_BARRIER()</literal>. This prevents code +being moved by the compiler and is necessary in some order-sensitive +code. This macro is actually defined identically in all architecture, +so it can just be copied. +</para> +</listitem> + +<listitem> +<para> +Define breakpoint support. The macro +<literal>HAL_BREAKPOINT(label)</literal> needs to be an inline assembly +fragment that invokes a breakpoint. The breakpoint instruction should +be labeled with the <parameter>label</parameter> +argument. <literal>HAL_BREAKINST</literal> and +<literal>HAL_BREAKINST_SIZE</literal> define the breakpoint +instruction for debugging purposes. +</para> +</listitem> + +<listitem> +<para> +Define GDB support. GDB views the registers of the target as a linear +array, with each register having a well defined offset. This array may +differ from the ordering defined in +<structname>HAL_SavedRegisters</structname>. The macros +<literal>HAL_GET_GDB_REGISTERS()</literal> and +<literal>HAL_SET_GDB_REGISTERS()</literal> translate between the GDB +array and the <structname>HAL_SavedRegisters</structname> structure. +The <literal>HAL_THREAD_GET_SAVED_REGISTERS()</literal> translates a +stack pointer saved by the context switch macros into a pointer to a +<structname>HAL_SavedRegisters</structname> structure. Usually this is +a one-to-one translation, but this macro allows it to differ if +necessary. +</para> +</listitem> + +<listitem> +<para> +Define long jump support. The type <type>hal_jmp_buf</type> and the +functions <function>hal_setjmp()</function> and +<literal>hal_longjmp()</literal> provide the underlying implementation +of the C library <function>setjmp()</function> and +<function>longjmp()</function>. +</para> +</listitem> + +<listitem> +<para> +Define idle thread action. Generally the macro +<literal>HAL_IDLE_THREAD_ACTION()</literal> is defined to call a +function in <filename>hal_misc.c</filename>. +</para> +</listitem> + +<listitem> +<para> +Define stack sizes. The macros +<literal>CYGNUM_HAL_STACK_SIZE_MINIMUM</literal> and +<literal>CYGNUM_HAL_STACK_SIZE_TYPICAL</literal> should be defined to +the minimum size for any thread stack and a reasonable default for +most threads respectively. It is usually best to construct these out +of component sizes for the CPU save state and procedure call stack +usage. These definitions should not use anything other than numerical +values since they can be used from assembly code in some HALs. +</para> +</listitem> + +<listitem> +<para> +Define memory access macros. These macros provide translation between +cached and uncached and physical memory spaces. They usually consist +of masking out bits of the supplied address and ORing in alternative +address bits. +</para> +</listitem> + +<listitem> +<para> +Define global pointer save/restore macros. These really only need +defining if the calling conventions of the architecture require a +global pointer (as does the MIPS architecture), they may be empty +otherwise. If it is necessary to define these, then take a look at the +MIPS implementation for an example. +</para> +</listitem> + +</itemizedlist> + +</listitem> + +<listitem> +<para> +Copy <filename>hal_intr.h</filename> from an example HAL. Within this +file you should change or define the following: +</para> + + +<itemizedlist> +<listitem> +<para> +Define the exception vectors. These should be detailed in the +architecture specification. Essentially for each exception entry point +defined by the architecture there should be an entry in the VSR +table. The offsets of these VSR table entries should be defined here +by <literal>CYGNUM_HAL_VECTOR_*</literal> definitions. The size of the +VSR table also needs to be defined here. +</para> +</listitem> + +<listitem> +<para> +Map any hardware exceptions to standard names. There is a group of +exception vector name of the form +<literal>CYGNUM_HAL_EXCEPTION_*</literal> that define a wide variety +of possible exceptions that many architectures raise. Generic code +detects whether the architecture can raise a given exception by +testing whether a given <literal>CYGNUM_HAL_EXCEPTION_*</literal> +definition is present. If it is present then its value is the vector +that raises that exception. This does not need to be a one-to-one +correspondence, and several <literal>CYGNUM_HAL_EXCEPTION_*</literal> +definitions may have the same value. +</para> + +<para> +Interrupt vectors are usually defined in the variant or platform +HALs. The interrupt number space may either be continuous with the VSR +number space, where they share a vector table (as in the i386) or may +be a separate space where a separate decode stage is used (as in MIPS +or PowerPC). +</para> + +</listitem> + +<listitem> +<para> +Declare any static data used by the HAL to handle interrupts and +exceptions. This is usually three vectors for interrupts: +<literal>hal_interrupt_handlers[]</literal>, +<literal>hal_interrupt_data[]</literal> and +<literal>hal_interrupt_objects[]</literal>, which are sized according +to the interrupt vector definitions. In addition a definition for the +VSR table, <literal>hal_vsr_table[]</literal> should be made. These +vectors are normally defined in either <filename>vectors.S</filename> +or <filename>hal_misc.c</filename>. +</para> +</listitem> + +<listitem> +<para> +Define interrupt enable/disable macros. These are normally inline +assembly fragments to execute the instructions, or manipulate the CPU +register, that contains the CPU interrupt enable bit. +</para> +</listitem> + +<listitem> +<para> +A feature that many HALs support is the ability to execute DSRs on the +interrupt stack. This is not an essential feature, and is better left +unimplemented in the initial porting effort. If this is required, then +the macro <literal>HAL_INTERRUPT_STACK_CALL_PENDING_DSRS()</literal> +should be defined to call a function in +<filename>vectors.S</filename>. +</para> +</listitem> + +<listitem> +<para> +Define the interrupt and VSR attachment macros. If the same arrays as +for other HALs have been used for VSR and interrupt vectors, then +these macro can be copied across unchanged. +</para> +</listitem> + +</itemizedlist> + +</listitem> + +<listitem> +<para> +A number of other header files also need to be filled in: +</para> +<itemizedlist> +<listitem> +<para> +<filename>basetype.h</filename>. This file defines the basic types +used by eCos, together with the endianness and some other +characteristics. This file only really needs to contain definitions +if the architecture differs significantly from the defaults defined +in <filename>cyg_type.h</filename> +</para> +</listitem> + +<listitem> +<para> +<filename>hal_io.h</filename>. This file contains macros for accessing +device IO registers. If the architecture uses memory mapped IO, then +these can be copied unchanged from an existing HAL such as MIPS. If +the architecture uses special IO instructions, then these macros must +be defined as inline assembler fragments. See the I386 HAL for an +example. PCI bus access macros are usually defined in the variant or +platform HALs. +</para> +</listitem> + +<listitem> +<para> +<filename>hal_cache.h</filename>. This file contains cache access +macros. If the architecture defines cache instructions, or control +registers, then the access macros should be defined here. Otherwise +they must be defined in the variant or platform HAL. Usually the cache +dimensions (total size, line size, ways etc.) are defined in the +variant HAL. +</para> +</listitem> + +<listitem> +<para> +<filename>arch.inc</filename> and +<filename><architecture>.inc</filename>. These files are +assembler headers used by <filename>vectors.S</filename> and +<filename>context.S</filename>. +<filename><architecture>.inc</filename> is a general purpose +header that should contain things like register aliases, ABI +definitions and macros useful to general assembly +code. If there are no such definitions, then this file need not be +provided. <filename>arch.inc</filename> contains macros for performing +various eCos related operations such as initializing the CPU, caches, +FPU etc. The definitions here may often be configured or overridden by +definitions in the variant or platform HALs. See the MIPS HAL for an +example of this. +</para> +</listitem> + +</itemizedlist> + +</listitem> + +<listitem> +<para> +Write <filename>vectors.S</filename>. This is the most important file +in the HAL. It contains the CPU initialization code, exception and +interrupt handlers. While other HALs should be consulted for +structures and techniques, there is very little here that can be +copied over without major edits. +</para> + +<para> +The main pieces of code that need to be defined here are: +</para> + +<itemizedlist> +<listitem> +<para> +Reset vector. This usually need to be positioned at the start of the +ROM or FLASH, so should be in a linker section of its own. It can then be +placed correctly by the linker script. Normally this code is little +more than a jump to the label <literal>_start</literal>. +</para> +</listitem> + +<listitem> +<para> +Exception vectors. These are the trampoline routines connected to the +hardware exception entry points that vector through the VSR table. In +many architectures these are adjacent to the reset vector, and should +occupy the same linker section. If the architecture allow the vectors +to be moved then it may be necessary for these trampolines to be +position independent so they can be relocated at runtime. +</para> + +<para> +The trampolines should do the minimum necessary to transfer control +from the hardware vector to the VSR pointed to by the matching table +entry. Exactly how this is done depends on the architecture. Usually +the trampoline needs to get some working registers by either saving +them to CPU special registers (e.g. PowerPC SPRs), using reserved +general registers (MIPS K0 and K1), using only memory based +operations (IA32), or just jumping directly (ARM). The VSR table index +to be used is either implicit in the entry point taken (PowerPC, IA32, +ARM), or must be determined from a CPU register (MIPS). +</para> +</listitem> + +<listitem> +<para> +Write kernel startup code. This is the location the reset vector jumps +to, and can be in the main text section of the executable, rather than +a special section. The code here should first initialize the CPU and other +hardware subsystems. The best approach is to use a set of macro +calls that are defined either in <filename>arch.inc</filename> or +overridden in the variant or platform HALs. Other jobs that this code +should do are: initialize stack pointer; copy the data section from +ROM to RAM if necessary; zero the BSS; call variant and platform +initializers; call <function>cyg_hal_invoke_constructors()</function>; +call <function>initialize_stub()</function> if necessary. Finally it +should call <function>cyg_start()</function>. See <xref +linkend="hal-startup"> for details. +</para> +</listitem> + +<listitem> +<para> +Write the default exception VSR. This VSR is installed in the VSR +table for all synchronous exception vectors. See <xref +linkend="hal-default-synchronous-exception-handling"> for details of +what this VSR does. +</para> +</listitem> + +<listitem> +<para> +Write the default interrupt VSR. This is installed in all VSR table +entries that correspond to external interrupts. See <xref +linkend="hal-default-synchronous-exception-handling"> for details of +what this VSR does. +</para> +</listitem> + +<listitem> +<para> +Write +<function>hal_interrupt_stack_call_pending_dsrs()</function>. If this +function is defined in <filename>hal_arch.h</filename> then it should +appear here. The purpose of this function is to call DSRs on the +interrupt stack rather than the current thread's stack. This is not an +essential feature, and may be left until later. However it interacts +with the stack switching that goes on in the interrupt VSR, so it may +make sense to write these pieces of code at the same time to ensure +consistency. +</para> + +<para> +When this function is implemented it should do the following: +</para> + +<itemizedlist> +<listitem> +<para> +Take a copy of the current SP and then switch to the interrupt stack. +</para> +</listitem> + +<listitem> +<para> +Save the old SP, together with the CPU status register (or whatever +register contains the interrupt enable status) and any other +registers that may be corrupted by a function call (such as any link +register) to locations in the interrupt stack. +</para> +</listitem> + +<listitem> +<para> +Enable interrupts. +</para> +</listitem> + +<listitem> +<para> +Call <function>cyg_interrupt_call_pending_DSRs()</function>. This is a +kernel functions that actually calls any pending DSRs. +</para> +</listitem> + +<listitem> +<para> +Retrieve saved registers from the interrupt stack and switch back to +the current thread stack. +</para> +</listitem> + +<listitem> +<para> +Merge the interrupt enable state recorded in the save CPU status +register with the current value of the status register to restore the +previous enable state. If the status register does not contain any +other persistent state then this can be a simple restore of the +register. However if the register contains other state bits that might +have been changed by a DSR, then care must be taken not to disturb +these. +</para> +</listitem> + +</itemizedlist> + +</listitem> + + +<listitem> +<para> +Define any data items needed. Typically <filename>vectors.S</filename> +may contain definitions for the VSR table, the interrupt tables and the +interrupt stack. Sometimes these are only default definitions that may +be overridden by the variant or platform HALs. +</para> +</listitem> + +</itemizedlist> + +</listitem> + +<listitem> +<para> +Write <filename>context.S</filename>. This file contains the context +switch code. See <xref linkend="hal-context-switch"> for details of +how these functions operate. This file may also contain the +implementation of <function>hal_setjmp()</function> and +<function>hal_longjmp()</function>. +</para> +</listitem> + +<listitem> +<para> +Write <filename>hal_misc.c</filename>. This file contains any C +data and functions needed by the HAL. These might include: +</para> + +<itemizedlist> +<listitem> +<para> +<varname>hal_interrupt_*[]</varname>. In some HALs, if these arrays +are not defined in <filename>vectors.S</filename> then they must be +defined here. +</para> +</listitem> + +<listitem> +<para> +<function>cyg_hal_exception_handler()</function>. This function is +called from the exception VSR. It usually does extra decoding of the +exception and invokes any special handlers for things like FPU traps, +bus errors or memory exceptions. If there is nothing special to be +done for an exception, then it either calls into the GDB stubs, by +calling <function>__handle_exception()</function>, or +invokes the kernel by calling +<function>cyg_hal_deliver_exception()</function>. +</para> +</listitem> + +<listitem> +<para> +<function>hal_arch_default_isr()</function>. The +<varname>hal_interrupt_handlers[]</varname> array is usually +initialized with pointers to <filename>hal_default_isr()</filename>, +which is defined in the common HAL. This function handles things like +Ctrl-C processing, but if that is not relevant, then it will call +<function>hal_arch_default_isr()</function>. Normally this function +should just return zero. +</para> +</listitem> + +<listitem> +<para> +<function>cyg_hal_invoke_constructors()</function>. This calls the +constructors for all static objects before the program starts. eCos +relies on these being called in the correct order for it to function +correctly. The exact way in which constructors are handled may differ +between architectures, although most use a simple table of function +pointers between labels <literal>__CTOR_LIST__</literal> and +<literal>__CTOR_END__</literal> which must called in order from the +top down. Generally, this function can be copied directly from an +existing architecture HAL. +</para> +</listitem> + +<listitem> +<para> +Bit indexing functions. If the macros +<literal>HAL_LSBIT_INDEX()</literal> and +<literal>HAL_MSBIT_INDEX()</literal> are defined as function calls, +then the functions should appear here. The main reason for doing this +is that the architecture does not have support for bit indexing and +these functions must provide the functionality by conventional +means. While the trivial implementation is a simple for loop, it is +expensive and non-deterministic. Better, constant time, +implementations can be found in several HALs (MIPS for example). +</para> +</listitem> + +<listitem> +<para> +<function>hal_delay_us()</function>. If the macro +<literal>HAL_DELAY_US()</literal> is defined in <filename +class="headerfile">hal_intr.h</filename> then it should be defined to +call this function. While most of the time this function is called +with very small values, occasionally (particularly in some ethernet +drivers) it is called with values of several seconds. Hence the +function should take care to avoid overflow in any calculations. +</para> +</listitem> + +<listitem> +<para> +<function>hal_idle_thread_action()</function>. This function is called +from the idle thread via the +<literal>HAL_IDLE_THREAD_ACTION()</literal> macro, if so +defined. While normally this function does nothing, during development +this is often a good place to report various important system +parameters on LCDs, LED or other displays. This function can also +monitor system state and report any anomalies. If the architecture +supports a <literal>halt</literal> instruction then this is a good +place to put an inline assembly fragment to execute it. It is also a +good place to handle any power saving activity. +</para> +</listitem> + +</itemizedlist> +</listitem> + +<listitem> +<para> +Create the <filename><architecture>.ld</filename> file. While +this file may need to be moved to the variant HAL in the future, it +should initially be defined here, and only moved if necessary. +</para> +<para> +This file defines a set of macros that are used by the platform +<literal>.ldi</literal> files to generate linker scripts. Most GCC +toolchains are very similar so the correct approach is to copy the +file from an existing architecture and edit it. The main things that +will need editing are the <literal>OUTPUT_FORMAT()</literal> directive +and maybe the creation or allocation of extra sections to various +macros. Running the target linker with just the +<literal>--verbose</literal> argument will cause it to output its +default linker script. This can be compared with the +<literal>.ld</literal> file and appropriate edits made. +</para> +</listitem> + +<listitem> +<para> +If GDB stubs are to be supported in RedBoot or eCos, then support must +be included for these. The most important of these are <filename +class="headerfile">include/<architecture>-stub.h</filename> and +<filename>src/<architecture>-stub.c</filename>. In all existing +architecture HALs these files, and any support files they need, have +been derived from files supplied in <literal>libgloss</literal>, as +part of the GDB toolchain package. If this is a totally new +architecture, this may not have been done, and they must be created +from scratch. +</para> + +<para> +<filename +class="headerfile">include/<architecture>-stub.h</filename> +contains definitions that are used by the GDB stubs to describe the +size, type, number and names of CPU registers. This information is +usually found in the GDB support files for the architecture. It also +contains prototypes for the functions exported by +<filename>src/<architecture>-stub.c</filename>; however, since +this is common to all architectures, it can be copied from some other +HAL. +</para> + +<para> +<filename>src/<architecture>-stub.c</filename> implements the +functions exported by the header. Most of this is fairly straight +forward: the implementation in existing HALs should show exactly what +needs to be done. The only complex part is the support for +single-stepping. This is used a lot by GDB, so it cannot be +avoided. If the architecture has support for a trace or single-step +trap then that can be used for this purpose. If it does not then this +must be simulated by planting a breakpoint in the next +instruction. This can be quite involved since it requires some +analysis of the current instruction plus the state of the CPU to +determine where execution is going to go next. +</para> + +</listitem> + +</orderedlist> + + +</section> + +<!-- }}} --> +<!-- {{{ CDL Requirements --> + +<section id="hal-porting-architecture-cdl"> +<title>CDL Requirements</title> + +<para> +The CDL needed for any particular architecture HAL depends to a large +extent on the needs of that architecture. This includes issues such as +support for different variants, use of FPUs, MMUs and caches. The +exact split between the architecture, variant and platform HALs for +various features is also somewhat fluid. +</para> + +<para> +To give a rough idea about how the CDL for an architecture is +structured, we will take as an example the I386 CDL. +</para> + +<para> +This first section introduces the CDL package and placed it under the +main HAL package. Include files from this package will be put in the +<filename>include/cyg/hal</filename> directory, and definitions from +this file will be placed in +<filename>include/pkgconf/hal_i386.h</filename>. The +<literal>compile</literal> line specifies the files in the +<filename>src</filename> directory that are to be compiled as part of +this package. +</para> + +<programlisting width=72> +cdl_package CYGPKG_HAL_I386 { + display "i386 architecture" + parent CYGPKG_HAL + hardware + include_dir cyg/hal + define_header hal_i386.h + description " + The i386 architecture HAL package provides generic + support for this processor architecture. It is also + necessary to select a specific target platform HAL + package." + + compile hal_misc.c context.S i386_stub.c hal_syscall.c +</programlisting> + +<para> +Next we need to generate some files using non-standard make rules. The +first is <filename>vectors.S</filename>, which is not put into the +library, but linked explicitly with all applications. The second is +the generation of the <filename>target.ld</filename> file from +<filename>i386.ld</filename> and the startup-selected +<filename>.ldi</filename> file. Both of these are essentially +boilerplate code that can be copied and edited. +</para> + +<programlisting width=72> + + make { + <PREFIX>/lib/vectors.o : <PACKAGE>/src/vectors.S + $(CC) -Wp,-MD,vectors.tmp $(INCLUDE_PATH) $(CFLAGS) -c -o $@ $< + @echo $@ ": \\" > $(notdir $@).deps + @tail +2 vectors.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm vectors.tmp + } + + make { + <PREFIX>/lib/target.ld: <PACKAGE>/src/i386.ld + $(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(CFLAGS) -o $@ $< + @echo $@ ": \\" > $(notdir $@).deps + @tail +2 target.tmp >> $(notdir $@).deps + @echo >> $(notdir $@).deps + @rm target.tmp + } +</programlisting> + +<para> +The i386 is currently the only architecture that supports SMP. The +following CDL simply enabled the HAL SMP support if +required. Generally this will get enabled as a result of a +<literal>requires</literal> statement in the kernel. The +<literal>requires</literal> statement here turns off lazy FPU +switching in the FPU support code, since it is inconsistent with SMP +operation. +</para> + +<programlisting width=72> + + cdl_component CYGPKG_HAL_SMP_SUPPORT { + display "SMP support" + default_value 0 + requires { CYGHWR_HAL_I386_FPU_SWITCH_LAZY == 0 } + + cdl_option CYGPKG_HAL_SMP_CPU_MAX { + display "Max number of CPUs supported" + flavor data + default_value 2 + } + } +</programlisting> + +<para> +The i386 HAL has optional FPU support, which is enabled by default. It +can be disabled to improve system performance. There are two FPU +support options: either to save and restore the FPU state on every +context switch, or to only switch the FPU state when necessary. +</para> + +<programlisting width=72> + + cdl_component CYGHWR_HAL_I386_FPU { + display "Enable I386 FPU support" + default_value 1 + description "This component enables support for the + I386 floating point unit." + + cdl_option CYGHWR_HAL_I386_FPU_SWITCH_LAZY { + display "Use lazy FPU state switching" + flavor bool + default_value 1 + + description " + This option enables lazy FPU state switching. + The default behaviour for eCos is to save and + restore FPU state on every thread switch, interrupt + and exception. While simple and deterministic, this + approach can be expensive if the FPU is not used by + all threads. The alternative, enabled by this option, + is to use hardware features that allow the FPU state + of a thread to be left in the FPU after it has been + descheduled, and to allow the state to be switched to + a new thread only if it actually uses the FPU. Where + only one or two threads use the FPU this can avoid a + lot of unnecessary state switching." + } + } +</programlisting> + +<para> +The i386 HAL also has support for different classes of CPU. In +particular, Pentium class CPUs have extra functional units, and some +variants of GDB expect more registers to be reported. These options +enable these features. Generally these are enabled by +<literal>requires</literal> statements in variant or platform +packages, or in <literal>.ecm</literal> files. +</para> + +<programlisting width=72> + + cdl_component CYGHWR_HAL_I386_PENTIUM { + display "Enable Pentium class CPU features" + default_value 0 + description "This component enables support for various + features of Pentium class CPUs." + + cdl_option CYGHWR_HAL_I386_PENTIUM_SSE { + display "Save/Restore SSE registers on context switch" + flavor bool + default_value 0 + + description " + This option enables SSE state switching. The default + behaviour for eCos is to ignore the SSE registers. + Enabling this option adds SSE state information to + every thread context." + } + + cdl_option CYGHWR_HAL_I386_PENTIUM_GDB_REGS { + display "Support extra Pentium registers in GDB stub" + flavor bool + default_value 0 + + description " + This option enables support for extra Pentium registers + in the GDB stub. These are registers such as CR0-CR4, and + all MSRs. Not all GDBs support these registers, so the + default behaviour for eCos is to not include them in the + GDB stub support code." + } + } +</programlisting> + +<para> +In the i386 HALs, the linker script is provided by the architecture +HAL. In other HALs, for example MIPS, it is provided in the variant +HAL. The following option provides the name of the linker script to +other elements in the configuration system. +</para> + +<programlisting width=72> + cdl_option CYGBLD_LINKER_SCRIPT { + display "Linker script" + flavor data + no_define + calculated { "src/i386.ld" } + } +</programlisting> + +<para> +Finally, this interface indicates whether the platform supplied an +implementation of the +<function>hal_i386_mem_real_region_top()</function> function. If it +does then it will contain a line of the form: <literal>implements +CYGINT_HAL_I386_MEM_REAL_REGION_TOP</literal>. This allows packages +such as RedBoot to detect the presence of this function so that they +may call it. +</para> + +<programlisting width=72> + + cdl_interface CYGINT_HAL_I386_MEM_REAL_REGION_TOP { + display "Implementations of hal_i386_mem_real_region_top()" + } + +} +</programlisting> + +</section> + +<!-- }}} --> + +<!-- +<para><a href="hal-arch-process.html">Porting process</a> +<para><a href="hal-cache.html">HAL Cache Controls</a> +<para><a href="hal-linking.html">Linker Script Macros</a> +<para><a href="hal-arch-cdl.html">CDL requirements</a> + +--> + +</section> + +<!-- }}} --> + +</CHAPTER> + +<!-- + +Notes added by Nickg: + +The following are my notes from the HAL Porting course I did at +Agilent in Feb 2002. It was my intention to incorporate some stuff +from here into the Platform Porting section and to include some of +the things I learned while doing the course. The main things I wanted +to do were: to change the porting process to concentrate on getting +RedBoot to run rather than the GDB stubs ROM; update the descriptions +to match current practice - some of it is now quite old; remove all +the TBDs and FIXMEs; mend the worst of Jesper's danglish :-) + +Also the variant and architecture porting guides are still in the +incomplete state that Jesper left them; and there are some other bits +and pieces in the original HTML porting guide that I have not yet +moved over. + +The ridiculous demands of management to sacrifice quality to +expediency mean that this is not now possible and this document has to +be abandoned in mid-flux. So I'm just dumping this stuff here. Maybe +one day someone will get around to doing it properly. + + + + +Porting Principals +================== + +Copy an existing HAL. + - choose a HAL with which you are familiar and/or which is + similar to the intended target. + - copy the files + - rename them appropriately + - rename configuration variables + - empty/reimplement platform specific code. + - old code is a good indicator of what you need to do. + - concentrate on getting it all to compile, so just commenting + out the platform specific bits is often a good idea. + +Follow execution order. + - gives a good indication of what to do next. + +Concentrate on RedBoot first. + - simpler environment - no interrupts, no threads. + + +CDL +=== + +CDL changes made as part of the copy/edit above should be done. + +Need to add entries to ecos.db for the new packages. + +Platform: + +package CYGPKG_HAL_ARM_ARM9_XXXXXXXX { + alias { "XXXXXXXX unit" hal_arm_arm9_xxxxxxxx xxxxxxxx } + directory hal/arm/arm9/xxxxxxxx + script hal_arm_arm9_xxxxxxxx.cdl + hardware + description " + The XXXXXXXX HAL package provides the support needed to run + eCos on an XXXXXXXX board." +} + +Target: + +target xxxxxxxx { + alias { "XXXXXXXX unit" aaed } + packages { CYGPKG_HAL_ARM + CYGPKG_HAL_ARM_ARM9 + CYGPKG_HAL_ARM_ARM9_XXXXXXXX + } + description " + The XXXXXXXX target provides the packages needed to run + eCos on an XXXXXXXX board." +} + +================================================================== + +Getting RedBoot Going +===================== + +Startup +======= + +1. Reset entry point. At location 0. + Transfer control to ROM entry point: reset_vector. + +2. Here we call invoke PLATFORM_SETUP1 macro. This does the following: + - disable interrupts + - disable and clear caches + - Init memory controllers. may involve discovery of what RAM is + present. + - Set up clock frequencies. + - Init MMU table + - sets up TTBR and DACR to default values + - fills in MMU table to map + - DRAM at 0x00000000 cacheable/buffered + - Device registers elsewhere uncacheable/unbuffered usually 1-1 + - DRAM at 0xF0000000 uncacheable/unbuffered (1-1 in aaed2000) + - remap ROM at 0 elsewhere + - Enable MMU + - Relocate image to RAM for ROMRAM startup + - Any other CPU setup required + +3. Jump to HAL startup. + - Plant vector intructions at 0+ + - copy .data section to RAM + - Init CPSR and SPSR + - Set SP + - Clear .bss + - Call hal_hardware_init() + - call initialize_stub() if GDB stubs included + - call hal_ctrlc_isr_init() + - call cyg_hal_invoke_constructors() + - call cyg_start() + + +HAL Serial support +================== + +Set up CDL in platform CDL file. + CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS + number of channels usually 0, 1 or 2 + CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL + channel to use for GDB + CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD + initial baud rate + CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL + channel to use for console + CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD + initial baud rate + CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT + default console channel + +The code in hal_diag.c need to be converted to the new serial device. +If this the same as a device already supported, copy that. + +Things that need to be written: + +struct channel_data_t; + Structure containing base address, timeout and ISR vector + number for each serial device. + +xxxx_ser_channels[]; + Array of channel_data_t, initialized with parameters of each + channel. + +void cyg_hal_plf_serial_init_channel(void *__ch_data) + Initialize the serial device. parameter is a pointer to a + channel_data_t. + +void cyg_hal_plf_serial_putc(void * __ch_data, char *c) + Send a character to the serial device. + Poll for ready, write the char. + Maybe poll for char sent. + +bool cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) + Look for a character and return it if available. + If none available, return false. + +int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t +__func, ...) + An IOCTL-like function for controlling various aspects of the + serial device. + May need to do some work in __COMMCTL_IRQ_ENABLE and + __COMMCTL_IRQ_DISABLE cases to enable/disable interrupts. + +int cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, + CYG_ADDRWORD __vector, CYG_ADDRWORD __data) + Interrupt handler, specifically for dealing with Ctrl-C. + - Check for an incoming character. + - Read the character and call cyg_hal_is_break(). + - If result is true, set *__ctrlc to 1. + - return CYG_ISR_HANDLED; + +void cyg_hal_plf_serial_init() + Initialize each of the serial channels. + - call cyg_hal_plf_serial_init_channel() for each channel. + - call CYGACC_COMM_IF_* macros for each channel - + cut/paste/edit these. + + +Interrupt Controller +==================== + +ARM platforms have interrupt controller access in functions in variant +or platform source file. + +void hal_interrupt_mask(int vector) + Manipulate interrupt controller to mask the interrupt. + +void hal_interrupt_unmask(int vector) + Manipulate interrupt controller to unmask the interrupt. + +void hal_interrupt_acknowledge(int vector) + Manipulate interrupt controller to acknowledge the interrupt. + May not be needed in some platforms. + +void hal_interrupt_configure(int vector, int level, int up) + Set interrupt detection: level vs. edge; high/low + rising/falling. + Leave empty where not implemented. + +void hal_interrupt_set_level(int vector, int level) + Set interrupt priority level. + Leave empty where not implemented. + + +Redboot Configuration +===================== + +Having done all of the above, you should be in a position to get +RedBoot running. + +If the platform you copied has redboot, there should be some .ecm +files in the misc directory. Named redboot_<startup>.ecm. + +Choose a startup and edit the .ecm file. + - remove any options that are not relevant + - comment out FLASH, ETH and COMPRESS packages + +Configure for redboot: + +% setenv ECOS_REPOSITORY <path to source repository> +% ecosconfig new xxxxxxxx redboot +% ecosconfig import $ECOS_REPOSITORY/hal/arm/arm9/xxxxxxxx/current/misc/redboot_ROM.ecm +% ecosconfig tree +% make + +Repeat until successful. + +Load into hardware by either programming FLASH from existing ROM +monitor, via JTAG or whatever. + +Run. Debug. Edit. Repeat. + +================================================================== + +Getting eCos Going +================== + +Once RedBoot is up and running, it should be possible to configure and +build eCos. + +Use the kernel template to start with. + + +Clock Support +============= + +We will use the RTC to test that interrupts are working. First step is +to get RTC working. + +void hal_clock_initialize(cyg_uint32 period) + Initialize the RTC device to interrupt every period ticks. The + CDL should have defined period according to the frequency + required. + This should start the clock going. + +void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) + Perform any work to cause the clock to start another timing + period. On many platforms this can be empty. On others the + counter or compare register may need to be reloaded. + +void hal_clock_read(cyg_uint32 *pvalue) + Returns the number of hardware ticks since the last interrupt. + For count-up timers this is just the value of the timer. + For count-down timers the result needs to be subtracted from the + initial period. + +void hal_delay_us(cyg_int32 usecs) + Busy delay for the given number of microseconds. + Normally this works by polling the timer device until the + required number of usecs has passed. + Beware of timer wrap-around, resets, and arithmetic overflows. + This function does not have to be very accurate - it's used + mostly to provide short timing delays during hardware access. + +Interrupt Handling +================== + +Quick overview of interrupt handling: + + +1. Hardware interrupts are delivered to either the IRQ or FIQ vectors at + 0x18 and 0x1c respectively. + +2. These contain single instructions that load the contents of the memory + location 0x20 later in memory and jump there. + +3. The code called is a VSR - Vector Service Routine. FIQ VSR fakes + CPU state to make it look like an IRQ, then drops into IRQ. + +4. Switch back to supervisor mode. Save CPU state onto current stack. + +5. Switch to interrupt stack if not already there. + +6. Lock scheduler. + +7. Call hal_IRQ_handler(). This function inspects the interrupt + controller and returns the number of the highest priority pending, + unmasked interrupt. + +8. Use vector number to index hal_interrupt_handlers[] and + hal_interrupt_data[] to get ISR and data. + +9. Call ISR. keep the return value. + +10. Switch back to original stack. + +11. Index hal_interrupt_objects[] with vector number to get interrupt + object pointer. + +12. Call interrupt_end(isr_ret, *object, *save_regs). + This will: + - post the onterrupt object's DSR if CYG_ISR_CALL_DSR is set in + return code. + - Unlock scheduler. During this the following may happen: + - Any pending DSRs may be called + - The current thread may be preempted, either by a higher + priority thread scheduled by a DSR, or it may be timesliced. + +13. The return from interrupt_end() may occur some time after the + call: lots of threads may have run in the meantime. + +14. Restore CPU state and resume interrupted code. + + +The only thing that needs doing in a platform port is to write +hal_IRQ_handler(). + + + +Once the clock and IRQ code is done, eCos should be able to run all of +the kernel tests. The best all-round test is tm_basic. Other tests +that should be run are: + clocktruth - tests accuracy of timer setup + except1 - checks exception handling works + timeslice - checks timeslicing works + +Run. Debug. Edit. Repeat. + + + + +--> + + diff --git a/ecos/packages/hal/common/current/include/dbg-thread-syscall.h b/ecos/packages/hal/common/current/include/dbg-thread-syscall.h new file mode 100644 index 0000000..f0a62ba --- /dev/null +++ b/ecos/packages/hal/common/current/include/dbg-thread-syscall.h @@ -0,0 +1,110 @@ +//======================================================================== +// +// dbg-thread-syscall.h +// +// Supports thread-aware debugging +// +//======================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Red Hat, nickg +// Contributors: Red Hat, nickg +// Date: 1998-08-25 +// Purpose: +// Description: Supports thread-aware debugging +// Usage: This header is not to be included by user code. +// This file should be included only by +// thread-syscall-relay.c and dbg-thread-demux.c +// +//####DESCRIPTIONEND#### +// +//======================================================================== + + +enum dbg_syscall_ids + { + dbg_null_func , + dbg_capabilities_func, + dbg_currthread_func, + dbg_threadlist_func, + dbg_threadinfo_func, + dbg_getthreadreg_func, + dbg_setthreadreg_func, + dbg_scheduler_func, + } ; + + +union dbg_thread_syscall_parms +{ + struct + { + struct dbg_capabilities * abilities ; + } cap_parms ; + + struct + { + threadref * ref ; + } currthread_parms ; + + struct + { + int startflag ; + threadref * lastid ; + threadref * nextthreadid ; + } threadlist_parms ; + + struct + { + threadref * ref ; + struct cygmon_thread_debug_info * info ; + } info_parms ; + + struct + { + threadref * thread ; + int regcount ; + void * registers ; + } reg_parms ; + struct + { + threadref * thread ; /* 64-bit thread identifier */ + int lock; /* 0 == unlock, 1 == lock */ + int mode; /* 0 == short (step), 1 == continue */ + } scheduler_parms ; +} ; + + +typedef int (*dbg_syscall_func) (enum dbg_syscall_ids id, + union dbg_thread_syscall_parms * p ) ; diff --git a/ecos/packages/hal/common/current/include/dbg-threads-api.h b/ecos/packages/hal/common/current/include/dbg-threads-api.h new file mode 100644 index 0000000..777716c --- /dev/null +++ b/ecos/packages/hal/common/current/include/dbg-threads-api.h @@ -0,0 +1,160 @@ +//======================================================================== +// +// dbg-threads-api.h +// +// Supports thread-aware debugging +// +//======================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Red Hat, nickg +// Contributors: Red Hat, nickg +// Date: 1998-08-25 +// Purpose: +// Description: These are the calls used to extract operating system +// specific information used in supporting thread aware +// debugging. The Operating Environment being debugged +// needs to supply these functions. +// Usage: This header is not to be included by user code. +// +//####DESCRIPTIONEND#### +// +//======================================================================== + +#if !defined(DBG_THREADS_API_INCLUDED) +#define DBG_THREADS_API_INCLUDED 1 + +#include <cyg/infra/cyg_type.h> /* externC */ + +#define has_thread_void 0 +#define has_thread_current 1 +#define has_thread_registers 2 +#define has_thread_reg_change 4 +#define has_thread_list 8 +#define has_thread_info 16 + +typedef unsigned char threadref[8] ; + +struct dbg_capabilities +{ + unsigned long mask1 ; +} ; + + +/* fill in the list of thread aware capabilities */ +externC int dbg_thread_capabilities(struct dbg_capabilities * cbp) ; + + +/* Fillin the identifier of the current thread */ +/* return 1 if defined, 0 if not defined */ +externC int dbg_currthread(threadref * varparm) ; + +/* Return the unique ID number of a given thread. */ +/* Return 0 if not valid. */ +externC int dbg_thread_id(threadref *threadid); + +/* Return the unique ID number of the current thread. */ +externC int dbg_currthread_id(void); + +/* get the first or next member of the list of known threads */ +externC int dbg_threadlist(int startflag, + threadref * lastthreadid, + threadref * next_thread + ) ; + +/* return 1 if next_threadid has been filled in with a value */ +/* return 0 if there are none or no more */ + +/* The O.S can fill in the following information about a thread when queried. + The structure of thise strings is determined by the O.S. + It is display oriented, so figure out what the users need to see. + Nulls are OK but GDB will fill some not so meaningful data. + These pointers may be in the calles private structures, the info will + get copied immediatly after the call to retreive it. + */ +struct cygmon_thread_debug_info +{ + threadref thread_id ; + int context_exists ; /* To the point where examining its state, + registers and stack makes sense to GDB */ + char * thread_display ; /* As shown in thread status window, name, state */ + char * unique_thread_name ; /* human readable identifier, window label */ + char * more_display ; /* more detailed info about thread. + priority, queuedepth, state, stack usage, statistics */ +} ; + + + + +externC int dbg_threadinfo( + threadref * threadid, + struct cygmon_thread_debug_info * info) ; + +/* Return 1 if threadid is defined and info copied, 0 otherwise */ + +/* The O.S should fillin the array of registers using values from the +saves context. The array MUST be in GDB register save order even if +the saved context is different or smaller. Do not alter the values of +registers which are NOT in the O.S. thread context. Their default values +have already been assigned. +*/ + +externC int dbg_getthreadreg( + threadref * osthreadid, + int regcount, /* count of registers in the array */ + void * regval) ; /* fillin this array */ + + +/* The O.S. should scan through this list of registers which are in +GDB order and the O.S. should replace the values of all registers +which are defined in the saved context of thread or process identified +by osthreadid. Return 0 if the threadis does not map to a known +process or other error. Return 1 if the setting is successful. */ + +externC int dbg_setthreadreg( + threadref * osthreadid, + int regcount , /* number of registers */ + void * regval) ; + +/* Control over OS scheduler. With the scheduler locked it should not + perform any rescheduling in response to interrupts. */ +externC int dbg_scheduler( + threadref * osthreadid, + int lock, /* 0 == unlock, 1 == lock */ + int mode); /* 0 == step, 1 == continue */ + + + +#endif /* DBG_THREADS_API_INCLUDED */ diff --git a/ecos/packages/hal/common/current/include/drv_api.h b/ecos/packages/hal/common/current/include/drv_api.h new file mode 100644 index 0000000..bf697fa --- /dev/null +++ b/ecos/packages/hal/common/current/include/drv_api.h @@ -0,0 +1,250 @@ +#ifndef CYGONCE_HAL_DRV_API_H +#define CYGONCE_HAL_DRV_API_H + +/*========================================================================== +// +// drv_api.h +// +// Native API for Kernel +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Date: 1999-02-24 +// Purpose: Driver API +// Description: This file defines the API used by device drivers to access +// system services. When the kernel is present it maps directly +// to the Kernel C API. When the kernel is absent, it is provided +// by a set of HAL functions. +// +// Usage: #include <cyg/kernel/kapi.h> +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <pkgconf/hal.h> +#include <cyg/infra/cyg_type.h> + +#ifdef CYGPKG_KERNEL + +/*------------------------------------------------------------------------*/ +/* Kernel co-resident version of API */ + +#include <pkgconf/kernel.h> + +#ifndef CYGFUN_KERNEL_API_C +#error Driver API requres Kernel API to be present +#endif + +#include <cyg/kernel/kapi.h> + +#define cyg_drv_isr_lock cyg_interrupt_disable +#define cyg_drv_isr_unlock cyg_interrupt_enable + +#define cyg_drv_dsr_lock cyg_scheduler_lock +#define cyg_drv_dsr_unlock cyg_scheduler_unlock + +#define cyg_drv_mutex_t cyg_mutex_t +#define cyg_drv_mutex_init cyg_mutex_init +#define cyg_drv_mutex_destroy cyg_mutex_destroy +#define cyg_drv_mutex_lock cyg_mutex_lock +#define cyg_drv_mutex_trylock cyg_mutex_trylock +#define cyg_drv_mutex_unlock cyg_mutex_unlock +#define cyg_drv_mutex_release cyg_mutex_release + +#define cyg_drv_cond_t cyg_cond_t +#define cyg_drv_cond_init cyg_cond_init +#define cyg_drv_cond_destroy cyg_cond_destroy +#define cyg_drv_cond_wait cyg_cond_wait +#define cyg_drv_cond_signal cyg_cond_signal +#define cyg_drv_cond_broadcast cyg_cond_broadcast + +#define cyg_drv_interrupt_create cyg_interrupt_create +#define cyg_drv_interrupt_delete cyg_interrupt_delete +#define cyg_drv_interrupt_attach cyg_interrupt_attach +#define cyg_drv_interrupt_detach cyg_interrupt_detach +#define cyg_drv_interrupt_mask cyg_interrupt_mask +#define cyg_drv_interrupt_unmask cyg_interrupt_unmask +#define cyg_drv_interrupt_mask_intunsafe cyg_interrupt_mask_intunsafe +#define cyg_drv_interrupt_unmask_intunsafe cyg_interrupt_unmask_intunsafe +#define cyg_drv_interrupt_acknowledge cyg_interrupt_acknowledge +#define cyg_drv_interrupt_configure cyg_interrupt_configure +#define cyg_drv_interrupt_level cyg_interrupt_level +#define cyg_drv_interrupt_set_cpu cyg_interrupt_set_cpu +#define cyg_drv_interrupt_get_cpu cyg_interrupt_get_cpu + +#define cyg_drv_spinlock_t cyg_spinlock_t +#define cyg_drv_spinlock_init cyg_spinlock_init +#define cyg_drv_spinlock_spin cyg_spinlock_spin +#define cyg_drv_spinlock_clear cyg_spinlock_clear +#define cyg_drv_spinlock_try cyg_spinlock_try +#define cyg_drv_spinlock_test cyg_spinlock_test +#define cyg_drv_spinlock_spin_intsave cyg_spinlock_spin_intsave +#define cyg_drv_spinlock_clear_intsave cyg_spinlock_clear_intsave + +#else /* CYGPKG_KERNEL */ + +/*------------------------------------------------------------------------*/ +/* Non-kernel version of API */ + +typedef CYG_ADDRWORD cyg_addrword_t; /* May hold pointer or word */ +typedef cyg_addrword_t cyg_handle_t; /* Object handle */ +typedef cyg_uint32 cyg_priority_t; /* type for priorities */ +typedef cyg_uint32 cyg_vector_t; /* Interrupt vector id */ +typedef cyg_uint32 cyg_cpu_t; /* CPU id */ +typedef int cyg_bool_t; +typedef cyg_int32 cyg_code_t; /* type for various codes */ + +typedef cyg_uint32 cyg_ISR_t( cyg_vector_t vector, cyg_addrword_t data); +typedef void cyg_DSR_t(cyg_vector_t vector, + cyg_ucount32 count, + cyg_addrword_t data); + + +externC void cyg_drv_isr_lock(void); +externC void cyg_drv_isr_unlock(void); + +externC void cyg_drv_dsr_lock(void); +externC void cyg_drv_dsr_unlock(void); + +typedef struct +{ + cyg_atomic lock; +} cyg_drv_mutex_t; + +externC void cyg_drv_mutex_init( cyg_drv_mutex_t *mutex ); +externC void cyg_drv_mutex_destroy( cyg_drv_mutex_t *mutex ); +externC cyg_bool_t cyg_drv_mutex_lock( cyg_drv_mutex_t *mutex ); +externC cyg_bool_t cyg_drv_mutex_trylock( cyg_drv_mutex_t *mutex ); +externC void cyg_drv_mutex_unlock( cyg_drv_mutex_t *mutex ); +externC void cyg_drv_mutex_release( cyg_drv_mutex_t *mutex ); + +typedef struct +{ + cyg_atomic wait; + cyg_drv_mutex_t *mutex; +} cyg_drv_cond_t; + +externC void cyg_drv_cond_init( cyg_drv_cond_t *cond, cyg_drv_mutex_t *mutex ); +externC void cyg_drv_cond_destroy( cyg_drv_cond_t *cond ); +externC cyg_bool_t cyg_drv_cond_wait( cyg_drv_cond_t *cond ); +externC void cyg_drv_cond_signal( cyg_drv_cond_t *cond ); +externC void cyg_drv_cond_broadcast( cyg_drv_cond_t *cond ); + +typedef struct cyg_interrupt +{ + cyg_vector_t vector; + cyg_priority_t priority; + cyg_ISR_t *isr; + cyg_DSR_t *dsr; + CYG_ADDRWORD data; + + struct cyg_interrupt* volatile next_dsr; + volatile cyg_int32 dsr_count; + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN + struct cyg_interrupt *next; +#endif + +} cyg_interrupt; + +externC void cyg_drv_interrupt_create( + cyg_vector_t vector, + cyg_priority_t priority, + cyg_addrword_t data, + cyg_ISR_t *isr, + cyg_DSR_t *dsr, + cyg_handle_t *handle, + cyg_interrupt *intr + ); +externC void cyg_drv_interrupt_delete( cyg_handle_t interrupt ); +externC void cyg_drv_interrupt_attach( cyg_handle_t interrupt ); +externC void cyg_drv_interrupt_detach( cyg_handle_t interrupt ); + +externC void cyg_drv_interrupt_mask( cyg_vector_t vector ); +externC void cyg_drv_interrupt_mask_intunsafe( cyg_vector_t vector ); +externC void cyg_drv_interrupt_unmask( cyg_vector_t vector ); +externC void cyg_drv_interrupt_unmask_intunsafe( cyg_vector_t vector ); +externC void cyg_drv_interrupt_acknowledge( cyg_vector_t vector ); +externC void cyg_drv_interrupt_configure( + cyg_vector_t vector, + cyg_bool_t level, + cyg_bool_t up + ); +externC void cyg_drv_interrupt_level( cyg_vector_t vector, cyg_priority_t level ); +externC void cyg_drv_interrupt_set_cpu( cyg_vector_t vector, cyg_cpu_t cpu ); +externC cyg_cpu_t cyg_drv_interrupt_get_cpu( cyg_vector_t vector ); + + +enum cyg_ISR_results +{ + CYG_ISR_HANDLED = 1, /* Interrupt was handled */ + CYG_ISR_CALL_DSR = 2 /* Schedule DSR */ +}; + + +typedef struct +{ + cyg_atomic lock; +} cyg_drv_spinlock_t; + +void cyg_drv_spinlock_init( + cyg_drv_spinlock_t *lock, /* spinlock to initialize */ + cyg_bool_t locked /* init locked or unlocked */ +); + +void cyg_drv_spinlock_destroy( cyg_drv_spinlock_t *lock ); + +void cyg_drv_spinlock_spin( cyg_drv_spinlock_t *lock ); + +void cyg_drv_spinlock_clear( cyg_drv_spinlock_t *lock ); + +cyg_bool_t cyg_drv_spinlock_try( cyg_drv_spinlock_t *lock ); + +cyg_bool_t cyg_drv_spinlock_test( cyg_drv_spinlock_t *lock ); + +void cyg_drv_spinlock_spin_intsave( cyg_drv_spinlock_t *lock, + cyg_addrword_t *istate ); + +void cyg_drv_spinlock_clear_intsave( cyg_drv_spinlock_t *lock, + cyg_addrword_t istate ); + +#endif /* CYGPKG_KERNEL */ + +/*------------------------------------------------------------------------*/ +/* EOF drv_api.h */ +#endif // CYGONCE_HAL_DRV_API_H diff --git a/ecos/packages/hal/common/current/include/generic-stub.h b/ecos/packages/hal/common/current/include/generic-stub.h new file mode 100644 index 0000000..ff4cb09 --- /dev/null +++ b/ecos/packages/hal/common/current/include/generic-stub.h @@ -0,0 +1,364 @@ +//======================================================================== +// +// generic-stub.h +// +// Definitions for the generic GDB remote stub +// +//======================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Red Hat, nickg +// Contributors: Red Hat, nickg, dmoseley +// Date: 1998-06-08 +// Purpose: +// Description: Definitions for the generic GDB remote stub +// Usage: This header is not to be included by user code, and is +// only placed in a publically accessible directory so +// that platform stub packages are able to include it +// if required. +// +//####DESCRIPTIONEND#### +// +//======================================================================== + + +#ifndef GENERIC_STUB_H +#define GENERIC_STUB_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Three typedefs must be provided before including this file. + target_register_t should correspond to the largest register value on + this target processor. + regnames_t corresponds to a type representing a register number. + uint32 must correspond to at least a 32-bit unsigned integer type + (it may be larger). */ + +#ifndef ASM + +#ifndef __ECOS__ +#include "dbg-serial.h" +#endif // __ECOS__ + +struct gdb_packet +{ + /* The checksum calculated so far. */ + uint32 checksum; + /* The checksum we've received from the remote side. */ + uint32 xmitcsum; + /* Contents of the accumulated packet. */ + char *contents; + /* Number of characters received. */ + uint32 length; + /* + * state is the current state: + * 0 = looking for start of packet + * 1 = got start of packet, looking for # terminator + * 2 = looking for first byte of checksum + * 3 = looking for second byte of checksum (indicating end of packet) + */ + char state; + char err; // This is set if the packet should be tossed because of overflow +}; + +/* Return the currently-saved value corresponding to register REG. */ +extern target_register_t get_register (regnames_t reg); + +/* Write the contents of register WHICH into VALUE as raw bytes */ +extern int get_register_as_bytes (regnames_t which, char *value); + +#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING +// Return the validity of register REG. +extern int get_register_valid (regnames_t reg); +#endif + +/* Store VALUE in the register corresponding to WHICH. */ +extern void put_register (regnames_t which, target_register_t value); + +extern int put_register_as_bytes (regnames_t which, char *value); + +/* Set the next instruction to be executed when the user program resumes + execution to PC. */ +#if !defined(SET_PC_PROTOTYPE_EXISTS) && !defined(set_pc) +#define SET_PC_PROTOTYPE_EXISTS +extern void set_pc (target_register_t pc); +#endif + +/* Set the return value of the currently-pending syscall to VALUE. */ +extern void set_syscall_value (target_register_t value); + +/* Return the Nth argument to the currently-pending syscall (starting from + 0). */ +extern target_register_t get_syscall_arg (int n); + +/* Initialize the stub. This will also install any trap handlers needed by + the stub. */ +extern void initialize_stub (void); + +/* Initialize the hardware. */ +extern void initHardware (void); + +/* Skip the current instruction. */ +extern void __skipinst (void); + +/* If the address in the PC register corresponds to the breakpoint() + instruction, return a non-zero value. */ +#ifndef __is_breakpoint_function +extern int __is_breakpoint_function (void); +#endif + +/* Execute a breakpoint instruction. Restarting will cause the instruction + to be skipped. */ +#ifndef breakpoint +extern void breakpoint (void); +#endif + +/* Return the syscall # corresponding to this system call. */ +extern int __get_syscall_num (void); + +/* Transfer exception event processing to the stub. */ +extern void __switch_to_stub (void); + +/* Send an exit packet containing the specified status. */ +extern void __send_exit_status (int status); + +/* Copy COUNT bytes of memory from ADDR to BUF. + ADDR is assumed to live in the user program's space. + Returns number of bytes successfully read + (caller must check to see if less than requested). */ +extern int __read_mem_safe (void *buf, + void *addr, + int count); + +extern int __read_progmem_safe (void *buf, + void *addr, + int count); + +/* Copy COUNT bytes of memory from BUF to ADDR. + ADDR is assumed to live in the user program's space. + Returns number of bytes successfully read + (caller must check to see if less than requested). */ +#ifndef __write_mem_safe +extern int __write_mem_safe (void *buf, + void *addr, + int count); +#endif + +extern int __write_progmem_safe (void *buf, + void *addr, + int count); + +/* Set to a non-zero value if a memory fault occurs while + __set_mem_fault_trap () is running. */ +extern volatile int __mem_fault; + +#ifndef __ECOS__ +#if 1 +#include "stub-tservice.h" /* target dependent stub services */ +#else +/* Flush the instruction cache. */ +extern void flush_i_cache (void); + +/* Flush the data cache. */ +extern void __flush_d_cache (void); + +typedef enum { + CACHE_NOOP, CACHE_ENABLE, CACHE_DISABLE, CACHE_FLUSH +} cache_control_t; + +/* Perform the specified operation on the instruction cache. + Returns 1 if the cache is enabled, 0 otherwise. */ +extern int __instruction_cache (cache_control_t request); +/* Perform the specified operation on the data cache. + Returns 1 if the cache is enabled, 0 otherwise. */ +extern int __data_cache (cache_control_t request); +#endif +#endif // __ECOS__ + +/* Write the 'T' packet in BUFFER. SIGVAL is the signal the program + received. */ +extern void __build_t_packet (int sigval, char *buffer); + +/* Return 1 when a complete packet has been received, 0 if the packet + is not yet complete, or -1 if an erroneous packet was NAKed. */ +int __add_char_to_packet (unsigned character, struct gdb_packet *packet); + +typedef int (*__PFI)(int); +typedef void (*__PFV)(void); + +/* When an exception occurs, __process_exception_vec will be invoked with + the signal number corresponding to the trap/exception. The function + should return zero if it wishes execution to resume from the saved + register values; a non-zero value indicates that the exception handler + should be reinvoked. */ +#if !defined(PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS) +#define PROCESS_EXCEPTION_VEC_PROTOTYPE_EXISTS +extern volatile __PFI __process_exception_vec; +#endif + +/* __process_exit_vec is invoked when a 'k' kill packet is received + from GDB. */ +extern volatile __PFV __process_exit_vec; + +/* If SIGSYSCALL is defined, and such a signal value is returned from + __computeSignal (), the function pointed to by this vector will + be invoked. + + If the return value is negative, the user program is assumed to + have received the corresponding positive signal value, and an + exception will be processed. Otherwise, the user program is + restarted from the next instruction. */ +extern volatile __PFI __process_syscall_vec; + +/* A continue packet was received from GDB with a signal value. The function + pointed to by __process_signal_vec will be invoked with this signal + value. + + If a zero value is returned, we will ignore the signal, and proceed + with the continue request. Otherwise, the program will be killed + with the signal. */ +extern volatile __PFI __process_signal_vec; + +/* If non-NULL, __init_vec is called right before the user program is + resumed. */ +extern volatile __PFV __init_vec; +/* if non-NULL, __cleanup_vec is called after the user program takes + an exception. */ +extern volatile __PFV __cleanup_vec; + +/* Send an 'O' packet to GDB containing STR. */ +extern int __output_gdb_string (target_register_t addr, int string_len); + +/* Request MAXLEN bytes of input from GDB to be stored in DEST. If BLOCK + is set, GDB should block until MAXLEN bytes are available to be + read; otherwise, it will return immediately with whatever data is + available. + The return value is the number of bytes written into DEST. */ +extern int __get_gdb_input (target_register_t dest, int maxlen, int block); + +/* Return the ASCII equivalent of C (C>=0 && C<=15). The result will be + lower-case. */ +extern char __tohex (int c); + +/* Convert COUNT bytes of the memory region in MEM to a hexadecimal + string in DEST. + The resulting string will contain 2*COUNT characters. + If MAY_FAULT is non-zero, memory faults are trapped; if a fault occurs, + a NULL value will be returned. + The value returned is one byte past the end of the string written. */ +extern char *__mem2hex (char *mem, char *dest, int count, int may_fault); + +/* Given a hexadecimal string in MEM, write the equivalent bytes to DEST. + The string is assumed to contain 2*COUNT characters. + If MAY_FAULT is non-zero, memory faults are trapped; if a fault occurs, + a NULL value will be returned. + Otherwise, the value returned is one byte past the last byte written. */ +extern char *__hex2mem (char *buf, char *mem, int count, int may_fault); + +#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS +/* Set the program arguments passed into the user program's main */ +extern void __set_program_args (int argc, char **argv); + +/* Return the user program arguments passed in from GDB (via an 'A' + packet). argcPtr is a pointer into the user program, which will hold + the number of arguments; the strings are returned. */ +extern char **__get_program_args (target_register_t argcPtr); +#endif + +/* Encode PACKET as a remote protocol packet and send it to GDB; this takes + care of sending the initial '$' character, as well as the trailing '#' + and checksum, and also waits for an ACK from the remote side, resending + as necessary. */ +extern void __putpacket (char *packet); + +/* Retrieve the next remote protocol packet from GDB, taking care of verifying + the checksum and sending an ACK when necessary. */ +extern void __getpacket (char *buffer); + +/* Convert the hexadecimal string pointed to by *PTR into an integer, + and store it in the value pointed to by INTVALUE. The number of + characters read from *PTR will be returned; *PTR will point to the first + non-hexadecmial character encountered. */ +extern unsigned int __hexToInt (char **ptr, target_register_t *intValue); + +/* Convert the value in INTVALUE into a string of hexadecimal + characters stored in PTR. NUMBITS are the number of bits to use + in INTVALUE. The number of characters written to PTR will be returned. */ +extern unsigned int __intToHex (char *ptr, + target_register_t intValue, + int numBits); + +/* Handle an exception, usually some sort of hardware or software trap. + This is responsible for communicating the exception to GDB. */ +extern void __handle_exception (void); + +/* Send a 'X' packet with signal SIGVAL to GDB. */ +extern void __kill_program (int sigval); + +/* Given a packet pointed to by PACKETCONTENTS, decode it and respond to + GDB appropriately. */ +extern int __process_packet (char *packetContents); + +/* Write the C-style string pointed to by STR to the GDB comm port. + Used for printing debug messages. */ +extern void __putDebugStr (char *str); + +#if defined(NO_MALLOC) && !defined(MAX_BP_NUM) +#define MAX_BP_NUM 64 /* Maximum allowed # of breakpoints */ +#endif + +extern int hal_syscall_handler(void); +extern int __is_bsp_syscall(void); + +extern void __install_breakpoint_list (void); +extern void __clear_breakpoint_list (void); +extern int __display_breakpoint_list (void (*print_func)(target_register_t)); + +/* 'Z' packet types */ +#define ZTYPE_SW_BREAKPOINT 0 +#define ZTYPE_HW_BREAKPOINT 1 +#define ZTYPE_HW_WATCHPOINT_WRITE 2 +#define ZTYPE_HW_WATCHPOINT_READ 3 +#define ZTYPE_HW_WATCHPOINT_ACCESS 4 + +#endif /* ASM */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* GENERIC_STUB_H */ diff --git a/ecos/packages/hal/common/current/include/hal_arbiter.h b/ecos/packages/hal/common/current/include/hal_arbiter.h new file mode 100644 index 0000000..b9b75a2 --- /dev/null +++ b/ecos/packages/hal/common/current/include/hal_arbiter.h @@ -0,0 +1,139 @@ +#ifndef CYGONCE_HAL_HAL_ARBITER_H +#define CYGONCE_HAL_HAL_ARBITER_H + +//============================================================================= +// +// hal_arbiter.h +// +// Functionality used by ISR arbiters +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov +// Date: 2001-06-29 +// Purpose: Functionality used by ISR arbiters +// Usage: #include <cyg/hal/hal_arbiter.h> +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <cyg/hal/hal_intr.h> // hal_interrupt_x tables +#include <cyg/hal/drv_api.h> // CYG_ISR_HANDLED + +//============================================================================= +// Function used to call ISRs from ISR arbiters +// An arbiter is hooked on the shared interrupt vector and looks like this: +// +// cyg_uint32 _arbitration_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +// { +// cyg_uint32 isr_ret; +// // decode interrupt source and for each active source call the ISR +// if (source_A_active) { +// isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SOURCE_A); +// #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN +// if (isr_ret & CYG_ISR_HANDLED) +// #endif +// return isr_ret; +// } +// if (source_B_active) { +// isr_ret = hal_call_isr (CYGNUM_HAL_INTERRUPT_SOURCE_B); +// #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN +// if (isr_ret & CYG_ISR_HANDLED) +// #endif +// return isr_ret; +// } +// ... +// return 0; +// } +// +// Remember to attach and enable the arbiter source: +// HAL_INTERRUPT_ATTACH(CYGNUM_HAL_INTERRUPT_ARBITER, &_arbitration_isr, 0, 0); +// HAL_INTERRUPT_SET_LEVEL(CYGNUM_HAL_INTERRUPT_ARBITER, 1); +// HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_ARBITER); +// + +typedef cyg_uint32 cyg_ISR(cyg_uint32 vector, CYG_ADDRWORD data); + +extern void cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj ); + +#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN + +static inline cyg_uint32 +hal_call_isr (cyg_uint32 vector) +{ + cyg_ISR *isr; + CYG_ADDRWORD data; + cyg_uint32 isr_ret; + + isr = (cyg_ISR*) hal_interrupt_handlers[vector]; + data = hal_interrupt_data[vector]; + + isr_ret = (*isr) (vector, data); + + if (isr_ret & CYG_ISR_CALL_DSR) { + cyg_interrupt_post_dsr (hal_interrupt_objects[vector]); + } + + return isr_ret & ~CYG_ISR_CALL_DSR; +} + +#else + +// In chained mode, assume vector 0 points to the chain +// handler. Simply call it with the vector number and let it find the +// ISR to call - it will also post DSRs as required. +static inline cyg_uint32 +hal_call_isr (cyg_uint32 vector) +{ + cyg_ISR *isr; + CYG_ADDRWORD data; + cyg_uint32 isr_ret; + + isr = (cyg_ISR*) hal_interrupt_handlers[0]; + data = hal_interrupt_data[0]; + + isr_ret = (*isr) (vector, data); + + return isr_ret; +} + +#endif + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_HAL_ARBITER_H +// End of hal_arbiter.h diff --git a/ecos/packages/hal/common/current/include/hal_endian.h b/ecos/packages/hal/common/current/include/hal_endian.h new file mode 100644 index 0000000..80e59d4 --- /dev/null +++ b/ecos/packages/hal/common/current/include/hal_endian.h @@ -0,0 +1,109 @@ +#ifndef CYGONCE_HAL_HAL_ENDIAN_H +#define CYGONCE_HAL_HAL_ENDIAN_H + +//============================================================================= +// +// hal_endian.h +// +// Endian conversion macros +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov +// Date: 2001-10-04 +// Purpose: Endian conversion macros +// Usage: #include <cyg/hal/hal_endian.h> +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal.h> // CYGBLD_HAL_ENDIAN_H +#include <cyg/infra/cyg_type.h> // endian setting + +// Allow HALs to override the generic implementation of swap macros +#ifdef CYGBLD_HAL_ENDIAN_H +# include CYGBLD_HAL_ENDIAN_H +#endif + +#ifndef CYG_SWAP16 +# define CYG_SWAP16(_x_) \ + ({ cyg_uint16 _x = (_x_); (cyg_uint16)((_x << 8) | (_x >> 8)); }) +#endif + +#ifndef CYG_SWAP32 +# define CYG_SWAP32(_x_) \ + ({ cyg_uint32 _x = (_x_); \ + ((_x << 24) | \ + ((0x0000FF00UL & _x) << 8) | \ + ((0x00FF0000UL & _x) >> 8) | \ + (_x >> 24)); }) +#endif + + +#if (CYG_BYTEORDER == CYG_LSBFIRST) +# define CYG_CPU_TO_BE16(_x_) CYG_SWAP16((_x_)) +# define CYG_CPU_TO_BE32(_x_) CYG_SWAP32((_x_)) +# define CYG_BE16_TO_CPU(_x_) CYG_SWAP16((_x_)) +# define CYG_BE32_TO_CPU(_x_) CYG_SWAP32((_x_)) + +# define CYG_CPU_TO_LE16(_x_) (_x_) +# define CYG_CPU_TO_LE32(_x_) (_x_) +# define CYG_LE16_TO_CPU(_x_) (_x_) +# define CYG_LE32_TO_CPU(_x_) (_x_) + +#elif (CYG_BYTEORDER == CYG_MSBFIRST) + +# define CYG_CPU_TO_BE16(_x_) (_x_) +# define CYG_CPU_TO_BE32(_x_) (_x_) +# define CYG_BE16_TO_CPU(_x_) (_x_) +# define CYG_BE32_TO_CPU(_x_) (_x_) + +# define CYG_CPU_TO_LE16(_x_) CYG_SWAP16((_x_)) +# define CYG_CPU_TO_LE32(_x_) CYG_SWAP32((_x_)) +# define CYG_LE16_TO_CPU(_x_) CYG_SWAP16((_x_)) +# define CYG_LE32_TO_CPU(_x_) CYG_SWAP32((_x_)) + +#else + +# error "Endian mode not selected" + +#endif + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_HAL_ENDIAN_H +// End of hal_endian.h diff --git a/ecos/packages/hal/common/current/include/hal_if.h b/ecos/packages/hal/common/current/include/hal_if.h new file mode 100644 index 0000000..ae68100 --- /dev/null +++ b/ecos/packages/hal/common/current/include/hal_if.h @@ -0,0 +1,756 @@ +#ifndef CYGONCE_HAL_HAL_IF_H +#define CYGONCE_HAL_HAL_IF_H + +//============================================================================= +// +// hal_if.h +// +// HAL header for ROM/RAM calling interface. +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov, woehler +// Date: 2000-06-07 +// Purpose: HAL RAM/ROM calling interface +// Description: ROM/RAM calling interface table definitions. The layout is a +// combination of libbsp and vectors already in use by some +// eCos platforms. +// Usage: #include <cyg/hal/hal_if.h> +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <cyg/infra/cyg_type.h> // types & externC +#include <cyg/hal/dbg-threads-api.h> +#include <cyg/hal/dbg-thread-syscall.h> + +#include <stdarg.h> + +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + +// Architecture/var/platform may override the accessor macros. +#include <cyg/hal/hal_arch.h> + +// Special monitor locking procedures. These are necessary when the monitor +// and eCos share facilities, e.g. the network hardware. +#if defined (CYGPKG_NET) || defined (CYGPKG_NET_LWIP) +#include <cyg/hal/hal_intr.h> +#include <cyg/hal/drv_api.h> // cyg_drv_dsr_lock(), etc +#define _ENTER_MONITOR() \ + cyg_uint32 ints; \ + HAL_DISABLE_INTERRUPTS(ints); \ + cyg_drv_dsr_lock() + +#define _EXIT_MONITOR() \ + cyg_drv_dsr_unlock(); \ + HAL_RESTORE_INTERRUPTS(ints) +#else // !CYGPKG_NET && !CYGPKG_NET_LWIP +#define _ENTER_MONITOR() CYG_EMPTY_STATEMENT +#define _EXIT_MONITOR() CYG_EMPTY_STATEMENT +#endif + +//-------------------------------------------------------------------------- +#ifndef _BSP_HANDLER_T_DEFINED +#define _BSP_HANDLER_T_DEFINED +typedef int (*bsp_handler_t)(int __irq_nr, void *__regs); +#endif // _BSP_HANDLER_T_DEFINED + +//-------------------------------------------------------------------------- +// Communication interface table. CYGNUM_CALL_IF_CONSOLE_PROCS and +// CYGNUM_CALL_IF_DEBUG_PROCS point to instances (possibly the same) +// of this table. + +typedef enum { + /* + * For serial ports, the control function may be used to set and get the + * current baud rate. Usage: + * + * err = (*__control)(COMMCTL_SETBAUD, int bits_per_second); + * err => Zero if successful, -1 if error. + * + * baud = (*__control)(COMMCTL_GETBAUD); + * baud => -1 if error, current baud otherwise. + */ + __COMMCTL_SETBAUD=0, + __COMMCTL_GETBAUD, + + /* + * Install and remove debugger interrupt handlers. These are the receiver + * interrupt routines which are used to change control from a running + * program to the debugger stub. + */ + __COMMCTL_INSTALL_DBG_ISR, + __COMMCTL_REMOVE_DBG_ISR, + + /* + * Disable comm port interrupt. Returns TRUE if interrupt was enabled, + * FALSE otherwise. + */ + __COMMCTL_IRQ_DISABLE, + + /* + * Enable comm port interrupt. + */ + __COMMCTL_IRQ_ENABLE, + + /* + * Returns the number of the interrupt vector used by the debug + * interrupt handler. + */ + __COMMCTL_DBG_ISR_VECTOR, + + /* + * Returns the current timeout value and sets a new timeout. + * Timeout resolution is in milliseconds. + * old_timeout = (*__control)(__COMMCTL_SET_TIMEOUT, + * cyg_int32 new_timeout); + */ + __COMMCTL_SET_TIMEOUT, + + /* + * Forces driver to send all characters which may be buffered in + * the driver. This only flushes the driver buffers, not necessarily + * any hardware FIFO, etc. + */ + __COMMCTL_FLUSH_OUTPUT, + + /* + * Forces driver to enable or disable flushes when a newline is + * seen in the output stream. Flushing at line boundaries occurs + * in the driver, not necessarily any hardware FIFO, etc. Line + * buffering is optional and may only be available in some drivers. + */ + __COMMCTL_ENABLE_LINE_FLUSH, + __COMMCTL_DISABLE_LINE_FLUSH, + +} __comm_control_cmd_t; + + +#define CYGNUM_COMM_IF_CH_DATA 0 +#define CYGNUM_COMM_IF_WRITE 1 +#define CYGNUM_COMM_IF_READ 2 +#define CYGNUM_COMM_IF_PUTC 3 +#define CYGNUM_COMM_IF_GETC 4 +#define CYGNUM_COMM_IF_CONTROL 5 +#define CYGNUM_COMM_IF_DBG_ISR 6 +#define CYGNUM_COMM_IF_GETC_TIMEOUT 7 + +#define CYGNUM_COMM_IF_TABLE_SIZE 8 + +typedef volatile CYG_ADDRWORD hal_virtual_comm_table_t[CYGNUM_COMM_IF_TABLE_SIZE]; + +// The below is a (messy) attempt at adding some type safety to the +// above array. At the same time, the accessors allow the +// implementation to be easily changed in the future (both tag->data +// table and structure implementations have been suggested). + +typedef void* __comm_if_ch_data_t; +typedef void (*__comm_if_write_t)(void* __ch_data, const cyg_uint8* __buf, + cyg_uint32 __len); +typedef int (*__comm_if_read_t)(void* __ch_data, cyg_uint8* __buf, + cyg_uint32 __len); +typedef void (*__comm_if_putc_t)(void* __ch_data, cyg_uint8 __ch); +typedef cyg_uint8 (*__comm_if_getc_t)(void* __ch_data); +typedef int (*__comm_if_control_t)(void *__ch_data, + __comm_control_cmd_t __func, ...); +typedef int (*__comm_if_dbg_isr_t)(void *__ch_data, + int* __ctrlc, CYG_ADDRWORD __vec, + CYG_ADDRWORD __data); +typedef cyg_bool (*__comm_if_getc_timeout_t)(void* __ch_data, cyg_uint8* __ch); + +#define __call_COMM0(_n_,_rt_,_t_) \ +static __inline__ _rt_ \ +__call_COMM_##_n_(hal_virtual_comm_table_t t) \ +{ \ + _rt_ res; \ + void *dp = (__comm_if_ch_data_t)t[CYGNUM_COMM_IF_CH_DATA]; \ + _ENTER_MONITOR(); \ + res = ((_t_)(t[CYGNUM_COMM_##_n_]))(dp); \ + _EXIT_MONITOR(); \ + return res; \ +} + +#define __call_voidCOMM(_n_,_rt_,_t_) \ +static __inline__ _rt_ \ +__call_COMM_##_n_(hal_virtual_comm_table_t t) \ +{ \ + void *dp = (__comm_if_ch_data_t)t[CYGNUM_COMM_IF_CH_DATA]; \ + _ENTER_MONITOR(); \ + ((_t_)(t[CYGNUM_COMM_##_n_]))(dp); \ + _EXIT_MONITOR(); \ +} + +#define __call_COMM1(_n_,_rt_,_t_,_t1_) \ +static __inline__ _rt_ \ +__call_COMM_##_n_(hal_virtual_comm_table_t t, _t1_ _p1_) \ +{ \ + _rt_ res; \ + void *dp = (__comm_if_ch_data_t)t[CYGNUM_COMM_IF_CH_DATA]; \ + _ENTER_MONITOR(); \ + res = ((_t_)(t[CYGNUM_COMM_##_n_]))(dp, _p1_); \ + _EXIT_MONITOR(); \ + return res; \ +} + +#define __call_voidCOMM1(_n_,_rt_,_t_,_t1_) \ +static __inline__ _rt_ \ +__call_COMM_##_n_(hal_virtual_comm_table_t t, _t1_ _p1_) \ +{ \ + void *dp = (__comm_if_ch_data_t)t[CYGNUM_COMM_IF_CH_DATA]; \ + _ENTER_MONITOR(); \ + ((_t_)(t[CYGNUM_COMM_##_n_]))(dp, _p1_); \ + _EXIT_MONITOR(); \ +} + +#define __call_COMM2(_n_,_rt_,_t_,_t1_,_t2_) \ +static __inline__ _rt_ \ +__call_COMM_##_n_(hal_virtual_comm_table_t t, _t1_ _p1_, _t2_ _p2_) \ +{ \ + _rt_ res; \ + void *dp = (__comm_if_ch_data_t)t[CYGNUM_COMM_IF_CH_DATA]; \ + _ENTER_MONITOR(); \ + res = ((_t_)(t[CYGNUM_COMM_##_n_]))(dp, _p1_, _p2_); \ + _EXIT_MONITOR(); \ + return res; \ +} + +#define __call_voidCOMM2(_n_,_rt_,_t_,_t1_,_t2_) \ +static __inline__ _rt_ \ +__call_COMM_##_n_(hal_virtual_comm_table_t t, _t1_ _p1_, _t2_ _p2_) \ +{ \ + void *dp = (__comm_if_ch_data_t)t[CYGNUM_COMM_IF_CH_DATA]; \ + _ENTER_MONITOR(); \ + ((_t_)(t[CYGNUM_COMM_##_n_]))(dp, _p1_, _p2_); \ + _EXIT_MONITOR(); \ +} + +#define __call_COMM3(_n_,_rt_,_t_,_t1_,_t2_,_t3_) \ +static __inline__ _rt_ \ +__call_COMM_##_n_(hal_virtual_comm_table_t t, _t1_ _p1_, _t2_ _p2_, _t3_ _p3_) \ +{ \ + _rt_ res; \ + void *dp = (__comm_if_ch_data_t)t[CYGNUM_COMM_IF_CH_DATA]; \ + _ENTER_MONITOR(); \ + res = ((_t_)(t[CYGNUM_COMM_##_n_]))(dp, _p1_, _p2_, _p3_); \ + _EXIT_MONITOR(); \ + return res; \ +} + +#define __call_voidCOMM3(_n_,_rt_,_t_,_t1_,_t2_,_t3_) \ +static __inline__ _rt_ \ +__call_COMM_##_n_(hal_virtual_comm_table_t t, _t1_ _p1_, _t2_ _p2_, _t3_ _p3_) \ +{ \ + void *dp = (__comm_if_ch_data_t)t[CYGNUM_COMM_IF_CH_DATA]; \ + _ENTER_MONITOR(); \ + ((_t_)(t[CYGNUM_COMM_##_n_]))(dp, _p1_, _p2_, _p3_); \ + _EXIT_MONITOR(); \ +} + +#ifndef CYGACC_COMM_IF_DEFINED + +#define CYGACC_COMM_IF_CH_DATA(_t_) \ + ((__comm_if_ch_data_t)((_t_)[CYGNUM_COMM_IF_CH_DATA])) +#define CYGACC_COMM_IF_CH_DATA_SET(_t_, _x_) \ + (_t_)[CYGNUM_COMM_IF_CH_DATA]=(CYG_ADDRWORD)(_x_) + +__call_voidCOMM2(IF_WRITE, void, __comm_if_write_t, const cyg_uint8 *, cyg_uint32) +#define CYGACC_COMM_IF_WRITE(_t_, _b_, _l_) \ + __call_COMM_IF_WRITE(_t_, _b_, _l_) +#define CYGACC_COMM_IF_WRITE_SET(_t_, _x_) \ + (_t_)[CYGNUM_COMM_IF_WRITE]=(CYG_ADDRWORD)(_x_) + +__call_voidCOMM2(IF_READ, void, __comm_if_read_t, cyg_uint8 *, cyg_uint32) +#define CYGACC_COMM_IF_READ(_t_, _b_, _l_) \ + __call_COMM_IF_READ(_t_, _b_, _l_) +#define CYGACC_COMM_IF_READ_SET(_t_, _x_) \ + (_t_)[CYGNUM_COMM_IF_READ]=(CYG_ADDRWORD)(_x_) + +__call_voidCOMM1(IF_PUTC, void, __comm_if_putc_t, cyg_uint8) +#define CYGACC_COMM_IF_PUTC(_t_, _c_) \ + __call_COMM_IF_PUTC(_t_,_c_) +#define CYGACC_COMM_IF_PUTC_SET(_t_, _x_) \ + (_t_)[CYGNUM_COMM_IF_PUTC]=(CYG_ADDRWORD)(_x_) + +__call_COMM0(IF_GETC, cyg_uint8, __comm_if_getc_t) +#define CYGACC_COMM_IF_GETC(_t_) \ + __call_COMM_IF_GETC(_t_) +#define CYGACC_COMM_IF_GETC_SET(_t_, _x_) \ + (_t_)[CYGNUM_COMM_IF_GETC]=(CYG_ADDRWORD)(_x_) + +// This macro has not been changed to use inline functions like the +// others, simply because it uses variable arguments, and the change +// would break binary compatibility. +#define CYGACC_COMM_IF_CONTROL(_t_, args...) \ + ({ int res; \ + _ENTER_MONITOR(); \ + res = ((__comm_if_control_t)((_t_)[CYGNUM_COMM_IF_CONTROL]))(CYGACC_COMM_IF_CH_DATA(_t_), args); \ + _EXIT_MONITOR(); \ + res;}) +#define CYGACC_COMM_IF_CONTROL_SET(_t_, _x_) \ + (_t_)[CYGNUM_COMM_IF_CONTROL]=(CYG_ADDRWORD)(_x_) + +__call_COMM3(IF_DBG_ISR, int, __comm_if_dbg_isr_t, int *, CYG_ADDRWORD, CYG_ADDRWORD) +#define CYGACC_COMM_IF_DBG_ISR(_t_, _c_, _v_, _d_) \ + __call_COMM_IF_DBG_ISR(_t_, _c_, _v_, _d_) +#define CYGACC_COMM_IF_DBG_ISR_SET(_t_, _x_) \ + (_t_)[CYGNUM_COMM_IF_DBG_ISR]=(CYG_ADDRWORD)(_x_) + +__call_COMM1(IF_GETC_TIMEOUT, cyg_bool, __comm_if_getc_timeout_t, cyg_uint8 *) +#define CYGACC_COMM_IF_GETC_TIMEOUT(_t_, _c_) \ + __call_COMM_IF_GETC_TIMEOUT(_t_, _c_) +#define CYGACC_COMM_IF_GETC_TIMEOUT_SET(_t_, _x_) \ + (_t_)[CYGNUM_COMM_IF_GETC_TIMEOUT]=(CYG_ADDRWORD)(_x_) + +#endif // CYGACC_COMM_IF_DEFINED + +//-------------------------------------------------------------------------- +// Main calling interface table. Will be assigned a location by the +// linker script. Both ROM and RAM startup applications will know about +// the location. +#define CYGNUM_CALL_IF_VERSION 0 +#define CYGNUM_CALL_IF_available_1 1 +#define CYGNUM_CALL_IF_available_2 2 +#define CYGNUM_CALL_IF_available_3 3 +#define CYGNUM_CALL_IF_KILL_VECTOR 4 +#define CYGNUM_CALL_IF_CONSOLE_PROCS 5 +#define CYGNUM_CALL_IF_DEBUG_PROCS 6 +#define CYGNUM_CALL_IF_available_7 7 +#define CYGNUM_CALL_IF_available_8 8 +#define CYGNUM_CALL_IF_available_9 9 +#define CYGNUM_CALL_IF_available_10 10 +#define CYGNUM_CALL_IF_available_11 11 +#define CYGNUM_CALL_IF_SET_DEBUG_COMM 12 +#define CYGNUM_CALL_IF_SET_CONSOLE_COMM 13 +#define CYGNUM_CALL_IF_MONITOR_VERSION 14 +#define CYGNUM_CALL_IF_DBG_SYSCALL 15 +#define CYGNUM_CALL_IF_RESET 16 +#define CYGNUM_CALL_IF_CONSOLE_INTERRUPT_FLAG 17 +#define CYGNUM_CALL_IF_DELAY_US 18 +#define CYGNUM_CALL_IF_DBG_DATA 19 +#define CYGNUM_CALL_IF_FLASH_CFG_OP 20 +#define CYGNUM_CALL_IF_MONITOR_RETURN 21 +#define CYGNUM_CALL_IF_FLASH_FIS_OP 22 +#define CYGNUM_CALL_IF_FLASH_FIS_OP2 23 + +#define CYGNUM_CALL_IF_LAST_ENTRY CYGNUM_CALL_IF_FLASH_FIS_OP2 + +#define CYGNUM_CALL_IF_INSTALL_BPT_FN 35 + +#define CYGNUM_CALL_IF_TABLE_SIZE 64 + +externC volatile CYG_ADDRWORD hal_virtual_vector_table[CYGNUM_CALL_IF_TABLE_SIZE]; + +// Table version contains version information for both the CALL table +// itself (the number of the last active entry in the table), and the +// COMM table (the size of the table). +#define CYGNUM_CALL_IF_TABLE_VERSION_CALL CYGNUM_CALL_IF_LAST_ENTRY +#define CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK (CYGNUM_CALL_IF_TABLE_SIZE+1) +#define CYGNUM_CALL_IF_TABLE_VERSION_CALL_MAX CYGNUM_CALL_IF_TABLE_SIZE +#define CYGNUM_CALL_IF_TABLE_VERSION_COMM CYGNUM_COMM_IF_TABLE_SIZE +#define CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK 0x0000ffff +#define CYGNUM_CALL_IF_TABLE_VERSION_COMM_MASK 0xffff0000 +#define CYGNUM_CALL_IF_TABLE_VERSION_COMM_shift 16 + + +// These are special debug/console procs IDs +// QUERY_CURRENT will cause the ID of the currently selected proc ID to be +// returned. +// EMPTY this is the ID used for an empty procs table (i.e, NULL +// pointer) +// MANGLER selects the procs space reserved for the console mangler +// allowing the application to temporarily disable mangling +// or temporarily switch in different console procs. +#define CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT -1 +#define CYGNUM_CALL_IF_SET_COMM_ID_EMPTY -2 +#define CYGNUM_CALL_IF_SET_COMM_ID_MANGLER -3 + +// The below is a (messy) attempt at adding some type safety to the +// above array. At the same time, the accessors allow the +// implementation to be easily changed in the future (both tag->data +// table and structure implementations have been suggested). + +typedef int __call_if_version_t; +typedef void* __call_if_ictrl_table_t; +typedef void* __call_if_exc_table_t; +typedef bsp_handler_t *__call_if_dbg_vector_t; +typedef bsp_handler_t __call_if_kill_vector_t; +typedef hal_virtual_comm_table_t *__call_if_console_procs_t; +typedef hal_virtual_comm_table_t *__call_if_debug_procs_t; +typedef int (__call_if_set_debug_comm_t)(int __comm_id); +typedef int (__call_if_set_console_comm_t)(int __comm_id); +typedef void* __call_if_dbg_data_t; +typedef int (__call_if_dbg_syscall_t) (enum dbg_syscall_ids id, + union dbg_thread_syscall_parms *p ); +typedef void (__call_if_reset_t)(void); +typedef int __call_if_console_interrupt_flag_t; +typedef void (__call_if_delay_us_t)(cyg_int32 usecs); +typedef void (__call_if_install_bpt_fn_t)(void *__epc); +typedef char *__call_if_monitor_version_t; +typedef void (__call_if_monitor_return_t)(int status); +typedef cyg_bool (__call_if_flash_fis_op_fn_t)(int __oper, char *__name, void *__val); + +// +// This structure is used to pass parameters to/from the fis routines +// +struct fis_table_entry { + unsigned char name[16]; + CYG_ADDRESS flash_base; + CYG_ADDRESS mem_base; + unsigned long size; + CYG_ADDRESS entry_point; + unsigned long data_length; + unsigned long desc_cksum; + unsigned long file_cksum; +}; + +typedef int (__call_if_flash_fis_op2_fn_t)(int __oper, unsigned int index, struct fis_table_entry *__fis_entry); +// +// This structure is used to pass parameters to/from the fconfig routines. +// This allows a single virtual vector interface, with widely varying functionality +// +struct cyg_fconfig { + char *key; // Datum 'key' + int keylen; // Length of key + void *val; // Pointer to data + int type; // Type of datum + int offset; // Offset within data (used by _NEXT) +}; +typedef cyg_bool (__call_if_flash_cfg_op_fn_t)(int __oper, struct cyg_fconfig *__data); + +#ifndef CYGACC_CALL_IF_DEFINED + +#define __data_VV(_n_,_tt_) \ +static __inline__ _tt_ \ +__call_vv_##_n_(void) \ +{ \ + return ((_tt_)hal_virtual_vector_table[_n_]); \ +} + +#define __call_VV0(_n_,_tt_,_rt_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(void) \ +{ \ + _rt_ res; \ + _ENTER_MONITOR(); \ + res = ((_tt_ *)hal_virtual_vector_table[_n_])(); \ + _EXIT_MONITOR(); \ + return res; \ +} + +#define __call_voidVV0(_n_,_tt_,_rt_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(void) \ +{ \ + _ENTER_MONITOR(); \ + ((_tt_ *)hal_virtual_vector_table[_n_])(); \ + _EXIT_MONITOR(); \ +} + +#define __call_VV1(_n_,_tt_,_rt_,_t1_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(_t1_ _p1_) \ +{ \ + _rt_ res; \ + _ENTER_MONITOR(); \ + res = ((_tt_ *)hal_virtual_vector_table[_n_])(_p1_); \ + _EXIT_MONITOR(); \ + return res; \ +} + +#define __call_voidVV1(_n_,_tt_,_rt_,_t1_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(_t1_ _p1_) \ +{ \ + _ENTER_MONITOR(); \ + ((_tt_ *)hal_virtual_vector_table[_n_])(_p1_); \ + _EXIT_MONITOR(); \ +} + +#define __call_VV2(_n_,_tt_,_rt_,_t1_,_t2_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(_t1_ _p1_, _t2_ _p2_) \ +{ \ + _rt_ res; \ + _ENTER_MONITOR(); \ + res = ((_tt_ *)hal_virtual_vector_table[_n_])(_p1_,_p2_); \ + _EXIT_MONITOR(); \ + return res; \ +} + +#define __call_voidVV2(_n_,_tt_,_rt_,_t1_,_t2_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(_t1_ _p1_, _t2_ _p2_) \ +{ \ + _ENTER_MONITOR(); \ + ((_tt_ *)hal_virtual_vector_table[_n_])(_p1_,_p2_); \ + _EXIT_MONITOR(); \ +} + +#define __call_VV3(_n_,_tt_,_rt_,_t1_,_t2_,_t3_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(_t1_ _p1_, _t2_ _p2_, _t3_ _p3_) \ +{ \ + _rt_ res; \ + _ENTER_MONITOR(); \ + res = ((_tt_ *)hal_virtual_vector_table[_n_])(_p1_,_p2_,_p3_); \ + _EXIT_MONITOR(); \ + return res; \ +} + +#define __call_voidVV3(_n_,_tt_,_rt_,_t1_,_t2_,_t3_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(_t1_ _p1_, _t2_ _p2_, _t3_ _p3_) \ +{ \ + _ENTER_MONITOR(); \ + ((_tt_ *)hal_virtual_vector_table[_n_])(_p1_,_p2_,_p3_); \ + _EXIT_MONITOR(); \ +} + +#define __call_VV4(_n_,_tt_,_rt_,_t1_,_t2_,_t3_,_t4_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(_t1_ _p1_, _t2_ _p2_, _t3_ _p3_, _t4_ _p4_) \ +{ \ + _rt_ res; \ + _ENTER_MONITOR(); \ + res = ((_tt_ *)hal_virtual_vector_table[_n_])(_p1_,_p2_,_p3_,_p4_); \ + _EXIT_MONITOR(); \ + return res; \ +} + +#define __call_voidVV4(_n_,_tt_,_rt_,_t1_,_t2_,_t3_,_t4_) \ +static __inline__ _rt_ \ +__call_vv_##_n_(_t1_ _p1_, _t2_ _p2_, _t3_ _p3_, _t4_ _p4_) \ +{ \ + _ENTER_MONITOR(); \ + ((_tt_ *)hal_virtual_vector_table[_n_])(_p1_,_p2_,_p3_,_p4_); \ + _EXIT_MONITOR(); \ +} + + +#define CYGACC_DATA_VV(t,e) __call_vv_##e() +#define CYGACC_CALL_VV0(t,e) __call_vv_##e +#define CYGACC_CALL_VV1(t,e,p1) __call_vv_##e((p1)) +#define CYGACC_CALL_VV2(t,e,p1,p2) __call_vv_##e((p1),(p2)) +#define CYGACC_CALL_VV3(t,e,p1,p2,p3) __call_vv_##e((p1),(p2),(p3)) +#define CYGACC_CALL_VV4(t,e,p1,p2,p3,p4) __call_vv_##e((p1),(p2),(p3),(p4)) + +#define CYGACC_CALL_IF_VERSION() \ + CYGACC_DATA_VV(__call_if_version_t, CYGNUM_CALL_IF_VERSION) +__data_VV(CYGNUM_CALL_IF_VERSION, __call_if_version_t) +#define CYGACC_CALL_IF_VERSION_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_VERSION]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_KILL_VECTOR() \ + CYGACC_DATA_VV(__call_if_kill_vector_t, CYGNUM_CALL_IF_KILL_VECTOR) +__data_VV(CYGNUM_CALL_IF_KILL_VECTOR, __call_if_kill_vector_t) +#define CYGACC_CALL_IF_KILL_VECTOR_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_KILL_VECTOR]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_CONSOLE_PROCS() \ + CYGACC_DATA_VV(__call_if_console_procs_t, CYGNUM_CALL_IF_CONSOLE_PROCS) +__data_VV(CYGNUM_CALL_IF_CONSOLE_PROCS, __call_if_console_procs_t) +#define CYGACC_CALL_IF_CONSOLE_PROCS_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_CONSOLE_PROCS]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_DEBUG_PROCS() \ + CYGACC_DATA_VV(__call_if_debug_procs_t, CYGNUM_CALL_IF_DEBUG_PROCS) +__data_VV(CYGNUM_CALL_IF_DEBUG_PROCS, __call_if_debug_procs_t) +#define CYGACC_CALL_IF_DEBUG_PROCS_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_DEBUG_PROCS]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_SET_DEBUG_COMM(_i_) \ + CYGACC_CALL_VV1(__call_if_set_debug_comm_t*, CYGNUM_CALL_IF_SET_DEBUG_COMM, (_i_)) +__call_VV1(CYGNUM_CALL_IF_SET_DEBUG_COMM, __call_if_set_debug_comm_t, int, int) +#define CYGACC_CALL_IF_SET_DEBUG_COMM_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_SET_DEBUG_COMM]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_SET_CONSOLE_COMM(_i_) \ + CYGACC_CALL_VV1(__call_if_set_console_comm_t*, CYGNUM_CALL_IF_SET_CONSOLE_COMM, (_i_)) +__call_VV1(CYGNUM_CALL_IF_SET_CONSOLE_COMM, __call_if_set_console_comm_t, int, int) +#define CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_SET_CONSOLE_COMM]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_DBG_DATA() \ + CYGACC_DATA_VV(__call_if_dbg_data_t, CYGNUM_CALL_IF_DBG_DATA) +__data_VV(CYGNUM_CALL_IF_DBG_DATA, __call_if_dbg_data_t) +#define CYGACC_CALL_IF_DBG_DATA_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_DBG_DATA]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_DBG_SYSCALL(_id_,_p_) \ + CYGACC_CALL_VV2(__call_if_dbg_syscall_t, CYGNUM_CALL_IF_DBG_SYSCALL, _id_, _p_) +__call_VV2(CYGNUM_CALL_IF_DBG_SYSCALL, __call_if_dbg_syscall_t, int, enum dbg_syscall_ids , union dbg_thread_syscall_parms *) +#define CYGACC_CALL_IF_DBG_SYSCALL_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_DBG_SYSCALL]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_RESET() \ + CYGACC_CALL_VV0(__call_if_reset_t*, CYGNUM_CALL_IF_RESET)() +__call_voidVV0(CYGNUM_CALL_IF_RESET, __call_if_reset_t, void) +#define CYGACC_CALL_IF_RESET_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_RESET]=(CYG_ADDRWORD)(_x_) +#define CYGACC_CALL_IF_RESET_GET() \ + ((__call_if_reset_t*)hal_virtual_vector_table[CYGNUM_CALL_IF_RESET]) + +#define CYGACC_CALL_IF_MONITOR_VERSION() \ + CYGACC_DATA_VV(__call_if_monitor_version_t, CYGNUM_CALL_IF_MONITOR_VERSION) +__data_VV(CYGNUM_CALL_IF_MONITOR_VERSION, __call_if_monitor_version_t) +#define CYGACC_CALL_IF_MONITOR_VERSION_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_MONITOR_VERSION]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG() \ + CYGACC_DATA_VV(__call_if_console_interrupt_flag_t, CYGNUM_CALL_IF_CONSOLE_INTERRUPT_FLAG) +__data_VV(CYGNUM_CALL_IF_CONSOLE_INTERRUPT_FLAG, __call_if_console_interrupt_flag_t) +#define CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_CONSOLE_INTERRUPT_FLAG]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_DELAY_US(_u_) \ + CYGACC_CALL_VV1(__call_if_delay_us_t*, CYGNUM_CALL_IF_DELAY_US, (_u_)) +__call_voidVV1(CYGNUM_CALL_IF_DELAY_US, __call_if_delay_us_t, void, cyg_int32) +#define CYGACC_CALL_IF_DELAY_US_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_DELAY_US]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_INSTALL_BPT_FN(_e_) \ + CYGACC_CALL_VV1(__call_if_install_bpt_fn_t*, CYGNUM_CALL_IF_INSTALL_BPT_FN, (_e_)) +__call_voidVV1(CYGNUM_CALL_IF_INSTALL_BPT_FN, __call_if_install_bpt_fn_t, void, void *) +#define CYGACC_CALL_IF_INSTALL_BPT_FN_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_INSTALL_BPT_FN]=(CYG_ADDRWORD)(_x_) + +// +// Access persistent data store - kept in FLASH or EEPROM by RedBoot +// +#define CYGNUM_CALL_IF_FLASH_CFG_GET (0) // Get a particular fconfig key +#define CYGNUM_CALL_IF_FLASH_CFG_NEXT (1) // Enumerate keys (get the next one) +#define CYGNUM_CALL_IF_FLASH_CFG_SET (2) // Update particular fconfig key +#define CYGACC_CALL_IF_FLASH_CFG_OP2(_o_,_d_) \ + CYGACC_CALL_VV2(__call_if_flash_cfg_op_fn_t*, CYGNUM_CALL_IF_FLASH_CFG_OP, (_o_),(_d_)) +__call_VV2(CYGNUM_CALL_IF_FLASH_CFG_OP, __call_if_flash_cfg_op_fn_t, cyg_bool, int, struct cyg_fconfig *) + +static __inline__ cyg_bool +__call_if_flash_cfg_op(int op, char *key, void *data, int type) +{ + struct cyg_fconfig info; + info.key = key; + info.val = data; + info.type = type; + info.offset = 0; + return CYGACC_CALL_IF_FLASH_CFG_OP2(op, &info); +} +#define CYGACC_CALL_IF_FLASH_CFG_OP(_o_,_k_,_d_,_t_) \ + __call_if_flash_cfg_op(_o_,_k_,_d_,_t_) +#define CYGACC_CALL_IF_FLASH_CFG_OP_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_FLASH_CFG_OP]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_MONITOR_RETURN(_u_) \ + CYGACC_CALL_VV1(__call_if_monitor_return_t*, CYGNUM_CALL_IF_MONITOR_RETURN, (_u_)) +__call_voidVV1(CYGNUM_CALL_IF_MONITOR_RETURN, __call_if_monitor_return_t, void, int) +#define CYGACC_CALL_IF_MONITOR_RETURN_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_MONITOR_RETURN]=(CYG_ADDRWORD)(_x_) + +#define CYGACC_CALL_IF_FLASH_FIS_OP(_o_,_k_,_d_) \ + CYGACC_CALL_VV3(__call_if_flash_fis_op_fn_t*, CYGNUM_CALL_IF_FLASH_FIS_OP, (_o_),(_k_),(_d_)) +__call_VV3(CYGNUM_CALL_IF_FLASH_FIS_OP, __call_if_flash_fis_op_fn_t, cyg_bool, int, char *, void *) +#define CYGACC_CALL_IF_FLASH_FIS_OP_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_FLASH_FIS_OP]=(CYG_ADDRWORD)(_x_) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE (0) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE (1) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_MEM_BASE (2) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_POINT (3) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_DATA_LENGTH (4) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_DESC_CKSUM (5) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_FILE_CKSUM (6) + +#define CYGACC_CALL_IF_FLASH_FIS_OP2(_o_,_k_,_d_) \ + CYGACC_CALL_VV3(__call_if_flash_fis_op2_fn_t*, CYGNUM_CALL_IF_FLASH_FIS_OP2, (_o_),(_k_),(_d_)) +__call_VV3(CYGNUM_CALL_IF_FLASH_FIS_OP2, __call_if_flash_fis_op2_fn_t, int, int, unsigned int, struct fis_table_entry *) +#define CYGACC_CALL_IF_FLASH_FIS_OP2_SET(_x_) \ + hal_virtual_vector_table[CYGNUM_CALL_IF_FLASH_FIS_OP2]=(CYG_ADDRWORD)(_x_) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_VERSION (0) +#define CYGNUM_CALL_IF_FLASH_FIS_INIT (1) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_COUNT (2) +#define CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY (3) +#define CYGNUM_CALL_IF_FLASH_FIS_START_UPDATE (4) +#define CYGNUM_CALL_IF_FLASH_FIS_FINISH_UPDATE (5) +#define CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY (6) + + + +// These need to be kept uptodate with the (unadorned) masters +// in RedBoot's flash_config.h: +#define CYGNUM_FLASH_CFG_TYPE_CONFIG_EMPTY 0 +#define CYGNUM_FLASH_CFG_TYPE_CONFIG_BOOL 1 +#define CYGNUM_FLASH_CFG_TYPE_CONFIG_INT 2 +#define CYGNUM_FLASH_CFG_TYPE_CONFIG_STRING 3 +#define CYGNUM_FLASH_CFG_TYPE_CONFIG_SCRIPT 4 +#define CYGNUM_FLASH_CFG_TYPE_CONFIG_IP 5 +#define CYGNUM_FLASH_CFG_TYPE_CONFIG_ESA 6 + +#endif // CYGACC_CALL_IF_DEFINED + +//-------------------------------------------------------------------------- +// Diag wrappers. +externC void hal_if_diag_init(void); +externC void hal_if_diag_write_char(char c); +externC void hal_if_diag_read_char(char *c); + +//-------------------------------------------------------------------------- +// Ctrl-c support. +externC cyg_uint32 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data); +externC cyg_bool hal_ctrlc_check(CYG_ADDRWORD vector, CYG_ADDRWORD data); + +#define HAL_CTRLC_ISR hal_ctrlc_isr +#define HAL_CTRLC_CHECK hal_ctrlc_check + +#else + +#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) +// Then other code might invoke this macro +#define HAL_CTRLC_CHECK(a1,a2) (0) // Nothing, no CTRLC here +#endif + +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + +//-------------------------------------------------------------------------- +// Functions provided by the HAL interface. +externC void hal_if_init(void); +#if 0 != CYGINT_HAL_PLF_IF_INIT +externC void plf_if_init(void); +#endif + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_HAL_IF_H +// End of hal_if.h diff --git a/ecos/packages/hal/common/current/include/hal_misc.h b/ecos/packages/hal/common/current/include/hal_misc.h new file mode 100644 index 0000000..22f0c16 --- /dev/null +++ b/ecos/packages/hal/common/current/include/hal_misc.h @@ -0,0 +1,122 @@ +#ifndef CYGONCE_HAL_HAL_MISC_H +#define CYGONCE_HAL_HAL_MISC_H + +//============================================================================= +// +// hal_misc.h +// +// HAL header for miscellaneous helper routines +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov +// Date: 2000-06-08 +// Purpose: Miscellaneous routines shared between HALs +// Usage: #include <cyg/hal/hal_misc.h> +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#ifndef __ASSEMBLER__ +#include <cyg/infra/cyg_type.h> // types & externC + +//============================================================================= +externC cyg_bool cyg_hal_is_break(char *buf, int size); +externC void cyg_hal_user_break( CYG_ADDRWORD *regs ); +#endif + +//============================================================================= + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#define SZ_1K 0x00000400 +#define SZ_2K 0x00000800 +#define SZ_4K 0x00001000 +#define SZ_8K 0x00002000 +#define SZ_16K 0x00004000 +#define SZ_32K 0x00008000 +#define SZ_64K 0x00010000 +#define SZ_128K 0x00020000 +#define SZ_256K 0x00040000 +#define SZ_512K 0x00080000 +#define SZ_1M 0x00100000 +#define SZ_2M 0x00200000 +#define SZ_4M 0x00400000 +#define SZ_8M 0x00800000 +#define SZ_16M 0x01000000 +#define SZ_32M 0x02000000 +#define SZ_64M 0x04000000 +#define SZ_128M 0x08000000 +#define SZ_256M 0x10000000 +#define SZ_512M 0x20000000 +#define SZ_1G 0x40000000 + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_HAL_MISC_H +// End of hal_misc.h diff --git a/ecos/packages/hal/common/current/include/hal_spd.h b/ecos/packages/hal/common/current/include/hal_spd.h new file mode 100644 index 0000000..677cff7 --- /dev/null +++ b/ecos/packages/hal/common/current/include/hal_spd.h @@ -0,0 +1,77 @@ +#ifndef CYGONCE_HAL_HAL_SPD_H +#define CYGONCE_HAL_HAL_SPD_H + +//============================================================================= +// +// hal_spd.h +// +// HAL header for SDRAM Serial Presence Detect support. +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): msalter +// Contributors:msalter +// Date: 2002-01-17 +// Purpose: Generic HAL SPD header. +// Usage: #include <cyg/hal/hal_spd.h> +// Description: This header provides byte numbers and bit definitions for +// serial EEPROM containing SDRAM module information. +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +// Commonly used bytes +#define SPD_BANKCNT 5 // number of module banks +#define SPD_CONFIG 11 // DIMM configuration type (Parity or not, EEC) +#define SPD_REFRESH 12 // Referesh rate +#define SPD_SDRAM_WIDTH 13 // DRAM width +#define SPD_MOD_ATTRIB 21 // DRAM module attribute +#define SPD_BANKSZ 31 // module bank density +#define SPD_CHECKSUM 63 // checksum for bytes 0-62 + +// SPD_MOD_ATTRIB bits +#define SPD_ATTRIB_BUF_CTL 0x01 // Buffered Addr/Control inputs +#define SPD_ATTRIB_REG_CTL 0x02 // Registered Addr/Control inputs +#define SPD_ATTRIB_PLL 0x04 // On-card PLL +#define SPD_ATTRIB_BUF_DQ 0x08 // Buffered DQMB inputs +#define SPD_ATTRIB_REG_DQ 0x10 // Registered DQMB inputs +#define SPD_ATTRIB_DIFF 0x20 // Differential clock input +#define SPD_ATTRIB_RRA 0x40 // Redundant Row Address + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_HAL_SPD_H +// End of hal_spd.h diff --git a/ecos/packages/hal/common/current/include/hal_stub.h b/ecos/packages/hal/common/current/include/hal_stub.h new file mode 100644 index 0000000..009ebbb --- /dev/null +++ b/ecos/packages/hal/common/current/include/hal_stub.h @@ -0,0 +1,406 @@ +#ifndef CYGONCE_HAL_HAL_STUB_H +#define CYGONCE_HAL_HAL_STUB_H + +//============================================================================= +// +// hal_stub.h +// +// HAL header for GDB stub support. +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2008 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov +// Date: 1999-02-12 +// Purpose: Generic HAL stub header. +// Usage: #include <cyg/hal/hal_stub.h> +// Description: This header is included by generic-stub.c to provide an +// interface to the eCos-specific stub implementation. It is +// not to be included by user code, and is only placed in a +// publically accessible directory so that platform stub packages +// are able to include it if required. +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal.h> + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +#define USE_GDBSTUB_PROTOTYPES 0 // avoid stub-tservice.h atm +#ifndef __ECOS__ +#define __ECOS__ // use to mark eCos hacks +#endif + +#include <cyg/hal/basetype.h> // HAL_LABEL_NAME +#include <cyg/hal/hal_arch.h> // HAL header +#include <cyg/infra/cyg_type.h> // cyg_uint32 and CYG_BYTEORDER + +#ifndef __CYGMON_TYPES +#define __CYGMON_TYPES +typedef cyg_uint32 uint32; +typedef cyg_int32 int32; +#endif // __CYGMON_TYPES + +#ifdef CYGBLD_HAL_PLATFORM_STUB_H +#include CYGBLD_HAL_PLATFORM_STUB_H +#else +#include <cyg/hal/plf_stub.h> +#endif +#include <cyg/hal/generic-stub.h> + +// Some architectures use registers of different sizes, so NUMREGS +// alone is not sufficient to size the register save area. For those +// architectures, HAL_STUB_REGISTERS_SIZE is defined as the number +// of target_register_t sized elements in the register save area. +#ifndef HAL_STUB_REGISTERS_SIZE +#define HAL_STUB_REGISTERS_SIZE NUMREGS +#endif + + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} // to make below format correctly. +#endif + +//----------------------------------------------------------------------------- +// Definitions for generic-stub.c + +#define __set_mem_fault_trap(x) ({__mem_fault = 0; x(); __mem_fault;}) + +#if (CYG_BYTEORDER==CYG_LSBFIRST) +# if !defined(__LITTLE_ENDIAN__) +# define __LITTLE_ENDIAN__ +# endif +# if !defined(_LITTLE_ENDIAN) +# define _LITTLE_ENDIAN +# endif +#endif + +//----------------------------------------------------------------------------- +// Dummy definitions for harvard memory support for princeton memory systems. +#ifndef TARGET_HAS_HARVARD_MEMORY +typedef target_register_t target_addr_t; +#define TARGET_ADDR_IS_PROGMEM(x) 0 +#define TARGET_ADDR_TO_PTR(x) ((char *) (x)) +#endif + +//---------------------------------------------------------------------------- +// Signal definitions to avoid 'signal.h'/ +#define SIGHUP 1 /* hangup */ +#define SIGINT 2 /* interrupt */ +#define SIGQUIT 3 /* quit */ +#define SIGILL 4 /* illegal instruction (not reset when caught) */ +#define SIGTRAP 5 /* trace trap (not reset when caught) */ +#define SIGIOT 6 /* IOT instruction */ +#define SIGABRT 6 /* used by abort, replace SIGIOT in the future */ +#define SIGEMT 7 /* EMT instruction */ +#define SIGFPE 8 /* floating point exception */ +#define SIGKILL 9 /* kill (cannot be caught or ignored) */ +#define SIGBUS 10 /* bus error */ +#define SIGSEGV 11 /* segmentation violation */ +#define SIGSYS 12 /* bad argument to system call */ +#define SIGPIPE 13 /* write on a pipe with no one to read it */ +#define SIGALRM 14 /* alarm clock */ +#define SIGTERM 15 /* software termination signal from kill */ + +//---------------------------------------------------------------------------- +// Thread support. This setting is used in thread-pkts.h +#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT +#define DEBUG_THREADS 1 +#else +#define DEBUG_THREADS 0 +#endif + +// The function stub_copy_registers() is statically defined in +// thread-packets.c, but in eCos this external stub is defined as it +// is used in dbg_gdb.cxx. +externC void __stub_copy_registers(target_register_t *dest, + target_register_t *src); + +//---------------------------------------------------------------------------- +// Hardware Watch/Breakpoint support. These are the possible return values +// of HAL_STUB_IS_STOPPED_BY_HARDWARE(). +#define HAL_STUB_HW_STOP_NONE 0 // target did not stop for hw watch/break +#define HAL_STUB_HW_STOP_BREAK 1 // target stopped for hw breakpoint +#define HAL_STUB_HW_STOP_WATCH 2 // target stopped for write-only watchpoint +#define HAL_STUB_HW_STOP_RWATCH 3 // target stopped for read-only watchpoint +#define HAL_STUB_HW_STOP_AWATCH 4 // target stopped for access watchpoint + +//---------------------------------------------------------------------------- +// Memory accessor functions. +#define TARGET_HAS_OWN_MEM_FUNCS + +//---------------------------------------------------------------------------- +// Memory access checks. + +#ifndef CYG_HAL_STUB_PERMIT_DATA_READ +#define CYG_HAL_STUB_PERMIT_DATA_READ(_addr_, __count_) (1) +#endif + +#ifndef CYG_HAL_STUB_PERMIT_DATA_WRITE +#define CYG_HAL_STUB_PERMIT_DATA_WRITE(_addr_, __count_) (1) +#endif + +#ifdef TARGET_HAS_HARVARD_MEMORY + +#ifndef CYG_HAL_STUB_PERMIT_CODE_READ +#define CYG_HAL_STUB_PERMIT_CODE_READ(_addr_, __count_) (1) +#endif + +#ifndef CYG_HAL_STUB_PERMIT_CODE_WRITE +#define CYG_HAL_STUB_PERMIT_CODE_WRITE(_addr_, __count_) (1) +#endif + +#endif + +//---------------------------------------------------------------------------- +// Target extras?! +extern int __process_target_query(char * pkt, char * out, int maxOut); +extern int __process_target_set(char * pkt, char * out, int maxout); +extern int __process_target_packet(char * pkt, char * out, int maxout); + +//--------------------------------------------------------------------------- +// Declarations to avoid compiler warnings. + +// Set the baud rate for the current serial port. +extern void __set_baud_rate (int baud); + +// Write C to the current serial port. +extern void putDebugChar (int c); + +// Read one character from the current serial port. +extern int getDebugChar (void); + +// Push CH back onto the debug stream. +extern void ungetDebugChar (int ch); + +// Reset the board. +extern void __reset (void); + +// Multi-bp support. +#ifndef __set_breakpoint +extern int __set_breakpoint (target_register_t addr, target_register_t len); +#endif +#ifndef __remove_breakpoint +extern int __remove_breakpoint (target_register_t addr, target_register_t len); +#endif +#ifndef __set_hw_breakpoint +extern int __set_hw_breakpoint (target_register_t addr, target_register_t len); +#endif +#ifndef __remove_hw_breakpoint +extern int __remove_hw_breakpoint (target_register_t addr, target_register_t len); +#endif +#ifndef __set_hw_watchpoint +extern int __set_hw_watchpoint (target_register_t addr, target_register_t len, int ztype); +#endif +#ifndef __remove_hw_watchpoint +extern int __remove_hw_watchpoint (target_register_t addr, target_register_t len, int ztype); +#endif + +/* Install the standard set of trap handlers for the stub. */ +extern void __install_traps (void); + +/* Address in text section of a breakpoint instruction. */ + +#ifndef BREAKINST_DEFINED +#define BREAKINST_DEFINED +extern void _breakinst (void); +#endif + +/* The opcode for a breakpoint instruction. */ + +extern unsigned long __break_opcode (void); + +/* Function to flush output buffers */ +extern void hal_flush_output(void); + +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT +// This one may assume a valid saved interrupt context on some platforms +extern void cyg_hal_gdb_interrupt (target_register_t pc); +// This one does not; use from CRITICAL_IO_REGION macros below. +extern void cyg_hal_gdb_place_break (target_register_t pc); +// Remove a break from either above - or not if cyg_hal_gdb_running_step +extern int cyg_hal_gdb_remove_break (target_register_t pc); +// Bool: is such a breakpoint set? +extern int cyg_hal_gdb_break_is_set (void); + +/* This is used so that the generic stub can tell + * cyg_hal_gdb_remove_break() not to bother when we are avoiding stepping + * through a critical region ie. hal_diag_write_char() usually - that + * shares the GDB IO device. + */ +extern volatile int cyg_hal_gdb_running_step; + +// Use these in hal_diag.c when about to write a whole $O packet to GDB. +// NB they require __builtin_return_address() to work: if your platform +// does not support this, use HAL_DISABLE_INTERRUPTS &c instead. +// These are used to ensure the user's GDB cannot step through the critical +// region, causing everything to go horribly wrong - particularly likely +// with watching variables. Instead it will magically skip over the region. + +#if 1 // Can use the address of a label: this is more portable + +// This macro may already have been defined by the architecture HAL +#ifndef CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION +#define CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION( _old_ ) \ +do { \ + HAL_DISABLE_INTERRUPTS(_old_); \ + cyg_hal_gdb_place_break( (target_register_t)&&cyg_hal_gdb_break_place ); \ +} while ( 0 ) +#endif + +// This macro may already have been defined by the architecture HAL +// Notice the trick to *use* the label - sometimes the tools want to +// move the label if unused, which is bad. +#ifndef CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION +#define CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION( _old_ ) \ +do { \ + cyg_hal_gdb_remove_break( (target_register_t)&&cyg_hal_gdb_break_place ); \ + HAL_RESTORE_INTERRUPTS(_old_); \ + /* The following is solely to provide the label without the compiler \ + * optimising it away. By referencing an external function, it can't \ + * remove or reorder it. And because we have just called \ + * cyg_hal_gdb_remove_break(), we know cyg_hal_gdb_break_is_set() will \ + * return 0. \ + */ \ +cyg_hal_gdb_break_place:; \ + if ( cyg_hal_gdb_break_is_set() ) /* ...or the compiler might move it! */ \ + goto cyg_hal_gdb_break_place; \ +} while ( 0 ) +#endif + +#else // use __builtin_return_address instead. + +#define CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION( _old_ ) \ +do { \ + HAL_DISABLE_INTERRUPTS(_old_); \ + cyg_hal_gdb_place_break((target_register_t)__builtin_return_address(0)); \ +} while ( 0 ) + +#define CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION( _old_ ) \ +do { \ + cyg_hal_gdb_remove_break((target_register_t)__builtin_return_address(0)); \ + HAL_RESTORE_INTERRUPTS(_old_); \ +} while ( 0 ) + +#endif + +#else // NO debug_gdb_break_support + +// so define these just to do interrupts: +#define CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION( _old_ ) \ +do { \ + HAL_DISABLE_INTERRUPTS(_old_); \ +} while (0); + +#define CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION( _old_ ) \ +do { \ + HAL_RESTORE_INTERRUPTS(_old_); \ +} while (0); + +#endif + +//---------------------------------------------------------------------------- +// eCos extensions to the stub + +extern void hal_output_gdb_string(target_register_t str, int string_len); + +extern target_register_t registers[]; // The current saved registers. +extern target_register_t * _registers ; +extern HAL_SavedRegisters *_hal_registers; + +extern int cyg_hal_gdb_break; + +#ifdef CYGPKG_ISOINFRA +# include <pkgconf/isoinfra.h> +#endif +#ifdef CYGINT_ISO_STRING_STRFUNCS +# include <string.h> +#else +//----------------------------------------------------------------------------- +// String helpers. These really should come from ISOINFRA +static inline char *strcpy( char *s, const char *t) +{ + char *r = s; + + while( *t ) *s++ = *t++; + + // Terminate the copied string. + *s = 0; + + return r; +} + +static inline size_t strlen( const char *s ) +{ + int r = 0; + while( *s++ ) r++; + return r; +} +#endif + +//----------------------------------------------------------------------------- +// Repeat the cache definitions here to avoid too much hackery in +// generic-stub.h +/* Flush the instruction cache. */ +extern void flush_i_cache (void); + +/* Flush the data cache. */ +extern void __flush_d_cache (void); + +typedef enum { + CACHE_NOOP, CACHE_ENABLE, CACHE_DISABLE, CACHE_FLUSH +} cache_control_t; + +/* Perform the specified operation on the instruction cache. + Returns 1 if the cache is enabled, 0 otherwise. */ +extern int __instruction_cache (cache_control_t request); +/* Perform the specified operation on the data cache. + Returns 1 if the cache is enabled, 0 otherwise. */ +extern int __data_cache (cache_control_t request); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_HAL_STUB_H +// End of hal_stub.h diff --git a/ecos/packages/hal/common/current/include/hal_tables.h b/ecos/packages/hal/common/current/include/hal_tables.h new file mode 100644 index 0000000..e385be8 --- /dev/null +++ b/ecos/packages/hal/common/current/include/hal_tables.h @@ -0,0 +1,116 @@ +#ifndef CYGONCE_HAL_TABLES_H +#define CYGONCE_HAL_TABLES_H + +/*========================================================================== +// +// hal_tables.h +// +// Data table management +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Date: 2000-09-04 +// Purpose: Provide HAL tables +// Description: This file defines a mechanism to include "tables" of objects +// that are always included in the image no matter what, and are +// constrained between labels. +// +// Usage: #include <cyg/hal/hal_tables.h> +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <pkgconf/hal.h> +#include <cyg/infra/cyg_type.h> + +#include <cyg/hal/hal_arch.h> + +/*------------------------------------------------------------------------*/ + +#define __string(_x) #_x +#define __xstring(_x) __string(_x) + +#ifndef CYG_HAL_TABLE_BEGIN +#define CYG_HAL_TABLE_BEGIN( _label, _name ) \ +__asm__(".section \".ecos.table." __xstring(_name) ".begin\",\"aw\"\n" \ + ".globl " __xstring(CYG_LABEL_DEFN(_label)) "\n" \ + ".type " __xstring(CYG_LABEL_DEFN(_label)) ",object\n" \ + ".p2align " __xstring(CYGARC_P2ALIGNMENT) "\n" \ +__xstring(CYG_LABEL_DEFN(_label)) ":\n" \ + ".previous\n" \ + ) +#endif + +#ifndef CYG_HAL_TABLE_END +#define CYG_HAL_TABLE_END( _label, _name ) \ +__asm__(".section \".ecos.table." __xstring(_name) ".finish\",\"aw\"\n" \ + ".globl " __xstring(CYG_LABEL_DEFN(_label)) "\n" \ + ".type " __xstring(CYG_LABEL_DEFN(_label)) ",object\n" \ + ".p2align " __xstring(CYGARC_P2ALIGNMENT) "\n" \ +__xstring(CYG_LABEL_DEFN(_label)) ":\n" \ + ".previous\n" \ + ) +#endif + +// This macro must be applied to any types whose objects are to be placed in +// tables +#ifndef CYG_HAL_TABLE_TYPE +#define CYG_HAL_TABLE_TYPE CYGBLD_ATTRIB_ALIGN( CYGARC_ALIGNMENT ) +#endif + +#ifndef CYG_HAL_TABLE_EXTRA +#define CYG_HAL_TABLE_EXTRA( _name ) \ + CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".extra") +#endif + +#ifndef CYG_HAL_TABLE_ENTRY +#define CYG_HAL_TABLE_ENTRY( _name ) \ + CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".data") \ + CYGBLD_ATTRIB_USED +#endif + +#ifndef CYG_HAL_TABLE_QUALIFIED_ENTRY +#define CYG_HAL_TABLE_QUALIFIED_ENTRY( _name, _qual ) \ + CYGBLD_ATTRIB_SECTION(".ecos.table." __xstring(_name) ".data." \ + __xstring(_qual)) \ + CYGBLD_ATTRIB_USED +#endif + +/*------------------------------------------------------------------------*/ +/* EOF hal_tables.h */ +#endif // CYGONCE_HAL_TABLES_H diff --git a/ecos/packages/hal/common/current/src/board.h b/ecos/packages/hal/common/current/src/board.h new file mode 100644 index 0000000..15e7c6f --- /dev/null +++ b/ecos/packages/hal/common/current/src/board.h @@ -0,0 +1,69 @@ +#ifndef CYGONCE_HAL_BOARD_H +#define CYGONCE_HAL_BOARD_H + +//============================================================================= +// +// board.h +// +// libstub board.h file for eCos HAL +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov +// Date: 1999-02-12 +// Purpose: libstub board.h file for eCos HAL +// Description: This file simplifies libstub integration. The board.h file +// for eCos simply includes the hal_stub.h file which defines +// the necessary architecture and platform information for +// any of the possible eCos target configurations. +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +// Define __ECOS__; allows all eCos specific additions to be easily identified. +#define __ECOS__ + +#include <cyg/hal/hal_stub.h> + +#ifdef CYGPKG_REDBOOT +#include <pkgconf/redboot.h> +#endif + +//----------------------------------------------------------------------------- +#endif // CYGONCE_HAL_BOARD_H +// End of board.h diff --git a/ecos/packages/hal/common/current/src/bplist-dynamic.c b/ecos/packages/hal/common/current/src/bplist-dynamic.c new file mode 100644 index 0000000..3ce9434 --- /dev/null +++ b/ecos/packages/hal/common/current/src/bplist-dynamic.c @@ -0,0 +1,449 @@ +//========================================================================== +// +// bplist-dynamic.c +// +// Dynamic breakpoint list. +// Currently only statically allocated. (ie NO_MALLOC is assumed) +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: dmoseley +// Date: 2000-07-11 +// Purpose: Dynamic breakpoint list. +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================= + +#include <pkgconf/system.h> +#include <pkgconf/hal.h> + +#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) && (CYGNUM_HAL_BREAKPOINT_LIST_SIZE > 0) && defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) + +#define CYGARC_HAL_COMMON_EXPORT_CPU_MACROS +#include <cyg/hal/hal_stub.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_cache.h> + +#ifdef TARGET_HAS_HARVARD_MEMORY +#define __read_mem_safe __read_progmem_safe +#define __write_mem_safe __write_progmem_safe +#endif + +/* + * A simple target breakpoint list without using malloc. + * To use this package, you must define HAL_BREAKINST_SIZE to be the size + * in bytes of a trap instruction (max if there's more than one), + * HAL_BREAKINST to the opcode value of the instruction, and + * HAL_BREAKINST_TYPE to be the type necessary to hold the opcode value. + */ + +struct breakpoint_list { + target_register_t addr; + char old_contents [HAL_BREAKINST_SIZE]; + struct breakpoint_list *next; + char in_memory; + char length; +} *breakpoint_list = NULL; + +#ifndef HAL_BREAKINST_ADDR +static HAL_BREAKINST_TYPE break_inst = HAL_BREAKINST; +#define HAL_BREAKINST_ADDR(x) ((void*)&break_inst) +#endif + +static struct breakpoint_list bp_list [CYGNUM_HAL_BREAKPOINT_LIST_SIZE]; +static struct breakpoint_list *free_bp_list = NULL; +static int curr_bp_num = 0; + +int +__set_breakpoint (target_register_t addr, target_register_t len) +{ + struct breakpoint_list **addent = &breakpoint_list; + struct breakpoint_list *l = breakpoint_list; + struct breakpoint_list *newent; + + while (l != NULL && l->addr < addr) + { + addent = &l->next; + l = l->next; + } + + if (l != NULL && l->addr == addr) + return 2; + + if (free_bp_list != NULL) + { + newent = free_bp_list; + free_bp_list = free_bp_list->next; + } + else + { + if (curr_bp_num < CYGNUM_HAL_BREAKPOINT_LIST_SIZE) + { + newent = &bp_list[curr_bp_num++]; + } + else + { + return 1; + } + } + + newent->addr = addr; + newent->in_memory = 0; + newent->next = l; + newent->length = len; + *addent = newent; + + return 0; +} + +int +__remove_breakpoint (target_register_t addr, target_register_t len) +{ + struct breakpoint_list *l = breakpoint_list; + struct breakpoint_list *prev = NULL; + + while (l != NULL && l->addr < addr) + { + prev = l; + l = l->next; + } + + if ((l == NULL) || (l->addr != addr)) + return 1; + + if (l->in_memory) + { + __write_mem_safe (&l->old_contents[0], + (void*)l->addr, + sizeof (l->old_contents)); + } + + if (prev == NULL) + breakpoint_list = l->next; + else + prev->next = l->next; + + l->next = free_bp_list; + free_bp_list = l; + + return 0; +} + +#if defined(HAL_STUB_HW_BREAKPOINT_LIST_SIZE) && (HAL_STUB_HW_BREAKPOINT_LIST_SIZE > 0) +#ifndef HAL_STUB_HW_BREAKPOINT +#error "Must define HAL_STUB_HW_BREAKPOINT" +#endif +struct hw_breakpoint_list { + target_register_t addr; + target_register_t len; + char used; + char installed; +}; +static struct hw_breakpoint_list hw_bp_list [HAL_STUB_HW_BREAKPOINT_LIST_SIZE]; + +int +__set_hw_breakpoint (target_register_t addr, target_register_t len) +{ + int i; + + for (i = 0; i < HAL_STUB_HW_BREAKPOINT_LIST_SIZE; i++) + { + if (hw_bp_list[i].used == 0) + { + hw_bp_list[i].addr = addr; + hw_bp_list[i].len = len; + hw_bp_list[i].used = 1; + hw_bp_list[i].installed = 0; + return 0; + } + } + return -1; +} + +int +__remove_hw_breakpoint (target_register_t addr, target_register_t len) +{ + int i; + + for (i = 0; i < HAL_STUB_HW_BREAKPOINT_LIST_SIZE; i++) + { + if (hw_bp_list[i].used && hw_bp_list[i].addr == addr + && hw_bp_list[i].len == len) + { + if (hw_bp_list[i].installed) + HAL_STUB_HW_BREAKPOINT(0, (void *)addr, (int)len); + hw_bp_list[i].used = 0; + return 0; + } + } + return -1; +} + +static void +__install_hw_breakpoint_list (void) +{ + int i; + + for (i = 0; i < HAL_STUB_HW_BREAKPOINT_LIST_SIZE; i++) + { + if (hw_bp_list[i].used && hw_bp_list[i].installed == 0) + { + HAL_STUB_HW_BREAKPOINT(1, (void *)hw_bp_list[i].addr, + (int)hw_bp_list[i].len); + hw_bp_list[i].installed = 1; + } + } +} + +static void +__clear_hw_breakpoint_list (void) +{ + int i; + + for (i = 0; i < HAL_STUB_HW_BREAKPOINT_LIST_SIZE; i++) + { + if (hw_bp_list[i].used && hw_bp_list[i].installed) + { + HAL_STUB_HW_BREAKPOINT(0, (void *)hw_bp_list[i].addr, + (int)hw_bp_list[i].len); + hw_bp_list[i].installed = 0; + } + } +} +#endif // HAL_STUB_HW_BREAKPOINT_LIST_SIZE + +#if defined(HAL_STUB_HW_WATCHPOINT_LIST_SIZE) && (HAL_STUB_HW_WATCHPOINT_LIST_SIZE > 0) +#ifndef HAL_STUB_HW_WATCHPOINT +#error "Must define HAL_STUB_HW_WATCHPOINT" +#endif +struct hw_watchpoint_list { + target_register_t addr; + target_register_t len; + int ztype; + char used; + char installed; +}; +static struct hw_watchpoint_list hw_wp_list [HAL_STUB_HW_WATCHPOINT_LIST_SIZE]; + +int +__set_hw_watchpoint (target_register_t addr, target_register_t len, int ztype) +{ + int i; + + for (i = 0; i < HAL_STUB_HW_WATCHPOINT_LIST_SIZE; i++) + { + if (hw_wp_list[i].used == 0) + { + hw_wp_list[i].addr = addr; + hw_wp_list[i].len = len; + hw_wp_list[i].ztype = ztype; + hw_wp_list[i].used = 1; + hw_wp_list[i].installed = 0; + return 0; + } + } + return -1; +} + +int +__remove_hw_watchpoint (target_register_t addr, target_register_t len, int ztype) +{ + int i; + + for (i = 0; i < HAL_STUB_HW_WATCHPOINT_LIST_SIZE; i++) + { + if (hw_wp_list[i].used && hw_wp_list[i].addr == addr + && hw_wp_list[i].len == len && hw_wp_list[i].ztype == ztype ) + { + if (hw_wp_list[i].installed) + HAL_STUB_HW_WATCHPOINT(0, (void *)addr, (int)len, ztype); + hw_wp_list[i].used = 0; + return 0; + } + } + return -1; +} + +static void +__install_hw_watchpoint_list (void) +{ + int i; + + for (i = 0; i < HAL_STUB_HW_WATCHPOINT_LIST_SIZE; i++) + { + if (hw_wp_list[i].used && hw_wp_list[i].installed == 0) + { + HAL_STUB_HW_WATCHPOINT(1, (void *)hw_wp_list[i].addr, + (int)hw_wp_list[i].len, hw_wp_list[i].ztype); + hw_wp_list[i].installed = 1; + } + } +} + +static void +__clear_hw_watchpoint_list (void) +{ + int i; + + for (i = 0; i < HAL_STUB_HW_WATCHPOINT_LIST_SIZE; i++) + { + if (hw_wp_list[i].used && hw_wp_list[i].installed) + { + HAL_STUB_HW_WATCHPOINT(0, (void *)hw_wp_list[i].addr, + (int)hw_wp_list[i].len, hw_wp_list[i].ztype); + hw_wp_list[i].installed = 0; + } + } +} +#endif // HAL_STUB_HW_WATCHPOINT_LIST_SIZE + + + +void +__install_breakpoint_list (void) +{ + struct breakpoint_list *l = breakpoint_list; + + while (l != NULL) + { + if (! l->in_memory) + { + int len = sizeof (l->old_contents); + if (__read_mem_safe (&l->old_contents[0], (void*)l->addr, len) == len) + { + if (__write_mem_safe (HAL_BREAKINST_ADDR(l->length), + (void*)l->addr, l->length) == l->length) + { + l->in_memory = 1; + } + } + } + l = l->next; + } +#if defined(HAL_STUB_HW_BREAKPOINT_LIST_SIZE) && (HAL_STUB_HW_BREAKPOINT_LIST_SIZE > 0) + __install_hw_breakpoint_list(); +#endif +#if defined(HAL_STUB_HW_WATCHPOINT_LIST_SIZE) && (HAL_STUB_HW_WATCHPOINT_LIST_SIZE > 0) + __install_hw_watchpoint_list(); +#endif + HAL_ICACHE_SYNC(); +} + +void +__clear_breakpoint_list (void) +{ + struct breakpoint_list *l = breakpoint_list; + + while (l != NULL) + { + if (l->in_memory) + { + int len = sizeof (l->old_contents); + if (__write_mem_safe (&l->old_contents[0], (void*)l->addr, len) == len) + { + l->in_memory = 0; + } + } + l = l->next; + } +#if defined(HAL_STUB_HW_BREAKPOINT_LIST_SIZE) && (HAL_STUB_HW_BREAKPOINT_LIST_SIZE > 0) + __clear_hw_breakpoint_list(); +#endif +#if defined(HAL_STUB_HW_WATCHPOINT_LIST_SIZE) && (HAL_STUB_HW_WATCHPOINT_LIST_SIZE > 0) + __clear_hw_watchpoint_list(); +#endif + HAL_ICACHE_INVALIDATE_ALL(); +} + +int +__display_breakpoint_list (void (*print_func)(target_register_t)) +{ + struct breakpoint_list *l = breakpoint_list; + + while (l != NULL) + { + print_func(l->addr); + l = l->next; + } + + return 0; +} +#else // (CYGNUM_HAL_BREAKPOINT_LIST_SIZE == 0) or UNDEFINED + +#include <cyg/hal/hal_stub.h> // Our header + +#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS +// We don't know that type target_register_t is yet. +// Let's just pick a type so we can compile. Since +// these versions of the functions don't actually do +// anything with the parameters, the actualy types +// don't matter. +typedef unsigned long target_register_t; +#endif + +int +__set_breakpoint (target_register_t addr, target_register_t len) +{ + return 1; +} + +int +__remove_breakpoint (target_register_t addr, target_register_t len) +{ + return 1; +} + +void +__install_breakpoint_list (void) +{ +} + +void +__clear_breakpoint_list (void) +{ +} + +int +__display_breakpoint_list (void (*print_func)(target_register_t)) +{ + return 0; +} +#endif // (CYGNUM_HAL_BREAKPOINT_LIST_SIZE > 0) + diff --git a/ecos/packages/hal/common/current/src/dbg-threads-syscall.c b/ecos/packages/hal/common/current/src/dbg-threads-syscall.c new file mode 100644 index 0000000..58583be --- /dev/null +++ b/ecos/packages/hal/common/current/src/dbg-threads-syscall.c @@ -0,0 +1,216 @@ +//======================================================================== +// +// dbg-threads-syscall.c +// +// Pseudo system calls for multi-threaded debug support +// +//======================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Red Hat, nickg +// Contributors: Red Hat, nickg +// Date: 1998-08-25 +// Purpose: +// Description: Pseudo system calls to bind system specific multithread +// debug support with a ROM monitor, cygmon. We call it +// Cygmon, but the feature lives in libstub. +// Usage: +// +//####DESCRIPTIONEND#### +// +//======================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/hal.h> + +#if !defined(CYGPKG_KERNEL) && defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT) + +/* Only include this code if we do not have a kernel. Otherwise the kernel + * supplies these functions for the app we are linked with. + */ + +#include <cyg/hal/dbg-threads-api.h> +#include <cyg/hal/dbg-thread-syscall.h> + + +static dbg_syscall_func * dbg_syscall_ptr ; + +static union dbg_thread_syscall_parms tcall ; + +/* ----- INIT_THREADS_SYSCALL --------------------------------------- */ +/* Some external bing and configuration logic knows how to setup + the ststem calls. In the first implementation, we have used a vector + in the secondary vector table. This functions allows us to isolate that + sort of system specific detail. Similarly, we do not export the + specific detail of a dbg_syscall_func. + */ + + +void init_threads_syscall(void * vector) +{ + dbg_syscall_ptr = vector ; /* AH, the easy compatability of the + void pointer*/ +} /* init_threads_syscall */ + +/* All forms of failure return 0 */ +/* Whether non support, incomplete initialization, unknown thread */ +static __inline__ int dbg_thread_syscall( + enum dbg_syscall_ids id) +{ + dbg_syscall_func f ; /* double indirect via */ + if (0 == dbg_syscall_ptr) return 0; /* dbg_syscall_ptr never init'd */ + if (0 ==(f = *dbg_syscall_ptr)) return 0 ; /* vector not initialized */ + return (*f)(id,&tcall); +} + + + + +/* ------- INIT_THREAD_SYSCALL ------------------------------------------- */ +/* Received the address of the entry in the secondary interrupt vector table */ +/* This table is the interchange between the O.S. and Cygmon/libstub */ +/* This could get more complex so, I am doing it with a function + rather than exposing the internals. + */ +void init_thread_syscall(void * vector) +{ + dbg_syscall_ptr = vector ; +} + +int dbg_thread_capabilities(struct dbg_capabilities * cbp) +{ +#if 0 + tcall.cap_parms.abilities = cbp ; + return dbg_thread_syscall(dbg_capabilities_func) ; +#else + cbp->mask1 = has_thread_current | + has_thread_registers | + has_thread_reg_change | + has_thread_list | + has_thread_info ; + return 1 ; +#endif +} + +int dbg_currthread(threadref * varparm) +{ + tcall.currthread_parms.ref = varparm ; + return dbg_thread_syscall(dbg_currthread_func) ; +} + + +int dbg_threadlist( + int startflag, + threadref * lastthreadid, + threadref * next_thread + ) +{ + tcall.threadlist_parms.startflag = startflag ; + tcall.threadlist_parms.lastid = lastthreadid ; + tcall.threadlist_parms.nextthreadid = next_thread ; + return dbg_thread_syscall(dbg_threadlist_func) ; +} + +int dbg_threadinfo( + threadref * threadid, + struct cygmon_thread_debug_info * info) +{ + tcall.info_parms.ref = threadid ; + tcall.info_parms.info = info ; + return dbg_thread_syscall(dbg_threadinfo_func) ; +} + +int dbg_getthreadreg( + threadref * osthreadid, + int regcount, /* count of registers in the array */ + void * regval) /* fillin this array */ +{ + tcall.reg_parms.thread = osthreadid ; + tcall.reg_parms.regcount = regcount ; + tcall.reg_parms.registers = regval ; + return dbg_thread_syscall(dbg_getthreadreg_func) ; +} + +int dbg_setthreadreg( + threadref * osthreadid, + int regcount , /* number of registers */ + void * regval) +{ + tcall.reg_parms.thread = osthreadid ; + tcall.reg_parms.regcount = regcount ; + tcall.reg_parms.registers = regval ; + return dbg_thread_syscall(dbg_setthreadreg_func) ; +} /* dbg_setthreadreg */ + +int dbg_scheduler(threadref *thread_id, int lock, int mode) +{ + tcall.scheduler_parms.thread = thread_id; + tcall.scheduler_parms.lock = lock ; + tcall.scheduler_parms.mode = mode ; + + return dbg_thread_syscall(dbg_scheduler_func) ; +} + + + +#if (CYG_BYTEORDER == CYG_LSBFIRST) + +unsigned long swap32(unsigned long x) +{ + unsigned long r = 0; + + r |= (x>>24)&0xFF; + r |= ((x>>16)&0xFF)<<8; + r |= ((x>>8)&0xFF)<<16; + r |= ((x)&0xFF)<<24; + + return r; +} + +#else + +#define swap32(x) ((unsigned long)(x)) + +#endif + +int dbg_currthread_id(void) +{ + threadref ref; + if( dbg_currthread( &ref ) ) + return (cyg_uint16)swap32(((unsigned long *)ref)[1]); + else return 0; +} + +#endif diff --git a/ecos/packages/hal/common/current/src/drv_api.c b/ecos/packages/hal/common/current/src/drv_api.c new file mode 100644 index 0000000..a9c751a --- /dev/null +++ b/ecos/packages/hal/common/current/src/drv_api.c @@ -0,0 +1,943 @@ +//========================================================================== +// +// drv_api.c +// +// Driver API for non-kernel configurations +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Nick Garnett +// Date: 1999-02-24 +// Purpose: Driver API for non-kernel configurations +// Description: These functions are used to support drivers when the kernel +// is not present. +// +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/system.h> + +#ifndef CYGPKG_KERNEL + +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_trac.h> +#include <cyg/infra/cyg_ass.h> + +#include <pkgconf/hal.h> +#include <cyg/hal/drv_api.h> + +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_intr.h> + +//-------------------------------------------------------------------------- +// Statics + +static volatile cyg_int32 isr_disable_counter = 1; // ISR disable counter + +static CYG_INTERRUPT_STATE isr_disable_state; + +volatile cyg_int32 dsr_disable_counter // DSR disable counter + CYGBLD_ATTRIB_ASM_ALIAS( cyg_scheduler_sched_lock ); + +static cyg_interrupt* volatile dsr_list; // List of pending DSRs + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN + +cyg_interrupt *chain_list[CYGNUM_HAL_ISR_COUNT]; + +#endif + +//-------------------------------------------------------------------------- +// DSR handling functions. +// post_dsr() places a DSR on the list of DSRs to be called. +// call_dsrs() calls the DSRs. + +static void post_dsr( cyg_interrupt *intr ) +{ + CYG_INTERRUPT_STATE old_intr; + + CYG_REPORT_FUNCTION(); + + HAL_DISABLE_INTERRUPTS(old_intr); + + if( intr->dsr_count++ == 0 ) + { + intr->next_dsr = dsr_list; + dsr_list = intr; + } + + HAL_RESTORE_INTERRUPTS(old_intr); + + CYG_REPORT_RETURN(); +} + +static void call_dsrs(void) +{ + CYG_REPORT_FUNCTION(); + + while( dsr_list != NULL ) + { + cyg_interrupt *intr; + cyg_int32 count; + CYG_INTERRUPT_STATE old_intr; + + HAL_DISABLE_INTERRUPTS(old_intr); + + intr = dsr_list; + dsr_list = intr->next_dsr; + count = intr->dsr_count; + intr->dsr_count = 0; + + HAL_RESTORE_INTERRUPTS(old_intr); + + intr->dsr( intr->vector, count, (CYG_ADDRWORD)intr->data ); + } + + CYG_REPORT_RETURN(); + +} + +//-------------------------------------------------------------------------- +// This is referenced from the HAL, although it does not actually get called. + +externC void +cyg_interrupt_call_pending_DSRs(void) +{ + call_dsrs(); +} + +//-------------------------------------------------------------------------- +// This is called from springboard ISRs in some HALs. + +externC void +cyg_interrupt_post_dsr(CYG_ADDRWORD data) +{ + cyg_interrupt * intr = (cyg_interrupt *)data; + post_dsr(intr); +} + +//-------------------------------------------------------------------------- +// Interrupt end function called from HAL VSR to tidy up. This is where +// DSRs will be called if necessary. + +externC void +interrupt_end( + cyg_uint32 isr_ret, + cyg_interrupt *intr, + HAL_SavedRegisters *regs + ) +{ + CYG_REPORT_FUNCTION(); + +#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN + + // Only do this if we are in a non-chained configuration. + // If we are chained, then chain_isr will do the DSR + // posting. + + if( isr_ret & CYG_ISR_CALL_DSR && intr != NULL ) post_dsr(intr); + +#endif + + if( dsr_disable_counter == 0 ) call_dsrs(); + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// ISR for handling chained interrupts. + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN + +cyg_uint32 chain_isr(cyg_vector_t vector, CYG_ADDRWORD data) +{ + cyg_interrupt *p = *(cyg_interrupt **)data; + register cyg_uint32 isr_ret = 0; + register cyg_uint32 isr_chain_ret = 0; + + CYG_REPORT_FUNCTION(); + + while( p != NULL ) + { + if( p->vector == vector ) + { + isr_ret = p->isr(vector, p->data); + + isr_chain_ret |= isr_ret; + + if( isr_ret & CYG_ISR_CALL_DSR ) post_dsr(p); + + if( isr_ret & CYG_ISR_HANDLED ) break; + } + + p = p->next; + } + +#ifdef HAL_DEFAULT_ISR + if( (isr_chain_ret & (CYG_ISR_CALL_DSR|CYG_ISR_HANDLED)) == 0 ) + { + // If we finished the loop for some reason other than that an + // ISR has handled the interrupt, call any default ISR to either + // report the spurious interrupt, or do some other HAL level processing + // such as GDB interrupt detection etc. + + HAL_DEFAULT_ISR( vector, 0 ); + } +#endif + + CYG_REPORT_RETURN(); + + return isr_ret & CYG_ISR_CALL_DSR; +} + +#endif + +//-------------------------------------------------------------------------- +// ISR lock. This disables interrupts and keeps a count of the number +// times it has been called. + +externC void cyg_drv_isr_lock() +{ + CYG_REPORT_FUNCTION(); + + if( isr_disable_counter == 0 ) + HAL_DISABLE_INTERRUPTS(isr_disable_state); + + CYG_ASSERT( isr_disable_counter >= 0 , "Disable counter negative"); + + isr_disable_counter++; + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Unlock ISRs. This decrements the count and re-enables interrupts if it +// goes zero. + +externC void cyg_drv_isr_unlock() +{ + CYG_REPORT_FUNCTION(); + + CYG_ASSERT( isr_disable_counter > 0 , "Disable counter not greater than zero"); + + isr_disable_counter--; + + if ( isr_disable_counter == 0 ) + { + HAL_RESTORE_INTERRUPTS(isr_disable_state); + } + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Lock DSR lock. Simply increment the counter. + +externC void cyg_drv_dsr_lock() +{ + CYG_REPORT_FUNCTION(); + + dsr_disable_counter++; + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Unlock DSR lock. If the counter is about to go zero, call any pending +// DSRs and then zero the counter. + +externC void cyg_drv_dsr_unlock() +{ + CYG_REPORT_FUNCTION(); + + do + { + if( dsr_disable_counter == 1 ) + { + call_dsrs(); + } + + HAL_REORDER_BARRIER(); + + dsr_disable_counter = 0; + + HAL_REORDER_BARRIER(); + + // Check that no DSRs have been posted between calling + // call_dsrs() and zeroing dsr_disable_counter. If so, + // loop back and call them. + + if( dsr_list != NULL ) + { + dsr_disable_counter = 1; + continue; + } + + CYG_REPORT_RETURN(); + + return; + + } while(1); + + CYG_FAIL( "Should not be executed" ); +} + +//-------------------------------------------------------------------------- +// Initialize a mutex. + +externC void cyg_drv_mutex_init( cyg_drv_mutex_t *mutex ) +{ + CYG_REPORT_FUNCTION(); + + mutex->lock = 0; + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Destroy a mutex. + +externC void cyg_drv_mutex_destroy( cyg_drv_mutex_t *mutex ) +{ + CYG_REPORT_FUNCTION(); + + mutex->lock = -1; + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Lock a mutex. We check that we are not trying to lock a locked or +// destroyed mutex and if not, set it locked. + +externC cyg_bool_t cyg_drv_mutex_lock( cyg_drv_mutex_t *mutex ) +{ + CYG_REPORT_FUNCTION(); + + CYG_ASSERT( mutex->lock == 0 , "Trying to lock locked mutex"); + + mutex->lock = 1; + + CYG_REPORT_RETURN(); + + return true; +} + +//-------------------------------------------------------------------------- +// Attempt to claim a mutex, and return if it cannot be. + +externC cyg_bool_t cyg_drv_mutex_trylock( cyg_drv_mutex_t *mutex ) +{ + cyg_bool_t result = true; + + CYG_REPORT_FUNCTION(); + + if( mutex->lock == 1 ) result = false; + + mutex->lock = 1; + + CYG_REPORT_RETURN(); + + return result; +} + +//-------------------------------------------------------------------------- +// Unlock a mutex. We check that the mutex is actually locked before doing +// this. + +externC void cyg_drv_mutex_unlock( cyg_drv_mutex_t *mutex ) +{ + CYG_REPORT_FUNCTION(); + + CYG_ASSERT( mutex->lock == 1 , "Trying to unlock unlocked mutex"); + + mutex->lock = 0; + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Release all threads waiting for the mutex. +// This is really for threads, so we do nothing here. + +externC void cyg_drv_mutex_release( cyg_drv_mutex_t *mutex ) +{ + CYG_REPORT_FUNCTION(); + + + + CYG_REPORT_RETURN(); +} + + +//-------------------------------------------------------------------------- +// Initialized a condition variable. + +externC void cyg_drv_cond_init( cyg_drv_cond_t *cond, cyg_drv_mutex_t *mutex ) +{ + CYG_REPORT_FUNCTION(); + + cond->wait = 0; + cond->mutex = mutex; + + CYG_REPORT_RETURN(); +} + + +//-------------------------------------------------------------------------- +// Destroy a condition variable. + +externC void cyg_drv_cond_destroy( cyg_drv_cond_t *cond ) +{ + CYG_REPORT_FUNCTION(); + + cond->wait = -1; + cond->mutex = NULL; + + CYG_REPORT_RETURN(); +} + +// ------------------------------------------------------------------------- +// Wait for a condition variable to be signalled. We simply busy wait +// polling the condition variable's wait member until a DSR sets it to +// 0. Note that the semantics of condition variables means that the +// wakeup only happens if there is a thread actually waiting on the CV +// when the signal is sent. + +externC cyg_bool cyg_drv_cond_wait( cyg_drv_cond_t *cond ) +{ + CYG_REPORT_FUNCTION(); + + CYG_ASSERT( cond->mutex != NULL, "Uninitialized condition variable"); + CYG_ASSERT( cond->mutex->lock, "Mutex not locked"); + + cyg_drv_dsr_lock(); + + cond->wait = 1; + + while( cond->wait == 1 ) + { + // While looping we call call_dsrs() to service any DSRs that + // get posted. One of these will make the call to cond_signal + // to break us out of this loop. If we do not have the DSR + // lock claimed, then a race condition could occur and keep us + // stuck here forever. + + call_dsrs(); + } + + cyg_drv_dsr_unlock(); + + CYG_REPORT_RETURN(); + + return true; +} + +//-------------------------------------------------------------------------- +// Signal a condition variable. This sets the wait member to zero, which +// has no effect when there is no waiter, but will wake up any waiting +// thread. + +externC void cyg_drv_cond_signal( cyg_drv_cond_t *cond ) +{ + CYG_REPORT_FUNCTION(); + + cond->wait = 0; + + CYG_REPORT_RETURN(); +} + + +//-------------------------------------------------------------------------- +// Broadcast to condition variable. This is exactly the same a signal since +// there can only be one waiter. + +externC void cyg_drv_cond_broadcast( cyg_drv_cond_t *cond ) +{ + CYG_REPORT_FUNCTION(); + + cond->wait = 0; + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Spinlock support. +// Since we can only support a single CPU in this version of the API, we only +// set and clear the lock variable to keep track of what's happening. + +void cyg_drv_spinlock_init( + cyg_drv_spinlock_t *lock, /* spinlock to initialize */ + cyg_bool_t locked /* init locked or unlocked */ +) +{ + CYG_REPORT_FUNCTION(); + + lock->lock = locked; + + CYG_REPORT_RETURN(); +} + +void cyg_drv_spinlock_destroy( cyg_drv_spinlock_t *lock ) +{ + CYG_REPORT_FUNCTION(); + + lock->lock = -1; + + CYG_REPORT_RETURN(); +} + +void cyg_drv_spinlock_spin( cyg_drv_spinlock_t *lock ) +{ + CYG_REPORT_FUNCTION(); + + CYG_ASSERT( lock->lock == 0 , "Trying to lock locked spinlock"); + + lock->lock = 1; + + CYG_REPORT_RETURN(); +} + +void cyg_drv_spinlock_clear( cyg_drv_spinlock_t *lock ) +{ + CYG_REPORT_FUNCTION(); + + CYG_ASSERT( lock->lock == 1 , "Trying to clear cleared spinlock"); + + lock->lock = 0; + + CYG_REPORT_RETURN(); +} + +cyg_bool_t cyg_drv_spinlock_try( cyg_drv_spinlock_t *lock ) +{ + cyg_bool_t result = true; + + CYG_REPORT_FUNCTION(); + + if( lock->lock == 1 ) result = false; + + lock->lock = 1; + + CYG_REPORT_RETURN(); + + return result; +} + +cyg_bool_t cyg_drv_spinlock_test( cyg_drv_spinlock_t *lock ) +{ + cyg_bool_t result = true; + + CYG_REPORT_FUNCTION(); + + if( lock->lock == 1 ) result = false; + + CYG_REPORT_RETURN(); + + return result; +} + +void cyg_drv_spinlock_spin_intsave( cyg_drv_spinlock_t *lock, + cyg_addrword_t *istate ) +{ + CYG_REPORT_FUNCTION(); + + HAL_DISABLE_INTERRUPTS( *istate ); + + lock->lock = 1; + + CYG_REPORT_RETURN(); +} + + +void cyg_drv_spinlock_clear_intsave( cyg_drv_spinlock_t *lock, + cyg_addrword_t istate ) +{ + CYG_REPORT_FUNCTION(); + + lock->lock = 0; + + HAL_RESTORE_INTERRUPTS( istate ); + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Create an interrupt object. + +externC void cyg_drv_interrupt_create( + cyg_vector_t vector, + cyg_priority_t priority, + cyg_addrword_t data, + cyg_ISR_t *isr, + cyg_DSR_t *dsr, + cyg_handle_t *handle, + cyg_interrupt *intr + ) +{ + CYG_REPORT_FUNCTION(); + + intr->vector = vector; + intr->priority = priority; + intr->isr = isr; + intr->dsr = dsr; + intr->data = data; + intr->next_dsr = NULL; + intr->dsr_count = 0; + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN + + intr->next = NULL; + +#endif + + *handle = (cyg_handle_t)intr; + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Delete an interrupt object. This merely ensures that it is detached from +// the vector. + +externC void cyg_drv_interrupt_delete( cyg_handle_t interrupt ) +{ + CYG_REPORT_FUNCTION(); + + cyg_drv_interrupt_detach( interrupt ); + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// + +externC void cyg_drv_interrupt_attach( cyg_handle_t interrupt ) +{ + cyg_interrupt *intr = (cyg_interrupt *)interrupt; + + CYG_REPORT_FUNCTION(); + + CYG_ASSERT( intr->vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( intr->vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + + HAL_INTERRUPT_SET_LEVEL( intr->vector, intr->priority ); + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN + + CYG_ASSERT( intr->next == NULL , "cyg_interrupt already on a list"); + + { + cyg_uint32 index; + + HAL_TRANSLATE_VECTOR( intr->vector, index ); + + if( chain_list[index] == NULL ) + { + // First Interrupt on this chain, just assign it and + // register the chain_isr with the HAL. + + chain_list[index] = intr; + + HAL_INTERRUPT_ATTACH( intr->vector, chain_isr, + &chain_list[index], NULL ); + } + else + { + // There are already interrupts chained, add this one into + // the chain in priority order. + + cyg_interrupt **p = &chain_list[index]; + + while( *p != NULL ) + { + cyg_interrupt *n = *p; + + if( n->priority < intr->priority ) break; + + p = &n->next; + } + intr->next = *p; + *p = intr; + } + } + +#else + + HAL_INTERRUPT_ATTACH( intr->vector, intr->isr, intr->data, intr ); + +#endif + + CYG_REPORT_RETURN(); +} + + +//-------------------------------------------------------------------------- +// Detach an interrupt from its vector. + +externC void cyg_drv_interrupt_detach( cyg_handle_t interrupt ) +{ + cyg_interrupt *intr = (cyg_interrupt *)interrupt; + + CYG_REPORT_FUNCTION(); + + CYG_ASSERT( intr->vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( intr->vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + +#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN + + // Remove the interrupt object from the vector chain. + + { + cyg_uint32 index; + cyg_interrupt **p; + + HAL_TRANSLATE_VECTOR( intr->vector, index ); + + p = &chain_list[index]; + + while( *p != NULL ) + { + cyg_interrupt *n = *p; + + if( n == intr ) + { + *p = intr->next; + break; + } + + p = &n->next; + } + + // If this was the last one, detach the vector. + + if( chain_list[index] == NULL ) + HAL_INTERRUPT_DETACH( intr->vector, chain_isr ); + } + +#else + + HAL_INTERRUPT_DETACH( intr->vector, intr->isr ); + +#endif + + CYG_REPORT_RETURN(); +} + + +//-------------------------------------------------------------------------- +// Mask delivery of an interrupt at the interrupt controller. +// (Interrupt safe) + +externC void cyg_drv_interrupt_mask( cyg_vector_t vector ) +{ + CYG_INTERRUPT_STATE old_ints; + + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1("vector=%d", vector); + + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + + HAL_DISABLE_INTERRUPTS(old_ints); + HAL_INTERRUPT_MASK( vector ); + HAL_RESTORE_INTERRUPTS(old_ints); + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Mask delivery of an interrupt at the interrupt controller. +// (Not interrupt safe) + +externC void cyg_drv_interrupt_mask_intunsafe( cyg_vector_t vector ) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1("vector=%d", vector); + + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + + HAL_INTERRUPT_MASK( vector ); + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Unmask delivery of an interrupt at the interrupt controller. +// (Interrupt safe) + +externC void cyg_drv_interrupt_unmask( cyg_vector_t vector ) +{ + CYG_INTERRUPT_STATE old_ints; + + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1("vector=%d", vector); + + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + + HAL_DISABLE_INTERRUPTS(old_ints); + HAL_INTERRUPT_UNMASK( vector ); + HAL_RESTORE_INTERRUPTS(old_ints); + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Unmask delivery of an interrupt at the interrupt controller. +// (Not interrupt safe) + +externC void cyg_drv_interrupt_unmask_intunsafe( cyg_vector_t vector ) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1("vector=%d", vector); + + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + + HAL_INTERRUPT_UNMASK( vector ); + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Acknowledge an interrupt at the controller to allow another interrupt +// to be delivered. + +externC void cyg_drv_interrupt_acknowledge( cyg_vector_t vector ) +{ +// CYG_REPORT_FUNCTION(); + + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + + HAL_INTERRUPT_ACKNOWLEDGE( vector ); + +// CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Configure interrupt detection parameters. + +externC void cyg_drv_interrupt_configure( + cyg_vector_t vector, + cyg_bool_t level, + cyg_bool_t up + ) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG3("vector = %d, level = %d, up = %d", vector, level, + up); + + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + + HAL_INTERRUPT_CONFIGURE( vector, level, up ); + + CYG_REPORT_RETURN(); +} + +//-------------------------------------------------------------------------- +// Configure interrupt priority level. + +externC void cyg_drv_interrupt_level( cyg_vector_t vector, cyg_priority_t level ) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2("vector = %d, level = %d", vector, level); + + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + + HAL_INTERRUPT_SET_LEVEL( vector, level ); + + CYG_REPORT_RETURN(); +} + +// ------------------------------------------------------------------------- +// CPU interrupt routing + +externC void cyg_drv_interrupt_set_cpu( cyg_vector_t vector, cyg_cpu_t cpu ) +{ + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG2("vector = %d, cpu = %d", vector, cpu); + + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + +#ifdef CYGPKG_HAL_SMP_SUPPORT + HAL_INTERRUPT_SET_CPU( vector, cpu ); +#endif + + CYG_REPORT_RETURN(); +} + +externC cyg_cpu_t cyg_drv_interrupt_get_cpu( cyg_vector_t vector ) +{ + cyg_cpu_t cpu = 0; + + CYG_REPORT_FUNCTION(); + CYG_REPORT_FUNCARG1("vector = %d", vector); + + CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector"); + CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector"); + +#ifdef CYGPKG_HAL_SMP_SUPPORT + HAL_INTERRUPT_GET_CPU( vector, cpu ); +#endif + + CYG_REPORT_RETURN(); + + return cpu; +} + +// ------------------------------------------------------------------------- +// Exception delivery function called from the HAL as a result of a +// hardware exception being raised. + +externC void cyg_hal_deliver_exception( CYG_WORD code, CYG_ADDRWORD data ) +{ + CYG_FAIL(" !!! Exception !!! "); +} + + +#endif + +//-------------------------------------------------------------------------- +// EOF drv_api.c diff --git a/ecos/packages/hal/common/current/src/dummy.c b/ecos/packages/hal/common/current/src/dummy.c new file mode 100644 index 0000000..c645be6 --- /dev/null +++ b/ecos/packages/hal/common/current/src/dummy.c @@ -0,0 +1,53 @@ +//========================================================================== +// +// dummy.c +// +// Guarantee the existence of libextras.a +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: bartv +// Date: 1999-04-16 +// +//####DESCRIPTIONEND#### +//========================================================================== + + +// This file should contain no code or data. Its sole purpose is to +// be compiled to an empty object file and placed into libtarget.a, +// thus ensuring that that file actually exists. This simplifies +// life elsewhere. diff --git a/ecos/packages/hal/common/current/src/gdb-fileio.c b/ecos/packages/hal/common/current/src/gdb-fileio.c new file mode 100644 index 0000000..ef0945a --- /dev/null +++ b/ecos/packages/hal/common/current/src/gdb-fileio.c @@ -0,0 +1,728 @@ +/*========================================================================== +// +// gdb-fileio.c +// +// Implementation of File I/O using the GDB remote protocol +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jlarmour +// Contributors: +// Date: 2002-04-09 +// Purpose: Implementation of File I/O using the GDB remote +// protocol +// Description: 'F' packet requests are of the form: +// F<name>[,<parameter>]... +// where name is the ASCII syscall name, and the +// parameters are generally included as hex ints, +// in ASCII. +// +//####DESCRIPTIONEND#### +//========================================================================*/ + +/* CONFIGURATION */ + +#include <pkgconf/hal.h> + +/* HEADERS */ + +#include <stddef.h> // size_t +#include <cyg/infra/cyg_type.h> +#ifdef CYGPKG_ISOINFRA +# include <pkgconf/isoinfra.h> +# include <string.h> +#endif +#include "board.h" // sets correct definitions for generic stub header +#include <cyg/hal/generic-stub.h> +#include "gdb-fileio.h" + +/* TYPES */ + +// this is used by newlib's mode_t so we should match it +#ifdef __GNUC__ +#define _ST_INT32 __attribute__ ((__mode__ (__SI__))) +#else +#define _ST_INT32 +#endif + +typedef int newlib_int_t; +typedef unsigned int newlib_uint_t; +typedef long newlib_long_t; +typedef long newlib_time_t; +typedef unsigned int newlib_mode_t _ST_INT32; +typedef short newlib_dev_t; +typedef unsigned short newlib_uid_t; +typedef unsigned short newlib_gid_t; +typedef unsigned short newlib_ino_t; +typedef unsigned short newlib_nlink_t; +typedef long newlib_off_t; + +struct newlib_timeval { + newlib_time_t tv_sec; + newlib_long_t tv_usec; +}; + +struct newlib_stat +{ + newlib_dev_t st_dev; + newlib_ino_t st_ino; + newlib_mode_t st_mode; + newlib_nlink_t st_nlink; + newlib_uid_t st_uid; + newlib_gid_t st_gid; + newlib_dev_t st_rdev; + newlib_off_t st_size; + // We assume we've been compiled with the same flags as newlib here +#if defined(__svr4__) && !defined(__PPC__) && !defined(__sun__) + newlib_time_t st_atime; + newlib_time_t st_mtime; + newlib_time_t st_ctime; +#else + newlib_time_t st_atime; + newlib_long_t st_spare1; + newlib_time_t st_mtime; + newlib_long_t st_spare2; + newlib_time_t st_ctime; + newlib_long_t st_spare3; + newlib_long_t st_blksize; + newlib_long_t st_blocks; + newlib_long_t st_spare4[2]; +#endif +}; + +/* EXTERNS */ + +__externC char __remcomInBuffer[]; // from generic-stub.c, for packet data +__externC char __remcomOutBuffer[]; // ditto + +/* STATICS/GLOBALS */ + +static int __fileio_retcode, __fileio_errno; +static cyg_bool __fileio_retcode_set, __fileio_errno_set, __fileio_ctrlc_set; + +/* MACROS */ + +// endian independent conversion functions from big endian protocol types +// to newlib types + +#define GDBFILEIO_FIO_TO_NEWLIB( _f, _n, _ftype ) \ +CYG_MACRO_START \ + char *_cf = (char *)(_f); \ + int _i; \ + char _sign = 0; \ + if (*_cf == '-') { \ + _sign = 1; \ + _cf++; \ + } \ + (_n) = 0; \ + for (_i=0; _i<sizeof(_ftype); _i++) { \ + (_n) = ((_n) << 8) | _cf[_i]; \ + } \ + if (_sign) \ + (_n) = -(_n); \ +CYG_MACRO_END + +#define GDBABS(_x_) (((_x_) < 0) ? (-(_x_)) : (_x_)) + +#define GDBFILEIO_NEWLIB_TO_FIO( _f, _n, _ftype ) \ +CYG_MACRO_START \ + char *_cf = (char *)(_f); \ + int _i = 0; \ + if ((_n) < 0) \ + _cf[_i++] = '-'; \ + for (; _i<sizeof(_ftype); _i++) { \ + _cf[_i] = ((GDBABS(_n)) >> 8*(sizeof(_ftype)-_i-1)) & 0xff; \ + } \ +CYG_MACRO_END + + +/* FUNCTIONS */ + +#ifndef CYGINT_ISO_STRING_STRFUNCS +static size_t strlen( const char *s ) +{ + size_t retval; + const char *start = s; + while (*s) + s++; + retval = s - start; + return retval; +} +#endif + +static int +chars_to_hex( char *charsin, char *hexout, int bytes ) +{ + int numChars = 0; + int allzero = true; + + while (bytes--) { + if (0 != *charsin) + allzero = false; + *hexout++ = __tohex( (*charsin / 16) & 15 ); + *hexout++ = __tohex( (*charsin++) & 15 ); + numChars += 2; + } + if (allzero) // doesn't matter if we actually set more than needed above + return (numChars > 2 ? 2 : numChars); + return numChars; +} + +static void +gdbfileio_fio_to_newlib_time_t( fio_time_t *f, newlib_time_t *n ) +{ + GDBFILEIO_FIO_TO_NEWLIB( f, *n, fio_time_t ); +} // gdbfileio_fio_to_newlib_time_t() + +static void +gdbfileio_newlib_to_fio_int_t( newlib_int_t *n, fio_int_t *f ) +{ + GDBFILEIO_NEWLIB_TO_FIO( f, *n, fio_int_t ); +} // gdbfileio_newlib_to_fio_int_t() + +static void +gdbfileio_newlib_to_fio_uint_t( newlib_uint_t *n, fio_uint_t *f ) +{ + GDBFILEIO_NEWLIB_TO_FIO( f, *n, fio_uint_t ); +} // gdbfileio_newlib_to_fio_uint_t() + +static void +gdbfileio_fio_to_newlib_long_t( fio_long_t *f, newlib_long_t *n ) +{ + GDBFILEIO_FIO_TO_NEWLIB( f, *n, fio_long_t ); +} // gdbfileio_fio_to_newlib_long_t() + +static void +gdbfileio_newlib_to_fio_long_t( newlib_long_t *n, fio_long_t *f ) +{ + GDBFILEIO_NEWLIB_TO_FIO( f, *n, fio_long_t ); +} // gdbfileio_newlib_to_fio_long_t() + +static void +gdbfileio_fio_to_newlib_mode_t( fio_mode_t *f, newlib_mode_t *n ) +{ + GDBFILEIO_FIO_TO_NEWLIB( f, *n, fio_mode_t ); +} // gdbfileio_fio_to_newlib_mode_t() + +static void +gdbfileio_newlib_to_fio_mode_t( newlib_mode_t *n, fio_mode_t *f ) +{ + GDBFILEIO_NEWLIB_TO_FIO( f, *n, fio_mode_t ); +} // gdbfileio_newlib_to_fio_mode_t() + +static void +gdbfileio_fio_to_newlib_dev_t( fio_uint_t *f, newlib_dev_t *n ) +{ + GDBFILEIO_FIO_TO_NEWLIB( f, *n, fio_uint_t ); +} // gdbfileio_fio_to_newlib_dev_t() + +static void +gdbfileio_fio_to_newlib_ino_t( fio_uint_t *f, newlib_ino_t *n ) +{ + GDBFILEIO_FIO_TO_NEWLIB( f, *n, fio_uint_t ); +} // gdbfileio_fio_to_newlib_ino_t() + +// these defines are good enough for now (to save code size) as they +// are the same functions in practice +#define gdbfileio_fio_to_newlib_nlink_t gdbfileio_fio_to_newlib_ino_t +#define gdbfileio_fio_to_newlib_uid_t gdbfileio_fio_to_newlib_ino_t +#define gdbfileio_fio_to_newlib_gid_t gdbfileio_fio_to_newlib_ino_t +#define gdbfileio_fio_to_newlib_off_t gdbfileio_fio_to_newlib_long_t + + +// this function is commonly used by most functions to handle everything +// once the packet has been constructed. It doesn't have to be used - it's +// just nice to keep this in one place for maintenance reasons. +static int +gdbfileio_common_sendpkt( char *buf, int *sig ) +{ + int status; + + __putpacket( buf ); + + do { + __getpacket( __remcomInBuffer ); + status = __process_packet( __remcomInBuffer ); + } while ( status == 0 ); + + if ( __fileio_ctrlc_set ) + *sig = SIGINT; + if ( !__fileio_retcode_set ) // deal with protocol failure + return -FILEIO_EINVAL; + if ( __fileio_retcode < 0 && __fileio_errno_set ) + return -__fileio_errno; + else + return __fileio_retcode; +} // gdbfileio_common_sendpkt() + +// deal with a received F packet. This is called from __process_packet in +// generic-stub.c +__externC void +cyg_hal_gdbfileio_process_F_packet( char *packet, + char *__remcomOutBuffer ) +{ + // Reply packet structure: + // F<retcode>[,<errno>[,<Ctrl-C flag>]][;<call specific attachment>] + + char *p = &packet[1]; + cyg_bool minus = false; + target_register_t temptrt; + + __fileio_retcode_set = __fileio_errno_set = __fileio_ctrlc_set = false; + + if (*p == '-') { + minus = true; + p++; + } + + __hexToInt( &p, &temptrt ); + __fileio_retcode = minus ? -(int)temptrt : (int)temptrt; + __fileio_retcode_set = true; + + if ( *p++ == ',' ) { + // get errno + __hexToInt( &p, &temptrt ); + __fileio_errno = (int)temptrt; + __fileio_errno_set = true; + if ( *p++ == ',' ) { + if ( *p == 'C' ) { + __fileio_ctrlc_set = true; + } + } + } + // ignore anything afterwards (e.g. call specific attachment) for now + +} // cyg_hal_gdbfileio_process_F_packet() + +__externC int +cyg_hal_gdbfileio_open( const char *name, int flags, int mode, int *sig ) +{ + size_t namelen; + unsigned int i=0; + fio_mode_t fmode; + fio_int_t fflags; + + // clear out unsupported flags/modes, as per the spec + flags &= FILEIO_O_SUPPORTED; + mode &= FILEIO_S_SUPPORTED; + + gdbfileio_newlib_to_fio_int_t( &flags, &fflags ); + gdbfileio_newlib_to_fio_mode_t( &mode, &fmode ); + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'o'; + __remcomOutBuffer[i++] = 'p'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = 'n'; + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)name, + sizeof(name)*8 ); + // i now points after the parameter + __remcomOutBuffer[i++] = '/'; + namelen = strlen( name )+1; // includes '\0' + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)namelen, + sizeof(namelen)*8 ); + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&fflags, &__remcomOutBuffer[i], sizeof(fflags) ); + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&fmode, &__remcomOutBuffer[i], sizeof(fmode) ); + __remcomOutBuffer[i] = 0; + + return gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); +} // cyg_hal_gdbfileio_open() + +__externC int +cyg_hal_gdbfileio_close( int fd, int *sig ) +{ + unsigned int i=0; + fio_int_t ffd; + + gdbfileio_newlib_to_fio_int_t( &fd, &ffd ); + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'c'; + __remcomOutBuffer[i++] = 'l'; + __remcomOutBuffer[i++] = 'o'; + __remcomOutBuffer[i++] = 's'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&ffd, &__remcomOutBuffer[i], sizeof(ffd) ); + // i now points after the parameter + __remcomOutBuffer[i] = 0; + + return gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); +} // cyg_hal_gdbfileio_close() + +__externC int +cyg_hal_gdbfileio_read( int fd, void *buf, size_t count, int *sig ) +{ + unsigned int i=0; + fio_int_t ffd; + fio_uint_t fcount; + unsigned int uicount = (unsigned int)count; + + gdbfileio_newlib_to_fio_int_t( &fd, &ffd ); + gdbfileio_newlib_to_fio_uint_t( &uicount, &fcount ); + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'r'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = 'a'; + __remcomOutBuffer[i++] = 'd'; + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&ffd, &__remcomOutBuffer[i], sizeof(ffd) ); + // i now points after the parameter + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)buf, + sizeof(buf)*8 ); + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&fcount, &__remcomOutBuffer[i], sizeof(fcount) ); + __remcomOutBuffer[i] = 0; + + return gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); +} // cyg_hal_gdbfileio_read() + +__externC int +cyg_hal_gdbfileio_write( int fd, const void *buf, size_t count, int *sig ) +{ + unsigned int i=0; + fio_int_t ffd; + fio_uint_t fcount; + unsigned int uicount = (unsigned int)count; + + gdbfileio_newlib_to_fio_int_t( &fd, &ffd ); + gdbfileio_newlib_to_fio_uint_t( &uicount, &fcount ); + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'w'; + __remcomOutBuffer[i++] = 'r'; + __remcomOutBuffer[i++] = 'i'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&ffd, &__remcomOutBuffer[i], sizeof(ffd) ); + // i now points after the parameter + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)buf, + sizeof(buf)*8 ); + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&fcount, &__remcomOutBuffer[i], sizeof(fcount) ); + __remcomOutBuffer[i] = 0; + + return gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); +} // cyg_hal_gdbfileio_write() + +__externC int +cyg_hal_gdbfileio_lseek( int fd, /* off_t */ long offset, int whence, int *sig ) +{ + unsigned int i=0; + fio_int_t ffd; + fio_long_t foffset; + fio_int_t fwhence; + + gdbfileio_newlib_to_fio_int_t( &fd, &ffd ); + gdbfileio_newlib_to_fio_long_t( &offset, &foffset ); + gdbfileio_newlib_to_fio_int_t( &whence, &fwhence ); + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'l'; + __remcomOutBuffer[i++] = 's'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = 'k'; + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&ffd, &__remcomOutBuffer[i], sizeof(ffd) ); + // i now points after the parameter + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&foffset, &__remcomOutBuffer[i], + sizeof(foffset) ); + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&fwhence, &__remcomOutBuffer[i], + sizeof(fwhence) ); + __remcomOutBuffer[i] = 0; + + return gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); +} // cyg_hal_gdbfileio_lseek() + +__externC int +cyg_hal_gdbfileio_rename( const char *oldpath, const char *newpath, int *sig ) +{ + unsigned int i=0; + size_t namelen; + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'r'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = 'n'; + __remcomOutBuffer[i++] = 'a'; + __remcomOutBuffer[i++] = 'm'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)oldpath, + sizeof(oldpath)*8 ); + // i now points after the parameter + __remcomOutBuffer[i++] = '/'; + namelen = strlen( oldpath )+1; // includes '\0' + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)namelen, + sizeof(namelen)*8 ); + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)newpath, + sizeof(newpath)*8 ); + // i now points after the parameter + __remcomOutBuffer[i++] = '/'; + namelen = strlen( newpath )+1; // includes '\0' + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)namelen, + sizeof(namelen)*8 ); + __remcomOutBuffer[i] = 0; + + return gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); +} // cyg_hal_gdbfileio_rename() + +__externC int +cyg_hal_gdbfileio_unlink( const char *pathname, int *sig ) +{ + unsigned int i=0; + size_t namelen; + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'u'; + __remcomOutBuffer[i++] = 'n'; + __remcomOutBuffer[i++] = 'l'; + __remcomOutBuffer[i++] = 'i'; + __remcomOutBuffer[i++] = 'n'; + __remcomOutBuffer[i++] = 'k'; + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)pathname, + sizeof(pathname)*8 ); + // i now points after the parameter + __remcomOutBuffer[i++] = '/'; + namelen = strlen( pathname )+1; // includes '\0' + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)namelen, + sizeof(namelen)*8 ); + __remcomOutBuffer[i] = 0; + + return gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); +} // cyg_hal_gdbfileio_unlink() + +__externC int +cyg_hal_gdbfileio_isatty( int fd, int *sig ) +{ + unsigned int i=0; + fio_int_t ffd; + + gdbfileio_newlib_to_fio_int_t( &fd, &ffd ); + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'i'; + __remcomOutBuffer[i++] = 's'; + __remcomOutBuffer[i++] = 'a'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = 'y'; + __remcomOutBuffer[i++] = ','; + i += chars_to_hex( (char *)&ffd, &__remcomOutBuffer[i], sizeof(ffd) ); + // i now points after the parameter + __remcomOutBuffer[i] = 0; + + return gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); +} // cyg_hal_gdbfileio_isatty() + +__externC int +cyg_hal_gdbfileio_system( const char *command, int *sig ) +{ + unsigned int i=0; + size_t namelen; + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 's'; + __remcomOutBuffer[i++] = 'y'; + __remcomOutBuffer[i++] = 's'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = 'm'; + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)command, + sizeof(command)*8 ); + // i now points after the parameter + __remcomOutBuffer[i++] = '/'; + namelen = strlen( command )+1; // includes '\0' + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)namelen, + sizeof(namelen)*8 ); + __remcomOutBuffer[i] = 0; + + return gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); +} // cyg_hal_gdbfileio_system() + +__externC int +cyg_hal_gdbfileio_gettimeofday( void *tv, void *tz, int *sig ) +{ + unsigned int i=0; + struct newlib_timeval *ntv = (struct newlib_timeval *)tv; + struct fio_timeval ftv; + int rc; + + // protocol doesn't support non-null timezone. Just enforce it here. + if (NULL != tz) + return -FILEIO_EINVAL; + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'g'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = 'i'; + __remcomOutBuffer[i++] = 'm'; + __remcomOutBuffer[i++] = 'e'; + __remcomOutBuffer[i++] = 'o'; + __remcomOutBuffer[i++] = 'f'; + __remcomOutBuffer[i++] = 'd'; + __remcomOutBuffer[i++] = 'a'; + __remcomOutBuffer[i++] = 'y'; + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)&ftv, + sizeof(&ftv)*8 ); + __remcomOutBuffer[i++] = ','; + __remcomOutBuffer[i++] = '0'; // tzptr + __remcomOutBuffer[i] = 0; + + rc = gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); + + // now ftv should have its contents filled + gdbfileio_fio_to_newlib_time_t( &ftv.tv_sec, &ntv->tv_sec ); + gdbfileio_fio_to_newlib_long_t( &ftv.tv_usec, &ntv->tv_usec ); + + return rc; +} // cyg_hal_gdbfileio_gettimeofday() + +__externC int +cyg_hal_gdbfileio_stat( const char *pathname, struct newlib_stat *buf, + int *sig ) +{ + unsigned int i=0; + int rc; + size_t namelen; + struct fio_stat fbuf; + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 's'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = 'a'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)pathname, + sizeof(pathname)*8 ); + // i now points after the parameter + __remcomOutBuffer[i++] = '/'; + namelen = strlen( pathname )+1; // includes '\0' + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)namelen, + sizeof(namelen)*8 ); + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)&fbuf, + sizeof(&fbuf)*8 ); + __remcomOutBuffer[i] = 0; + + rc = gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); + + // now fbuf should have its contents filled + gdbfileio_fio_to_newlib_dev_t( &fbuf.st_dev, &buf->st_dev ); + gdbfileio_fio_to_newlib_ino_t( &fbuf.st_ino, &buf->st_ino ); + gdbfileio_fio_to_newlib_mode_t( &fbuf.st_mode, &buf->st_mode ); + gdbfileio_fio_to_newlib_nlink_t( &fbuf.st_nlink, &buf->st_nlink ); + gdbfileio_fio_to_newlib_uid_t( &fbuf.st_uid, &buf->st_uid ); + gdbfileio_fio_to_newlib_gid_t( &fbuf.st_gid, &buf->st_gid ); + gdbfileio_fio_to_newlib_dev_t( &fbuf.st_rdev, &buf->st_rdev ); + gdbfileio_fio_to_newlib_off_t( &fbuf.st_size, &buf->st_size ); + gdbfileio_fio_to_newlib_off_t( &fbuf.st_size, &buf->st_size ); + gdbfileio_fio_to_newlib_off_t( &fbuf.st_size, &buf->st_size ); + gdbfileio_fio_to_newlib_off_t( &fbuf.st_size, &buf->st_size ); +#if !defined(__svr4__) || defined(__PPC__) || defined(__sun__) + gdbfileio_fio_to_newlib_long_t( &fbuf.st_blksize, &buf->st_blksize ); + gdbfileio_fio_to_newlib_long_t( &fbuf.st_blocks, &buf->st_blocks ); +#endif + gdbfileio_fio_to_newlib_time_t( &fbuf.st_atime, &buf->st_atime ); + gdbfileio_fio_to_newlib_time_t( &fbuf.st_mtime, &buf->st_mtime ); + gdbfileio_fio_to_newlib_time_t( &fbuf.st_ctime, &buf->st_ctime ); + + return rc; +} // cyg_hal_gdbfileio_stat() + +__externC int +cyg_hal_gdbfileio_fstat( int fd, struct newlib_stat *buf, int *sig ) +{ + unsigned int i=0; + int rc; + struct fio_stat fbuf; + + __remcomOutBuffer[i++] = 'F'; + __remcomOutBuffer[i++] = 'f'; + __remcomOutBuffer[i++] = 's'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = 'a'; + __remcomOutBuffer[i++] = 't'; + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)fd, + sizeof(fd)*8 ); + // i now points after the parameter + __remcomOutBuffer[i++] = ','; + i += __intToHex( &__remcomOutBuffer[i], (target_register_t)&fbuf, + sizeof(&fbuf)*8 ); + __remcomOutBuffer[i] = 0; + + rc = gdbfileio_common_sendpkt( __remcomOutBuffer, sig ); + + // now fbuf should have its contents filled + gdbfileio_fio_to_newlib_dev_t( &fbuf.st_dev, &buf->st_dev ); + gdbfileio_fio_to_newlib_ino_t( &fbuf.st_ino, &buf->st_ino ); + gdbfileio_fio_to_newlib_mode_t( &fbuf.st_mode, &buf->st_mode ); + gdbfileio_fio_to_newlib_nlink_t( &fbuf.st_nlink, &buf->st_nlink ); + gdbfileio_fio_to_newlib_uid_t( &fbuf.st_uid, &buf->st_uid ); + gdbfileio_fio_to_newlib_gid_t( &fbuf.st_gid, &buf->st_gid ); + gdbfileio_fio_to_newlib_dev_t( &fbuf.st_rdev, &buf->st_rdev ); + gdbfileio_fio_to_newlib_off_t( &fbuf.st_size, &buf->st_size ); + gdbfileio_fio_to_newlib_off_t( &fbuf.st_size, &buf->st_size ); + gdbfileio_fio_to_newlib_off_t( &fbuf.st_size, &buf->st_size ); + gdbfileio_fio_to_newlib_off_t( &fbuf.st_size, &buf->st_size ); +#if !defined(__svr4__) || defined(__PPC__) || defined(__sun__) + gdbfileio_fio_to_newlib_long_t( &fbuf.st_blksize, &buf->st_blksize ); + gdbfileio_fio_to_newlib_long_t( &fbuf.st_blocks, &buf->st_blocks ); +#endif + gdbfileio_fio_to_newlib_time_t( &fbuf.st_atime, &buf->st_atime ); + gdbfileio_fio_to_newlib_time_t( &fbuf.st_mtime, &buf->st_mtime ); + gdbfileio_fio_to_newlib_time_t( &fbuf.st_ctime, &buf->st_ctime ); + + return rc; +} // cyg_hal_gdbfileio_fstat() + +/* EOF gdb-fileio.c */ diff --git a/ecos/packages/hal/common/current/src/gdb-fileio.h b/ecos/packages/hal/common/current/src/gdb-fileio.h new file mode 100644 index 0000000..8e22d98 --- /dev/null +++ b/ecos/packages/hal/common/current/src/gdb-fileio.h @@ -0,0 +1,139 @@ +/* gdb-fileio.h. + Contains definitions used inside of the File I/O facility. + + Copyright 2002 Free Software Foundation, Inc. + +*/ + +#ifndef _GDB_FILEIO_H_ +#define _GDB_FILEIO_H_ + +#include <sys/types.h> + +/* The following flags are defined to be independent of the host + as well as the target side implementation of these constants. + All constants are defined with a leading FILEIO_ in the name + to allow the usage of these constants together with the + corresponding implementation dependent constants in one module. */ + +/* open(2) flags */ +#define FILEIO_O_RDONLY 0x0 +#define FILEIO_O_WRONLY 0x1 +#define FILEIO_O_RDWR 0x2 +#define FILEIO_O_APPEND 0x8 +#define FILEIO_O_CREAT 0x200 +#define FILEIO_O_TRUNC 0x400 +#define FILEIO_O_EXCL 0x800 +#define FILEIO_O_BINARY 0x10000 +#define FILEIO_O_TEXT 0x20000 +#define FILEIO_O_SUPPORTED (FILEIO_O_RDONLY | FILEIO_O_WRONLY| \ + FILEIO_O_RDWR | FILEIO_O_APPEND| \ + FILEIO_O_CREAT | FILEIO_O_TRUNC| \ + FILEIO_O_EXCL | FILEIO_O_BINARY | \ + FILEIO_O_TEXT ) + +/* mode_t bits */ +#define FILEIO_S_IFREG 0100000 +#define FILEIO_S_IFDIR 040000 +#define FILEIO_S_IFCHR 020000 +#define FILEIO_S_IRUSR 0400 +#define FILEIO_S_IWUSR 0200 +#define FILEIO_S_IXUSR 0100 +#define FILEIO_S_IRWXU 0700 +#define FILEIO_S_IRGRP 040 +#define FILEIO_S_IWGRP 020 +#define FILEIO_S_IXGRP 010 +#define FILEIO_S_IRWXG 070 +#define FILEIO_S_IROTH 04 +#define FILEIO_S_IWOTH 02 +#define FILEIO_S_IXOTH 01 +#define FILEIO_S_IRWXO 07 +#define FILEIO_S_SUPPORTED (FILEIO_S_IFREG|FILEIO_S_IFDIR| \ + FILEIO_S_IRWXU|FILEIO_S_IRWXG| \ + FILEIO_S_IRWXO) + +/* lseek(2) flags */ +#define FILEIO_SEEK_SET 0 +#define FILEIO_SEEK_CUR 1 +#define FILEIO_SEEK_END 2 + +/* errno values */ +#define FILEIO_EPERM 1 +#define FILEIO_ENOENT 2 +#define FILEIO_EINTR 4 +#define FILEIO_EIO 5 +#define FILEIO_EBADF 9 +#define FILEIO_EACCES 13 +#define FILEIO_EFAULT 14 +#define FILEIO_EBUSY 16 +#define FILEIO_EEXIST 17 +#define FILEIO_ENODEV 19 +#define FILEIO_ENOTDIR 20 +#define FILEIO_EISDIR 21 +#define FILEIO_EINVAL 22 +#define FILEIO_ENFILE 23 +#define FILEIO_EMFILE 24 +#define FILEIO_EFBIG 27 +#define FILEIO_ENOSPC 28 +#define FILEIO_ESPIPE 29 +#define FILEIO_EROFS 30 +#define FILEIO_ENOSYS 88 +#define FILEIO_ENAMETOOLONG 91 +#define FILEIO_EUNKNOWN 9999 + +/* limits */ +#define FILEIO_INT_MIN -2147483648L +#define FILEIO_INT_MAX 2147483647L +#define FILEIO_UINT_MAX 4294967295UL +#define FILEIO_LONG_MIN -9223372036854775808LL +#define FILEIO_LONG_MAX 9223372036854775807LL +#define FILEIO_ULONG_MAX 18446744073709551615ULL + +/* Integral types as used in protocol. */ +#if 0 +typedef __int32_t fio_int_t; +typedef __uint32_t fio_uint_t, fio_mode_t, fio_time_t; +typedef __int64_t fio_long_t; +typedef __uint64_t fio_ulong_t; +#endif + +#define FIO_INT_LEN 4 +#define FIO_UINT_LEN 4 +#define FIO_MODE_LEN 4 +#define FIO_TIME_LEN 4 +#define FIO_LONG_LEN 8 +#define FIO_ULONG_LEN 8 + +typedef char fio_int_t[FIO_INT_LEN]; +typedef char fio_uint_t[FIO_UINT_LEN]; +typedef char fio_mode_t[FIO_MODE_LEN]; +typedef char fio_time_t[FIO_TIME_LEN]; +typedef char fio_long_t[FIO_LONG_LEN]; +typedef char fio_ulong_t[FIO_ULONG_LEN]; + +/* Struct stat as used in protocol. For complete independence + of host/target systems, it's defined as an array with offsets + to the members. */ + +struct fio_stat { + fio_uint_t st_dev; + fio_uint_t st_ino; + fio_mode_t st_mode; + fio_uint_t st_nlink; + fio_uint_t st_uid; + fio_uint_t st_gid; + fio_uint_t st_rdev; + fio_ulong_t st_size; + fio_ulong_t st_blksize; + fio_ulong_t st_blocks; + fio_time_t st_atime; + fio_time_t st_mtime; + fio_time_t st_ctime; +}; + +struct fio_timeval { + fio_time_t tv_sec; + fio_long_t tv_usec; +}; + +#endif /* _GDB_FILEIO_H_ */ diff --git a/ecos/packages/hal/common/current/src/generic-stub.c b/ecos/packages/hal/common/current/src/generic-stub.c new file mode 100644 index 0000000..724cc4d --- /dev/null +++ b/ecos/packages/hal/common/current/src/generic-stub.c @@ -0,0 +1,2057 @@ +#include "board.h" + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +/* Eventually, this should default to ON */ +#if USE_GDBSTUB_PROTOTYPES +#include "stub-tservice.h" +#include "generic-stub.h" +#else +// Function declarations (prevents compiler warnings) +int stubhex (unsigned char ch); +static void unlock_thread_scheduler (void); +static uint32 crc32 (target_addr_t mem, int len, uint32 crc); +#endif + +#include "thread-pkts.h" + /* Defines function macros if thread support is not selected in board.h */ + +#ifdef __ECOS__ +char GDB_stubs_version[] CYGBLD_ATTRIB_WEAK = + "eCos GDB stubs - built " __DATE__ " / " __TIME__; +#endif + +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + +****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for SPARC by Stu Grossman, Red Hat. + * Modified for generic CygMON stub support by Bob Manson, Red Hat. + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps () is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint (). Breakpoint () + * simulates a breakpoint by executing a trap #1. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * bBB..BB Set baud rate to BB..BB OK or BNN, then sets + * baud rate + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $<packet info>#<checksum>. + * + * where + * <packet info> :: <characters representing the command or response> + * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#ifdef __ECOS__ + +// We cannot share memcpy and memset with the rest of the system since +// the user may want to step through it. +static inline void* +_memcpy(void* dest, void* src, int size) +{ + unsigned char* __d = (unsigned char*) dest; + unsigned char* __s = (unsigned char*) src; + + while(size--) + *__d++ = *__s++; + + return dest; +} + +static inline void* +_memset(void* s, int c, int size) +{ + unsigned char* __s = (unsigned char*) s; + unsigned char __c = (unsigned char) c; + + while(size--) + *__s++ = __c; + + return s; +} + +#else +#include <string.h> +#include <signal.h> +#define _memcpy memcpy +#define _memset memset +#endif // __ECOS__ + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ +/* at least NUMREGBYTES*2 are needed for register packets */ +#ifdef __ECOS__ +#ifdef NUMREGBYTES +#define BUFMAX (32 + (NUMREGBYTES*2)) +#else +#define BUFMAX 2048 +#endif +#else +#define BUFMAX 2048 +#endif + +static int initialized = 0; /* !0 means we've been initialized */ + +static int process_exception (int sigval); +static void do_nothing (void); /* and do it gracefully */ +static int syscall_do_nothing (int); + +#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS +void __free_program_args (void); +static char *__add_program_arg (int argnum, uint32 arglen); +#endif + +volatile __PFI __process_exception_vec = process_exception; +volatile __PFV __process_exit_vec = do_nothing; +volatile __PFI __process_syscall_vec = syscall_do_nothing; +volatile __PFI __process_signal_vec = NULL; +volatile __PFV __init_vec = NULL; +volatile __PFV __cleanup_vec = NULL; + +static const char hexchars[] = "0123456789abcdef"; + +static void process_query (char *pkt); +static void process_set (char *pkt); + +char +__tohex (int c) +{ + return hexchars [c & 15]; +} + +#define __tohex(c) hexchars[(c) & 15] + +#ifndef NUMREGS_GDB +#define NUMREGS_GDB NUMREGS +#endif + +/* One pushback character. */ +int ungot_char = -1; + +static int +readDebugChar (void) +{ + if (ungot_char > 0) + { + int result = ungot_char; + ungot_char = -1; + return result; + } + else + return getDebugChar (); +} + +/* Convert ch from a hex digit to an int. */ + +int +stubhex (ch) + unsigned char ch; +{ + if (ch >= 'a' && ch <= 'f') + return ch-'a'+10; + if (ch >= '0' && ch <= '9') + return ch-'0'; + if (ch >= 'A' && ch <= 'F') + return ch-'A'+10; + return -1; +} + +void +__getpacket (buffer) + char *buffer; +{ + struct gdb_packet packet; + int res; + + packet.state = 0; + packet.contents = buffer; + packet.err = 0; + while ((res = __add_char_to_packet (readDebugChar () & 0xff, &packet)) != 1) { + if (res == -2) { + putDebugChar ('-'); // Tell host packet was not processed + // Reset for the next packet + packet.state = 0; + packet.err = 0; + } + } +} + +int +__add_char_to_packet (ch, packet) + unsigned int ch; + struct gdb_packet *packet; +{ + if (packet->state == 0) + { + if (ch == '$') + { + packet->state = 1; + packet->length = 0; + packet->checksum = 0; + packet->xmitcsum = -1; + } + return 0; + } + + if (packet->state == 1) + { + if (packet->length == BUFMAX) + { + packet->state = 0; + packet->err = 1; + } + else if (ch == '#') + { + packet->contents[packet->length] = 0; + packet->state = 2; + } + else + { + packet->checksum += ch; + packet->contents[packet->length++] = ch; + } + return 0; + } + + if (packet->state == 2) + { + packet->xmitcsum = stubhex (ch) << 4; + packet->state = 3; + return 0; + } + + if (packet->state == 3) + { + packet->xmitcsum |= stubhex (ch); + if (packet->err) { + // Packet was too long - just tell the consumer + return -2; + } + if ((packet->checksum & 255) != packet->xmitcsum) + { + putDebugChar ('-'); /* failed checksum */ + packet->state = 0; + return -1; + } + else + { + putDebugChar ('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (packet->contents[2] == ':') + { + uint32 count = packet->length; + uint32 i; + putDebugChar (packet->contents[0]); + putDebugChar (packet->contents[1]); + /* remove sequence chars from buffer */ + for (i=3; i <= count; i++) + packet->contents[i-3] = packet->contents[i]; + } + return 1; + } + } + /* We should never get here. */ + packet->state = 0; + return -1; +} + +/* send the packet in buffer. */ + +void +__putpacket (buffer) + char *buffer; +{ + unsigned char checksum; + uint32 count; + unsigned char ch; + + /* $<packet info>#<checksum>. */ + do + { + putDebugChar ('$'); + checksum = 0; + count = 0; + + while ((ch = buffer[count])) + { + putDebugChar (ch); + checksum += ch; + count += 1; + } + + putDebugChar ('#'); + putDebugChar (hexchars[(checksum >> 4) & 0xf]); + putDebugChar (hexchars[checksum & 0xf]); + + } + while ((readDebugChar () & 0x7f) != '+'); +} + +char __remcomInBuffer[BUFMAX]; +char __remcomOutBuffer[BUFMAX]; + +/* Indicate to caller of mem2hex or hex2mem that there has been an + error. */ +volatile int __mem_fault = 0; + + +#ifndef TARGET_HAS_OWN_MEM_FUNCS +/* + * _target_readmem_hook / _target_writemem_hook: + * Allow target to get involved in reading/writing memory. + * + * If these hooks are defined by the target, they will be + * called for each user program memory access. Otherwise, the stub + * will simply dereference a pointer to access user program memory. + */ + +unsigned char (*_target_readmem_hook) (unsigned char* addr); +void (*_target_writemem_hook) (unsigned char* addr, + unsigned char value); + +static unsigned char +get_target_byte (volatile unsigned char *address) +{ + if (_target_readmem_hook) /* target needs to control memory access */ + return _target_readmem_hook ((unsigned char *) address); + else + return *address; +} + +static void +put_target_byte (volatile unsigned char *address, unsigned char value) +{ + if (_target_writemem_hook) /* target needs to control memory access */ + _target_writemem_hook ((unsigned char *) address, value); + else + *address = value; +} + +/* These are the "arguments" to __do_read_mem and __do_write_mem, + which are passed as globals to avoid squeezing them thru + __set_mem_fault_trap. */ + +static volatile target_register_t memCount; +static volatile unsigned char *memSrc, *memDst; + +/* + * __do_read_mem: + * Copy from target memory to trusted memory. + */ + +static void +__do_read_mem (void) +{ + __mem_fault = 0; + while (memCount) + { + unsigned char ch = get_target_byte (memSrc++); + + if (__mem_fault) + return; + *memDst++ = ch; + memCount--; + } +} + +/* + * __do_write_mem: + * Copy from trusted memory to target memory. + */ + +static void +__do_write_mem (void) +{ + __mem_fault = 0; + while (memCount) + { + unsigned char ch = *memSrc++; + + put_target_byte (memDst++, ch); + if (__mem_fault) + return; + memCount--; + } +} + +/* + * __read_mem_safe: + * Get contents of target memory, abort on error. + */ + +int +__read_mem_safe (void *dst, target_register_t src, int count) +{ + memCount = count; + memSrc = (unsigned char *) src; + memDst = (unsigned char *) dst; + __set_mem_fault_trap (__do_read_mem); + return count - memCount; /* return number of bytes successfully read */ +} + +/* + * __write_mem_safe: + * Set contents of target memory, abort on error. + */ + +int +__write_mem_safe (unsigned char *src, target_register_t dst, int count) +{ + memCount = count; + memSrc = (unsigned char *) src; + memDst = (unsigned char *) dst; + __set_mem_fault_trap (__do_write_mem); + return count - memCount; /* return number of bytes successfully read */ +} + +#endif /* TARGET_HAS_OWN_MEM_FUNCS */ + +/* These are the "arguments" to __mem2hex_helper and __hex2mem_helper, + which are passed as globals to avoid squeezing them thru + __set_mem_fault_trap. */ + +static int hexMemCount; +static char *hexMemSrc, *hexMemDst; +static int may_fault_mode; +#ifdef TARGET_HAS_HARVARD_MEMORY +static int progMem; +#endif + +/* Hamburger helper? */ +static void +__mem2hex_helper (void) +{ + union { + unsigned long long_val; + unsigned char bytes[sizeof(long)]; + } val; + int len, i; + unsigned char ch; + __mem_fault = 0; + while (hexMemCount > 0) { + if (may_fault_mode) { + if ((hexMemCount >= sizeof(long)) && + (((target_register_t)hexMemSrc & (sizeof(long)-1)) == 0)) { + // Should be safe to access via a long + len = sizeof(long); + } else if ((hexMemCount >= sizeof(short)) && + (((target_register_t)hexMemSrc & (sizeof(short)-1)) == 0)) { + // Should be safe to access via a short + len = sizeof(short); + } else { + len = 1; + } +#ifdef TARGET_HAS_HARVARD_MEMORY + if (progMem) + __read_progmem_safe(&val.bytes[0], hexMemSrc, len); + else +#endif + __read_mem_safe(&val.bytes[0], hexMemSrc, len); + } else { + len = 1; + val.bytes[0] = *hexMemSrc; + } + if (__mem_fault) + return; + + for (i = 0; i < len; i++) { + ch = val.bytes[i]; + *(hexMemDst++) = hexchars[(ch >> 4) & 0xf]; + if (__mem_fault) + return; + *(hexMemDst++) = hexchars[ch & 0xf]; + if (__mem_fault) + return; + } + hexMemCount -= len; + hexMemSrc += len; + } +} + +/* Convert the memory pointed to by MEM into HEX, placing result in BUF. + * Return a pointer to the last char put in buf (NUL). In case of a memory + * fault, return 0. + * If MAY_FAULT is non-zero, then we will handle memory faults by returning + * a 0 (and assume that MEM is a pointer into the user program), else we + * treat a fault like any other fault in the stub (and assume that MEM is + * a pointer into the stub's memory). + */ + +char * +__mem2hex (mem, buf, count, may_fault) + char *mem; + char *buf; + int count; + int may_fault; +{ + hexMemDst = (char *) buf; + hexMemSrc = (char *) mem; + hexMemCount = count; + may_fault_mode = may_fault; +#ifdef TARGET_HAS_HARVARD_MEMORY + progMem = 0; +#endif + + if (may_fault) + { + if (__set_mem_fault_trap (__mem2hex_helper)) + return 0; + } + else + __mem2hex_helper (); + + *hexMemDst = 0; + + return (char *) hexMemDst; +} + +/* Convert the target memory identified by MEM into HEX, placing result in BUF. + * Return a pointer to the last char put in buf (NUL). In case of a memory + * fault, return 0. + */ + +static char * +__mem2hex_safe (target_addr_t mem, char *buf, int count) +{ + hexMemDst = (char *) buf; + hexMemSrc = (char *) TARGET_ADDR_TO_PTR(mem); + hexMemCount = count; + may_fault_mode = 1; +#ifdef TARGET_HAS_HARVARD_MEMORY + progMem = TARGET_ADDR_IS_PROGMEM(mem); +#endif + + if (__set_mem_fault_trap (__mem2hex_helper)) + return 0; + + *hexMemDst = 0; + + return (char *) hexMemDst; +} + + + +static void +__hex2mem_helper (void) +{ + union { + unsigned long long_val; + unsigned char bytes[sizeof(long)]; + } val; + int len, i; + unsigned char ch = '\0'; + + __mem_fault = 0; + while (hexMemCount > 0 && *hexMemSrc) { + if (may_fault_mode) { + if ((hexMemCount >= sizeof(long)) && + (((target_register_t)hexMemDst & (sizeof(long)-1)) == 0)) { + len = sizeof(long); + } else if ((hexMemCount >= sizeof(short)) && + (((target_register_t)hexMemDst & (sizeof(short)-1)) == 0)) { + len = sizeof(short); + } else { + len = 1; + } + } else { + len = 1; + } + + for (i = 0; i < len; i++) { + // Check for short data? + ch = stubhex (*(hexMemSrc++)) << 4; + if (__mem_fault) + return; + ch |= stubhex (*(hexMemSrc++)); + if (__mem_fault) + return; + val.bytes[i] = ch; + } + + if (may_fault_mode) { +#ifdef TARGET_HAS_HARVARD_MEMORY + if (progMem) + __write_progmem_safe (&val.bytes[0], hexMemDst, len); + else +#endif + __write_mem_safe (&val.bytes[0], hexMemDst, len); + } else + *hexMemDst = ch; + + if (__mem_fault) + return; + hexMemCount -= len; + hexMemDst += len; + } +} + +/* Convert COUNT bytes of the hex array pointed to by BUF into binary + to be placed in MEM. Return a pointer to the character AFTER the + last byte written. + + If MAY_FAULT is set, we will return a non-zero value if a memory + fault occurs (and we assume that MEM is a pointer into the user + program). Otherwise, we will take a trap just like any other memory + fault (and assume that MEM points into the stub's memory). */ + +char * +__hex2mem (buf, mem, count, may_fault) + char *buf; + char *mem; + int count; + int may_fault; +{ + hexMemSrc = (char *) buf; + hexMemDst = (char *) mem; + hexMemCount = count; + may_fault_mode = may_fault; +#ifdef TARGET_HAS_HARVARD_MEMORY + progMem = 0; +#endif + + if (may_fault) + { + if (__set_mem_fault_trap (__hex2mem_helper)) + return 0; + } + else + __hex2mem_helper (); + + return (char *) hexMemDst; +} + +/* Convert COUNT bytes of the hex array pointed to by BUF into binary + to be placed in target MEM. Return a pointer to the character AFTER + the last byte written. +*/ +char * +__hex2mem_safe (char *buf, target_addr_t mem, int count) +{ + hexMemSrc = (char *) buf; + hexMemDst = (char *) TARGET_ADDR_TO_PTR(mem); + hexMemCount = count; + may_fault_mode = 1; +#ifdef TARGET_HAS_HARVARD_MEMORY + progMem = TARGET_ADDR_IS_PROGMEM(mem); +#endif + + if (__set_mem_fault_trap (__hex2mem_helper)) + return 0; + + return (char *) hexMemDst; +} + + +void +set_debug_traps (void) +{ + __install_traps (); + initialized = 1; /* FIXME: Change this to dbg_stub_initialized */ +} + +/* + * While we find nice hex chars, build an int. + * Return number of chars processed. + */ + +unsigned int +__hexToInt (char **ptr, target_register_t *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = stubhex (**ptr); + if (hexValue < 0) + break; + + *intValue = (*intValue << 4) | hexValue; + numChars ++; + + (*ptr)++; + } + + return (numChars); +} + +/* + * While we find nice hex chars, build a target memory address. + * Return number of chars processed. + */ + +unsigned int +__hexToAddr (char **ptr, target_addr_t *val) +{ + int numChars = 0; + int hexValue; + + *val = 0; + + while (**ptr) + { + hexValue = stubhex (**ptr); + if (hexValue < 0) + break; + + *val = (*val << 4) | hexValue; + numChars ++; + + (*ptr)++; + } + + return (numChars); +} + + +/* + * Complement of __hexToInt: take an int of size "numBits", + * convert it to a hex string. Return length of (unterminated) output. + */ + +unsigned int +__intToHex (char *ptr, target_register_t intValue, int numBits) +{ + int numChars = 0; + + if (intValue == 0) + { + *(ptr++) = '0'; + *(ptr++) = '0'; + return 2; + } + + numBits = (numBits + 7) / 8; + while (numBits) + { + int v = (intValue >> ((numBits - 1) * 8)); + if (v || (numBits == 1)) + { + v = v & 255; + *(ptr++) = __tohex ((v / 16) & 15); + *(ptr++) = __tohex (v & 15); + numChars += 2; + } + numBits--; + } + + return (numChars); +} + +#if DEBUG_THREADS +/* + * Kernel Thread Control + * + * If the current thread is set to other than zero (or minus one), + * then ask the kernel to lock it's scheduler so that only that thread + * can run. + */ + +static unsigned char did_lock_scheduler = 0; +static unsigned char did_disable_interrupts = 0; + +/* Pointer to "kernel call" for scheduler control */ +static int (*schedlock_fn) (int, int, long) = stub_lock_scheduler; + +/* Pointer to target stub call for disabling interrupts. + Target stub will initialize this if it can. */ +int (*__disable_interrupts_hook) (int); /* don't initialize here! */ +#endif + +static void +lock_thread_scheduler (int kind) /* "step" or "continue" */ +{ +#if DEBUG_THREADS + int ret = 0; + + /* GDB will signal its desire to run a single thread + by setting _gdb_cont_thread to non-zero / non-negative. */ + if (_gdb_cont_thread <= 0) + return; + + if (schedlock_fn) /* kernel call */ + ret = (*schedlock_fn) (1, kind, _gdb_cont_thread); + + if (ret == 1) + { + did_lock_scheduler = 1; + return; + } + + if (schedlock_fn == 0 || /* no kernel scheduler call */ + ret == -1) /* kernel asks stub to handle it */ + if (__disable_interrupts_hook) /* target stub has capability */ + if ((*__disable_interrupts_hook) (1)) + { + did_disable_interrupts = 1; + return; + } +#endif /* DEBUG_THREADS */ +} + +static void +unlock_thread_scheduler () +{ +#if DEBUG_THREADS + if (did_lock_scheduler) + if (schedlock_fn) /* kernel call */ + { + (*schedlock_fn) (0, 0, _gdb_cont_thread); + /* I could check the return value, but + what would I do if it failed??? */ + did_lock_scheduler = 0; + } + if (did_disable_interrupts) + if (__disable_interrupts_hook) /* target stub call */ + { + (*__disable_interrupts_hook) (0); + /* Again, I could check the return value, but + what would I do if it failed??? */ + did_disable_interrupts = 0; + } +#endif /* DEBUG_THREADS */ +} + +#ifdef CYGPKG_CYGMON +int processing_breakpoint_function = 0; +#endif + +void +__handle_exception (void) +{ + int sigval = 0; + +#ifdef TARGET_HAS_NEXT_STEP + if (! __next_step_done ()) + { + __clear_breakpoints (); + __install_breakpoints (); + __single_step (); + return; + } +#endif + +#ifdef __ECOS__ + // We need to unpack the registers before they are accessed. + if (__cleanup_vec != NULL) + __cleanup_vec (); + +#if defined(CYGSEM_REDBOOT_BSP_SYSCALLS) + // Temporary support for gnupro bsp SWIs + if (__is_bsp_syscall()) + { + sigval = hal_syscall_handler(); + if (sigval <= 0) + { + if (sigval < 0) + __process_exit_vec (); + + if (__init_vec != NULL) + __init_vec (); + return; + } + } +#endif + +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + // Special case for GDB BREAKs. This flag is set by cyg_stub_cleanup. + if (cyg_hal_gdb_break) { + cyg_hal_gdb_break = 0; + sigval = SIGINT; + } +#endif + + // Only compute sigval if it wasn't already computed (in + // hal_syscall_handler or as a result of a GDB async break) + if (0 == sigval) + sigval = __computeSignal (__get_trap_number ()); + +#else // __ECOS__ + /* reply to host that an exception has occurred */ + sigval = __computeSignal (__get_trap_number ()); +#endif // __ECOS__ + + if (__is_breakpoint_function ()) + { +#ifdef CYGPKG_CYGMON + processing_breakpoint_function = 1; +#endif + __skipinst (); + } else { +#ifdef CYGPKG_CYGMON + processing_breakpoint_function = 0; +#endif + } + +#ifndef __ECOS__ + if (__cleanup_vec != NULL) + __cleanup_vec (); +#endif // !__ECOS__ + + __clear_breakpoints (); + + /* Undo effect of previous single step. */ + unlock_thread_scheduler (); + __clear_single_step (); + +#ifdef __ECOS__ + /* Need to flush the data and instruction cache here, as we may have + removed a breakpoint in __single_step - and we may be sharing + some code with the application! */ + + __data_cache (CACHE_FLUSH) ; + __instruction_cache (CACHE_FLUSH) ; +#endif + +#ifdef SIGSYSCALL + if (sigval == SIGSYSCALL) + { + int val; + /* Do the skipinst FIRST. */ +#ifndef SYSCALL_PC_AFTER_INST + __skipinst (); +#endif + val = __process_syscall_vec (__get_syscall_num ()); + if (val < 0) + sigval = -val; + else + sigval = 0; + } + +#endif + + /* Indirect function call to stub, cygmon monitor or other */ + if (sigval != 0) + { + while (__process_exception_vec (sigval)) + { + /* Empty! */ + } + } + + __install_breakpoints (); + + if (__init_vec != NULL) + __init_vec (); +} + +/* + * _get_trace_register_hook: + * This function pointer will be non-zero if the trace component + * wants to intercept requests for register values. + * + * FIXME: evidently I need a new hook for large registers... + */ + +int (*_get_trace_register_hook) (regnames_t, target_register_t *); + +void +stub_format_registers(char *packet, char *ptr) +{ + int regnum; + int sr = 0, er = NUMREGS_GDB; + + if (packet[0] == 'p') + { + target_register_t regno; + char *p = &packet[1]; + if (__hexToInt (&p, ®no)) + { + sr = regno; + er = regno + 1; + } + else + { + strcpy (ptr, "INVALID"); + return; + } + } + + for (regnum = sr; regnum < er; regnum++) + { + /* We need to compensate for the value offset within the + register. */ + char dummyDat[32]; + target_register_t addr; + char *vptr; + int reg_valid = 1; + +#ifdef TARGET_HAS_LARGE_REGISTERS + if (sizeof (target_register_t) < REGSIZE (regnum)) { + get_register_as_bytes (regnum, dummyDat); + vptr = dummyDat; + } else +#endif + { + if (_get_trace_register_hook) + reg_valid = _get_trace_register_hook (regnum, &addr); + else + { + addr = get_register (regnum); +#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING + reg_valid = get_register_valid (regnum); +#endif + } + vptr = ((char *) &addr); + if (sizeof (addr) > REGSIZE(regnum)) { + /* May need to cope with endian-ness */ + +#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN) + vptr += sizeof (addr) - REGSIZE (regnum); +#endif + } else if (sizeof (addr) < REGSIZE (regnum)) { + int off = REGSIZE (regnum) - sizeof (addr); + int x; + char extend_val = 0; + +#ifdef CYGARC_SIGN_EXTEND_REGISTERS + { + unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 + target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); + if ((addr & sign_bit_mask) == sign_bit_mask) + extend_val = ~0; + } +#endif + +#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) + for (x = 0; x < off; x++) + dummyDat[x + sizeof(addr)] = extend_val; + _memcpy (dummyDat, &addr, sizeof (addr)); +#else + for (x = 0; x < off; x++) + dummyDat[x] = extend_val; + _memcpy (dummyDat + off, &addr, sizeof (addr)); +#endif + vptr = dummyDat; + } + } + if (reg_valid) { /* we have a valid reg value */ + ptr = __mem2hex (vptr, ptr, REGSIZE (regnum), 0); + } else { + /* Trace component returned a failure code. + This means that the register value is not available. + We'll fill it with 'x's, and GDB will understand. */ + _memset (ptr, 'x', 2 * REGSIZE (regnum)); + ptr += 2 * REGSIZE (regnum); + } + } +} + +void +stub_update_registers(char *in_ptr, char *out_ptr) +{ + char *ptr = &in_ptr[1]; + int x; + int sr = 0, er = NUMREGS_GDB; + + if (*in_ptr == 'P') { + target_register_t regno; + + if (__hexToInt (&ptr, ®no) && (*ptr++ == '=')) { + + sr = regno; + er = regno + 1; + } else { + strcpy (out_ptr, "P01"); + return; + } + } + + for (x = sr; x < er; x++) { + target_register_t value = 0; + char *vptr; + +#ifdef TARGET_HAS_LARGE_REGISTERS + if (sizeof (target_register_t) < REGSIZE (x)) { + char dummyDat [32]; + + __hex2mem (ptr, dummyDat, REGSIZE (x), 0); + put_register_as_bytes (x, dummyDat); + } else +#endif + { + vptr = ((char *) &value); +#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN) + vptr += sizeof (value) - REGSIZE (x); +#endif + __hex2mem (ptr, vptr, REGSIZE (x), 0); + put_register (x, value); + } + ptr += REGSIZE (x) * 2; + } + + strcpy (out_ptr, "OK"); +} + +int +__process_packet (char *packet) +{ + int is_binary = 0; +#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) + int is_Z = 0; +#endif + + __remcomOutBuffer[0] = 0; + switch (packet[0]) + { + case '?': + { + int sigval = __computeSignal (__get_trap_number ()); + __remcomOutBuffer[0] = 'S'; + __remcomOutBuffer[1] = hexchars[(sigval >> 4) & 0xf]; + __remcomOutBuffer[2] = hexchars[sigval & 0xf]; + __remcomOutBuffer[3] = 0; + break; + } + +#ifdef __ECOS__ +#if !defined(CYG_HAL_STARTUP_RAM) // Only for ROM based stubs +#if 0 // Disable to avoid conflict with stub-breakpoint z/Z-packets + case 'z': + /* report IO buffer sizes so download can achieve optimal + download speed */ + { + int i; + i = __intToHex (__remcomOutBuffer, BUFMAX, 32); + __remcomOutBuffer[i] = 0; + break; + } +#endif + case 'd': + /* toggle debug flag */ + strcpy(__remcomOutBuffer, GDB_stubs_version); + break; +#endif +#endif // __ECOS__ + + case 'q': + /* general query packet */ + process_query (&packet[1]); + break; + + case 'Q': + /* general set packet */ + process_set (&packet[1]); + break; + + case 'p': /* return the value of a single CPU register */ + case 'g': /* return the value of the CPU registers */ + { + stub_format_registers(&packet[0], __remcomOutBuffer); + break; + } + + case 'A': /* set program arguments */ + { +#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS + if (packet[1] == '\0') + { + __free_program_args (); + strcpy (__remcomOutBuffer, "OK"); + } + else + { + target_register_t arglen, argnum; + char *ptr = &packet[1]; + + while (1) + { + if (__hexToInt (&ptr, &arglen) + && (*ptr++ == ',') + && __hexToInt (&ptr, &argnum) + && (*ptr++ == ',')) + { + if (arglen > 0) + { + char *s = __add_program_arg (argnum, arglen); + if (s != NULL) + { + __hex2mem (ptr, s, arglen, 0); + } + ptr += arglen * 2; + } + + if (*ptr == ',') + ptr++; + else + break; + } + else + break; + } + if (*ptr == '\0') + strcpy (__remcomOutBuffer, "OK"); + else + strcpy (__remcomOutBuffer, "E01"); + } +#else + strcpy (__remcomOutBuffer, "E01"); +#endif + } + break; + + case 'P': + case 'G': /* set the value of the CPU registers - return OK */ + { + char *in_ptr = &packet[0]; + char *out_ptr = __remcomOutBuffer; + stub_update_registers(in_ptr, out_ptr); + break; + } + + case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + /* Try to read %x,%x. */ + { + target_register_t length; + char *ptr = &packet[1]; + target_addr_t addr; + + if (__hexToAddr (&ptr, &addr) + && *ptr++ == ',' + && __hexToInt (&ptr, &length)) + { + if (__mem2hex_safe (addr, __remcomOutBuffer, length)) + break; + + strcpy (__remcomOutBuffer, "E03"); + } + else + strcpy (__remcomOutBuffer, "E01"); + break; + } + + case 'X': + /* XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA */ + is_binary = 1; + /* fall through */ + case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + /* Try to read '%x,%x:'. */ + { + target_register_t length; + char *ptr = &packet[1], buf[128]; + int i; + target_addr_t addr; + + if (__hexToAddr (&ptr, &addr) + && *ptr++ == ',' + && __hexToInt (&ptr, &length) + && *ptr++ == ':') + { + /* GDB sometimes sends an impossible length */ + if (length < 0 || length >= BUFMAX) + strcpy (__remcomOutBuffer, "E01"); + + else if (is_binary) + { + while (length > 0) + { + for (i = 0; i < sizeof(buf) && i < length; i++) + if ((buf[i] = *ptr++) == 0x7d) + buf[i] = 0x20 | (*ptr++ & 0xff); + +#ifdef TARGET_HAS_HARVARD_MEMORY + if (TARGET_ADDR_IS_PROGMEM(addr)) { + if (__write_progmem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i) + break; + } else +#endif + if (__write_mem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i) + break; + + + length -= i; + addr += i; + } + if (length <= 0) + strcpy (__remcomOutBuffer, "OK"); + else + strcpy (__remcomOutBuffer, "E03"); + } + else + { + if (__hex2mem_safe (ptr, addr, length) != NULL) + strcpy (__remcomOutBuffer, "OK"); + else + strcpy (__remcomOutBuffer, "E03"); + } + } + else + strcpy (__remcomOutBuffer, "E02"); + break; + } + + case 'S': + case 's': /* sAA..AA Step from address AA..AA (optional) */ + case 'C': + case 'c': /* cAA..AA Continue at address AA..AA (optional) */ + /* try to read optional parameter, pc unchanged if no parm */ + + { + char *ptr = &packet[1]; + target_addr_t addr; + target_register_t sigval = 0; + + if (packet[0] == 'C' || packet[0] == 'S') + { + __hexToInt (&ptr, &sigval); + if (*ptr == ';') + ptr++; + } + + if (__hexToAddr (&ptr, &addr)) + set_pc ((target_register_t)TARGET_ADDR_TO_PTR(addr)); + + /* Need to flush the instruction cache here, as we may have + deposited a breakpoint, and the icache probably has no way of + knowing that a data ref to some location may have changed + something that is in the instruction cache. */ + +#ifdef __ECOS__ + __data_cache (CACHE_FLUSH) ; +#endif + __instruction_cache (CACHE_FLUSH) ; + + /* If we have a function to handle signals, call it. */ + if (sigval != 0 && __process_signal_vec != NULL) + { + /* If 0 is returned, we either ignored the signal or invoked a user + handler. Otherwise, the user program should die. */ + if (! __process_signal_vec (sigval)) + sigval = 0; + } + + if (sigval != 0) + { + sigval = SIGKILL; /* Always nuke the program */ + __kill_program (sigval); + return 0; + } + +#ifdef __ECOS__ + // CASE 102327 - watchpoints fight with output, so do not step + // through $O packet output routines. +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + if ( cyg_hal_gdb_break_is_set() ) { + packet[0] = 'c'; // Force it to be a "continue" instead of step. + cyg_hal_gdb_running_step = 1; // And tell the hal_stub... + } +#endif +#endif + + /* Set machine state to force a single step. */ + if (packet[0] == 's' || packet[0] == 'S') + { + lock_thread_scheduler (0); /* 0 == single-step */ +#ifdef __ECOS__ + // PR 19845 workaround: + // Make sure the single-step magic affects the correct registers. + _registers = ®isters[0]; +#endif + __single_step (); + } + else + { + lock_thread_scheduler (1); /* 1 == continue */ + } + +#ifdef __ECOS__ + /* Need to flush the data and instruction cache here, as we may have + deposited a breakpoint in __single_step. */ + + __data_cache (CACHE_FLUSH) ; + __instruction_cache (CACHE_FLUSH) ; + hal_flush_output(); +#endif + + return -1; + } + + case 'D' : /* detach */ + __putpacket (__remcomOutBuffer); + /* fall through */ + case 'k' : /* kill the program */ +#ifdef __ECOS__ + hal_flush_output(); +#endif + __process_exit_vec (); + return -1; + + case 'r': /* Reset */ + /* With the next 'k' packet, reset the board */ + __process_exit_vec = &__reset; + break; + + case 'H': + STUB_PKT_CHANGETHREAD (packet+1, __remcomOutBuffer, 300) ; + break ; + case 'T' : + STUB_PKT_THREAD_ALIVE (packet+1, __remcomOutBuffer, 300) ; + break ; + case 'B': + /* breakpoint */ + { + target_register_t addr; + char mode; + char *ptr = &packet[1]; + if (__hexToInt (&ptr, &addr) && *(ptr++) == ',') + { + mode = *(ptr++); + if (mode == 'C') + __remove_breakpoint (addr,0); + else + __set_breakpoint (addr,0); + strcpy (__remcomOutBuffer, "OK"); + } + else + { + strcpy (__remcomOutBuffer, "E01"); + } + break; + } + + case 'b': /* bBB... Set baud rate to BB... */ + { + target_register_t baudrate; + + char *ptr = &packet[1]; + if (!__hexToInt (&ptr, &baudrate)) + { + strcpy (__remcomOutBuffer, "B01"); + break; + } + + __putpacket ("OK"); /* Ack before changing speed */ + __set_baud_rate (baudrate); + break; + } + +#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) && (CYGNUM_HAL_BREAKPOINT_LIST_SIZE > 0) + case 'Z': + is_Z = 1; + case 'z': + { + char *ptr = &packet[1]; + target_register_t ztype, addr, length; + int err; + target_addr_t taddr; + + if (__hexToInt (&ptr, &ztype) && *(ptr++) == ',') + { + if (__hexToAddr (&ptr, &taddr)) + { + if (*(ptr++) == ',') + { + /* When there is a comma, there must be a length */ + if (!__hexToInt (&ptr, &length)) + { + strcpy (__remcomOutBuffer, "E02"); + break; + } + } + else + length = 0; + + addr = (target_register_t)TARGET_ADDR_TO_PTR(taddr); + + switch (ztype) + { + case ZTYPE_SW_BREAKPOINT: + /* sw breakpoint */ + if (is_Z) + err = __set_breakpoint(addr,length); + else + err = __remove_breakpoint(addr,length); + if (!err) + strcpy (__remcomOutBuffer, "OK"); + else + strcpy (__remcomOutBuffer, "E02"); + break; + case ZTYPE_HW_BREAKPOINT: +#if defined(HAL_STUB_HW_BREAKPOINT_LIST_SIZE) && (HAL_STUB_HW_BREAKPOINT_LIST_SIZE > 0) + if (is_Z) + err = __set_hw_breakpoint(addr, length); + else + err = __remove_hw_breakpoint(addr, length); + if (!err) + strcpy (__remcomOutBuffer, "OK"); + else +#endif + strcpy (__remcomOutBuffer, "E02"); + break; + case ZTYPE_HW_WATCHPOINT_WRITE: + case ZTYPE_HW_WATCHPOINT_READ: + case ZTYPE_HW_WATCHPOINT_ACCESS: +#if defined(HAL_STUB_HW_WATCHPOINT_LIST_SIZE) && (HAL_STUB_HW_WATCHPOINT_LIST_SIZE > 0) + if (is_Z) + err = __set_hw_watchpoint(addr, length, ztype); + else + err = __remove_hw_watchpoint(addr, length, ztype); + if (!err) + strcpy (__remcomOutBuffer, "OK"); + else +#endif + strcpy (__remcomOutBuffer, "E02"); + break; + } + } + } + break; + } +#endif // Z packet support +#ifdef CYGPKG_HAL_GDB_FILEIO // File I/O over the GDB remote protocol + case 'F': + { + extern void cyg_hal_gdbfileio_process_F_packet( char *, char *); + cyg_hal_gdbfileio_process_F_packet( packet, __remcomOutBuffer ); + return -1; + } +#endif + default: + __process_target_packet (packet, __remcomOutBuffer, 300); + break; + } + + /* reply to the request */ + __putpacket (__remcomOutBuffer); + return 0; +} + +static void +send_t_packet (int sigval) +{ + __build_t_packet (sigval, __remcomOutBuffer); + __putpacket (__remcomOutBuffer); +} + +/* + * This function does all command procesing for interfacing to gdb. + */ + +static int +process_exception (int sigval) +{ + int status; + + /* Nasty. */ + if (ungot_char < 0) + send_t_packet (sigval); + + do { + __getpacket (__remcomInBuffer); + status = __process_packet (__remcomInBuffer); + } while (status == 0); + + if (status < 0) + return 0; + else + return 1; +} + +void +__send_exit_status (int status) +{ + __remcomOutBuffer[0] = 'W'; + __remcomOutBuffer[1] = hexchars[(status >> 4) & 0xf]; + __remcomOutBuffer[2] = hexchars[status & 0xf]; + __remcomOutBuffer[3] = 0; + __putpacket (__remcomOutBuffer); +} + +/* Read up to MAXLEN bytes from the remote GDB client, and store in DEST + (which is a pointer in the user program). BLOCK indicates what mode + is being used; if it is set, we will wait for MAXLEN bytes to be + entered. Otherwise, the function will return immediately with whatever + bytes are waiting to be read. + + The value returned is the number of bytes read. A -1 indicates that an + error of some sort occurred. */ + +int +__get_gdb_input (target_register_t dest, int maxlen, int block) +{ + char buf[4]; + int len, i; + char d; + + buf[0] = 'I'; + buf[1] = '0'; + buf[2] = block ? '0' : '1'; + buf[3] = 0; + __putpacket (buf); + __getpacket (__remcomInBuffer); + if (__remcomInBuffer[0] != 'I') + return -1; + len = stubhex (__remcomInBuffer[1]) * 16 + stubhex (__remcomInBuffer[2]); + for (i = 0; i < len; i++) + { + d = stubhex (__remcomInBuffer[3 + i * 2]) * 16; + d |= stubhex (__remcomInBuffer[3 + i * 2 + 1]); + __write_mem_safe (&d, (void *)(dest + i), 1); + } + /* Write the trailing \0. */ + d = '\0'; + __write_mem_safe (&d, (void *)(dest + i), 1); + return len; +} + +void +__output_hex_value (target_register_t i) +{ + char buf[32], *ptr=buf+31; + unsigned int x; + + *ptr = 0; + for (x = 0; x < (sizeof (i) * 2); x++) + { + *(--ptr) = hexchars[i & 15]; + i = i >> 4; + } + while (*ptr) + { + putDebugChar (*(ptr++)); + } +} + +/* Write the C-style string pointed to by STR to the GDB comm port. */ +void +__putDebugStr (char *str) +{ + while (*str) + { + putDebugChar (*str); + str++; + } +} + +/* Send STRING_LEN bytes of STR to GDB, using 'O' packets. + STR is assumed to be in the program being debugged. */ + +int +__output_gdb_string (target_register_t str, int string_len) +{ + /* We will arbitrarily limit output packets to less than 400 bytes. */ + static char buf[400]; + int x; + int len; + + if (string_len == 0) + { + /* We can't do strlen on a user pointer. */ + return -1; + } + + len = string_len; + while (len > 0) + { + int packetlen = ((len < 175) ? len : 175); + buf[0] = 'O'; + for (x = 0; x < packetlen; x++) + { + char c; + + __read_mem_safe (&c, (void *)(str + x), 1); + buf[x*2+1] = hexchars[(c >> 4) & 0xf]; + buf[x*2+2] = hexchars[c % 16]; + } + str += x; + len -= x; + buf[x*2+1] = 0; + __putpacket (buf); + } + return string_len; +} + +static void +do_nothing (void) +{ + /* mmmm */ +} + +static int +syscall_do_nothing (int junk) +{ + return 0; +} + +/* Start the stub running. */ +void +__switch_to_stub (void) +{ + __process_exception_vec = process_exception; +#ifdef CYGPKG_CYGMON + // Cygmon will have consumed the '$' character for this packet. + // Let's put one in the unget buffer. + // Actually, Cygmon does an unget, but since it uses different + // unget handling, we need to do this here. + ungetDebugChar('$'); +#endif +} + +#if ! defined(BOARD_SPECIFIC_STUB_INIT) +void +initialize_stub (void) +{ + set_debug_traps (); + /* FIXME: This function should be renamed to specifically init the + hardware required by debug operations. If initHardware is implemented at + all, it should be called before main (). + */ + initHardware () ; + /* This acks any stale packets , NOT an effective solution */ + putDebugChar ('+'); +} +#endif + +void +ungetDebugChar (int c) +{ + ungot_char = c; +} + +void +__kill_program (int sigval) +{ + __remcomOutBuffer[0] = 'X'; + __remcomOutBuffer[1] = hexchars[(sigval >> 4) & 15]; + __remcomOutBuffer[2] = hexchars[sigval & 15]; + __remcomOutBuffer[3] = 0; + __putpacket (__remcomOutBuffer); +} + +#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS +#define MAX_ARG_COUNT 20 +#define MAX_ARGDATA 128 + +static char *program_argv [MAX_ARG_COUNT]; +static int program_argc; +static int last_program_arg; +static char program_argstr [MAX_ARGDATA], *argptr; +static int args_initted = 0; + +void +__free_program_args (void) +{ + last_program_arg = -1; + program_argc = 0; + program_argv [0] = NULL; + argptr = program_argstr; + args_initted = 1; +} + +static char * +__add_program_arg (int argc, uint32 len) +{ + char *res; + + if (! args_initted) + { + __free_program_args (); + } + + if ((argc >= (MAX_ARG_COUNT - 1)) + || ((argptr - program_argstr + len) > MAX_ARGDATA)) + { + return NULL; + } + + if (argc != last_program_arg) + { + if (argc >= program_argc) + { + program_argc = argc + 1; + program_argv [program_argc] = NULL; + } + program_argv [argc] = argptr; + last_program_arg = argc; + } + + res = argptr; + argptr += len; + + return res; +} + +void +__set_program_args (int argc, char **argv) +{ + int x; + + __free_program_args (); + if (argc) + { + for (x = 0; x < argc; x++) + { + uint32 len = strlen (argv[x])+1; + char *s = __add_program_arg (x, len); + + if (s == NULL) + return; + + _memcpy (s, argv[x], len); + } + } +} + +char ** +__get_program_args (target_register_t argcPtr) +{ + if (!args_initted) + { + __free_program_args (); + } + __write_mem_safe ((char *) &program_argc, (void *)argcPtr, sizeof (program_argc)); + return program_argv; +} +#endif + +/* Table used by the crc32 function to calcuate the checksum. */ +#ifdef CYGDBG_HAL_CRCTABLE_LOCATION_RAM +static uint32 crc32_table[256]; +static int tableInit = 0; +#else +static const uint32 crc32_table[256]={ + 0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005, + 0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd, + 0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75, + 0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd, + 0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5, + 0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d, + 0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95, + 0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d, + 0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072, + 0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca, + 0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02, + 0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba, + 0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692, + 0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a, + 0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2, + 0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a, + 0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb, + 0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53, + 0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b, + 0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623, + 0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b, + 0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3, + 0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b, + 0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3, + 0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c, + 0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,0x68860bfd,0x6c47164a,0x61043093,0x65c52d24, + 0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec, + 0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654, + 0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c, + 0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4, + 0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c, + 0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4, +}; +#endif + +/* + Calculate a CRC-32 using LEN bytes of PTR. CRC is the initial CRC + value. + PTR is assumed to be a pointer in the user program. */ + +static uint32 +crc32 (target_addr_t mem, int len, uint32 crc) +{ + unsigned char *ptr = (unsigned char *)TARGET_ADDR_TO_PTR(mem); +#ifdef TARGET_HAS_HARVARD_MEMORY + int is_progmem = TARGET_ADDR_IS_PROGMEM(mem); +#endif + +#ifdef CYGDBG_HAL_CRCTABLE_LOCATION_RAM + if (! tableInit) + { + /* Initialize the CRC table and the decoding table. */ + uint32 i, j; + uint32 c; + + tableInit = 1; + for (i = 0; i < 256; i++) + { + for (c = i << 24, j = 8; j > 0; --j) + c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1); + crc32_table[i] = c; + } + } +#endif + + __mem_fault = 0; + while (len--) + { + unsigned char ch; + +#ifdef TARGET_HAS_HARVARD_MEMORY + if (is_progmem) + __read_progmem_safe (&ch, (void *)ptr, 1); + else +#endif + __read_mem_safe (&ch, (void *)ptr, 1); + if (__mem_fault) + { + break; + } + crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ ch) & 255]; + ptr++; + } + return crc; +} + +/* Handle the 'q' request */ + +static void +process_query (char *pkt) +{ + __remcomOutBuffer[0] = '\0'; +#ifdef __ECOS__ + if ('C' == pkt[0] && + 'R' == pkt[1] && + 'C' == pkt[2] && + ':' == pkt[3]) +#else // __ECOS__ + if (strncmp (pkt, "CRC:", 4) == 0) +#endif // __ECOS__ + { + target_addr_t startmem; + target_register_t length; + uint32 our_crc; + + pkt += 4; + if (__hexToAddr (&pkt, &startmem) + && *(pkt++) == ',' + && __hexToInt (&pkt, &length)) + { + our_crc = crc32 (startmem, length, 0xffffffff); + if (__mem_fault) + { + strcpy (__remcomOutBuffer, "E01"); + } + else + { + int numb = __intToHex (__remcomOutBuffer + 1, our_crc, 32); + __remcomOutBuffer[0] = 'C'; + __remcomOutBuffer[numb + 1] = 0; + } + } + return; + } +#ifdef CYG_HAL_STUB_PROCESS_QUERY + else if (CYG_HAL_STUB_PROCESS_QUERY (pkt, __remcomOutBuffer, sizeof(__remcomOutBuffer))) + return; +#endif + else + { + char ch ; + char *subpkt CYGBLD_ATTRIB_UNUSED; + ch = *pkt ; + subpkt = pkt + 1 ; + switch (ch) + { + case 'L' : /* threadlistquery */ + STUB_PKT_GETTHREADLIST (subpkt, __remcomOutBuffer, 300); + break ; + case 'P' : /* Thread or process information request */ + STUB_PKT_GETTHREADINFO (subpkt, __remcomOutBuffer, 300); + break ; + case 'C' : /* current thread query */ + STUB_PKT_CURRTHREAD(subpkt, __remcomOutBuffer, sizeof(__remcomOutBuffer)); + break; + default: + __process_target_query (pkt, __remcomOutBuffer, 300); + break ; + } + } +} + +/* Handle the 'Q' request */ + +static void +process_set (char *pkt) +{ + char ch ; + +#ifdef CYG_HAL_STUB_PROCESS_SET + if (CYG_HAL_STUB_PROCESS_SET (pkt, __remcomOutBuffer, sizeof(__remcomOutBuffer))) + return; +#endif + + ch = *pkt ; + switch (ch) + { + case 'p' : /* Set current process or thread */ + /* reserve the packet id even if support is not present */ + /* Dont strip the 'p' off the header, there are several variations of + this packet */ + STUB_PKT_CHANGETHREAD (pkt, __remcomOutBuffer, 300) ; + break ; + default: + __process_target_set (pkt, __remcomOutBuffer, 300); + break ; + } +} +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS diff --git a/ecos/packages/hal/common/current/src/hal_if.c b/ecos/packages/hal/common/current/src/hal_if.c new file mode 100644 index 0000000..d46fbdb --- /dev/null +++ b/ecos/packages/hal/common/current/src/hal_if.c @@ -0,0 +1,1116 @@ +//============================================================================= +// +// hal_if.c +// +// ROM/RAM interfacing functions +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2011 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors:jskov, woehler, jld +// Date: 2000-06-07 +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal.h> + +#ifdef CYGPKG_KERNEL +# include <pkgconf/kernel.h> +#endif + +#include <cyg/infra/cyg_ass.h> // assertions + +#include <cyg/hal/hal_arch.h> // set/restore GP + +#include <cyg/hal/hal_io.h> // IO macros +#include <cyg/hal/hal_if.h> // our interface + +#include <cyg/hal/hal_diag.h> // Diag IO +#include <cyg/hal/hal_misc.h> // User break + +#include <cyg/hal/hal_stub.h> // stub functionality + +#include <cyg/hal/hal_intr.h> // hal_vsr_table and others + +#ifdef CYGPKG_REDBOOT +#include <pkgconf/redboot.h> +#ifdef CYGSEM_REDBOOT_FLASH_CONFIG +#include <redboot.h> +#include <flash_config.h> +#endif +#ifdef CYGOPT_REDBOOT_FIS +#include <fis.h> +#endif +#endif + +//-------------------------------------------------------------------------- + +externC void patch_dbg_syscalls(void * vector); +externC void init_thread_syscall(void * vector); + +//-------------------------------------------------------------------------- +// Implementations and function wrappers for monitor services + +// flash config state queries +#ifdef CYGSEM_REDBOOT_FLASH_CONFIG + +static __call_if_flash_cfg_op_fn_t flash_config_op; + +static cyg_bool +flash_config_op(int op, struct cyg_fconfig *fc) +{ + cyg_bool res = false; + + CYGARC_HAL_SAVE_GP(); + + switch (op) { + case CYGNUM_CALL_IF_FLASH_CFG_GET: + res = flash_get_config(fc->key, fc->val, fc->type); + break; + case CYGNUM_CALL_IF_FLASH_CFG_NEXT: + res = flash_next_key(fc->key, fc->keylen, &fc->type, &fc->offset); + break; + case CYGNUM_CALL_IF_FLASH_CFG_SET: + res = flash_set_config(fc->key, fc->val, fc->type); + break; + default: + // nothing else supported yet - though it is expected that "set" + // will fit the same set of arguments, potentially. + break; + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} +#endif + +#ifdef CYGOPT_REDBOOT_FIS + +static __call_if_flash_fis_op_fn_t flash_fis_op; + +static cyg_bool +flash_fis_op( int op, char *name, void *val) +{ + cyg_bool res = false; + struct fis_image_desc *fis; + int num; + + CYGARC_HAL_SAVE_GP(); + fis = fis_lookup(name, &num); + if(fis != NULL) + { + switch ( op ) { + case CYGNUM_CALL_IF_FLASH_FIS_GET_FLASH_BASE: + *(CYG_ADDRESS *)val = fis->flash_base; + res = true; + break; + case CYGNUM_CALL_IF_FLASH_FIS_GET_SIZE: + *(unsigned long *)val = fis->size; + res = true; + break; + case CYGNUM_CALL_IF_FLASH_FIS_GET_MEM_BASE: + *(CYG_ADDRESS *)val = fis->mem_base; + res = true; + break; + case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_POINT: + *(CYG_ADDRESS *)val = fis->entry_point; + res = true; + break; + case CYGNUM_CALL_IF_FLASH_FIS_GET_DATA_LENGTH: + *(unsigned long *)val = fis->data_length; + res = true; + break; + case CYGNUM_CALL_IF_FLASH_FIS_GET_DESC_CKSUM: + *(unsigned long *)val = fis->desc_cksum; + res = true; + break; + case CYGNUM_CALL_IF_FLASH_FIS_GET_FILE_CKSUM: + *(unsigned long *)val = fis->file_cksum; + res = true; + break; + default: + break; + } + } + CYGARC_HAL_RESTORE_GP(); + return res; +} + +#include <cyg/io/flash.h> + +extern int __flash_init; +extern int fisdir_size; +extern int flash_block_size; +extern void* fis_addr; +#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS +extern void* redundant_fis_addr; +#endif +extern void* fis_work_block; +extern int do_flash_init(void); +extern int fis_start_update_directory(int autolock); +extern int fis_update_directory(int autolock, int error); + +static __call_if_flash_fis_op2_fn_t flash_fis_op2; + +static int +flash_fis_op2( int op, unsigned int index, struct fis_table_entry *entry) +{ + int res=0; + CYGARC_HAL_SAVE_GP(); + switch ( op ) { + case CYGNUM_CALL_IF_FLASH_FIS_GET_VERSION: + res=CYG_REDBOOT_FIS_VERSION; + break; + case CYGNUM_CALL_IF_FLASH_FIS_INIT: + __flash_init=0; //force reinitialization + res=do_flash_init(); + break; + case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY_COUNT: + res=fisdir_size / sizeof(struct fis_image_desc); + break; + case CYGNUM_CALL_IF_FLASH_FIS_GET_ENTRY: + { + struct fis_image_desc* img = (struct fis_image_desc *)fis_work_block; + CYG_ASSERT(entry!=0, "fis_table_entry == 0 !"); + memcpy(entry->name, img[index].u.name, 16); + entry->flash_base=img[index].flash_base; + entry->mem_base=img[index].mem_base; + entry->size=img[index].size; + entry->entry_point=img[index].entry_point; + entry->data_length=img[index].data_length; + entry->desc_cksum=img[index].desc_cksum; + entry->file_cksum=img[index].file_cksum; + res=0; + } + break; + case CYGNUM_CALL_IF_FLASH_FIS_START_UPDATE: + fis_start_update_directory(1); + break; + case CYGNUM_CALL_IF_FLASH_FIS_FINISH_UPDATE: + fis_update_directory(1, index); + break; + case CYGNUM_CALL_IF_FLASH_FIS_MODIFY_ENTRY: + { + res=0; + if (entry->name[0]!=0xff) + { + if ((entry->size==0) + || ((entry->size % flash_block_size) !=0) + || (flash_verify_addr((void*)entry->flash_base)!=0) + || (flash_verify_addr((void*)(entry->flash_base+entry->size-1))!=0) + || (entry->size < entry->data_length)) + res=-1; + } + + if (res==0) + { + struct fis_image_desc* img = (struct fis_image_desc *)fis_work_block; + memcpy(img[index].u.name, entry->name, 16); + img[index].flash_base=entry->flash_base; + img[index].mem_base=entry->mem_base; + img[index].size=entry->size; + img[index].entry_point=entry->entry_point; + img[index].data_length=entry->data_length; + img[index].desc_cksum=entry->desc_cksum; + img[index].file_cksum=entry->file_cksum; + } + } + break; + default: + break; + } + CYGARC_HAL_RESTORE_GP(); + return res; +} + +#endif + +//---------------------------- +// Delay uS +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US + +static __call_if_delay_us_t delay_us; + +static void +delay_us(cyg_int32 usecs) +{ + CYGARC_HAL_SAVE_GP(); +#if defined(CYGPKG_KERNEL) && defined(HAL_CLOCK_READ) + { + cyg_uint32 start, elapsed_hal; + cyg_int32 elapsed, elapsed_usec; + cyg_int32 slice; + cyg_int32 usec_per_period = CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000; + cyg_int32 ticks_per_usec = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/usec_per_period; + + do { + // Spin in slices of 1/2 the RTC period. Allows interrupts + // time to run without messing up the algorithm. If we + // spun for 1 period (or more) of the RTC, there would also + // be problems figuring out when the timer wrapped. We + // may lose a tick or two for each cycle but it shouldn't + // matter much. + + // The tests against CYGNUM_KERNEL_COUNTERS_RTC_PERIOD + // check for a value that would cause a 32 bit signed + // multiply to overflow. But this also implies that just + // multiplying by ticks_per_usec will yield a good + // approximation. Otherwise we need to do the full + // multiply+divide to get sufficient accuracy. Note that + // this test is actually constant, so the compiler will + // eliminate it and only compile the branch that is + // selected. + + if( usecs > usec_per_period/2 ) + slice = CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2; + else if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD/2 >= 0x7FFFFFFF/usec_per_period ) + slice = usecs * ticks_per_usec; + else + { + slice = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; + slice /= usec_per_period; + } + + HAL_CLOCK_READ(&start); + do { + HAL_CLOCK_READ(&elapsed_hal); + elapsed = (elapsed_hal - start); // counts up! + if (elapsed < 0) + elapsed += CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; + } while (elapsed < slice); + + // Adjust by elapsed, not slice, since an interrupt may + // have been stalling us for some time. + + if( CYGNUM_KERNEL_COUNTERS_RTC_PERIOD >= 0x7FFFFFFF/usec_per_period ) + elapsed_usec = elapsed / ticks_per_usec; + else + { + elapsed_usec = elapsed * usec_per_period; + elapsed_usec = elapsed_usec / CYGNUM_KERNEL_COUNTERS_RTC_PERIOD; + } + + // It is possible for elapsed_usec to end up zero in some + // circumstances and we could end up looping indefinitely. + // Avoid that by ensuring that we always decrement usec by + // at least 1 each time. + + usecs -= elapsed_usec ? elapsed_usec : 1; + + } while (usecs > 0); + } +#else // CYGPKG_KERNEL +#ifdef HAL_DELAY_US + // Use a HAL feature if defined + HAL_DELAY_US(usecs); +#else + // If no accurate delay mechanism, just spin for a while. Having + // an inaccurate delay is much better than no delay at all. The + // count of 10 should mean the loop takes something resembling + // 1us on most CPUs running between 30-100MHz [depends on how many + // instructions this compiles to, how many dispatch units can be + // used for the simple loop, actual CPU frequency, etc] + while (usecs-- > 0) { + int i; + for (i = 0; i < 10; i++); + } +#endif // HAL_DELAY_US +#endif // CYGPKG_KERNEL + CYGARC_HAL_RESTORE_GP(); +} +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US + +// Reset functions +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET + +static __call_if_reset_t reset; + +static void +reset(void) +{ + CYGARC_HAL_SAVE_GP(); + // With luck, the platform defines some magic that will cause a hardware + // reset. +#ifdef HAL_PLATFORM_RESET + HAL_PLATFORM_RESET(); +#endif + +#ifdef HAL_PLATFORM_RESET_ENTRY + // If that's not the case (above is an empty statement) there may + // be defined an address we can jump to - and effectively + // reinitialize the system. Not quite as good as a reset, but it + // is often enough. + goto *HAL_PLATFORM_RESET_ENTRY; + +#else +#error " no RESET_ENTRY" +#endif + CYG_FAIL("Reset failed"); + CYGARC_HAL_RESTORE_GP(); +} + +#endif + +//------------------------------------ +// NOP service +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE) || \ + defined(CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS) +static int +nop_service(void) +{ + // This is the default service. It always returns false (0), and + // _does not_ trigger any assertions. Clients must either cope + // with the service failure or assert. + return 0; +} +#endif + +//---------------------------------- +// Comm controls +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS + +#ifdef CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS +#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \ + (CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS+CYGNUM_HAL_VIRTUAL_VECTOR_AUX_CHANNELS) +#else +#define CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS \ + CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS +#endif + +static hal_virtual_comm_table_t comm_channels[CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1]; + +static int +set_debug_comm(int __comm_id) +{ + static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY; + hal_virtual_comm_table_t* __chan; + int interrupt_state = 0; + int res = 1, update = 0; + CYGARC_HAL_SAVE_GP(); + + CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER + && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS, + "Invalid channel"); + + switch (__comm_id) { + case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT: + if (__selected_id > 0) + res = __selected_id-1; + else if (__selected_id == 0) + res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER; + else + res = __selected_id; + break; + + case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY: + CYGACC_CALL_IF_DEBUG_PROCS_SET(0); + __selected_id = __comm_id; + break; + + case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER: + __comm_id = 0; + update = 1; + break; + + default: + __comm_id++; // skip mangler entry + update = 1; + break; + } + + if (update) { + // Find the interrupt state of the channel. + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + if (__chan) + interrupt_state = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); + + __selected_id = __comm_id; + CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]); + + // Set interrupt state on the new channel. + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + if (interrupt_state) + CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE); + else + CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} + +static int +set_console_comm(int __comm_id) +{ + static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY; + int res = 1, update = 0; + CYGARC_HAL_SAVE_GP(); + + CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER + && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS, + "Invalid channel"); + + switch (__comm_id) { + case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT: + if (__selected_id > 0) + res = __selected_id-1; + else if (__selected_id == 0) + res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER; + else + res = __selected_id; + break; + + case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY: + CYGACC_CALL_IF_CONSOLE_PROCS_SET(0); + __selected_id = __comm_id; + break; + + case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER: + __comm_id = 0; + update = 1; + break; + + default: + __comm_id++; // skip mangler entry + update = 1; + break; + } + + if (update) { + __selected_id = __comm_id; + + CYGACC_CALL_IF_CONSOLE_PROCS_SET(comm_channels[__comm_id]); + } + + CYGARC_HAL_RESTORE_GP(); + return res; +} +#endif + +#if defined(CYGSEM_HAL_VIRTUAL_VECTOR_DIAG) +//----------------------------------------------------------------------------- +// GDB console output mangler (O-packetizer) +// COMMS init function at end. + +// This gets called via the virtual vector console comms entry and +// handles O-packetization. The debug comms entries are used for the +// actual device IO. +static cyg_uint8 +cyg_hal_diag_mangler_gdb_getc(void* __ch_data) +{ + cyg_uint8 __ch; + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + CYGARC_HAL_SAVE_GP(); + + __ch = CYGACC_COMM_IF_GETC(*__chan); + + CYGARC_HAL_RESTORE_GP(); + + return __ch; +} + +static char __mangler_line[100]; +static int __mangler_pos = 0; + +static void +cyg_hal_diag_mangler_gdb_flush(void* __ch_data) +{ + CYG_INTERRUPT_STATE old; + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); +#if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0 + int tries = CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES; +#endif + + + // Nothing to do if mangler buffer is empty. + if (__mangler_pos == 0) + return; + + // Disable interrupts. This prevents GDB trying to interrupt us + // while we are in the middle of sending a packet. The serial + // receive interrupt will be seen when we re-enable interrupts + // later. +#if defined(CYG_HAL_STARTUP_ROM) \ + || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION) + HAL_DISABLE_INTERRUPTS(old); +#else + CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old); +#endif + +#if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0 + // Only wait 500ms for data to arrive - avoid "stuck" connections + CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, CYGNUM_HAL_DEBUG_GDB_PROTOCOL_TIMEOUT); +#endif + + while(1) + { + static const char hex[] = "0123456789ABCDEF"; + cyg_uint8 csum = 0; + char c1; + int i; + + CYGACC_COMM_IF_PUTC(*__chan, '$'); + CYGACC_COMM_IF_PUTC(*__chan, 'O'); + csum += 'O'; + for( i = 0; i < __mangler_pos; i++ ) + { + char ch = __mangler_line[i]; + char h = hex[(ch>>4)&0xF]; + char l = hex[ch&0xF]; + CYGACC_COMM_IF_PUTC(*__chan, h); + CYGACC_COMM_IF_PUTC(*__chan, l); + csum += h; + csum += l; + } + CYGACC_COMM_IF_PUTC(*__chan, '#'); + CYGACC_COMM_IF_PUTC(*__chan, hex[(csum>>4)&0xF]); + CYGACC_COMM_IF_PUTC(*__chan, hex[csum&0xF]); + + nak: +#if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0 + if (CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, &c1) == 0) { + c1 = '-'; + if (tries && (--tries == 0)) c1 = '+'; + } +#else + c1 = CYGACC_COMM_IF_GETC(*__chan); +#endif + + if( c1 == '+' ) break; + + if( cyg_hal_is_break( &c1 , 1 ) ) { + // Caller's responsibility to react on this. + CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(1); + break; + } + if( c1 != '-' ) goto nak; + } + + __mangler_pos = 0; + // And re-enable interrupts +#if defined(CYG_HAL_STARTUP_ROM) \ + || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION) + HAL_RESTORE_INTERRUPTS(old); +#else + CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old); +#endif +} + +static void +cyg_hal_diag_mangler_gdb_putc(void* __ch_data, cyg_uint8 c) +{ + // No need to send CRs + if( c == '\r' ) return; + + CYGARC_HAL_SAVE_GP(); + + __mangler_line[__mangler_pos++] = c; + + if( c == '\n' || __mangler_pos == sizeof(__mangler_line) ) + cyg_hal_diag_mangler_gdb_flush(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_diag_mangler_gdb_write(void* __ch_data, + const cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_diag_mangler_gdb_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_diag_mangler_gdb_read(void* __ch_data, + cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_diag_mangler_gdb_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +static int +cyg_hal_diag_mangler_gdb_control(void *__ch_data, + __comm_control_cmd_t __func, ...) +{ + CYGARC_HAL_SAVE_GP(); + + if (__func == __COMMCTL_FLUSH_OUTPUT) + cyg_hal_diag_mangler_gdb_flush(__ch_data); + + CYGARC_HAL_RESTORE_GP(); + return 0; +} + +// This is the COMMS init function. It gets called both by the stubs +// and diag init code to initialize the COMMS mangler channel table - +// that's all. The callers have to decide whether to actually use this +// channel. +void +cyg_hal_diag_mangler_gdb_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Initialize mangler procs + CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_gdb_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_gdb_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_gdb_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_gdb_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_gdb_control); + + // Restore the original console channel. + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +//----------------------------------------------------------------------------- +// Null console output mangler +// COMMS init function at end. + +// This gets called via the virtual vector console comms entry and +// just forwards IO to the debug comms entries. +// This differs from setting the console channel to the same as the +// debug channel in that console output will go to the debug channel +// even if the debug channel is changed. +static cyg_uint8 +cyg_hal_diag_mangler_null_getc(void* __ch_data) +{ + cyg_uint8 __ch; + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + CYGARC_HAL_SAVE_GP(); + + __ch = CYGACC_COMM_IF_GETC(*__chan); + + CYGARC_HAL_RESTORE_GP(); + + return __ch; +} + + +static void +cyg_hal_diag_mangler_null_putc(void* __ch_data, cyg_uint8 c) +{ + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + + CYGARC_HAL_SAVE_GP(); + + CYGACC_COMM_IF_PUTC(*__chan, c); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_diag_mangler_null_write(void* __ch_data, + const cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + cyg_hal_diag_mangler_null_putc(__ch_data, *__buf++); + + CYGARC_HAL_RESTORE_GP(); +} + +static void +cyg_hal_diag_mangler_null_read(void* __ch_data, + cyg_uint8* __buf, cyg_uint32 __len) +{ + CYGARC_HAL_SAVE_GP(); + + while(__len-- > 0) + *__buf++ = cyg_hal_diag_mangler_null_getc(__ch_data); + + CYGARC_HAL_RESTORE_GP(); +} + +static int +cyg_hal_diag_mangler_null_control(void *__ch_data, + __comm_control_cmd_t __func, ...) +{ + // Do nothing (yet). + return 0; +} + +// This is the COMMS init function. It gets called both by the stubs +// and diag init code to initialize the COMMS mangler channel table - +// that's all. The callers have to decide whether to actually use this +// channel. +void +cyg_hal_diag_mangler_null_init(void) +{ + hal_virtual_comm_table_t* comm; + int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); + + // Initialize mangler procs + CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER); + comm = CYGACC_CALL_IF_CONSOLE_PROCS(); + CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_diag_mangler_null_write); + CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_diag_mangler_null_read); + CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_diag_mangler_null_putc); + CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_diag_mangler_null_getc); + CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_diag_mangler_null_control); + + // Restore the original console channel. + CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); +} + +//----------------------------------------------------------------------------- +// Console IO functions that adhere to the virtual vector table semantics in +// order to ensure proper debug agent mangling when required. +// +externC void cyg_hal_plf_comms_init(void); + +void +hal_if_diag_init(void) +{ + // This function may be called from various places and the code + // should only run once. + static cyg_uint8 called = 0; + if (called) return; + called = 1; + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE + +#if defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN) + // Use the mangler channel, which in turn uses the debug channel. + CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_MANGLER); + + // Initialize the mangler channel. +#if defined(CYGSEM_HAL_DIAG_MANGLER_GDB) + cyg_hal_diag_mangler_gdb_init(); +#elif defined(CYGSEM_HAL_DIAG_MANGLER_None) + cyg_hal_diag_mangler_null_init(); +#endif + +#else // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN + + // Use an actual (raw) IO channel + CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL); + +#endif // CYGDBG_HAL_DIAG_TO_DEBUG_CHAN + +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_INHERIT_CONSOLE +} + +void +hal_if_diag_write_char(char c) +{ + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); + + if (__chan) + CYGACC_COMM_IF_PUTC(*__chan, c); + else { + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + + // FIXME: What should be done if assertions are not enabled? + // This is a bad bad situation - we have no means for diag + // output; we want to hit a breakpoint to alert the developer + // or something like that. + CYG_ASSERT(__chan, "No valid channel set"); + + CYGACC_COMM_IF_PUTC(*__chan, c); + } + + // Check interrupt flag + if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { + CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); + cyg_hal_user_break(0); + } +} + +void +hal_if_diag_read_char(char *c) +{ + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); + + if (__chan) + *c = CYGACC_COMM_IF_GETC(*__chan); + else { + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + + // FIXME: What should be done if assertions are not enabled? + // This is a bad bad situation - we have no means for diag + // output; we want to hit a breakpoint to alert the developer + // or something like that. + CYG_ASSERT(__chan, "No valid channel set"); + + *c = CYGACC_COMM_IF_GETC(*__chan); + } +} +#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG + +//============================================================================= +// CtrlC support +//============================================================================= + +#if CYGINT_HAL_COMMON_SAVED_INTERRUPT_STATE_REQUIRED > 0 +struct Hal_SavedRegisters *hal_saved_interrupt_state; +#endif + +#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) + +void +hal_ctrlc_isr_init(void) +{ + // A ROM monitor never enables the interrupt itself. This is left + // to the (RAM) application. +#ifndef CYGSEM_HAL_ROM_MONITOR + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + +#if 1 // Prevents crash on older stubs + int v_m; + // Allow only ctrl-c interrupt enabling when version in table is + // below legal max and above the necessary service, and _not_ + // the value we set it to below. + v_m = CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK; + if (v_m >= CYGNUM_CALL_IF_TABLE_VERSION_CALL_MAX + || v_m < CYGNUM_CALL_IF_SET_DEBUG_COMM + || v_m == CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK) + return; + + // Now trash that value - otherwise downloading an image with + // builtin stubs on a board with older stubs (which will cause the + // version to be set to VERSION_CALL) may cause all subsequent + // runs to (wrongly) fall through to the below code. If there is + // a new stub on the board, it will reinitialize the version field + // on reset. Yes, this is a gross hack! + CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK); +#endif + + // We can only enable interrupts on a valid debug channel. + if (__chan) + CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE); +#endif +} + +cyg_uint32 +hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + int isr_ret = 0, ctrlc = 0; + + if (__chan) { + isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data); + if (ctrlc) + cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); + } + return isr_ret; +} + +cyg_bool +hal_ctrlc_check(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + int gdb_vector = vector-1; + int ctrlc = 0; + + // This check only to avoid crash on older stubs in case of unhandled + // interrupts. It is a bit messy, but required in a transition period. + if (__chan && + (CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK == + (CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK))){ + gdb_vector = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DBG_ISR_VECTOR); + } + if (vector == gdb_vector) { + CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data); + if (ctrlc) { + cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); + return true; + } + } + return false; +} +#endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT || CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT + +//-------------------------------------------------------------------------- +// Init function. It should be called from the platform initialization code. +// For monitor configurations it will initialize the calling interface table, +// for client configurations it will patch the existing table as per +// configuration. +void +hal_if_init(void) +{ + //********************************************************************** + // + // Note that if your RAM application is configured to initialize + // the whole table _or_ the communication channels, you _cannot_ + // step through this function with the debugger. If your channel + // configurations are set to the default, you should be able to + // simply step over this function though (or use 'finish' once you + // have entered this function if that GDB command works). + // + // If you really do need to debug this code, the best approach is + // to have a working RedBoot / GDB stub in ROM and then change the + // hal_virtual_vector_table to reside at some other address in the + // RAM configuration than that used by the ROM monitor. Then + // you'll be able to use the ROM monitor to debug the below code + // and check that it does the right thing. + // + // Note that if you have a ROM monitor in ROM/flash which does + // support virtual vectors, you should be able to disable the + // option CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE. On some + // targets (which predate the introduction of virtual vectors) + // that option is enabled per default and needs to be explicitly + // disabled when you have an updated ROM monitor. + // + //********************************************************************** + +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE + { + int i; + + // Initialize tables with the NOP service. + // This should only be done for service routine entries - data + // pointers should be NULLed. + for (i = 0; i < CYGNUM_CALL_IF_TABLE_SIZE; i++) + hal_virtual_vector_table[i] = (CYG_ADDRWORD) &nop_service; + + // Version number + CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL + |((CYG_ADDRWORD)CYGNUM_CALL_IF_TABLE_VERSION_COMM<<CYGNUM_CALL_IF_TABLE_VERSION_COMM_shift)); + } +#endif + + // Miscellaneous services with wrappers in this file. +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_RESET + CYGACC_CALL_IF_RESET_SET(reset); +#endif +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US + CYGACC_CALL_IF_DELAY_US_SET(delay_us); +#endif + +#ifdef CYGSEM_REDBOOT_FLASH_CONFIG + CYGACC_CALL_IF_FLASH_CFG_OP_SET(flash_config_op); +#endif + +#ifdef CYGOPT_REDBOOT_FIS + CYGACC_CALL_IF_FLASH_FIS_OP_SET(flash_fis_op); + CYGACC_CALL_IF_FLASH_FIS_OP2_SET(flash_fis_op2); +#endif + + // Data entries not currently supported in eCos +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DATA + CYGACC_CALL_IF_DBG_DATA_SET(0); +#endif + +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_VERSION + CYGACC_CALL_IF_MONITOR_VERSION_SET(0); +#endif + + // Comm controls +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_COMMS + { + int i, j; + + // Clear out tables with safe dummy function. + for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS+1; j++) + for (i = 0; i < CYGNUM_COMM_IF_TABLE_SIZE; i++) + comm_channels[j][i] = (CYG_ADDRWORD) &nop_service; + + // Set accessor functions + CYGACC_CALL_IF_SET_DEBUG_COMM_SET(set_debug_comm); + CYGACC_CALL_IF_SET_CONSOLE_COMM_SET(set_console_comm); + + // Initialize console/debug procs. Note that these _must_ + // be set to empty before the comms init call. + set_debug_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY); + set_console_comm(CYGNUM_CALL_IF_SET_COMM_ID_EMPTY); + + // Initialize channels. This used to be done in + // hal_diag_init() and the stub initHardware() functions, but + // it makes more sense to have here. + cyg_hal_plf_comms_init(); + + // Always set the debug channel. If stubs are included, it is + // necessary. If no stubs are included it does not hurt and is + // likely to be required by the hal_if_diag_init code anyway + // as it may rely on it if using a mangler. + set_debug_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL); + // Set console channel to a safe default. hal_if_diag_init + // will override with console channel or mangler if necessary. + set_console_comm(CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL); + } + + // Reset console interrupt flag. + CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); +#endif + + // Set up services provided by clients +#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ + ( defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) \ + || defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon)) + + patch_dbg_syscalls( (void *)(hal_virtual_vector_table) ); +#endif + + // Init client services +#if !defined(CYGPKG_KERNEL) && defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT) + // Only include this code if we do not have a kernel. Otherwise + // the kernel supplies the functionality for the app we are linked + // with. + + // Prepare for application installation of thread info function in + // vector table. + init_thread_syscall( (void *)&hal_virtual_vector_table[CYGNUM_CALL_IF_DBG_SYSCALL] ); +#endif + + // Finally, install async breakpoint handler if it is configured in. + // FIXME: this should probably check for STUBS instead (but code is + // conditional on BREAK for now) +#if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) + // Install async breakpoint handler into vector table. + CYGACC_CALL_IF_INSTALL_BPT_FN_SET(&cyg_hal_gdb_interrupt); +#endif + +#if 0 != CYGINT_HAL_PLF_IF_INIT + // Call platform specific initializations - should only be used + // to augment what has already been set up, etc. + plf_if_init(); +#endif +} + diff --git a/ecos/packages/hal/common/current/src/hal_misc.c b/ecos/packages/hal/common/current/src/hal_misc.c new file mode 100644 index 0000000..cbc7229 --- /dev/null +++ b/ecos/packages/hal/common/current/src/hal_misc.c @@ -0,0 +1,200 @@ +//========================================================================== +// +// hal_misc.c +// +// Common HAL miscellaneous functions +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg, jskov +// Date: 2000-06-08 +// Purpose: HAL miscellaneous functions +// Description: This file contains miscellaneous functions provided by the +// HAL. +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <pkgconf/hal.h> + +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_if.h> + +#include <cyg/hal/hal_intr.h> +#include <cyg/hal/hal_misc.h> // our header + +#include <cyg/infra/cyg_type.h> // Base types +#include <cyg/infra/cyg_trac.h> // tracing macros +#include <cyg/infra/cyg_ass.h> // assertion macros + +//-------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +// Macro for finding return address. +#ifndef CYGARC_HAL_GET_RETURN_ADDRESS + +#define CYGARC_HAL_GET_RETURN_ADDRESS(_x_, _dummy_) \ + CYG_MACRO_START \ + (_dummy_) = 1; \ + (_x_) = (CYG_ADDRWORD)&&__backup_return_address; \ + CYG_MACRO_END + +#define CYGARC_HAL_GET_RETURN_ADDRESS_BACKUP(_dummy_) \ + CYG_MACRO_START \ +__backup_return_address: \ + if ((_dummy_)-- > 0) \ + goto __backup_return_address; \ + CYG_MACRO_END +#endif + +//-------------------------------------------------------------------------- +// Macro for finding PC in saved regs +#ifndef CYGARC_HAL_GET_PC_REG +#define CYGARC_HAL_GET_PC_REG(_regs_,_val_) ((_val_) = (_regs_)->pc) +#endif + +//-------------------------------------------------------------------------- +// Macro for matching interrupt vector to GDB comm channel. +#ifndef CYGHWR_HAL_GDB_PORT_VECTORS_MATCH +#define CYGHWR_HAL_GDB_PORT_VECTORS_MATCH(_v_,_gv_) ((_v_)==(_gv_)) +#endif + +#if defined(CYGPKG_CYGMON) +unsigned long cygmon_memsize = 0; +#endif + +//-------------------------------------------------------------------------- +// Functions to support the detection and execution of a user provoked +// program break. These are usually called from interrupt routines. + +cyg_bool +cyg_hal_is_break(char *buf, int size) +{ + while( size ) + if( buf[--size] == 0x03 ) return true; + + return false; +} + +// Keep this variable global, to prevent the compiler removing it (and +// the goto-reference) due to being local to the function where it is +// used. Yes, it's ugly. +int _cyg_hal_compiler_dummy; + +void +cyg_hal_user_break( CYG_ADDRWORD *regs ) +{ +#if defined(CYGSEM_HAL_USE_ROM_MONITOR_GDB_stubs) \ + || defined(CYGSEM_HAL_USE_ROM_MONITOR_CygMon) \ + || defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) + + CYG_ADDRWORD __ra; + CYG_WORD32 __pc; + HAL_SavedRegisters *sreg = (HAL_SavedRegisters *)regs; + + CYGARC_HAL_GET_RETURN_ADDRESS(__ra, _cyg_hal_compiler_dummy); + + if( regs == NULL ) __pc = __ra; + else CYGARC_HAL_GET_PC_REG(sreg, __pc); + + CYGACC_CALL_IF_INSTALL_BPT_FN((void *)__pc); + + CYGARC_HAL_GET_RETURN_ADDRESS_BACKUP(_cyg_hal_compiler_dummy); + +#else + + HAL_BREAKPOINT(breakinst); + +#endif +} + + +//-------------------------------------------------------------------------- +// The system default interrupt ISR. It calls the architecture default +// ISR as well if necessary. +externC cyg_uint32 hal_arch_default_isr(CYG_ADDRWORD vector, + CYG_ADDRWORD data); + +cyg_uint32 +hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) +{ + cyg_uint32 result; + +#if (defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ + || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)) && \ + (defined(CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT) || \ + defined(CYGHWR_HAL_GDB_PORT_VECTOR) && \ + defined(HAL_CTRLC_ISR)) + +#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN +#if CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + int gdb_vector = -1; + // This check only to avoid crash on older stubs in case of unhandled + // interrupts. It is a bit messy, but required in a transition period. +#ifndef CYGSEM_HAL_ROM_MONITOR + if (CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK == + (CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK)) +#endif + { + hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + if (__chan) + gdb_vector = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DBG_ISR_VECTOR); + } + if( CYGHWR_HAL_GDB_PORT_VECTORS_MATCH(vector, gdb_vector) ) +#else + // Old code using hardwired channels. This should go away eventually. + if( vector == CYGHWR_HAL_GDB_PORT_VECTOR ) +#endif +#endif + { + result = HAL_CTRLC_ISR( vector, data ); + if( 0 != result ) return result; + } +#endif + + result = hal_arch_default_isr (vector, data); + if( 0 != result) return result; + + CYG_TRACE2(true, "Interrupt: %d, Data: 0x%08x", vector, data); + CYG_FAIL("Spurious Interrupt!!!"); + return 0; +} + + +//-------------------------------------------------------------------------- +// End of hal_misc.c diff --git a/ecos/packages/hal/common/current/src/hal_stub.c b/ecos/packages/hal/common/current/src/hal_stub.c new file mode 100644 index 0000000..d60c79d --- /dev/null +++ b/ecos/packages/hal/common/current/src/hal_stub.c @@ -0,0 +1,1037 @@ +//============================================================================= +// +// hal_stub.c +// +// Helper functions for stub, specific to eCos HAL +// +//============================================================================= +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov (based on powerpc/cogent hal_stub.c) +// Contributors:jskov, dmoseley +// Date: 1999-02-12 +// Purpose: Helper functions for stub, specific to eCos HAL +// Description: Parts of the GDB stub requirements are provided by +// the eCos HAL, rather than target and/or board specific +// code. +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include <pkgconf/hal.h> +#ifdef CYGPKG_CYGMON +#include <pkgconf/cygmon.h> +#endif + +#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS + +#include <cyg/hal/hal_stub.h> // Our header + +#include <cyg/hal/hal_arch.h> // HAL_BREAKINST +#include <cyg/hal/hal_cache.h> // HAL_xCACHE_x +#include <cyg/hal/hal_intr.h> // interrupt disable/restore + +#include <cyg/hal/hal_if.h> // ROM calling interface +#include <cyg/hal/hal_misc.h> // Helper functions + +#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT +#include <cyg/hal/dbg-threads-api.h> // dbg_currthread_id +#endif + +#ifdef USE_LONG_NAMES_FOR_ENUM_REGNAMES +#ifndef PC +#define PC REG_PC +#endif +#ifndef SP +#define SP REG_SP +#endif +#endif + +//----------------------------------------------------------------------------- +// Extra eCos data. + +// Saved registers. +HAL_SavedRegisters *_hal_registers; +target_register_t registers[HAL_STUB_REGISTERS_SIZE]; +target_register_t alt_registers[HAL_STUB_REGISTERS_SIZE] ; // Thread or saved process state +target_register_t * _registers = registers; // Pointer to current set of registers +#ifndef CYGPKG_REDBOOT +target_register_t orig_registers[HAL_STUB_REGISTERS_SIZE]; // Registers to get back to original state +#endif + +#if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT) +static int _hw_stop_reason; // Reason we were stopped by hw. + +//#define HAL_STUB_HW_SEND_STOP_REASON_TEXT +#ifdef CYGINT_HAL_ARM_ARCH_XSCALE +#define HAL_STUB_HW_SEND_STOP_REASON_TEXT +#endif + +#ifdef HAL_STUB_HW_SEND_STOP_REASON_TEXT +// strings indexed by hw stop reasons defined in hal_stub.h + +// Not all GDBs understand this. +static const char * const _hw_stop_str[] = { + "", + "hbreak", + "watch", + "rwatch", + "awatch" +}; +#endif // HAL_STUB_HW_SEND_STOP_REASON_TEXT + +static void *_watch_data_addr; // The data address if stopped by watchpoint +#endif // defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT) + +// Register validity checking +#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING +int registers_valid[NUMREGS]; +int *_registers_valid = registers_valid; +#endif + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away +// Interrupt control. +static volatile __PFI __interruptible_control; +#endif + +// Some architectures need extras regs reported in T packet +#ifndef HAL_STUB_ARCH_T_PACKET_EXTRAS +#define HAL_STUB_ARCH_T_PACKET_EXTRAS(x) +#endif + +//----------------------------------------------------------------------------- +// Register access + +#ifndef CYGARC_STUB_REGISTER_ACCESS_DEFINED +// Return the currently-saved value corresponding to register REG of +// the exception context. +target_register_t +get_register (regnames_t reg) +{ + return _registers[reg]; +} +#endif + +#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING +// Return the validity of register REG. +int +get_register_valid (regnames_t reg) +{ + return _registers_valid[reg]; +} +#endif + +#ifndef CYGARC_STUB_REGISTER_ACCESS_DEFINED +// Store VALUE in the register corresponding to WHICH in the exception +// context. +void +put_register (regnames_t which, target_register_t value) +{ +#ifdef CYGPKG_HAL_MIPS_VR4300 + // This is a rather nasty kludge to compensate for the fact that + // the VR4300 GDB is rather old and does not support proper 64 bit + // registers. The only time this really matters is when setting + // the PC after loading an executable. So here we detect this case + // and artificially sign extend it. + + if( which == PC && (value & 0x0000000080000000ULL ) ) + { + value |= 0xFFFFFFFF00000000ULL; + } +#endif + _registers[which] = value; +} +#endif // CYGARC_STUB_REGISTER_ACCESS_DEFINED + +//----------------------------------------------------------------------------- +// Serial stuff +#ifdef CYGPKG_CYGMON +extern void ecos_bsp_console_putc(char); +extern char ecos_bsp_console_getc(void); +#endif + +// Write C to the current serial port. +void +putDebugChar (int c) +{ +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); + CYGACC_COMM_IF_PUTC(*__debug_procs, c); +#elif defined(CYGPKG_CYGMON) + ecos_bsp_console_putc(c); +#else + HAL_STUB_PLATFORM_PUT_CHAR(c); +#endif +} + +// Read one character from the current serial port. +int +getDebugChar (void) +{ +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); + return CYGACC_COMM_IF_GETC(*__debug_procs); +#elif defined(CYGPKG_CYGMON) + return ecos_bsp_console_getc(); +#else + return HAL_STUB_PLATFORM_GET_CHAR(); +#endif +} + +// Flush output channel +void +hal_flush_output(void) +{ +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); + CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_FLUSH_OUTPUT); +#endif +} + + +// Set the baud rate for the current serial port. +void +__set_baud_rate (int baud) +{ +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); + CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_SETBAUD, baud); +#elif defined(CYGPKG_CYGMON) + // FIXME! +#else + HAL_STUB_PLATFORM_SET_BAUD_RATE(baud); +#endif +} + +//----------------------------------------------------------------------------- +// GDB interrupt (BREAK) support. + +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + +#ifndef CYGPKG_HAL_ARM + +#if (HAL_BREAKINST_SIZE == 1) +typedef cyg_uint8 t_inst; +#elif (HAL_BREAKINST_SIZE == 2) +typedef cyg_uint16 t_inst; +#elif (HAL_BREAKINST_SIZE == 4) +typedef cyg_uint32 t_inst; +#else +#error "Don't know how to handle that size" +#endif + +typedef struct +{ + t_inst *targetAddr; + t_inst savedInstr; +} instrBuffer; + +static instrBuffer break_buffer; + +volatile int cyg_hal_gdb_running_step = 0; + +void +cyg_hal_gdb_place_break (target_register_t pc) +{ + cyg_hal_gdb_interrupt( pc ); // Let's hope this becomes a drop-through: +} + +void +cyg_hal_gdb_interrupt (target_register_t pc) +{ + t_inst break_inst = HAL_BREAKINST; + + CYGARC_HAL_SAVE_GP(); + + // Clear flag that we Continued instead of Stepping + cyg_hal_gdb_running_step = 0; + // and override existing break? So that a ^C takes effect... + if (NULL != break_buffer.targetAddr) + cyg_hal_gdb_remove_break( (target_register_t)break_buffer.targetAddr ); + + if (NULL == break_buffer.targetAddr) { + // Not always safe to read/write directly to program + // memory due to possibly unaligned instruction, use the + // provided memory functions instead. + __read_mem_safe(&break_buffer.savedInstr, (t_inst*)pc, HAL_BREAKINST_SIZE); + __write_mem_safe(&break_inst, (t_inst*)pc, HAL_BREAKINST_SIZE); + + // Save the PC where we put the break, so we can remove + // it after the target takes the break. + break_buffer.targetAddr = (t_inst*)pc; + + __data_cache(CACHE_FLUSH); + __instruction_cache(CACHE_FLUSH); + } + + CYGARC_HAL_RESTORE_GP(); +} + +int +cyg_hal_gdb_remove_break (target_register_t pc) +{ + if ( cyg_hal_gdb_running_step ) + return 0; + + if ((t_inst*)pc == break_buffer.targetAddr) { + + __write_mem_safe(&break_buffer.savedInstr, (t_inst*)pc, HAL_BREAKINST_SIZE); + break_buffer.targetAddr = NULL; + + __data_cache(CACHE_FLUSH); + __instruction_cache(CACHE_FLUSH); + return 1; + } + return 0; +} + +int +cyg_hal_gdb_break_is_set (void) +{ + if (NULL != break_buffer.targetAddr) { + return 1; + } + return 0; +} + +#endif // CYGPKG_HAL_ARM + +#endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + +// Use this function to disable serial interrupts whenever reply +// characters are expected from GDB. The reason we want to control +// whether the target can be interrupted or not is simply that GDB on +// the host will be sending acknowledge characters/commands while the +// stub is running - if serial interrupts were still active, the +// characters would never reach the (polling) getDebugChar. +static void +interruptible(int state) +{ + static int __interrupts_suspended = 0; + + if (state) { + __interrupts_suspended--; + if (0 >= __interrupts_suspended) { + __interrupts_suspended = 0; +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away + { + hal_virtual_comm_table_t* __chan; + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE); + } +#else + if (__interruptible_control) + __interruptible_control(1); +#endif + } + } else { + __interrupts_suspended++; + if (1 == __interrupts_suspended) +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away + { + hal_virtual_comm_table_t* __chan; + __chan = CYGACC_CALL_IF_DEBUG_PROCS(); + CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); + } +#else + if (__interruptible_control) + __interruptible_control(0); +#endif + } +} + +//----------------------------------------------------------------------------- +// eCos stub entry and exit magic. + +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT +int cyg_hal_gdb_break; +#endif + +#ifdef CYGPKG_REDBOOT +// Trampoline for returning to RedBoot from exception/stub code +static void +return_from_stub(int exit_status) +{ + CYGACC_CALL_IF_MONITOR_RETURN(exit_status); +} +#endif + +// Called at stub *kill* +static void +handle_exception_exit( void ) +{ +#ifdef CYGPKG_REDBOOT +#ifdef CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF + { // Reset the timer to default and cancel any callback + extern void sys_profile_reset(void); + sys_profile_reset(); + } +#endif // CYGSEM_REDBOOT_BSP_SYSCALLS_GPROF + set_pc((target_register_t)return_from_stub); +#else + int i; + + for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++) + registers[i] = orig_registers[i]; +#endif +} + +// Called at stub *entry* +static void +handle_exception_cleanup( void ) +{ +#ifndef CYGPKG_REDBOOT + static int orig_registers_set = 0; +#endif + + interruptible(0); + + // Expand the HAL_SavedRegisters structure into the GDB register + // array format. + HAL_GET_GDB_REGISTERS(®isters[0], _hal_registers); + _registers = ®isters[0]; + +#ifndef CYGPKG_REDBOOT + if (!orig_registers_set) { + int i; + for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++) + orig_registers[i] = registers[i]; + _registers = &orig_registers[0]; + if (__is_breakpoint_function ()) + __skipinst (); + _registers = ®isters[0]; + orig_registers_set = 1; + } +#endif + +#ifdef HAL_STUB_PLATFORM_STUBS_FIXUP + // Some architectures may need to fix the PC in case of a partial + // or fully executed trap instruction. GDB only takes correct action + // when the PC is pointing to the breakpoint instruction it set. + // + // Most architectures would leave PC pointing at the trap + // instruction itself though, and so do not need to do anything + // special. + HAL_STUB_PLATFORM_STUBS_FIXUP(); +#endif + +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + // If we continued instead of stepping, when there was a break set + // ie. we were stepping within a critical region, clear the break, and + // that flag. If we stopped for some other reason, this has no effect. + if ( cyg_hal_gdb_running_step ) { + cyg_hal_gdb_running_step = 0; + cyg_hal_gdb_remove_break(get_register (PC)); + } + + // FIXME: (there may be a better way to do this) + // If we hit a breakpoint set by the gdb interrupt stub, make it + // seem like an interrupt rather than having hit a breakpoint. + cyg_hal_gdb_break = cyg_hal_gdb_remove_break(get_register (PC)); +#endif + +#if defined(HAL_STUB_HW_WATCHPOINT) || defined(HAL_STUB_HW_BREAKPOINT) + // For HW watchpoint/breakpoint support, we need to know if we + // stopped because of watchpoint or hw break. We do that here + // before GDB has a chance to remove the watchpoints and save + // the information for later use in building response packets. + _hw_stop_reason = HAL_STUB_IS_STOPPED_BY_HARDWARE(_watch_data_addr); +#endif +} + +// Called at stub *exit* +static void +handle_exception_init( void ) +{ + // Compact register array again. + HAL_SET_GDB_REGISTERS(_hal_registers, ®isters[0]); + + interruptible(1); +} + + +//----------------------------------------------------------------------------- +// Initialization. + +// Signal handler. +int +cyg_hal_process_signal (int signal) +{ + // We don't care about the signal (atm). + return 0; +} + +// Install the standard set of trap handlers for the stub. +void +__install_traps (void) +{ + // Set signal handling vector so we can treat 'C<signum>' as 'c'. + __process_signal_vec = &cyg_hal_process_signal; + __process_exit_vec = &handle_exception_exit; + + __cleanup_vec = &handle_exception_cleanup; + __init_vec = &handle_exception_init; + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + // Control of GDB interrupts. + __interruptible_control = HAL_STUB_PLATFORM_INTERRUPTIBLE; +#endif +#endif + + // Nothing further to do, handle_exception will be called when an + // exception occurs. +} + +// Initialize the hardware. +void +initHardware (void) +{ + static int initialized = 0; + + if (initialized) + return; + initialized = 1; + + // Get serial port initialized. + HAL_STUB_PLATFORM_INIT_SERIAL(); + +#ifdef HAL_STUB_PLATFORM_INIT + // If the platform defines any initialization code, call it here. + HAL_STUB_PLATFORM_INIT(); +#endif + +#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away +#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT + // Get interrupt handler initialized. + HAL_STUB_PLATFORM_INIT_BREAK_IRQ(); +#endif +#endif // !CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT +} + +// Reset the board. +void +__reset (void) +{ +#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT + __call_if_reset_t *__rom_reset = CYGACC_CALL_IF_RESET_GET(); + if (__rom_reset) + (*__rom_reset)(); +#else + HAL_PLATFORM_RESET(); +#endif +} + +//----------------------------------------------------------------------------- +// Breakpoint support. + +#ifndef CYGPKG_HAL_ARM +// This function will generate a breakpoint exception. It is used at +// the beginning of a program to sync up with a debugger and can be +// used otherwise as a quick means to stop program execution and +// "break" into the debugger. +void +breakpoint() +{ + HAL_BREAKPOINT(_breakinst); +} + +// This function returns the opcode for a 'trap' instruction. +unsigned long +__break_opcode () +{ + return HAL_BREAKINST; +} +#endif + +//----------------------------------------------------------------------------- +// Write the 'T' packet in BUFFER. SIGVAL is the signal the program received. +void +__build_t_packet (int sigval, char *buf) +{ + target_register_t addr; + char *ptr = buf; + target_register_t extend_val = 0; + + *ptr++ = 'T'; + *ptr++ = __tohex (sigval >> 4); + *ptr++ = __tohex (sigval); + +#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT + // Include thread ID if thread manipulation is required. + { + int id = dbg_currthread_id (); + + if (id != 0) { + *ptr++ = 't'; + *ptr++ = 'h'; + *ptr++ = 'r'; + *ptr++ = 'e'; + *ptr++ = 'a'; + *ptr++ = 'd'; + *ptr++ = ':'; + +#if (CYG_BYTEORDER == CYG_LSBFIRST) + // FIXME: Temporary workaround for PR 18903. Thread ID must be + // big-endian in the T packet. + { + unsigned char* bep = (unsigned char*)&id; + int be_id; + + be_id = id; + *bep++ = (be_id >> 24) & 0xff ; + *bep++ = (be_id >> 16) & 0xff ; + *bep++ = (be_id >> 8) & 0xff ; + *bep++ = (be_id & 0xff) ; + } +#endif + ptr = __mem2hex((char *)&id, ptr, sizeof(id), 0); + *ptr++ = ';'; + } + } +#endif + +#ifdef HAL_STUB_HW_WATCHPOINT + switch(_hw_stop_reason) { + case HAL_STUB_HW_STOP_WATCH: + case HAL_STUB_HW_STOP_RWATCH: + case HAL_STUB_HW_STOP_AWATCH: +#ifdef HAL_STUB_HW_SEND_STOP_REASON_TEXT + // Not all GDBs understand this. + strcpy(ptr, _hw_stop_str[_hw_stop_reason]); + ptr += strlen(_hw_stop_str[_hw_stop_reason]); +#endif + *ptr++ = ':'; + // Send address MSB first + ptr += __intToHex(ptr, (target_register_t)_watch_data_addr, + sizeof(_watch_data_addr) * 8); + *ptr++ = ';'; + break; + default: + break; + } +#endif + + *ptr++ = __tohex (PC >> 4); + *ptr++ = __tohex (PC); + *ptr++ = ':'; + addr = get_register (PC); + if (sizeof(addr) < REGSIZE(PC)) + { + // GDB is expecting REGSIZE(PC) number of bytes. + // We only have sizeof(addr) number. Let's fill + // the appropriate number of bytes intelligently. +#ifdef CYGARC_SIGN_EXTEND_REGISTERS + { + unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 + target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); + if ((addr & sign_bit_mask) == sign_bit_mask) + extend_val = ~0; + } +#endif + } +#if (CYG_BYTEORDER == CYG_MSBFIRST) + ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0); +#endif + ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); +#if (CYG_BYTEORDER == CYG_LSBFIRST) + ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0); +#endif + *ptr++ = ';'; + + *ptr++ = __tohex (SP >> 4); + *ptr++ = __tohex (SP); + *ptr++ = ':'; + addr = (target_register_t) get_register (SP); + if (sizeof(addr) < REGSIZE(SP)) + { + // GDB is expecting REGSIZE(SP) number of bytes. + // We only have sizeof(addr) number. Let's fill + // the appropriate number of bytes intelligently. + extend_val = 0; +#ifdef CYGARC_SIGN_EXTEND_REGISTERS + { + unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 + target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); + if ((addr & sign_bit_mask) == sign_bit_mask) + extend_val = ~0; + } +#endif + ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(SP) - sizeof(addr), 0); + } + ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); + *ptr++ = ';'; + + HAL_STUB_ARCH_T_PACKET_EXTRAS(ptr); + + *ptr++ = 0; +} + + +//----------------------------------------------------------------------------- +// Cache functions. + +// Perform the specified operation on the instruction cache. +// Returns 1 if the cache is enabled, 0 otherwise. +int +__instruction_cache (cache_control_t request) +{ + int state = 1; + + switch (request) { + case CACHE_ENABLE: + HAL_ICACHE_ENABLE(); + break; + case CACHE_DISABLE: + HAL_ICACHE_DISABLE(); + state = 0; + break; + case CACHE_FLUSH: + HAL_ICACHE_SYNC(); + break; + case CACHE_NOOP: + /* fall through */ + default: + break; + } + +#ifdef HAL_ICACHE_IS_ENABLED + HAL_ICACHE_IS_ENABLED(state); +#endif + + return state; +} + +// Perform the specified operation on the data cache. +// Returns 1 if the cache is enabled, 0 otherwise. +int +__data_cache (cache_control_t request) +{ + int state = 1; + + switch (request) { + case CACHE_ENABLE: + HAL_DCACHE_ENABLE(); + break; + case CACHE_DISABLE: + HAL_DCACHE_DISABLE(); + state = 0; + break; + case CACHE_FLUSH: + HAL_DCACHE_SYNC(); + break; + case CACHE_NOOP: + /* fall through */ + default: + break; + } +#ifdef HAL_DCACHE_IS_ENABLED + HAL_DCACHE_IS_ENABLED(state); +#endif + + return state; +} + +//----------------------------------------------------------------------------- +// Memory accessor functions. + +// The __mem_fault_handler pointer is volatile since it is only +// set/cleared by the function below - which does not rely on any +// other functions, so the compiler may decide to not bother updating +// the pointer at all. If any of the memory accesses cause an +// exception, the pointer must be set to ensure the exception handler +// can make use of it. + +void* volatile __mem_fault_handler = (void *)0; + +/* These are the "arguments" to __do_read_mem and __do_write_mem, + which are passed as globals to avoid squeezing them thru + __set_mem_fault_trap. */ + +static volatile target_register_t memCount; + +static void +__do_copy_mem (unsigned char* src, unsigned char* dst) +{ + unsigned long *long_dst; + unsigned long *long_src; + unsigned short *short_dst; + unsigned short *short_src; + + // Zero memCount is not really an error, but the goto is necessary to + // keep some compilers from reordering stuff across the 'err' label. + if (memCount == 0) goto err; + + __mem_fault = 1; /* Defaults to 'fail'. Is cleared */ + /* when the copy loop completes. */ + __mem_fault_handler = &&err; + + // See if it's safe to do multi-byte, aligned operations + while (memCount) { + if ((memCount >= sizeof(long)) && + (((target_register_t)dst & (sizeof(long)-1)) == 0) && + (((target_register_t)src & (sizeof(long)-1)) == 0)) { + + long_dst = (unsigned long *)dst; + long_src = (unsigned long *)src; + + *long_dst++ = *long_src++; + memCount -= sizeof(long); + + dst = (unsigned char *)long_dst; + src = (unsigned char *)long_src; + } else if ((memCount >= sizeof(short)) && + (((target_register_t)dst & (sizeof(short)-1)) == 0) && + (((target_register_t)src & (sizeof(short)-1)) == 0)) { + + short_dst = (unsigned short *)dst; + short_src = (unsigned short *)src; + + *short_dst++ = *short_src++; + memCount -= sizeof(short); + + dst = (unsigned char *)short_dst; + src = (unsigned char *)short_src; + } else { + *dst++ = *src++; + memCount--; + } + } + + __mem_fault = 0; + + err: + __mem_fault_handler = (void *)0; +} + +/* + * __read_mem_safe: + * Get contents of target memory, abort on error. + */ + +int +__read_mem_safe (void *dst, void *src, int count) +{ + if( !CYG_HAL_STUB_PERMIT_DATA_READ( src, count ) ) + return 0; + + memCount = count; + __do_copy_mem((unsigned char*) src, (unsigned char*) dst); + return count - memCount; // return number of bytes successfully read +} + +/* + * __write_mem_safe: + * Set contents of target memory, abort on error. + */ + +int +__write_mem_safe (void *src, void *dst, int count) +{ + if( !CYG_HAL_STUB_PERMIT_DATA_READ( dst, count ) ) + return 0; + + memCount = count; + __do_copy_mem((unsigned char*) src, (unsigned char*) dst); + return count - memCount; // return number of bytes successfully written +} + +#ifdef TARGET_HAS_HARVARD_MEMORY +static void +__do_copy_from_progmem (unsigned char* src, unsigned char* dst) +{ + unsigned long *long_dst; + unsigned long *long_src; + unsigned short *short_dst; + unsigned short *short_src; + + // Zero memCount is not really an error, but the goto is necessary to + // keep some compilers from reordering stuff across the 'err' label. + if (memCount == 0) goto err; + + __mem_fault = 1; /* Defaults to 'fail'. Is cleared */ + /* when the copy loop completes. */ + __mem_fault_handler = &&err; + + // See if it's safe to do multi-byte, aligned operations + while (memCount) { + if ((memCount >= sizeof(long)) && + (((target_register_t)dst & (sizeof(long)-1)) == 0) && + (((target_register_t)src & (sizeof(long)-1)) == 0)) { + + long_dst = (unsigned long *)dst; + long_src = (unsigned long *)src; + + *long_dst++ = __read_prog_uint32(long_src++); + memCount -= sizeof(long); + + dst = (unsigned char *)long_dst; + src = (unsigned char *)long_src; + } else if ((memCount >= sizeof(short)) && + (((target_register_t)dst & (sizeof(short)-1)) == 0) && + (((target_register_t)src & (sizeof(short)-1)) == 0)) { + + short_dst = (unsigned short *)dst; + short_src = (unsigned short *)src; + + *short_dst++ = __read_prog_uint16(short_src++); + memCount -= sizeof(short); + + dst = (unsigned char *)short_dst; + src = (unsigned char *)short_src; + } else { + *dst++ = __read_prog_uint8(src++); + memCount--; + } + } + + __mem_fault = 0; + + err: + __mem_fault_handler = (void *)0; +} + +static void +__do_copy_to_progmem (unsigned char* src, unsigned char* dst) +{ + unsigned long *long_dst; + unsigned long *long_src; + unsigned short *short_dst; + unsigned short *short_src; + + // Zero memCount is not really an error, but the goto is necessary to + // keep some compilers from reordering stuff across the 'err' label. + if (memCount == 0) goto err; + + __mem_fault = 1; /* Defaults to 'fail'. Is cleared */ + /* when the copy loop completes. */ + __mem_fault_handler = &&err; + + // See if it's safe to do multi-byte, aligned operations + while (memCount) { + if ((memCount >= sizeof(long)) && + (((target_register_t)dst & (sizeof(long)-1)) == 0) && + (((target_register_t)src & (sizeof(long)-1)) == 0)) { + + long_dst = (unsigned long *)dst; + long_src = (unsigned long *)src; + + __write_prog_uint32(long_dst++, *long_src++); + memCount -= sizeof(long); + + dst = (unsigned char *)long_dst; + src = (unsigned char *)long_src; + } else if ((memCount >= sizeof(short)) && + (((target_register_t)dst & (sizeof(short)-1)) == 0) && + (((target_register_t)src & (sizeof(short)-1)) == 0)) { + + short_dst = (unsigned short *)dst; + short_src = (unsigned short *)src; + + __write_prog_uint16(short_dst++, *short_src++); + memCount -= sizeof(short); + + dst = (unsigned char *)short_dst; + src = (unsigned char *)short_src; + } else { + __write_prog_uint8(dst++, *src++); + memCount--; + } + } + + __mem_fault = 0; + + err: + __mem_fault_handler = (void *)0; +} + +/* + * __read_progmem_safe: + * Get contents of target memory, abort on error. + */ + +int +__read_progmem_safe (void *dst, void *src, int count) +{ + if( !CYG_HAL_STUB_PERMIT_CODE_READ( src, count ) ) + return 0; + + memCount = count; + __do_copy_from_progmem((unsigned char*) src, (unsigned char*) dst); + return count - memCount; // return number of bytes successfully read +} + +/* + * __write_progmem_safe: + * Set contents of target memory, abort on error. + */ + +int +__write_progmem_safe (void *src, void *dst, int count) +{ + if( !CYG_HAL_STUB_PERMIT_CODE_WRITE( dst, count ) ) + return 0; + + memCount = count; + __do_copy_to_progmem((unsigned char*) src, (unsigned char*) dst); + return count - memCount; // return number of bytes successfully written +} +#endif + +//----------------------------------------------------------------------------- +// Target extras?! +int +__process_target_query(char * pkt, char * out, int maxOut) +{ return 0 ; } +int +__process_target_set(char * pkt, char * out, int maxout) +{ return 0 ; } +int +__process_target_packet(char * pkt, char * out, int maxout) +{ return 0 ; } + +// GDB string output, making sure interrupts are disabled. +// This function gets used by some diag output functions. +void +hal_output_gdb_string(target_register_t str, int string_len) +{ + unsigned long __state; + HAL_DISABLE_INTERRUPTS(__state); + __output_gdb_string(str, string_len); + HAL_RESTORE_INTERRUPTS(__state); +} + +#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS diff --git a/ecos/packages/hal/common/current/src/stubrom/stubrom.c b/ecos/packages/hal/common/current/src/stubrom/stubrom.c new file mode 100644 index 0000000..9beb908 --- /dev/null +++ b/ecos/packages/hal/common/current/src/stubrom/stubrom.c @@ -0,0 +1,60 @@ +/*========================================================================== +// +// stubrom.c +// +// GDB Stub ROM main +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 1998-06-02 +// Purpose: GDB Stub ROM main +// Description: Main program for GDB stub ROM. It simply set the debug +// traps and then breakpoints so we can talk to GDB. +// +//####DESCRIPTIONEND#### +// +//========================================================================*/ + +#include <cyg/hal/hal_stub.h> + +void cyg_start (void) +{ + for(;;) breakpoint(); +} + +// End of stubrom.c diff --git a/ecos/packages/hal/common/current/src/thread-packets.c b/ecos/packages/hal/common/current/src/thread-packets.c new file mode 100644 index 0000000..19f80ee --- /dev/null +++ b/ecos/packages/hal/common/current/src/thread-packets.c @@ -0,0 +1,1414 @@ +//======================================================================== +// +// thread-packets.c +// +// Provides multi-threaded debug support +// +//======================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2008 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Red Hat, nickg +// Contributors: Red Hat, nickg +// Date: 1998-08-25 +// Purpose: +// Description: Provides multi-threaded debug support +// Usage: +// +//####DESCRIPTIONEND#### +// +//======================================================================== + +// Define __ECOS__; allows all eCos specific additions to be easily identified. +#define __ECOS__ + + +// #ifdef __ECOS__ +#include <pkgconf/hal.h> + +#if defined(CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT) \ + && defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) +// #endif // __ECOS__ + +/* FIXME: Scan this module for correct sizes of fields in packets */ + +#ifdef __ECOS__ +#include <cyg/hal/dbg-threads-api.h> +#else // __ECOS__ +#include "dbg-threads-api.h" +#endif // __ECOS__ + +/* This file should ALWAYS define debug thread support */ +/* Dont include the object in the link if you dont need the support */ +/* This is NOT the internal unit debug flag, it is a feature control */ +#if defined(DEBUG_THREADS) +#undef DEBUG_THREADS +#endif + +#define DEBUG_THREADS 1 +#define UNIT_TEST 0 +#define GDB_MOCKUP 0 + + +#define STUB_BUF_MAX 300 /* for range checking of packet lengths */ + +#include "thread-pkts.h" + +#ifdef __ECOS__ +// Use HAL rather than board.h in eCos +#include <cyg/hal/hal_stub.h> +#else // __ECOS__ +#include "board.h" +#endif // __ECOS__ + +/* + * Export the continue and "general" (context) thread IDs from GDB. + */ +int _gdb_cont_thread ; +int _gdb_general_thread ; + +#if !defined(PKT_DEBUG) +#define PKT_DEBUG 0 +#endif +extern void output_string(char * message) ; + +#if PKT_DEBUG +void output_threadid(char * title,threadref * ref) ; +#warning "PKT_DEBUG macros engaged" +#define PKT_TRACE(title,packet) \ +{ output_string(title) ; output_string(packet) ; output_string("\n") ;} +#else +#define PKT_TRACE(title,packet) {} +#endif + + +/* This is going to be irregular because the various implementations + have adopted different names for registers. + It would be nice to fix them to have a common convention + _stub_registers + stub_registers + alt_stub_registers + */ + +extern target_register_t * _registers ; + /* A pointer to the current set of registers */ +extern target_register_t registers[]; /* The current saved registers */ +extern target_register_t alt_registers[] ; + /* Thread or saved process state */ + + +static void stub_copy_registers( + target_register_t * dest, + target_register_t *src + ) +{ + target_register_t * limit ; + limit = dest + HAL_STUB_REGISTERS_SIZE ; + + while (dest < limit) *dest++ = *src++ ; +} + +#ifdef __ECOS__ +void __stub_copy_registers(target_register_t * dest, + target_register_t *src) +{ + stub_copy_registers(dest, src); +} +#endif // __ECOS__ + +extern int stubhex(char ch) ; + +/* ----- STUB_PACK_NAK ----------------------------------- */ +/* Pack an error response into the response packet */ + +char * stub_pack_nak(char * outbuf) +{ + *outbuf++ = 'E' ; + *outbuf++ = '0' ; + *outbuf++ = '2' ; + return outbuf ; +} /* stub_pack_nak */ + +/* ----- STUB_PACK_ACK -------------------------- */ +/* Pack an OK achnowledgement */ +char * stub_pack_ack(char * outbuf) +{ + *outbuf++ = 'O' ; + *outbuf++ = 'K' ; + return outbuf ; +} /* stub_pack_ack */ + +/* ------- STUB_UNPACK_INT ------------------------------- */ +/* Unpack a few bytes and return its integer value */ +/* This is where I wish functions could return several values + I would also advance the buffer pointer */ + +int stub_unpack_int(char * buff,int fieldlength) +{ + int retval = 0 ; + int nibble ; + while (fieldlength) + { nibble = stubhex(*buff++) ; + retval |= nibble ; + fieldlength-- ; + if (fieldlength) retval = retval << 4 ; + } + return retval ; +} /* stub_unpack_int */ + +static char * unpack_byte(char * buf, int * value) +{ + *value = stub_unpack_int(buf,2) ; + return buf + 2 ; +} + +static char * unpack_int(char * buf, int * value) +{ + *value = stub_unpack_int(buf,8) ; + return buf + 8 ; +} + +/* We are NOT depending upon extensive libraries */ +static int ishex(char ch,int *val) +{ + if ((ch >= 'a') && (ch <= 'f')) + { *val =ch - 'a' + 10 ; return 1 ; } + if ((ch >= 'A') && (ch <= 'F')) + { *val = ch - 'A' + 10 ; return 1 ;} + if ((ch >= '0') && (ch <= '9')) + { *val = ch - '0' ; return 1 ; } + return 0 ; +} /* ishex */ + +static char * unpack_nibble(char * buf,int * val) +{ + ishex(*buf++,val) ; + return buf ; +} + + +static const char hexchars[] = "0123456789abcdef"; + +static char * pack_hex_byte(char * pkt, unsigned char byte) +{ + *pkt++ = hexchars[(byte >> 4) & 0xf] ; + *pkt++ = hexchars[(byte & 0xf)] ; + return pkt ; +} /* pack_hex_byte */ + +#ifndef __ECOS__ +/* ---- STUB_PACK_VARLEN_HEX ------------------------------------- */ +/* Format a variable length stream of hex bytes */ + +static char * pack_varlen_hex( + char * pkt, + unsigned int value) +{ + int i ; + static unsigned char n[8] ; + if (value == 0) + { + *pkt++ = '0' ; + return pkt ; + } + else + { + i = 8 ; + while (i-- >= 0 ) /* unpack nibbles into a char array */ + { + n[i] = value & 0x0f ; + value = value >> 4 ; + } + i = 0 ; /* we had decrmented it to -1 */ + while (n[i] == 0 ) i++ ; /* drop leading zeroes */ + while (i++ < 8) *pkt++ = hexchars[n[i]] ; /* pack the number */ + } + return pkt ; +} /* pack_varlen_hex */ +#endif // !__ECOS__ + + +/* ------ STUB_UNPACK_VARLEN_HEX -------------------------------- */ +/* Parse a stream of hex bytes which may be of variable length */ +/* return the pointer to the next char */ +/* modify a varparm containing the result */ +/* A failure would look like a non-increment of the buffer pointer */ + +/* This unpacks hex strings that may have been packed using sprintf(%x) */ +/* We assume some non-hex delimits them */ + +char * unpack_varlen_hex( + char * buff, /* packet to parse */ + int * result) +{ + int nibble ; + int retval ; + retval = 0 ; + + while (ishex(*buff,&nibble)) + { + buff++ ; + retval = retval << 4 ; + retval |= nibble & 0x0f ; + } + *result = retval ; + return buff ; +} /* stub_unpack_varlen_int */ + + +/* ------ UNPACK_THREADID ------------------------------- */ +/* A threadid is a 64 bit quantity */ + +#define BUFTHREADIDSIZ 16 /* encode 64 bits in 16 chars of hex */ + +static char * unpack_threadid(char * inbuf, threadref * id) +{ + char * altref ; + char * limit = inbuf + BUFTHREADIDSIZ ; + int x,y ; + altref = (char *) id ; + + while (inbuf < limit) + { + x = stubhex(*inbuf++) ; + y = stubhex(*inbuf++) ; + *altref++ = (x << 4) | y ; + } + return inbuf ; +} /* unpack_threadid */ + + + +/* Pack an integer use leading zeroes */ +static char * pack_int(char * buf,int value) +{ + buf = pack_hex_byte(buf,(value>> 24)& 0xff) ; + buf = pack_hex_byte(buf,(value >>16)& 0xff) ; + buf = pack_hex_byte(buf,(value >>8) & 0x0ff) ; + buf = pack_hex_byte(buf,(value & 0xff)) ; + return buf ; +} /* pack_int */ + + +/* -------- PACK_STRING ---------------------------------------------- */ +/* This stupid string better not contain any funny characters */ +/* Also, the GDB protocol will not cope with NULLs in the + string or at the end of it. + While is is posable to encapsulate the protocol in ays that + preclude filtering for # I am assuming this is a constraint. +*/ + +static char * pack_raw_string(char * pkt,char * string) +{ + char ch ; + while (0 != (ch = *string++)) *pkt++ = ch ; + return pkt ; +} + +static char * pack_string( + char * pkt, + char * string) +{ + char ch ; +#ifdef __ECOS__ + int len = 0; + char *s = string; + while( *s++ ) len++; +#else // __ECOS__ + int len ; + len = strlen(string) ; +#endif // __ECOS + if (len > 200 ) len = 200 ; /* Bigger than most GDB packets, junk??? */ + pkt = pack_hex_byte(pkt,len) ; + while (len-- > 0) + { + ch = *string++ ; + if ((ch == '\0') || (ch == '#')) ch = '*' ; /* Protect encapsulation */ + *pkt++ = ch ; + } + return pkt ; +} /* pack_string */ + + +/* ----- STUB_PACK_THREADID --------------------------------------------- */ +/* Convert a binary 64 bit threadid and pack it into a xmit buffer */ +/* Return the advanced buffer pointer */ + +static char * pack_threadid(char * pkt, threadref * id) +{ + char * limit ; + unsigned char * altid ; + altid = (unsigned char *) id ; + limit = pkt + BUFTHREADIDSIZ ; + while (pkt < limit) pkt = pack_hex_byte(pkt,*altid++) ; + return pkt ; +} /* stub_pack_threadid */ + +/* UNFORTUNATELY, not all of the extended debugging system has yet been + converted to 64 but thread references and process identifiers. + These routines do the conversion. + An array of bytes is the correct treatment of an opaque identifier. + ints have endian issues. + */ + +static void int_to_threadref(threadref * id, int value) +{ + unsigned char * scan ; + scan = (unsigned char *) id ; + { + int i = 4 ; + while (i--) *scan++ = 0 ; + } + *scan++ = (value >> 24) & 0xff ; + *scan++ = (value >> 16) & 0xff ; + *scan++ = (value >> 8) & 0xff ; + *scan++ = (value & 0xff) ; +} + +static int threadref_to_int(threadref * ref) +{ + int value = 0 ; + unsigned char * scan ; + int i ; + + scan = (unsigned char *) ref ; + scan += 4 ; + i = 4 ; + while (i-- > 0) value = (value << 8) | ((*scan++) & 0xff) ; + return value ; +} /* threadref_to_int */ + +void copy_threadref(threadref * dest, threadref * src) +{ + int i ; + unsigned char * csrc, * cdest ; + csrc = (unsigned char *) src ; + cdest = (unsigned char *) dest ; + i = 8 ; + while (i--) *cdest++ = *csrc++ ; +} + + +int threadmatch( + threadref * dest , + threadref * src + ) +{ + unsigned char * srcp, * destp ; + int i , result ; + srcp = (unsigned char *) src ; + destp = (unsigned char *) dest ; + i = 8 ; + result = 1 ; + while (i-- > 0 ) result &= (*srcp++ == *destp++) ? 1 : 0 ; + return result ; +} /* threadmatch */ + + + +static char * Tpkt_threadtag = "thread:" ; + +/* ----- STUB_PACK_TPKT_THREADID ------------------------------------ */ +/* retreive, tag and insert a thread identifier into a T packet. */ +/* Insert nothing if the thread identifier is not available */ + +char * stub_pack_Tpkt_threadid(char * pkt) +{ + static threadref thread ; + int fmt = 0 ; /* old format */ + PKT_TRACE("Tpkt-id","---") ; + if (dbg_currthread(&thread)) + { + pkt = pack_raw_string(pkt,Tpkt_threadtag) ; + if (fmt) + pkt = pack_threadid(pkt,&thread) ; + else + /* Until GDB lengthens its thread ids, we have to MASH + the threadid into somthing shorter. PLEASE FIX GDB */ + pkt = pack_int(pkt,threadref_to_int(&thread)) ; + *pkt++ = ';' ; /* terminate variable length int */ + *pkt = '\0' ; /* Null terminate to allow string to be printed, no++ */ + } + PKT_TRACE("packedTpkt","--") ; + return pkt ; +} /* stub_pack_Tpkt_threadid */ + +long stub_get_currthread (void) +{ + threadref thread ; + + if (dbg_currthread(&thread)) + return threadref_to_int(&thread) ; + else + return 0 ; +} + +void stub_pkt_currthread( + char * inbuf, + char * outbuf, + int bufmax) +{ + threadref thread ; +#if PKT_DEBUG + char * base_out ; + base_out = outbuf ; +#endif + if (dbg_currthread(&thread)) + { + *outbuf++ = 'Q' ; + *outbuf++ = 'C' ; /* FIXME: Is this a reasonable code */ + outbuf = pack_int(outbuf, threadref_to_int(&thread)) ; /* Short form */ + } + else outbuf = stub_pack_nak(outbuf) ; + *outbuf = '\0' ; /* terminate response packet */ + PKT_TRACE("stub_pkt_currthread(resp) ",base_out) ; +} /* stub_pkt_currthread */ + +/* ----- STUB_PKT_THREAD_ALIVE --------------------------------- */ +/* Answer the thread alive query */ + +static int thread_alive (int id) +{ + threadref thread ; + struct cygmon_thread_debug_info info ; + + int_to_threadref(&thread, id) ; + if (dbg_threadinfo(&thread, &info) && + info.context_exists) + return 1 ; + else + return 0 ; +} + +void stub_pkt_thread_alive(char * inbuf, + char * outbuf, + int bufmax) +{ + char * prebuf = inbuf ; + int result ; + + if (prebuf != (inbuf = unpack_varlen_hex(inbuf,&result))) + { + if (thread_alive(result)) + { + outbuf = stub_pack_ack(outbuf) ; + *outbuf = '\0' ; + return ; + } + } + outbuf = stub_pack_nak(outbuf) ; + *outbuf = '\0' ; /* terminate the response message */ +} /* stub_pkt_thread_alive */ + + + +/* ----- STUB_PKT_CHANGETHREAD ------------------------------- */ +/* Switch the display of registers to that of a saved context */ + +/* Changing the context makes NO sense, although the packets define the + capability. Therefore, the option to change the context back does + call the function to change registers. Also, there is no + forced context switch. + 'p' - New format, long long threadid, no special cases + 'c' - Old format, id for continue, 32 bit threadid max, possably less + -1 means continue all threads + 'g' - Old Format, id for general use (other than continue) + + replies: + OK for success + ENN for error + */ + +void stub_pkt_changethread( + char * inbuf, + char * outbuf, + int bufmax) +{ + threadref id ; + int idefined = -1 ; + char ch ; + PKT_TRACE("setthread-pkt ",inbuf) ; + + /* Parse the incoming packet for a thread identifier */ + switch (ch = *inbuf++ ) /* handle various packet formats */ + { + case 'p' : /* New format: mode:8,threadid:64 */ + inbuf = unpack_nibble(inbuf,&idefined) ; + inbuf = unpack_threadid(inbuf,&id) ; /* even if startflag */ + break ; + case 'c' : /* old format , specify thread for continue */ + if (inbuf[0] == '-' && inbuf[1] == '1') /* Hc-1 */ + _gdb_cont_thread = 0 ; + else + inbuf = unpack_varlen_hex(inbuf, &_gdb_cont_thread) ; + + if (_gdb_cont_thread == 0 || /* revert to any old thread */ + thread_alive(_gdb_cont_thread)) /* specified thread is alive */ + outbuf = stub_pack_ack(outbuf) ; + else + outbuf = stub_pack_nak(outbuf) ; + break ; + case 'g' : /* old format, specify thread for general operations */ + /* OLD format: parse a variable length hex string */ + /* OLD format consider special thread ids */ + { + inbuf = unpack_varlen_hex(inbuf, &_gdb_general_thread) ; + int_to_threadref(&id, _gdb_general_thread) ; + switch (_gdb_general_thread) + { + case 0 : /* pick a thread, any thread */ + idefined = 2 ; /* select original interrupted context */ + break ; + case -1 : /* all threads */ + idefined = 2 ; + break ; + default : + idefined = 1 ; /* select the specified thread */ + break ; + } + } + break ; + default: + outbuf = stub_pack_nak(outbuf) ; + break ; + } /* handle various packet formats */ + + switch (idefined) + { + case -1 : + /* Packet not supported, already NAKed, no further action */ + break ; + case 0 : + /* Switch back to interrupted context */ + _registers = ®isters[0] ; + break ; + case 1 : + /* copy the saved registers into the backup registers */ + stub_copy_registers(alt_registers,registers) ; + /* The OS will now update the values it has in a saved process context*/ + if (dbg_getthreadreg(&id,NUMREGS,&alt_registers[0])) + { + /* switch the registers pointer */ + _registers = &alt_registers[0] ; + outbuf = stub_pack_ack(outbuf) ; + } + else + outbuf = stub_pack_nak(outbuf) ; + break ; + case 2 : + /* switch to interrupted context */ + outbuf = stub_pack_ack(outbuf) ; + break ; + default: + outbuf = stub_pack_nak(outbuf) ; + break ; + } + *outbuf = '\0' ; /* Terminate response pkt */ +} /* stub_pkt_changethread */ + + +/* ---- STUB_PKT_GETTHREADLIST ------------------------------- */ +/* Get a portion of the threadlist or process list */ +/* This may be part of a multipacket transaction */ +/* It would be hard to tell in the response packet the difference + between the end of list and an error in threadid encoding. + */ + +void stub_pkt_getthreadlist(char * inbuf, + char * outbuf, + int bufmax) +{ + char * count_ptr ; + char * done_ptr ; + char * limit ; + int start_flag , batchsize , result , count ; + static threadref lastthread, nextthread ; + +#if PKT_DEBUG + char * r_base = outbuf ; +#endif + PKT_TRACE("pkt_getthreadlist: ",inbuf) ; + + count = 0 ; + inbuf = unpack_nibble(inbuf,&start_flag) ; + inbuf = unpack_byte(inbuf,&batchsize) ; + inbuf = unpack_threadid(inbuf,&lastthread) ; /* even if startflag */ + + /* Start building response packet */ + limit = outbuf + (bufmax - BUFTHREADIDSIZ - 10) ; /* id output packing limit */ + *outbuf++ = 'Q' ; + *outbuf++ = 'M' ; + + /* Default values for count and done fields, save ptr to repatch */ + count_ptr = outbuf ; /* save to repatch count */ + outbuf = pack_hex_byte(outbuf,0) ; + done_ptr = outbuf ; /* Backpatched later */ + *outbuf++ = '0' ; /* Done = 0 by default */ + outbuf = pack_threadid(outbuf,&lastthread) ; + + /* Loop through the threadid packing */ + while ((outbuf < limit) && (count < batchsize)) + { + result = dbg_threadlist(start_flag,&lastthread,&nextthread) ; + start_flag = 0 ; /* redundant but effective */ + if (!result) + { *done_ptr = '1' ; /* pack the done flag */ + break ; + } +#if 0 /* DEBUG */ + if (threadmatch(&lastthread,&nextthread)) + { + output_string("FAIL: Threadlist, not incrementing\n") ; + *done_ptr = '1' ; + break ; + } +#endif + count++ ; + outbuf = pack_threadid(outbuf,&nextthread) ; + copy_threadref(&lastthread,&nextthread) ; + } + pack_hex_byte(count_ptr,count) ;/* backpatch, Pack the count field */ + *outbuf = '\0' ; + PKT_TRACE("pkt_getthreadlist(resp) ",r_base) ; +} /* pkt_getthreadlist */ + + + + +/* ----- STUB_PKT_GETTHREADINFO ---------------------------------------- */ +/* Get the detailed information about a specific thread or process */ + +/* +Encoding: + 'Q':8,'P':8,mask:16 + + Mask Fields + threadid:1, # always request threadid + context_exists:2, + display:4, + unique_name:8, + more_display:16 + */ + +void stub_pkt_getthreadinfo( + char * inbuf, + char * outbuf, + int bufmax) +{ + int mask ; + int result ; + threadref thread ; + struct cygmon_thread_debug_info info ; + + info.context_exists = 0 ; + info.thread_display = 0 ; + info.unique_thread_name = 0 ; + info.more_display = 0 ; + + /* Assume the packet identification chars have already been + discarded by the packet demultiples routines */ + PKT_TRACE("PKT getthreadinfo",inbuf) ; + + inbuf = unpack_int(inbuf,&mask) ; + inbuf = unpack_threadid(inbuf,&thread) ; + + result = dbg_threadinfo(&thread,&info) ; /* Make system call */ + + if (result) + { + *outbuf++ = 'q' ; + *outbuf++ = 'p' ; + outbuf = pack_int(outbuf,mask) ; + outbuf = pack_threadid(outbuf,&info.thread_id) ; /* echo threadid */ + if (mask & 2) /* context-exists */ + { + outbuf = pack_int(outbuf,2) ; /* tag */ + outbuf = pack_hex_byte(outbuf,2) ; /* length */ + outbuf = pack_hex_byte(outbuf,info.context_exists) ; + } + if ((mask & 4) && info.thread_display)/* display */ + { + outbuf = pack_int(outbuf,4) ; /* tag */ + outbuf = pack_string(outbuf,info.thread_display) ; + } + if ((mask & 8) && info.unique_thread_name) /* unique_name */ + { + outbuf = pack_int(outbuf,8) ; + outbuf = pack_string(outbuf,info.unique_thread_name) ; + } + if ((mask & 16) && info.more_display) /* more display */ + { + outbuf = pack_int(outbuf,16) ; /* tag 16 */ + outbuf = pack_string(outbuf,info.more_display) ; + } + } + else + { + PKT_TRACE("FAIL: dbg_threadinfo\n", "") ; + outbuf = stub_pack_nak(outbuf) ; + } + *outbuf = '\0' ; +} /* stub_pkt_getthreadinfo */ + +int stub_lock_scheduler(int lock, /* 0 to unlock, 1 to lock */ + int mode, /* 0 for step, 1 for continue */ + long id) /* current thread */ +{ + threadref thread; + + int_to_threadref(&thread, id) ; + return dbg_scheduler(&thread, lock, mode) ; +} + + +#if GDB_MOCKUP +/* ------ MATCHED GDB SIDE PACKET ENCODING AND PARSING ----------------- */ + +char * pack_nibble(char * buf, int nibble) +{ + *buf++ = hexchars[(nibble & 0x0f)] ; + return buf ; +} /* pack_nibble */ + +#if 0 +static char * unpack_short(char * buf,int * value) +{ + *value = stub_unpack_int(buf,4) ; + return buf + 4 ; +} + +static char * pack_short( + char * buf, + unsigned int value) +{ + buf = pack_hex_byte(buf,(value >> 8) & 0xff) ; + buf = pack_hex_byte(buf,(value & 0xff)) ; + return buf ; +} /* pack_short */ +#endif + + +/* Generally, I dont bury xmit and receive calls inside packet formatters + and parsers + */ + + + + +/* ----- PACK_SETTHREAD_REQUEST ------------------------------------- */ +/* Encoding: ??? decode gdb/remote.c + 'Q':8,'p':8,idefined:8,threadid:32 ; + */ + +char * pack_setthread_request( + char * buf, + char fmt, /* c,g or, p */ + int idformat , + threadref * threadid ) +{ + *buf++ = fmt ; + + if (fmt == 'p') + { /* pack the long form */ + buf = pack_nibble(buf,idformat) ; + buf = pack_threadid(buf,threadid) ; + } + else + { /* pack the shorter form - Serious truncation */ + /* There are reserved identifieds 0 , -1 */ + int quickref = threadref_to_int(threadid) ; + buf = pack_varlen_hex(buf,quickref) ; + } + *buf++ = '\0' ; /* end_of_packet */ + return buf ; +} /* pack_setthread_request */ + + + +/* -------- PACK_THREADLIST-REQUEST --------------------------------- */ +/* Format: i'Q':8,i"L":8,initflag:8,batchsize:16,lastthreadid:32 */ + + +char * pack_threadlist_request( + char * pkt, + int startflag, + int threadcount, + threadref * nextthread + ) +{ + *pkt++ = 'q' ; + *pkt++ = 'L' ; + pkt = pack_nibble(pkt,startflag) ; /* initflag 1 bytes */ + pkt = pack_hex_byte(pkt,threadcount) ; /* threadcount 2 bytes */ + pkt = pack_threadid(pkt,nextthread) ; /* 64 bit thread identifier */ + *pkt = '\0' ; + return pkt ; +} /* remote_threadlist_request */ + + + + +/* ---------- PARSE_THREADLIST_RESPONSE ------------------------------------ */ +/* Encoding: 'q':8,'M':8,count:16,done:8,argthreadid:64,(threadid:64)* */ + +int parse_threadlist_response( + char * pkt, + threadref * original_echo, + threadref * resultlist, + int * doneflag) +{ + char * limit ; + int count, resultcount , done ; + resultcount = 0 ; + + /* assume the 'q' and 'M chars have been stripped */ + PKT_TRACE("parse-threadlist-response ",pkt) ; + limit = pkt + (STUB_BUF_MAX - BUFTHREADIDSIZ) ; /* done parse past here */ + pkt = unpack_byte(pkt,&count) ; /* count field */ + pkt = unpack_nibble(pkt,&done) ; + /* The first threadid is the argument threadid */ + pkt = unpack_threadid(pkt,original_echo) ; /* should match query packet */ + while ((count-- > 0) && (pkt < limit)) + { + pkt = unpack_threadid(pkt,resultlist++) ; + resultcount++ ; + } + if (doneflag) *doneflag = done ; + return resultcount ; /* successvalue */ +} /* parse_threadlist_response */ + +struct gdb_ext_thread_info +{ + threadref threadid ; + int active ; + char display[256] ; + char shortname[32] ; + char more_display[256] ; +} ; + + +/* ----- PACK_THREAD_INFO_REQUEST -------------------------------- */ + +/* + threadid:1, # always request threadid + context_exists:2, + display:4, + unique_name:8, + more_display:16 + */ + +/* Encoding: 'Q':8,'P':8,mask:32,threadid:64 */ + +char * pack_threadinfo_request(char * pkt, + int mode, + threadref * id + ) +{ + *pkt++ = 'Q' ; + *pkt++ = 'P' ; + pkt = pack_int(pkt,mode) ; /* mode */ + pkt = pack_threadid(pkt,id) ; /* threadid */ + *pkt = '\0' ; /* terminate */ + return pkt ; +} /* pack_thread_info_request */ + + + +static char * unpack_string( + char * src, + char * dest, + int length) +{ + while (length--) *dest++ = *src++ ; + *dest = '\0' ; + return src ; +} /* unpack_string */ + + +void output_threadid(char * title,threadref * ref) +{ + char hexid[20] ; + pack_threadid(&hexid[0],ref) ; /* Convert threead id into hex */ + hexid[16] = 0 ; + output_string(title) ; + output_string(&hexid[0]) ; + output_string("\n") ; +} + +/* ------ REMOTE_UPK_THREAD_INFO_RESPONSE ------------------------------- */ +/* Unpack the response of a detailed thread info packet */ +/* Encoding: i'Q':8,i'R':8,argmask:16,threadid:64,(tag:8,length:16,data:x)* */ + +#define TAG_THREADID 1 +#define TAG_EXISTS 2 +#define TAG_DISPLAY 4 +#define TAG_THREADNAME 8 +#define TAG_MOREDISPLAY 16 + + +int remote_upk_thread_info_response( + char * pkt, + threadref * expectedref , + struct gdb_ext_thread_info * info) +{ + int mask, length ; + unsigned int tag ; + threadref ref ; + char * limit = pkt + 500 ; /* plausable parsing limit */ + int retval = 1 ; + + PKT_TRACE("upk-threadinfo ",pkt) ; + + /* info->threadid = 0 ; FIXME: implement zero_threadref */ + info->active = 0 ; + info->display[0] = '\0' ; + info->shortname[0] = '\0' ; + info->more_display[0] = '\0' ; + + /* Assume the characters indicating the packet type have been stripped */ + pkt = unpack_int(pkt,&mask) ; /* arg mask */ + pkt = unpack_threadid(pkt , &ref) ; + + if (! threadmatch(&ref,expectedref)) + { /* This is an answer to a different request */ + output_string("FAIL Thread mismatch\n") ; + output_threadid("ref ",&ref) ; + output_threadid("expected ",expectedref) ; + return 0 ; + } + copy_threadref(&info->threadid,&ref) ; + + /* Loop on tagged fields , try to bail if somthing goes wrong */ + if (mask==0) output_string("OOPS NO MASK \n") ; + + while ((pkt < limit) && mask && *pkt) /* packets are terminated with nulls */ + { + pkt = unpack_int(pkt,&tag) ; /* tag */ + pkt = unpack_byte(pkt,&length) ; /* length */ + if (! (tag & mask)) /* tags out of synch with mask */ + { + output_string("FAIL: threadinfo tag mismatch\n") ; + retval = 0 ; + break ; + } + if (tag == TAG_THREADID) + { + output_string("unpack THREADID\n") ; + if (length != 16) + { + output_string("FAIL: length of threadid is not 16\n") ; + retval = 0 ; + break ; + } + pkt = unpack_threadid(pkt,&ref) ; + mask = mask & ~ TAG_THREADID ; + continue ; + } + if (tag == TAG_EXISTS) + { + info->active = stub_unpack_int(pkt,length) ; + pkt += length ; + mask = mask & ~(TAG_EXISTS) ; + if (length > 8) + { + output_string("FAIL: 'exists' length too long\n") ; + retval = 0 ; + break ; + } + continue ; + } + if (tag == TAG_THREADNAME) + { + pkt = unpack_string(pkt,&info->shortname[0],length) ; + mask = mask & ~TAG_THREADNAME ; + continue ; + } + if (tag == TAG_DISPLAY) + { + pkt = unpack_string(pkt,&info->display[0],length) ; + mask = mask & ~TAG_DISPLAY ; + continue ; + } + if (tag == TAG_MOREDISPLAY) + { + pkt = unpack_string(pkt,&info->more_display[0],length) ; + mask = mask & ~TAG_MOREDISPLAY ; + continue ; + } + output_string("FAIL: unknown info tag\n") ; + break ; /* Not a tag we know about */ + } + return retval ; +} /* parse-thread_info_response */ + + +/* ---- REMOTE_PACK_CURRTHREAD_REQUEST ---------------------------- */ +/* This is a request to emit the T packet */ + +/* FORMAT: 'q':8,'C' */ + +char * remote_pack_currthread_request(char * pkt ) +{ + *pkt++ = 'q' ; + *pkt++ = 'C' ; + *pkt = '\0' ; + return pkt ; +} /* remote_pack_currthread_request */ + + +/* ------- REMOTE_UPK_CURTHREAD_RESPONSE ----------------------- */ +/* Unpack the interesting part of a T packet */ + + +int remote_upk_currthread_response( + char * pkt, + int *thr ) /* Parse a T packet */ +{ + int retval = 0 ; + PKT_TRACE("upk-currthreadresp ",pkt) ; + +#if 0 + { + static char threadtag[8] = "thread" ; + int retval = 0 ; + int i , found ; + char ch ; + int quickid ; + + /* Unpack as a t packet */ + while (((ch = *pkt++) != ':') /* scan for : thread */ + && (ch != '\0')) /* stop at end of packet */ + + { + found = 0 ; + i = 0 ; + while ((ch = *pkt++) == threadtag[i++]) ; + if (i == 8) /* string match "thread" */ + { + pkt = unpack_varlen_hex(pkt,&quickid) ; + retval = 1; + break ; + } + retval = 0 ; + } + } +#else + pkt = unpack_threadid(pkt, thr) ; + retval = 1 ; +#endif + return retval ; +} /* remote_upk_currthread_response */ + + +/* -------- REMOTE_UPK-SIMPLE_ACK --------------------------------- */ +/* Decode a response which is eother "OK" or "Enn" + fillin error code, fillin pkfag-1== undef, 0==nak, 1 == ack ; + return advanced packet pointer */ + + +char * remote_upk_simple_ack( + char * buf, + int * pkflag, + int * errcode) +{ + int lclerr = 0 ; + char ch = *buf++ ; + int retval = -1 ; /* Undefined ACK , a protocol error */ + if (ch == 'E') /* NAK */ + { + buf = unpack_byte(buf,&lclerr) ; + retval = 0 ; /* transaction failed, explicitly */ + } + else + if ((ch == 'O') && (*buf++ == 'K')) /* ACK */ + retval = 1 ; /* transaction succeeded */ + *pkflag = retval ; + *errcode = lclerr ; + return buf ; +} /* remote-upk_simple_ack */ + + +/* -------- PACK_THREADALIVE_REQUEST ------------------------------- */ + +char * pack_threadalive_request( + char * buf, + threadref * threadid) +{ + *buf++ = 'T' ; + buf = pack_threadid(buf,threadid) ; + *buf = '\0' ; + return buf ; +} /* pack_threadalive_request */ + +#endif /* GDB_MOCKUP */ + +/* ---------------------------------------------------------------------- */ +/* UNIT_TESTS SUBSECTION */ +/* ---------------------------------------------------------------------- */ + + +#if UNIT_TEST +extern void output_string(char * message) ; +static char test_req[400] ; +static char t_response[400] ; + + + +/* ----- DISPLAY_THREAD_INFO ---------------------------------------------- */ +/* Use local cygmon string output utiities */ + +void display_thread_info(struct gdb_ext_thread_info * info) +{ + + output_threadid("Threadid: ",&info->threadid) ; + /* short name */ + output_string("Name: ") ; output_string(info->shortname) ; output_string("\n"); + /* format display state */ + output_string("State: ") ; output_string(info->display) ; output_string("\n") ; + /* additional data */ + output_string("other: ");output_string(info->more_display); + output_string("\n\n"); +} /* display_thread_info */ + + +/* --- CURRTHREAD-TEST -------------------------------------------- */ +static int currthread_test(threadref * thread) +{ + int result ; + int threadid ; + output_string("TEST: currthread\n") ; + remote_pack_currthread_request(test_req) ; + stub_pkt_currthread(test_req+2,t_response,STUB_BUF_MAX) ; + result = remote_upk_currthread_response(t_response+2, &threadid) ; + if (result) + { + output_string("PASS getcurthread\n") ; + /* FIXME: print the thread */ + } + else + output_string("FAIL getcurrthread\n") ; + return result ; +} /* currthread_test */ + +/* ------ SETTHREAD_TEST ------------------------------------------- */ + /* use a known thread from previous test */ + +static int setthread_test(threadref * thread) +{ + int result, errcode ; + output_string("TEST: setthread\n") ; + + pack_setthread_request(test_req,'p',1,thread) ; + stub_pkt_changethread(test_req,t_response,STUB_BUF_MAX) ; + remote_upk_simple_ack(t_response,&result,&errcode) ; + switch (result) + { + case 0 : + output_string("FAIL setthread\n") ; + break ; + case 1 : + output_string("PASS setthread\n") ; + break ; + default : + output_string("FAIL setthread -unrecognized response\n") ; + break ; + } + return result ; +} /* setthread_test */ + + +/* ------ THREADACTIVE_TEST ---------------------- */ + /* use known thread */ + /* pack threadactive packet */ + /* process threadactive packet */ + /* parse threadactive response */ + /* check results */ + + +int threadactive_test(threadref * thread) +{ + int result ; + int errcode ; + output_string("TEST: threadactive\n") ; + pack_threadalive_request(test_req,thread) ; + stub_pkt_thread_alive(test_req+1,t_response,STUB_BUF_MAX); + remote_upk_simple_ack(t_response,&result,&errcode) ; + switch (result) + { + case 0 : + output_string("FAIL threadalive\n") ; + break ; + case 1 : + output_string("PASS threadalive\n") ; + break ; + default : + output_string("FAIL threadalive -unrecognized response\n") ; + break ; + } + return result ; +} /* threadactive_test */ + +/* ------ REMOTE_GET_THREADINFO -------------------------------------- */ +int remote_get_threadinfo( + threadref * threadid, + int fieldset , /* TAG mask */ + struct gdb_ext_thread_info * info + ) +{ + int result ; + pack_threadinfo_request(test_req,fieldset,threadid) ; + stub_pkt_getthreadinfo(test_req+2,t_response,STUB_BUF_MAX) ; + result = remote_upk_thread_info_response(t_response+2,threadid,info) ; + return result ; +} /* remote_get-thrreadinfo */ + + +static struct gdb_ext_thread_info test_info ; + +static int get_and_display_threadinfo(threadref * thread) +{ + int mode ; + int result ; + /* output_string("TEST: get and display threadinfo\n") ; */ + + mode = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME + | TAG_MOREDISPLAY | TAG_DISPLAY ; + result = remote_get_threadinfo(thread,mode,&test_info) ; + if (result) display_thread_info(&test_info) ; +#if 0 /* silent subtest */ + if (result) + output_string("PASS: get_and_display threadinfo\n") ; + else + output_string("FAIL: get_and_display threadinfo\n") ; +#endif + return result ; +} /* get-and-display-threadinfo */ + + + +/* ----- THREADLIST_TEST ------------------------------------------ */ +#define TESTLISTSIZE 16 +#define TLRSIZ 2 +static threadref test_threadlist[TESTLISTSIZE] ; + +static int threadlist_test(void) +{ + int done, i , result_count ; + int startflag = 1 ; + int result = 1 ; + int loopcount = 0 ; + static threadref nextthread ; + static threadref echo_nextthread ; + + output_string("TEST: threadlist\n") ; + + done = 0 ; + while (! done) + { + if (loopcount++ > 10) + { + result = 0 ; + output_string("FAIL: Threadlist test -infinite loop-\n") ; + break ; + } + pack_threadlist_request(test_req,startflag,TLRSIZ,&nextthread) ; + startflag = 0 ; /* clear for later iterations */ + stub_pkt_getthreadlist(test_req+2,t_response,STUB_BUF_MAX); + result_count = parse_threadlist_response(t_response+2, + &echo_nextthread, + &test_threadlist[0],&done) ; + if (! threadmatch(&echo_nextthread,&nextthread)) + { + output_string("FAIL: threadlist did not echo arg thread\n"); + result = 0 ; + break ; + } + if (result_count <= 0) + { + if (done != 0) + { output_string("FAIL threadlist_test, failed to get list"); + result = 0 ; + } + break ; + } + if (result_count > TLRSIZ) + { + output_string("FAIL: threadlist response longer than requested\n") ; + result = 0 ; + break ; + } + /* Setup to resume next batch of thread references , set nestthread */ + copy_threadref(&nextthread,&test_threadlist[result_count-1]) ; + /* output_threadid("last-of-batch",&nextthread) ; */ + i = 0 ; + while (result_count--) + { + if (0) /* two display alternatives */ + output_threadid("truncatedisplay",&test_threadlist[i++]) ; + else + get_and_display_threadinfo(&test_threadlist[i++]) ; + } + + } + if (!result) + output_string("FAIL: threadlist test\n") ; + else output_string("PASS: Threadlist test\n") ; + return result ; +} /* threadlist_test */ + + +static threadref testthread ; + + +int test_thread_support(void) +{ + int result = 1 ; + output_string("TESTING Thread support infrastructure\n") ; + stub_pack_Tpkt_threadid(test_req) ; + PKT_TRACE("packing the threadid -> ",test_req) ; + result &= currthread_test(&testthread) ; + result &= get_and_display_threadinfo(&testthread) ; + result &= threadlist_test() ; + result &= setthread_test(&testthread) ; + if (result) + output_string("PASS: UNITTEST Thread support\n") ; + else + output_string("FAIL: UNITTEST Thread support\n") ; + return result ; +} /* test-thread_support */ +#endif /* UNIT_TEST */ + +// #ifdef __ECOS__ +#endif // ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT... +// #endif // __ECOS__ diff --git a/ecos/packages/hal/common/current/src/thread-pkts.h b/ecos/packages/hal/common/current/src/thread-pkts.h new file mode 100644 index 0000000..fbd6076 --- /dev/null +++ b/ecos/packages/hal/common/current/src/thread-pkts.h @@ -0,0 +1,105 @@ +//======================================================================== +// +// thread-pkts.h +// +// Optional packet processing for thread aware debugging. +// +//======================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//======================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Red Hat, nickg +// Contributors: Red Hat, nickg +// Date: 1998-08-25 +// Purpose: +// Description: Optional packet processing for thread aware debugging. +// Externs as called by central packet switch routine +// Usage: +// +//####DESCRIPTIONEND#### +// +//======================================================================== + + +/* The DEBUG_THREADS flag is usually set in board.h */ + +#if DEBUG_THREADS /* activate this in board.h */ + +/* export the thread id's sent by gdb: */ +extern int _gdb_cont_thread, _gdb_general_thread ; + +extern char * stub_pack_Tpkt_threadid(char * pkt) ; + +extern long stub_get_currthread(void) ; +extern int stub_lock_scheduler(int lock, int kind, long id) ; + +extern void stub_pkt_changethread(char * inbuf, + char * outbuf, + int bufmax) ; + + +extern void stub_pkt_getthreadlist(char * inbuf, + char * outbuf, + int bufmax) ; + + +extern void stub_pkt_getthreadinfo( + char * inbuf, + char * outbuf, + int bufmax) ; + +extern void stub_pkt_thread_alive( + char * inbuf, + char * outbuf, + int bufmax) ; + +extern void stub_pkt_currthread( + char * inbuf, + char * outbuf, + int bufmax) ; + +#define STUB_PKT_GETTHREADLIST(A,B,C) { stub_pkt_getthreadlist(A,B,C); } +#define STUB_PKT_GETTHREADINFO(A,B,C) { stub_pkt_getthreadinfo(A,B,C); } +#define STUB_PKT_CHANGETHREAD(A,B,C) { stub_pkt_changethread(A,B,C); } +#define STUB_PKT_THREAD_ALIVE(A,B,C) { stub_pkt_thread_alive(A,B,C); } +#define STUB_PKT_CURRTHREAD(A,B,C) { stub_pkt_currthread(A,B,C); } +#define PACK_THREAD_ID(PTR) { PTR = stub_pack_Tpkt_threadid (PTR); } +#else +#define STUB_PKT_GETTHREADLIST(A,B,C) {} +#define STUB_PKT_GETTHREADINFO(A,B,C) {} +#define STUB_PKT_CHANGETHREAD(A,B,C) {} +#define STUB_PKT_THREAD_ALIVE(A,B,C) {} +#define STUB_PKT_CURRTHREAD(A,B,C) {} +#define PACK_THREAD_ID(PTR) {} +#endif diff --git a/ecos/packages/hal/common/current/tests/basic.c b/ecos/packages/hal/common/current/tests/basic.c new file mode 100644 index 0000000..a229a0f --- /dev/null +++ b/ecos/packages/hal/common/current/tests/basic.c @@ -0,0 +1,109 @@ +//================================================================= +// +// basic.c +// +// HAL basic functions test +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2001-10-24 +//####DESCRIPTIONEND#### +//========================================================================== + +#include <cyg/infra/testcase.h> // test case macros +#include <cyg/infra/diag.h> // diag_printf +#include <cyg/infra/cyg_ass.h> // assertions + +#include <cyg/hal/hal_arch.h> // context macros + +// ------------------------------------------------------------------------- + +#define BITS(t) (sizeof(t)*8) + +void +entry(void) +{ + int res; + int i, mask, ndx; + hal_jmp_buf jmpbuf; + + res = 1; + + // Check HAL_MSBIT_NDEX() functions + mask = 1; // One bits set + for (i = 0; i < BITS(int); i++) { + HAL_MSBIT_INDEX(ndx, mask); + res &= (ndx == i); + HAL_LSBIT_INDEX(ndx, mask); + res &= (ndx == i); + mask <<= 1; + } + + mask = 3; // Two bits set + for (i = 0; i < BITS(int)-1; i++) { + HAL_MSBIT_INDEX(ndx, mask); + res &= (ndx == (i+1)); + HAL_LSBIT_INDEX(ndx, mask); + res &= (ndx == i); + mask <<= 1; + } + CYG_TEST_PASS_FAIL(res, "HAL_xSBIT_INDEX() basic functions"); + + res = 0; + if (hal_setjmp(jmpbuf)) { + res = 1; + } else { + hal_longjmp(jmpbuf, 1); + } + CYG_TEST_PASS_FAIL(res, "hal_setjmp()/hal_longjmp() basic functions"); + + CYG_TEST_FINISH("HAL basic functions test"); +} + +// ------------------------------------------------------------------------- + +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + + entry(); +} + +// ------------------------------------------------------------------------- +// EOF basic.c diff --git a/ecos/packages/hal/common/current/tests/cache.c b/ecos/packages/hal/common/current/tests/cache.c new file mode 100644 index 0000000..1fd4b66 --- /dev/null +++ b/ecos/packages/hal/common/current/tests/cache.c @@ -0,0 +1,240 @@ +/*================================================================= +// +// cache.c +// +// HAL Cache timing test +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): dsm +// Contributors: dsm, nickg +// Date: 1998-06-18 +//####DESCRIPTIONEND#### +*/ + +#include <pkgconf/hal.h> + +#include <cyg/infra/testcase.h> + +#include <cyg/hal/hal_cache.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/infra/diag.h> + +#if defined(HAL_DCACHE_SIZE) && HAL_DCACHE_SIZE != 0 + +// ------------------------------------------------------------------------- +// If the HAL does not supply this, we supply our own version + +#ifndef HAL_DCACHE_PURGE_ALL + +#ifdef HAL_DCACHE_SYNC + +# define HAL_DCACHE_PURGE_ALL() HAL_DCACHE_SYNC() + +#else + +static cyg_uint8 dca[HAL_DCACHE_SIZE + HAL_DCACHE_LINE_SIZE*2]; + +#define HAL_DCACHE_PURGE_ALL() \ +CYG_MACRO_START \ + volatile cyg_uint8 *addr = &dca[HAL_DCACHE_LINE_SIZE]; \ + volatile cyg_uint8 tmp = 0; \ + int i; \ + for( i = 0; i < HAL_DCACHE_SIZE; i += HAL_DCACHE_LINE_SIZE ) \ + { \ + tmp = addr[i]; \ + } \ +CYG_MACRO_END + +#endif // HAL_DCACHE_SYNC + +#endif // HAL_DCACHE_PURGE_ALL + +// ------------------------------------------------------------------------- + +#ifndef MAX_STRIDE +#define MAX_STRIDE 64 +#endif + +volatile char m[(HAL_DCACHE_SIZE/HAL_DCACHE_LINE_SIZE)*MAX_STRIDE]; + +// ------------------------------------------------------------------------- + +static void time0(register cyg_uint32 stride) +{ + register cyg_uint32 j,k; + register char c CYGBLD_ATTRIB_UNUSED; + + diag_printf("stride=%d\n", stride); + + k = 0; + if ( cyg_test_is_simulator ) + k = 3960; + + for(; k<4000;k++) { + for(j=0; j<(HAL_DCACHE_SIZE/HAL_DCACHE_LINE_SIZE); j++) { + c=m[stride*j]; + } + } +} + +// ------------------------------------------------------------------------- + +void time1(void) +{ + cyg_uint32 i; + + for(i=1; i<=MAX_STRIDE; i+=i) { + time0(i); + } +} + +// ------------------------------------------------------------------------- +// This test could be improved by counting number of passes possible +// in a given number of ticks. + +static void entry0( void ) +{ + register CYG_INTERRUPT_STATE oldints; + +#ifdef HAL_CACHE_UNIFIED + + HAL_DISABLE_INTERRUPTS(oldints); + HAL_DCACHE_PURGE_ALL(); // rely on above definition + HAL_UCACHE_INVALIDATE_ALL(); + HAL_UCACHE_DISABLE(); + HAL_RESTORE_INTERRUPTS(oldints); + CYG_TEST_INFO("Cache off"); + time1(); + + HAL_DISABLE_INTERRUPTS(oldints); + HAL_DCACHE_PURGE_ALL(); // rely on above definition + HAL_UCACHE_INVALIDATE_ALL(); + HAL_UCACHE_ENABLE(); + HAL_RESTORE_INTERRUPTS(oldints); + CYG_TEST_INFO("Cache on"); + time1(); + +#else // HAL_CACHE_UNIFIED + + HAL_DISABLE_INTERRUPTS(oldints); + HAL_DCACHE_PURGE_ALL(); + HAL_ICACHE_INVALIDATE_ALL(); + HAL_DCACHE_INVALIDATE_ALL(); + HAL_ICACHE_DISABLE(); + HAL_DCACHE_DISABLE(); + HAL_RESTORE_INTERRUPTS(oldints); + CYG_TEST_INFO("Dcache off Icache off"); + time1(); + + HAL_DISABLE_INTERRUPTS(oldints); + HAL_DCACHE_PURGE_ALL(); + HAL_ICACHE_INVALIDATE_ALL(); + HAL_DCACHE_INVALIDATE_ALL(); + HAL_ICACHE_DISABLE(); + HAL_DCACHE_ENABLE(); + HAL_RESTORE_INTERRUPTS(oldints); + CYG_TEST_INFO("Dcache on Icache off"); + time1(); + + HAL_DISABLE_INTERRUPTS(oldints); + HAL_DCACHE_PURGE_ALL(); + HAL_ICACHE_INVALIDATE_ALL(); + HAL_DCACHE_INVALIDATE_ALL(); + HAL_ICACHE_ENABLE(); + HAL_DCACHE_DISABLE(); + HAL_RESTORE_INTERRUPTS(oldints); + CYG_TEST_INFO("Dcache off Icache on"); + time1(); + + HAL_DISABLE_INTERRUPTS(oldints); + HAL_DCACHE_PURGE_ALL(); + HAL_ICACHE_INVALIDATE_ALL(); + HAL_DCACHE_INVALIDATE_ALL(); + HAL_ICACHE_ENABLE(); + HAL_DCACHE_ENABLE(); + HAL_RESTORE_INTERRUPTS(oldints); + CYG_TEST_INFO("Dcache on Icache on"); + time1(); + + HAL_DISABLE_INTERRUPTS(oldints); + HAL_DCACHE_PURGE_ALL(); + HAL_ICACHE_INVALIDATE_ALL(); + HAL_DCACHE_INVALIDATE_ALL(); + HAL_ICACHE_DISABLE(); + HAL_DCACHE_DISABLE(); + HAL_RESTORE_INTERRUPTS(oldints); + CYG_TEST_INFO("Dcache off Icache off"); + time1(); + +#endif // HAL_CACHE_UNIFIED + + CYG_TEST_PASS_FINISH("End of test"); +} + +// ------------------------------------------------------------------------- + +void cache_main( void ) +{ + CYG_TEST_INIT(); + + entry0(); + +} + +// ------------------------------------------------------------------------- + +externC void +cyg_start( void ) +{ + cache_main(); +} + +#else // HAL_DCACHE_SIZE +#define N_A_MSG "No cache" +#endif // HAL_DCACHE_SIZE + +#ifdef N_A_MSG +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_NA( N_A_MSG ); +} +#endif // N_A_MSG + +// ------------------------------------------------------------------------- +/* EOF cache.c */ diff --git a/ecos/packages/hal/common/current/tests/context.c b/ecos/packages/hal/common/current/tests/context.c new file mode 100644 index 0000000..4e96dd0 --- /dev/null +++ b/ecos/packages/hal/common/current/tests/context.c @@ -0,0 +1,120 @@ +/*================================================================= +// +// context.c +// +// HAL Thread context handling test +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 1998-10-07 +//####DESCRIPTIONEND#### +*/ + +#include <pkgconf/hal.h> + +#include <pkgconf/infra.h> + +#include <cyg/infra/testcase.h> + +#include <cyg/infra/cyg_trac.h> +#include <cyg/hal/hal_arch.h> + +#define CYG_TRACE_USER_BOOL 1 + +// ------------------------------------------------------------------------- + +#define THREADS 4 +#define STACKSIZE (2*1024) + +char stack[THREADS][STACKSIZE]; + +CYG_ADDRWORD sp[THREADS]; + +cyg_count32 switches = 0; + +// ------------------------------------------------------------------------- + +void entry0( CYG_ADDRWORD arg ) +{ + CYG_TRACE1B("Thread %d started\n", arg ); + + while( switches < 1000 ) + { + HAL_THREAD_SWITCH_CONTEXT( &sp[arg], &sp[(arg+1) % THREADS] ); + + CYG_TRACE1B("Thread %d resumed\n", arg ); + + switches++; + } + + CYG_TEST_PASS_FINISH("HAL Context test"); + +} + +// ------------------------------------------------------------------------- + +void context_main(void) +{ + int i; + + CYG_TEST_INIT(); + + // Init all thread contexts: + + for( i = 0 ; i < THREADS; i++ ) + { + sp[i] = (CYG_ADDRWORD)stack[i]+STACKSIZE; + + HAL_THREAD_INIT_CONTEXT( sp[i], i, entry0, i*0x01010000 ); + } + + // Load the first thread. + + HAL_THREAD_LOAD_CONTEXT( &sp[0] ); +} + +// ------------------------------------------------------------------------- + +externC void +cyg_start( void ) +{ + context_main(); +} + +// ------------------------------------------------------------------------- +/* EOF context.c */ diff --git a/ecos/packages/hal/common/current/tests/cpp1.c b/ecos/packages/hal/common/current/tests/cpp1.c new file mode 100644 index 0000000..9c5eaa3 --- /dev/null +++ b/ecos/packages/hal/common/current/tests/cpp1.c @@ -0,0 +1,108 @@ +/*================================================================= +// +// cpp1.c +// +// cpp arithmetic bug regression test +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 2001-04-30 +//####DESCRIPTIONEND#### +*/ + +#include <pkgconf/hal.h> + +#include <pkgconf/infra.h> + +#include <cyg/infra/testcase.h> + +// ----------------------------------------------------------------- +// This is smaller than 2048. +// Unless the parser binds '+' too strongly because it is after a ket, so +// it is mistaken for unary plus, when (4 * 20 + 2) * 4 * 20 is larger. +#define CYGNUM_HAL_STACK_SIZE_MINIMUM ((4 * 20) + 2 * 4 * 20) + +#define CYGNUM_UITRON_STACK_SIZE (2048) + +#ifdef CYGNUM_HAL_STACK_SIZE_MINIMUM +# ifdef CYGNUM_UITRON_STACK_SIZE +# if CYGNUM_UITRON_STACK_SIZE < CYGNUM_HAL_STACK_SIZE_MINIMUM + +// then override the configured stack size +# undef CYGNUM_UITRON_STACK_SIZE +# define CYGNUM_UITRON_STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM + +# endif // CYGNUM_UITRON_STACK_SIZE < CYGNUM_HAL_STACK_SIZE_MINIMUM +# endif // CYGNUM_UITRON_STACK_SIZE +#endif // CYGNUM_HAL_STACK_SIZE_MINIMUM + + +// This tests for the bug per se: +int i = CYGNUM_UITRON_STACK_SIZE; + +// This tests the workaround independently of more complex context: +#define MAX(_x_,_y_) ((_x_) > (_y_) ? (_x_) : (_y_)) + +static char stack1[ + MAX( + CYGNUM_HAL_STACK_SIZE_MINIMUM, + 2048) + ]; + +// Better to report a fully-fledged failure and test the workaround than +// fail early. +#if 0 +# if CYGNUM_UITRON_STACK_SIZE != 2048 +# error FAIL: CPP '+' binding bug detected +# endif +#endif + +// ------------------------------------------------------------------------- +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + CYG_TEST_PASS("CPP '+' binding test compiled OK"); + CYG_TEST_PASS_FAIL( 2048 == i, "initialized i should be 2048" ); + CYG_TEST_PASS_FAIL( 2048 == sizeof( stack1 ), + "workaround: sizeof( stack1 ) should be 2048" ); + CYG_TEST_EXIT("All done"); +} + +// ------------------------------------------------------------------------- +/* EOF cpp1.c */ diff --git a/ecos/packages/hal/common/current/tests/intr.c b/ecos/packages/hal/common/current/tests/intr.c new file mode 100644 index 0000000..9cf695c --- /dev/null +++ b/ecos/packages/hal/common/current/tests/intr.c @@ -0,0 +1,156 @@ +/*================================================================= +// +// intr.c +// +// HAL Interrupt API test +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: nickg +// Date: 1998-10-08 +//####DESCRIPTIONEND#### +*/ + +#include <pkgconf/hal.h> + +#include <cyg/infra/testcase.h> + +#include <cyg/hal/hal_intr.h> +#include <cyg/hal/drv_api.h> + +// Include HAL/Platform specifics +#include CYGBLD_HAL_PLATFORM_H + +#ifdef CYGPKG_KERNEL +#include <pkgconf/kernel.h> // Need to look for the RTC config. +#endif + +// Fallback defaults (in case HAL didn't define these) +#ifndef CYGNUM_HAL_RTC_NUMERATOR +#define CYGNUM_HAL_RTC_NUMERATOR 1000000000 +#define CYGNUM_HAL_RTC_DENOMINATOR 100 +#define CYGNUM_HAL_RTC_PERIOD 9999 +#endif + +// ------------------------------------------------------------------------- + +#define ISR_DATA 0xAAAA1234 + +// ------------------------------------------------------------------------- + +volatile cyg_count32 ticks = 0; +volatile cyg_count32 dsr_ticks = 0; +static cyg_interrupt intr; +static cyg_handle_t intr_handle; + +// ------------------------------------------------------------------------- + +cyg_uint32 isr( cyg_uint32 vector, CYG_ADDRWORD data ) +{ + CYG_TEST_CHECK( ISR_DATA == data , "Bad data passed to ISR"); + CYG_TEST_CHECK( CYGNUM_HAL_INTERRUPT_RTC == vector , + "Bad vector passed to ISR"); + + HAL_CLOCK_RESET( vector, CYGNUM_HAL_RTC_PERIOD ); + + HAL_INTERRUPT_ACKNOWLEDGE( vector ); + + ticks++; + + return CYG_ISR_CALL_DSR; +} + +// ------------------------------------------------------------------------- + +void dsr( cyg_uint32 vector, cyg_ucount32 count, CYG_ADDRWORD data ) +{ + CYG_TEST_CHECK( ISR_DATA == data , "Bad data passed to DSR"); + CYG_TEST_CHECK( CYGNUM_HAL_INTERRUPT_RTC == vector , + "Bad vector passed to DSR"); + + dsr_ticks += count; +} + +void intr_main( void ) +{ + CYG_INTERRUPT_STATE oldints; + + cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_RTC, 1, + ISR_DATA, isr, dsr, &intr_handle, &intr); + cyg_drv_interrupt_attach(intr_handle); + HAL_CLOCK_INITIALIZE( CYGNUM_HAL_RTC_PERIOD ); + cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_RTC); + + HAL_ENABLE_INTERRUPTS(); + + while( ticks < 10 ) + { + + } + + + CYG_TEST_CHECK( dsr_ticks == 10, "DSR not called sufficient times"); + + HAL_DISABLE_INTERRUPTS(oldints); + + CYG_TEST_PASS_FINISH("HAL interrupt test"); +} + + +// ------------------------------------------------------------------------- + +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + + // Attaching the ISR will not succeed if the kernel real-time + // clock has been configured in. +#ifndef CYGVAR_KERNEL_COUNTERS_CLOCK + + intr_main(); + +#else + + CYG_TEST_NA("Cannot override kernel real-time clock."); + +#endif +} + + +// ------------------------------------------------------------------------- +// EOF intr.c diff --git a/ecos/packages/hal/common/current/tests/vaargs.c b/ecos/packages/hal/common/current/tests/vaargs.c new file mode 100644 index 0000000..9bb621d --- /dev/null +++ b/ecos/packages/hal/common/current/tests/vaargs.c @@ -0,0 +1,156 @@ +//================================================================= +// +// vaargs.c +// +// HAL variable argument calls test +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later +// version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors: jskov +// Date: 2001-08-03 +//####DESCRIPTIONEND#### +//========================================================================== + +#include <cyg/infra/testcase.h> // test case macros +#include <cyg/infra/diag.h> // diag_printf +#include <cyg/infra/cyg_ass.h> // assertions + +#include <cyg/hal/hal_arch.h> // context macros + +#include <stdarg.h> // vaargs magic + +// ------------------------------------------------------------------------- + +int +function(int n, ...) +{ + va_list args; + int c = 11 * n; + int i = 1; + int res = 1; + + CYG_ASSERT(n >= 0 && n < 8, "Invalid count argument"); + + va_start(args, n); + + for (i = 1; i <= n; c++, i++) { + int v = va_arg(args, int); + if (v != c) { + diag_printf("FAIL:<Bad argument: index %d expected %d got %d>\n", i, c, v); + res = 0; + } + } + + va_end(args); + + return res; +} + +int +function_proxy(int n, va_list args) +{ + int c = 11 * n; + int i = 1; + int res = 1; + + CYG_ASSERT(n >= 0 && n < 8, "Invalid count argument"); + + for (i = 1; i <= n; c++, i++) { + int v = va_arg(args, int); + if (v != c) { + diag_printf("FAIL:<Bad argument: index %d expected %d got %d>\n", i, c, v); + res = 0; + } + } + + return res; +} + +int +proxy(int n, ...) +{ + int res; + va_list args; + + va_start(args, n); + res = function_proxy(n, args); + va_end(args); + + return res; +} + + +void +entry(void) +{ + int res; + + res = function(0); + res &= function(1, 11); + res &= function(2, 22, 23); + res &= function(3, 33, 34, 35); + res &= function(4, 44, 45, 46, 47); + res &= function(5, 55, 56, 57, 58, 59); + res &= function(6, 66, 67, 68, 69, 70, 71); + res &= function(7, 77, 78, 79, 80, 81, 82, 83); + CYG_TEST_PASS_FAIL(res, "Direct vaargs calls"); + + res = proxy(0); + res &= proxy(1, 11); + res &= proxy(2, 22, 23); + res &= proxy(3, 33, 34, 35); + res &= proxy(4, 44, 45, 46, 47); + res &= proxy(5, 55, 56, 57, 58, 59); + res &= proxy(6, 66, 67, 68, 69, 70, 71); + res &= proxy(7, 77, 78, 79, 80, 81, 82, 83); + CYG_TEST_PASS_FAIL(res, "Proxy vaargs calls"); + + CYG_TEST_FINISH("HAL vaargs test"); +} + +// ------------------------------------------------------------------------- + +externC void +cyg_start( void ) +{ + CYG_TEST_INIT(); + + entry(); +} + +// ------------------------------------------------------------------------- +// EOF vaargs.c |