OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/rtos/ecos-2.0/packages/hal/common/v2_0
    from Rev 27 to Rev 174
    Reverse comparison

Rev 27 → Rev 174

/cdl/interrupts.cdl
0,0 → 1,143
# ====================================================================
#
# 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 Red Hat, 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.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-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 1024 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."
}
/cdl/hal.cdl
0,0 → 1,473
# ====================================================================
#
# hal.cdl
#
# HAL configuration data
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
## Copyright (C) 2002 Gary Thomas
##
## 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.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): bartv
# Original data: nickg,jskov,jlarmour
# Contributors: dmoseley
# 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) -nostdlib -Wl,-r -Wl,--whole-archive -o $@ $<
}
 
 
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_CACHE
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_CACHE {
display "Claim cache virtual vectors"
default_value { CYGSEM_HAL_VIRTUAL_VECTOR_INIT_WHOLE_TABLE \
|| CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DEFAULT }
description "
This option will cause the cache virtual vectors
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 +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."
}
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."
}
 
}
}
/cdl/common.cdl
0,0 → 1,152
# ====================================================================
#
# 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 Red Hat, 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.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-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/debugging.cdl
0,0 → 1,153
# ====================================================================
#
# 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 Red Hat, 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.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): jskov
# Original data: nickg,jskov,jlarmour
# Contributors:
# 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 { !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
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 }
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)."
}
/tests/basic.c
0,0 → 1,110
//=================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
/tests/vaargs.c
0,0 → 1,157
//=================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
/tests/cpp1.c
0,0 → 1,109
/*=================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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 */
/tests/cache.c
0,0 → 1,241
/*=================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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;
 
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 */
/tests/context.c
0,0 → 1,121
/*=================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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 */
/tests/intr.c
0,0 → 1,145
/*=================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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;
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_HANDLED;
}
 
// -------------------------------------------------------------------------
 
 
void intr_main( void )
{
CYG_INTERRUPT_STATE oldints;
 
cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_RTC, 1,
ISR_DATA, isr, NULL, &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 )
{
}
 
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
/include/dbg-thread-syscall.h
0,0 → 1,111
//========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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 ) ;
/include/hal_spd.h
0,0 → 1,78
#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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
/include/dbg-threads-api.h
0,0 → 1,161
//========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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 */
/include/hal_arbiter.h
0,0 → 1,142
#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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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);
 
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
if (isr_ret & CYG_ISR_CALL_DSR) {
cyg_interrupt_post_dsr (hal_interrupt_objects[vector]);
}
#endif
 
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
/include/hal_tables.h
0,0 → 1,115
#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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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")
#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))
#endif
 
/*------------------------------------------------------------------------*/
/* EOF hal_tables.h */
#endif // CYGONCE_HAL_TABLES_H
/include/hal_misc.h
0,0 → 1,123
#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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
/include/hal_stub.h
0,0 → 1,390
#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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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>
 
#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.
 
#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_); \
_old_ = 1; /* actually use the label as a label... */ \
cyg_hal_gdb_break_place:; \
if ( (_old_)-- > 0 ) /* ...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
/include/hal_if.h
0,0 → 1,675
#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 Red Hat, Inc.
// Copyright (C) 2002 Gary Thomas
//
// 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jskov
// Contributors:jskov
// 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.
#ifdef CYGPKG_NET
#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
#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 __vector,
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_FLUSH_DCACHE 7
#define CYGNUM_CALL_IF_FLUSH_ICACHE 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_LAST_ENTRY CYGNUM_CALL_IF_MONITOR_RETURN
 
#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 void (__call_if_flush_dcache_t)(void *__p, int __nbytes);
typedef void (__call_if_flush_icache_t)(void *__p, int __nbytes);
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 cyg_bool (__call_if_flash_cfg_op_fn_t)(int __oper, char *__key,
void *__val, int __type);
typedef char *__call_if_monitor_version_t;
typedef void (__call_if_monitor_return_t)(int status);
 
#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_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_FLUSH_DCACHE(_p_, _n_) \
((__call_if_flush_dcache_t*)hal_virtual_vector_table[CYGNUM_CALL_IF_FLUSH_DCACHE])((_p_), (_n_))
#define CYGACC_CALL_IF_FLUSH_DCACHE_SET(_x_) \
hal_virtual_vector_table[CYGNUM_CALL_IF_FLUSH_DCACHE]=(CYG_ADDRWORD)(_x_)
 
#define CYGACC_CALL_IF_FLUSH_ICACHE(_p_, _n_) \
((__call_if_flush_icache_t*)hal_virtual_vector_table[CYGNUM_CALL_IF_FLUSH_ICACHE])((_p_), (_n_))
#define CYGACC_CALL_IF_FLUSH_ICACHE_SET(_x_) \
hal_virtual_vector_table[CYGNUM_CALL_IF_FLUSH_ICACHE]=(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_)
 
#define CYGACC_CALL_IF_FLASH_CFG_OP(_o_,_k_,_d_,_t_) \
CYGACC_CALL_VV4(__call_if_flash_cfg_op_fn_t*, CYGNUM_CALL_IF_FLASH_CFG_OP, (_o_),(_k_),(_d_),(_t_))
__call_VV4(CYGNUM_CALL_IF_FLASH_CFG_OP, __call_if_flash_cfg_op_fn_t, cyg_bool, int, char *, void *, int)
#define CYGACC_CALL_IF_FLASH_CFG_OP_SET(_x_) \
hal_virtual_vector_table[CYGNUM_CALL_IF_FLASH_CFG_OP]=(CYG_ADDRWORD)(_x_)
#define CYGNUM_CALL_IF_FLASH_CFG_GET (0)
 
#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_)
 
// These need to be kept uptodate with the (unadorned) masters
// in RedBoot's flash_config.h:
#define CYGNUM_FLASH_CFG_OP_CONFIG_EMPTY 0
#define CYGNUM_FLASH_CFG_OP_CONFIG_BOOL 1
#define CYGNUM_FLASH_CFG_OP_CONFIG_INT 2
#define CYGNUM_FLASH_CFG_OP_CONFIG_STRING 3
#define CYGNUM_FLASH_CFG_OP_CONFIG_SCRIPT 4
#define CYGNUM_FLASH_CFG_OP_CONFIG_IP 5
#define CYGNUM_FLASH_CFG_OP_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
/include/hal_endian.h
0,0 → 1,110
#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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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_); ((_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
/include/drv_api.h
0,0 → 1,251
#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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
/include/generic-stub.h
0,0 → 1,363
//========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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);
 
/* 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);
 
/* 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 */
/doc/porting.sgml
0,0 → 1,4387
<!-- {{{ Banner -->
 
<!-- =============================================================== -->
<!-- -->
<!-- porting.sgml -->
<!-- -->
<!-- eCos common HAL documentation -->
<!-- -->
<!-- =============================================================== -->
<!-- ####COPYRIGHTBEGIN#### -->
<!-- -->
<!-- =============================================================== -->
<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, 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 -->
<!-- =============================================================== -->
<!-- -->
<!-- ####COPYRIGHTEND#### -->
<!-- =============================================================== -->
<!-- #####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://sourceware.cygnus.com/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://sourceware.cygnus.com/ecos/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://sourceware.cygnus.com/ecos/docs-latest/">documentation</ulink>,
<ulink url="http://sourceware.cygnus.com/fom/ecos">FAQ</ulink> or
<ulink url="http://sourceware.cygnus.com/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@sourceware.cygnus.com?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://sourceware.cygnus.com/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://sourceware.cygnus.com/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/arch/current?cvsroot=ecos">(hal/&lt;architecture&gt;/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://sourceware.cygnus.com/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/mpc8xx/current?cvsroot=ecos">(hal/&lt;architecture&gt;/&lt;variant&gt;)</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://sourceware.cygnus.com/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/mbx/current?cvsroot=ecos">(hal/&lt;architecture&gt;/&lt;platform&gt;)</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://sourceware.cygnus.com/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/quicc/current?cvsroot=ecos">(hal/&lt;architecture&gt;/&lt;module&gt;)</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/&lt;arch&gt;_regs.h</filename></entry>
<entry>Architecture register definitions.</entry>
</row>
<row>
<entry><filename>include/&lt;arch&gt;_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/&lt;arch&gt;.inc</filename></entry>
<entry>Architecture convenience assembly macros.</entry>
</row>
<row>
<entry><filename>src/&lt;arch&gt;.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/&lt;arch&gt;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/&lt;arch&gt;_&lt;variant&gt;.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>
Some eCos platforms have supported full debugging capabilities via
CygMon since day one. Platforms of the architectures PowerPC, ARM, and
SH do not provide those features unless a GDB stub is included in the
application.
</para>
 
<para>
This is going to change. All platforms will (eventually) support
all the debugging features by relying on a ROM/RAM calling interface
(also referred to as virtual vector table) provided by the ROM
monitor. This calling interface is based on the tables used by libbsp
and is thus backwards compatible with the existing CygMon supported
platforms.
</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 &lt;var_intr.h&gt;
 
#ifndef MACRO_DEFINED
# define MACRO ...
# define MACRO_DEFINED
#endif
 
 
 
var_intr.h: #include &lt;plf_intr.h&gt;
 
#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 MLT related files should contain the
&lt;arch&gt;_&lt;variant&gt;_&lt;platform&gt; 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 MLT 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_&lt;STARTUP&gt;.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>&lt;platform&gt;_misc.c</filename>, PowerPC:
<filename>&lt;platform&gt;.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 &lt;target_name&gt; redboot
% ecosconfig import $(ECOS_REPOSITORY)/hal/&lt;architecture&gt;/&lt;platform&gt;/&lt;version&gt;/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: &lt;PLATFORM&gt; (&lt;ARCHITECTURE&gt; &lt;VARIANT&gt;)
Copyright (C) 2000, 2001, 2002, Red Hat, 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 &quot;detach&quot;.</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 &quot;the clock&quot;.
</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_&lt;architecture&gt;_&lt;variant&gt;_&lt;platform&gt;</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 &lt;pkgconf/hal_mips_tx39.h&gt;"
puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H &lt;pkgconf/hal_mips_tx39_jmr3904.h&gt;"
}
 
...
}
</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" ? "&lt;pkgconf/mlt_mips_tx39_jmr3904_ram.ldi&gt;" : \
"&lt;pkgconf/mlt_mips_tx39_jmr3904_rom.ldi&gt;" }
}
 
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" ? "&lt;pkgconf/mlt_mips_tx39_jmr3904_ram.h&gt;" : \
"&lt;pkgconf/mlt_mips_tx39_jmr3904_rom.h&gt;" }
}
}
 
</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 {
&lt;PREFIX&gt;/bin/gdb_module.bin : &lt;PREFIX&gt;/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 {
&lt;PREFIX&gt;/bin/redboot.bin : &lt;PREFIX&gt;/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>The platform memory layout is defined using the Memory
Configuration Window <!-- [FIXME: ref] --> in the Configuration Tool.</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 saved in three 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 three files are generated for each startup-type, since the
memory details usually differ.</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 &lt;pkgconf/hal_mips.h&gt;"
}
 
compile var_misc.c
 
make {
&lt;PREFIX&gt;/lib/target.ld: &lt;PACKAGE&gt;/src/mips_vr4300.ld
$(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(CFLAGS) -o $@ $&lt;
@echo $@ ": \\" &gt; $(notdir $@).deps
@tail +2 target.tmp &gt;&gt; $(notdir $@).deps
@echo &gt;&gt; $(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>&lt;architecture&gt;.inc</filename>. These files are
assembler headers used by <filename>vectors.S</filename> and
<filename>context.S</filename>.
<filename>&lt;architecture&gt;.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>&lt;architecture&gt;.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/&lt;architecture&gt;-stub.h</filename> and
<filename>src/&lt;architecture&gt;-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/&lt;architecture&gt;-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/&lt;architecture&gt;-stub.c</filename>; however, since
this is common to all architectures, it can be copied from some other
HAL.
</para>
 
<para>
<filename>src/&lt;architecture&gt;-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 {
&lt;PREFIX&gt;/lib/vectors.o : &lt;PACKAGE&gt;/src/vectors.S
$(CC) -Wp,-MD,vectors.tmp $(INCLUDE_PATH) $(CFLAGS) -c -o $@ $&lt;
@echo $@ ": \\" &gt; $(notdir $@).deps
@tail +2 vectors.tmp &gt;&gt; $(notdir $@).deps
@echo &gt;&gt; $(notdir $@).deps
@rm vectors.tmp
}
 
make {
&lt;PREFIX&gt;/lib/target.ld: &lt;PACKAGE&gt;/src/i386.ld
$(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(CFLAGS) -o $@ $&lt;
@echo $@ ": \\" &gt; $(notdir $@).deps
@tail +2 target.tmp &gt;&gt; $(notdir $@).deps
@echo &gt;&gt; $(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.
 
 
 
 
-->
 
 
/doc/hal.sgml
0,0 → 1,3019
<!-- {{{ Banner -->
 
<!-- =============================================================== -->
<!-- -->
<!-- HAL.sgml -->
<!-- -->
<!-- eCos common HAL documentation -->
<!-- -->
<!-- =============================================================== -->
<!-- ####COPYRIGHTBEGIN#### -->
<!-- -->
<!-- =============================================================== -->
<!-- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, 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 -->
<!-- =============================================================== -->
<!-- -->
<!-- ####COPYRIGHTEND#### -->
<!-- =============================================================== -->
<!-- #####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&plus;&plus;.
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&plus;&plus; 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, and realtime clock operations.
</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>&plus;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&rsquo;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>
<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 is an optional definition. If defined the macro implements a busy
loop delay for the given number of microseconds. This is usually
implemented by waiting for the required number of hardware timer ticks
to pass.
</para>
 
<para>
This operation should normally be used when a very short delay is
needed when controlling hardware, programming FLASH devices and similar
situations where a wait/timeout loop would otherwise be used. Since it
may disable interrupts, and is implemented by busy waiting, it should
not be used in code that is sensitive to interrupt or context switch
latencies.
</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>&lt;cyg/hal/hal_cache.h&gt;</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_&lt;architecture&gt;_&lt;variant&gt;_&lt;platform&gt;_&lt;startup&gt;.ldi</filename>
</para>
<para>
where <literal>&lt;architecture&gt;</literal>,
<literal>&lt;variant&gt;</literal> and
<literal>&lt;platform&gt;</literal> are the respective HAL package
names and <literal>&lt;startup&gt;</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_&lt;architecture&gt;_&lt;variant&gt;_&lt;platform&gt;_&lt;startup&gt;.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>
/src/bplist-dynamic.c
0,0 → 1,450
//==========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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)
 
/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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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 + NUMREGS ;
 
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 = (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 = (char *) src ;
destp = (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 ;
char * base_out ;
base_out = outbuf ;
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 = &registers[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__
/src/hal_misc.c
0,0 → 1,195
//==========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
 
#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( 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
/src/hal_stub.c
0,0 → 1,1012
//=============================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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.
 
// Some architectures use registers of different sizes, so NUMREGS
// alone is not suffucient 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
 
// 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
target_register_t orig_registers[HAL_STUB_REGISTERS_SIZE]; // Registers to get back to original state
 
#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)
{
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) {
break_buffer.targetAddr = (t_inst*) pc;
break_buffer.savedInstr = *(t_inst*)pc;
*(t_inst*)pc = (t_inst)HAL_BREAKINST;
 
__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) {
*(t_inst*)pc = break_buffer.savedInstr;
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
 
// Called at stub *kill*
static void
handle_exception_exit( void )
{
int i;
 
for (i = 0; i < (sizeof(registers)/sizeof(registers[0])); i++)
registers[i] = orig_registers[i];
}
 
// Called at stub *entry*
static void
handle_exception_cleanup( void )
{
static int orig_registers_set = 0;
 
interruptible(0);
 
// Expand the HAL_SavedRegisters structure into the GDB register
// array format.
HAL_GET_GDB_REGISTERS(&registers[0], _hal_registers);
_registers = &registers[0];
 
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 = &registers[0];
orig_registers_set = 1;
}
#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, &registers[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
/src/gdb-fileio.c
0,0 → 1,729
/*==========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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 */
/src/hal_if.c
0,0 → 1,973
//=============================================================================
//
// 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 Red Hat, Inc.
// Copyright (C) 2002 Gary Thomas
//
// 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): jskov
// Contributors:jskov
// 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
#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, char * key, void *val, int type)
{
cyg_bool res = false;
 
CYGARC_HAL_SAVE_GP();
 
switch ( op ) {
case CYGNUM_CALL_IF_FLASH_CFG_GET:
res = flash_get_config( key, val, 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
 
//----------------------------
// 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();
#ifdef CYGPKG_KERNEL
{
cyg_int32 start, elapsed;
cyg_int32 usec_ticks, slice;
 
// How many ticks total we should wait for.
usec_ticks = usecs*CYGNUM_KERNEL_COUNTERS_RTC_PERIOD;
usec_ticks /= CYGNUM_HAL_RTC_NUMERATOR/CYGNUM_HAL_RTC_DENOMINATOR/1000;
 
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'd be also problems
// figuring out when the timer wrapped. We may lose a tick or
// two for each cycle but it shouldn't matter much.
slice = usec_ticks % (CYGNUM_KERNEL_COUNTERS_RTC_PERIOD / 2);
HAL_CLOCK_READ(&start);
do {
HAL_CLOCK_READ(&elapsed);
elapsed = (elapsed - 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.
usec_ticks -= elapsed;
} while (usec_ticks > 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.
HAL_PLATFORM_RESET();
 
#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
 
CYGARC_HAL_RESTORE_GP();
}
 
// This is the system's default kill signal routine. Unless overridden
// by the application, it will cause a board reset when GDB quits the
// connection. (The user can avoid the reset by using the GDB 'detach'
// command instead of 'kill' or 'quit').
static int
kill_by_reset(int __irq_nr, void* __regs)
{
CYGARC_HAL_SAVE_GP();
 
reset();
 
CYGARC_HAL_RESTORE_GP();
return 0;
}
#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
 
//----------------------------------
// Cache functions
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE
 
static void
flush_icache(void *__p, int __nbytes)
{
CYGARC_HAL_SAVE_GP();
#ifdef HAL_ICACHE_FLUSH
HAL_ICACHE_FLUSH( __p , __nbytes );
#elif defined(HAL_ICACHE_INVALIDATE)
HAL_ICACHE_INVALIDATE();
#endif
CYGARC_HAL_RESTORE_GP();
}
 
static void
flush_dcache(void *__p, int __nbytes)
{
CYGARC_HAL_SAVE_GP();
#ifdef HAL_DCACHE_FLUSH
HAL_DCACHE_FLUSH( __p , __nbytes );
#elif defined(HAL_DCACHE_INVALIDATE)
HAL_DCACHE_INVALIDATE();
#endif
CYGARC_HAL_RESTORE_GP();
}
#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();
 
// 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, 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)
{
#if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0
int tries = CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES;
#endif
 
// 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 defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
 
struct Hal_SavedRegisters *hal_saved_interrupt_state;
 
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 isr_ret, 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) {
isr_ret = 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);
CYGACC_CALL_IF_KILL_VECTOR_SET(kill_by_reset);
#endif
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_DELAY_US
CYGACC_CALL_IF_DELAY_US_SET(delay_us);
#endif
 
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_CLAIM_CACHE
// Cache functions
CYGACC_CALL_IF_FLUSH_ICACHE_SET(flush_icache);
CYGACC_CALL_IF_FLUSH_DCACHE_SET(flush_dcache);
#endif
 
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
CYGACC_CALL_IF_FLASH_CFG_OP_SET(flash_config_op);
#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
}
/src/drv_api.c
0,0 → 1,935
//==========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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();
}
 
 
//--------------------------------------------------------------------------
// 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
/src/gdb-fileio.h
0,0 → 1,139
/* gdb-fileio.h.
Contains definitions used inside of the File I/O facility.
 
Copyright 2002 Red Hat, 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_ */
/src/generic-stub.c
0,0 → 1,2018
#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);
 
void __free_program_args (void);
 
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 char *__add_program_arg (int argnum, uint32 arglen);
 
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 = (unsigned char *) buf;
hexMemSrc = (unsigned 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 = (unsigned char *) buf;
hexMemSrc = (unsigned 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 = (unsigned char *) buf;
hexMemDst = (unsigned 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 = (unsigned char *) buf;
hexMemDst = (unsigned 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 (0 == sigval)
{
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, &regno))
{
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, &regno) && (*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 = &registers[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
#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
__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);
}
 
#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;
}
 
/* Table used by the crc32 function to calcuate the checksum. */
static uint32 crc32_table[256];
static int tableInit = 0;
 
/*
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
 
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;
}
}
 
__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 ;
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
/src/stubrom/stubrom.c
0,0 → 1,61
/*==========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
/src/thread-pkts.h
0,0 → 1,106
//========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
/src/dummy.c
0,0 → 1,54
//==========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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.
/src/board.h
0,0 → 1,70
#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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
/src/dbg-threads-syscall.c
0,0 → 1,217
//========================================================================
//
// 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 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-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
/ChangeLog
0,0 → 1,2163
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.
 
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, 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.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//===========================================================================

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.