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/<architecture>/arch)</ulink></entry> |
<entry>Functionality specific to the given architecture. Also default |
implementations of some functionality which can be overridden by |
variant or platform HALs.</entry> |
<entry>Architecture specific debugger functionality (handles single |
stepping, exception-to-signal conversion, etc.), |
exception/interrupt vector definitions and handlers, cache |
definition and control macros, context switching code, assembler |
functions for early system initialization, configuration options, |
and possibly tests. </entry> |
</row> |
<row> |
<entry>Variant HAL <ulink url="http://sourceware.cygnus.com/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/mpc8xx/current?cvsroot=ecos">(hal/<architecture>/<variant>)</ulink></entry> |
<entry>Some CPU architectures consist of a number variants, for example |
MIPS CPUs come in both 32 and 64 bit versions, and some variants |
have embedded features additional to the CPU core. |
</entry> |
<entry>Variant extensions to the architecture code (cache, |
exception/interrupt), configuration options, possibly drivers for |
variant on-core devices, and possibly tests.</entry> |
</row> |
<row> |
<entry>Platform HAL <ulink url="http://sourceware.cygnus.com/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/mbx/current?cvsroot=ecos">(hal/<architecture>/<platform>)</ulink></entry> |
<entry>Contains functionality and configuration options specific to the |
platform. |
</entry> |
<entry>Early platform initialization code, platform memory layout |
specification, configuration options (processor speed, compiler |
options), diagnostic IO functions, debugger IO functions, |
platform specific extensions to architecture or variant code |
(off-core interrupt controller), and possibly tests.</entry> |
</row> |
<row> |
<entry>Auxiliary HAL <ulink url="http://sourceware.cygnus.com/cgi-bin/cvsweb.cgi/ecos/packages/hal/powerpc/quicc/current?cvsroot=ecos">(hal/<architecture>/<module>)</ulink></entry> |
<entry>Some variants share common modules on the core. Motorola's PowerPC |
QUICC is an example of such a module. |
</entry> |
<entry>Module specific functionality (interrupt controller, simple |
device drivers), possibly tests. |
</entry> |
</row> |
</tbody> |
</tgroup> |
</informaltable> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ File Descriptions --> |
|
<section> |
<title>File Descriptions</title> |
|
<para> |
Listed below are the files found in various HALs, with a short |
description of what each file contains. When looking in existing HALs |
beware that they do not necessarily follow this naming scheme. |
If you are writing a new HAL, please try to follow it as |
closely as possible. Still, no two targets are the same, so sometimes |
it makes sense to use additional files. |
</para> |
|
<!-- {{{ Common HAL --> |
|
<section> |
<title>Common HAL</title> |
|
<informaltable frame=all> |
<tgroup cols=2 align=left colsep=1 rowsep=1> |
<thead> |
<row> |
<entry>File</entry> |
<entry>Description</entry> |
</row> |
</thead> |
<tbody> |
|
<row> |
<entry><filename>include/dbg-thread-syscall.h</filename></entry> |
<entry>Defines the thread debugging syscall function. This is used by |
the ROM monitor to access the thread debugging API in the RAM |
application. <!-- FIXME: link thread debug description -->.</entry> |
</row> |
<row> |
<entry><filename>include/dbg-threads-api.h</filename></entry> |
<entry>Defines the thread debugging API. <!-- FIXME: link thread |
debug description -->.</entry> |
</row> |
<row> |
<entry><filename>include/drv_api.h</filename></entry> |
<entry>Defines the driver API.</entry> |
</row> |
<row> |
<entry><filename>include/generic-stub.h</filename></entry> |
<entry>Defines the generic stub features.</entry> |
</row> |
<row> |
<entry><filename>include/hal_if.h</filename></entry> |
<entry>Defines the ROM/RAM calling interface API.</entry> |
</row> |
<row> |
<entry><filename>include/hal_misc.h</filename></entry> |
<entry>Defines miscellaneous helper functions shared by all HALs.</entry> |
</row> |
<row> |
<entry><filename>include/hal_stub.h</filename></entry> |
<entry>Defines eCos mappings of GDB stub features.</entry> |
</row> |
<row> |
<entry><filename>src/dbg-threads-syscall.c</filename></entry> |
<entry>Thread debugging implementation.</entry> |
</row> |
<row> |
<entry><filename>src/drv_api.c</filename></entry> |
<entry>Driver API implementation. Depending on configuration this |
provides either wrappers for the kernel API, or a minimal |
implementation of these features. This allows drivers to be written |
relying only on HAL features.</entry> |
</row> |
<row> |
<entry><filename>src/dummy.c</filename></entry> |
<entry>Empty dummy file ensuring creation of libtarget.a.</entry> |
</row> |
<row> |
<entry><filename>src/generic-stub.c</filename></entry> |
<entry>Generic GDB stub implementation. This provides the |
communication protocol used to communicate with GDB over a serial |
device or via the network.</entry> |
</row> |
<row> |
<entry><filename>src/hal_if.c</filename></entry> |
<entry>ROM/RAM calling interface implementation. Provides wrappers from |
the calling interface API to the eCos features used for the |
implementation.</entry> |
</row> |
<row> |
<entry><filename>src/hal_misc.c</filename></entry> |
<entry>Various helper functions shared by all platforms and |
architectures.</entry> |
</row> |
<row> |
<entry><filename>src/hal_stub.c</filename></entry> |
<entry>Wrappers from eCos HAL features to the features required by the |
generic GDB stub.</entry> |
</row> |
<row> |
<entry><filename>src/stubrom/stubrom.c</filename></entry> |
<entry>The file used to build eCos GDB stub images. Basically a |
cyg_start function with a hard coded breakpoint.</entry> |
</row> |
<row> |
<entry><filename>src/thread-packets.c</filename></entry> |
<entry>More thread debugging related functions.</entry> |
</row> |
<row> |
<entry><filename>src/thread-pkts.h</filename></entry> |
<entry>Defines more thread debugging related function.</entry> |
</row> |
</tbody> |
</tgroup> |
</informaltable> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Architecture HAL --> |
|
<section> |
<title>Architecture HAL</title> |
|
<para>Some architecture HALs may add extra files for architecture |
specific serial drivers, or for handling interrupts and exceptions if it |
makes sense.</para> |
|
<para>Note that many of the definitions in these files are only |
conditionally defined - if the equivalent variant or platform headers |
provide the definitions, those override the generic architecture |
definitions.</para> |
|
<informaltable frame=all> |
<tgroup cols=2 align=left colsep=1 rowsep=1> |
<thead> |
<row> |
<entry>File</entry> |
<entry>Description</entry> |
</row> |
</thead> |
<tbody> |
|
<row> |
<entry><filename>include/arch.inc</filename></entry> |
<entry>Various assembly macros used during system initialization.</entry> |
</row> |
<row> |
<entry><filename>include/basetype.h</filename></entry> |
<entry>Endian, label, alignment, and type size definitions. These |
override common defaults in CYGPKG_INFRA.</entry> |
</row> |
<row> |
<entry><filename>include/hal_arch.h</filename></entry> |
<entry>Saved register frame format, various thread, register and stack |
related macros.</entry> |
</row> |
<row> |
<entry><filename>include/hal_cache.h</filename></entry> |
<entry>Cache definitions and cache control macros.</entry> |
</row> |
<row> |
<entry><filename>include/hal_intr.h</filename></entry> |
<entry>Exception and interrupt definitions. Macros for configuring and |
controlling interrupts. eCos real-time clock control macros.</entry> |
</row> |
<row> |
<entry><filename>include/hal_io.h</filename></entry> |
<entry>Macros for accessing IO devices.</entry> |
</row> |
<row> |
<entry><filename>include/<arch>_regs.h</filename></entry> |
<entry>Architecture register definitions.</entry> |
</row> |
<row> |
<entry><filename>include/<arch>_stub.h</filename></entry> |
<entry>Architecture stub definitions. In particular the register frame |
layout used by GDB. This may differ from the one used by eCos.</entry> |
</row> |
<row> |
<entry><filename>include/<arch>.inc</filename></entry> |
<entry>Architecture convenience assembly macros.</entry> |
</row> |
<row> |
<entry><filename>src/<arch>.ld</filename></entry> |
<entry>Linker macros.</entry> |
</row> |
<row> |
<entry><filename>src/context.S</filename></entry> |
<entry>Functions handling context switching and setjmp/longjmp.</entry> |
</row> |
<row> |
<entry><filename>src/hal_misc.c</filename></entry> |
<entry>Exception and interrupt handlers in C. Various other utility |
functions.</entry> |
</row> |
<row> |
<entry><filename>src/hal_mk_defs.c</filename></entry> |
<entry>Used to export definitions from C header files to assembler |
header files.</entry> |
</row> |
<row> |
<entry><filename>src/hal_intr.c</filename></entry> |
<entry>Any necessary interrupt handling functions.</entry> |
</row> |
<row> |
<entry><filename>src/<arch>stub.c</filename></entry> |
<entry>Architecture stub code. Contains functions for translating eCos |
exceptions to UNIX signals and functions for single-stepping.</entry> |
</row> |
<row> |
<entry><filename>src/vectors.S</filename></entry> |
<entry>Exception, interrupt and early initialization code.</entry> |
</row> |
</tbody> |
</tgroup> |
</informaltable> |
|
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Variant HAL --> |
|
<section> |
<title>Variant HAL</title> |
|
<para>Some variant HALs may add extra files for variant specific serial |
drivers, or for handling interrupts/exceptions if it makes sense.</para> |
|
<para>Note that these files may be mostly empty if the CPU variant can be |
controlled by the generic architecture macros. The definitions present |
are only conditionally defined - if the equivalent platform headers |
provide the definitions, those override the variant definitions.</para> |
|
<informaltable frame=all> |
<tgroup cols=2 align=left colsep=1 rowsep=1> |
<thead> |
<row> |
<entry>File</entry> |
<entry>Description</entry> |
</row> |
</thead> |
<tbody> |
|
<row> |
<entry><filename>include/var_arch.h</filename></entry> |
<entry>Saved register frame format, various thread, register and stack |
related macros.</entry> |
</row> |
<row> |
<entry><filename>include/var_cache.h</filename></entry> |
<entry>Cache related macros.</entry> |
</row> |
<row> |
<entry><filename>include/var_intr.h</filename></entry> |
<entry>Interrupt related macros.</entry> |
</row> |
<row> |
<entry><filename>include/var_regs.h</filename></entry> |
<entry>Extra register definitions for the CPU variant.</entry> |
</row> |
<row> |
<entry><filename>include/variant.inc</filename></entry> |
<entry>Various assembly macros used during system initialization.</entry> |
</row> |
<row> |
<entry><filename>src/var_intr.c</filename></entry> |
<entry>Interrupt functions if necessary.</entry> |
</row> |
<row> |
<entry><filename>src/var_misc.c</filename></entry> |
<entry>hal_variant_init function and any necessary extra functions.</entry> |
</row> |
<row> |
<entry><filename>src/variant.S</filename></entry> |
<entry>Interrupt handler table definition.</entry> |
</row> |
<row> |
<entry><filename>src/<arch>_<variant>.ld</filename></entry> |
<entry>Linker macros.</entry> |
</row> |
</tbody> |
</tgroup> |
</informaltable> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Platform HAL --> |
|
<section> |
<title>Platform HAL</title> |
|
<para>Extras files may be added for platform specific serial |
drivers. Extra files for handling interrupts and exceptions will be |
present if it makes sense.</para> |
|
<informaltable frame=all> |
<tgroup cols=2 align=left colsep=1 rowsep=1> |
<thead> |
<row> |
<entry>File</entry> |
<entry>Description</entry> |
</row> |
</thead> |
<tbody> |
|
<row> |
<entry><filename>include/hal_diag.h</filename></entry> |
<entry>Defines functions used for HAL diagnostics output. This would |
normally be the ROM calling interface wrappers, but may also be the |
low-level IO functions themselves, saving a little overhead.</entry> |
</row> |
<row> |
<entry><filename>include/platform.inc</filename></entry> |
|
<entry>Platform initialization code. This includes memory controller, |
vectors, and monitor initialization. Depending on the architecture, |
other things may need defining here as well: interrupt decoding, |
status register initialization value, etc.</entry> |
|
</row> |
<row> |
<entry><filename>include/plf_cache.h</filename></entry> |
<entry>Platform specific cache handling.</entry> |
</row> |
<row> |
<entry><filename>include/plf_intr.h</filename></entry> |
<entry>Platform specific interrupt handling.</entry> |
</row> |
<row> |
<entry><filename>include/plf_io.h</filename></entry> |
<entry>PCI IO definitions and macros. May also be used to override |
generic HAL IO macros if the platform endianness differs from that of |
the CPU.</entry> |
</row> |
<row> |
<entry><filename>include/plf_stub.h</filename></entry> |
<entry>Defines stub initializer and board reset details.</entry> |
</row> |
<row> |
<entry><filename>src/hal_diag.c</filename></entry> |
<entry>May contain the low-level device drivers. But these may also |
reside in plf_stub.c</entry> |
</row> |
<row> |
<entry><filename>src/platform.S</filename></entry> |
<entry>Memory controller setup macro, and if necessary interrupt |
springboard code.</entry> |
</row> |
<row> |
<entry><filename>src/plf_misc.c</filename></entry> |
<entry>Platform initialization code.</entry> |
</row> |
<row> |
<entry><filename>src/plf_mk_defs.c</filename></entry> |
<entry>Used to export definitions from C header files to assembler |
header files.</entry> |
</row> |
<row> |
<entry><filename>src/plf_stub.c</filename></entry> |
<entry>Platform specific stub initialization and possibly the low-level |
device driver.</entry> |
</row> |
</tbody> |
</tgroup> |
</informaltable> |
|
<para>The platform HAL also contains files specifying the platform's |
memory layout. These files are located in |
<filename>include/pkgconf</filename>.</para> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Auxiliary HAL --> |
|
<section> |
<title>Auxiliary HAL</title> |
|
<para>Auxiliary HALs contain whatever files are necessary to provide the |
required functionality. There are no predefined set of files required |
in an auxiliary HAL.</para> |
|
</section> |
|
<!-- }}} --> |
|
</section> |
|
<!-- }}} --> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ ROM Monitor Calling Interface --> |
|
<section id="hal-calling-if"> |
<TITLE>Virtual Vectors (eCos/ROM Monitor Calling Interface)</TITLE> |
|
<para> |
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 <var_intr.h> |
|
#ifndef MACRO_DEFINED |
# define MACRO ... |
# define MACRO_DEFINED |
#endif |
|
|
|
var_intr.h: #include <plf_intr.h> |
|
#ifndef MACRO_DEFINED |
# define MACRO ... |
# define MACRO_DEFINED |
#endif |
|
|
plf_intr.h: |
|
# define MACRO ... |
# define MACRO_DEFINED |
</programlisting> |
|
<para>This means a platform can opt to rely on the variant or |
architecture implementation of a feature, or implement it itself.</para> |
|
</section> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Platform HAL Porting --> |
|
<section id="hal-porting-platform"> |
<title>Platform HAL Porting</title> |
|
<para> |
This is the type of port that takes the least effort. It basically |
consists of describing the platform (board) for the HAL: memory |
layout, early platform initialization, interrupt controllers, and a |
simple serial device driver. |
</para> |
|
<para> |
Doing a platform port requires a preexisting architecture and |
possibly a variant HAL port. |
</para> |
|
<!-- {{{ Porting Process --> |
|
<section> |
<TITLE>HAL Platform Porting Process</TITLE> |
|
<!-- {{{ Brief Overview --> |
|
<section> |
<title>Brief overview</title> |
|
<para>The easiest way to make a new platform HAL is simply to copy an |
existing platform HAL of the same architecture/variant and change all |
the files to match the new one. In case this is the first platform for |
the architecture/variant, a platform HAL from another architecture |
should be used as a template. |
</para> |
|
<para> |
The best way to start a platform port is to concentrate on getting |
RedBoot to run. RedBoot is a simpler environment than full eCos, it |
does not use interrupts or threads, but covers most of the |
basic startup requirements. |
</para> |
|
<para> |
RedBoot normally runs out of FLASH or ROM and provides program loading |
and debugging facilities. This allows further HAL development to |
happen using RAM startup configurations, which is desirable for the |
simple reason that downloading an image which you need to test is |
often many times faster than either updating a flash part, or indeed, |
erasing and reprogramming an EPROM. |
</para> |
|
<para>There are two approaches to getting to this first goal: |
</para> |
|
<orderedlist> |
<listitem> |
<para> |
The board is equipped with a ROM monitor which allows "load and go" of |
ELF, binary, S-record or some other image type which can be created |
using <application>objcopy</application>. This allows you to develop |
RedBoot by downloading and running the code (saving time). |
</para> |
|
<para> |
When the stub is running it is a good idea to examine the various |
hardware registers to help you write the platform initialization code. |
</para> |
|
<para> |
Then you may have to fiddle a bit going through step two (getting it |
to run from ROM startup). If at all possible, preserve the original |
ROM monitor so you can revert to it if necessary. |
</para> |
</listitem> |
|
<listitem> |
<para> |
The board has no ROM monitor. You need to get the platform |
initialization and stub working by repeatedly making changes, updating |
flash or EPROM and testing the changes. If you are lucky, you have a |
JTAG or similar CPU debugger to help you. If not, you will probably |
learn to appreciate LEDs. This approach may also be needed during the |
initial phase of moving RedBoot from RAM startup to ROM, since it is |
very unlikely to work first time. |
</para> |
</listitem> |
</orderedlist> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Step-by-step --> |
|
<section> |
<title>Step-by-step</title> |
|
<para>Given that no two platforms are exactly the same, you may have to |
deviate from the below. Also, you should expect a fair amount of |
fiddling - things almost never go right the first time. See the hints |
section below for some suggestions that might help debugging. |
</para> |
|
<para>The description below is based on the HAL layout used in the MIPS, |
PC and MN10300 HALs. Eventually all HALs should be converted to look like |
these - but in a transition period there will be other HALs which look |
substantially different. Please try to adhere to the following as much is |
possible without causing yourself too much grief integrating with a |
HAL which does not follow this layout. |
</para> |
|
<!-- ====================================================================== --> |
|
<section> |
<title>Minimal requirements</title> |
|
<para> |
These are the changes you must make before you attempt to build |
RedBoot. You are advised to read all the sources though. |
</para> |
|
<orderedlist> |
<listitem><para>Copy an existing platform HAL from the same or another |
architecture. Rename the files as necessary to follow the |
standard: CDL and MLT related files should contain the |
<arch>_<variant>_<platform> triplet.</para> |
</listitem> |
|
<listitem><para>Adjust CDL options. Primarily option naming, real-time |
clock/counter, and CYGHWR_MEMORY_LAYOUT variables, but also other |
options may need editing. Look through the architecture/variant |
CDL files to see if there are any requirements/features which |
where not used on the platform you copied. If so, add appropriate |
ones. See <xref linkend="hal-porting-cdl-requirements"> for more |
details.</para> |
</listitem> |
|
<listitem><para>Add the necessary packages and target descriptions to the |
top-level <filename>ecos.db</filename> file. See <xref |
linkend="hal-porting-ecos-database">. Initially, the target entry |
should only contain the HAL packages. Other hardware support |
packages will be added later.</para> |
</listitem> |
|
<listitem><para>Adjust the 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_<STARTUP>.ecm</filename> for |
the startup type you have chosen to begin with. Rename any |
platform specific options and remove any that do not apply. In the |
<literal>cdl_configuration</literal> section, comment out any |
extra packages that are added, particularly packages such as |
<literal>CYGPKG_IO_FLASH</literal> and |
<literal>CYGPKG_IO_ETH_DRIVERS</literal>. These are not needed for |
initial porting and will be added back later. |
</para> |
</listitem> |
|
<listitem><para>If the default IO macros are not correct, override them in |
plf_io.h. This may be necessary if the platform uses a different |
endianness from the default for the CPU.</para> |
</listitem> |
|
<listitem><para>Leave out/comment out code that enables caches and/or MMU if |
possible. Execution speed will not be a concern until the port is |
feature complete.</para> |
</listitem> |
|
<listitem><para>Implement a simple serial driver (polled mode only). Make sure the |
initialization function properly hooks the procedures up in the |
virtual vector IO channel tables. RedBoot will call the serial |
driver via these tables.</para> |
<para> |
By copying an existing platform HAL most of this code will be |
already done, and will only need the platform specific hardware |
access code to be written. |
</para> |
</listitem> |
|
<listitem><para>Adjust/implement necessary platform |
initialization. This can be found in |
<filename>platform.inc</filename> and |
<filename>platform.S</filename> files (ARM: |
<filename>hal_platform_setup.h</filename> and |
<filename><platform>_misc.c</filename>, PowerPC: |
<filename><platform>.S</filename>). This step can be |
postponed if you are doing a RAM startup RedBoot first and the |
existing ROM monitor handles board initialization.</para> |
</listitem> |
|
<listitem><para>Define <literal>HAL_STUB_PLATFORM_RESET</literal> |
(optionally empty) and |
<literal>HAL_STUB_PLATFORM_RESET_ENTRY</literal> so that RedBoot |
can reset-on-detach - this is very handy, often removing the need |
for physically resetting the board between downloads.</para> |
</listitem> |
|
</orderedlist> |
|
<para>You should now be able to build RedBoot. For ROM startup: |
</para> |
|
<programlisting width=72> |
% ecosconfig new <target_name> redboot |
% ecosconfig import $(ECOS_REPOSITORY)/hal/<architecture>/<platform>/<version>/misc/redboot_ROM.ecm |
% ecosconfig tree |
% make |
</programlisting> |
|
<para>You may have to make further changes than suggested above to get |
the make command to succeed. But when it does, you should find a |
RedBoot image in install/bin. To program this image into flash or |
EPROM, you may need to convert to some other file type, and possibly |
adjust the start address. When you have the correct |
<application>objcopy</application> command to do this, add it to the |
<literal>CYGBLD_BUILD_GDB_STUBS</literal> custom build rule in the |
platform CDL file. |
</para> |
|
<para>Having updated the flash/EPROM on the board, you should see output |
on the serial port looking like this when powering on the board: |
</para> |
|
<programlisting> |
RedBoot(tm) bootstrap and debug environment [ROMRAM] |
Non-certified release, version UNKNOWN - built 15:42:24, Mar 14 2002 |
|
Platform: <PLATFORM> (<ARCHITECTURE> <VARIANT>) |
Copyright (C) 2000, 2001, 2002, 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 "detach".</para> |
</listitem> |
|
<listitem> |
<para>Single-stepping is necessary for both instruction-level debugging |
and for breakpoint support. Single-stepping support should already be |
in place as part of the architecture/variant HAL, but you want to give |
it a quick test since you will come to rely on it.</para> |
</listitem> |
|
<listitem> |
<para>Real-time clock interrupts drive the eCos scheduler clock. Many |
embedded CPUs have an on-core timer (e.g. SH) or decrementer |
(e.g. MIPS, PPC) that can be used, and in this case it will already be |
supported by the architecture/variant HAL. You only have to calculate |
and enter the proper <literal>CYGNUM_HAL_RTC_CONSTANTS</literal> |
definitions in the platform CDL file. |
</para> |
|
<para>On some targets it may be necessary to use a platform-specific |
timer source for driving the real-time clock. In this case you also |
have to enter the proper CDL definitions, but must also define |
suitable versions of the <literal>HAL_CLOCK_XXXX</literal> macros.</para> |
</listitem> |
|
<listitem> |
<para>Interrupt decoding usually differs between platforms because the |
number and type of devices on the board differ. In |
<filename>plf_intr.h</filename> (ARM: |
<filename>hal_platform_ints.h</filename>) you must either extend or |
replace the default vector definitions provided by the architecture |
or variant interrupt headers. You may also have to define |
<literal>HAL_INTERRUPT_XXXX</literal> control macros.</para> |
</listitem> |
|
<listitem> |
<para>Caching may also differ from architecture/variant definitions. |
This maybe just the cache sizes, but there can also be bigger |
differences for example if the platform supports 2nd level caches. |
</para> |
|
<para>When cache definitions are in place, enable the caches on |
startup. First verify that the system is stable for RAM startups, then |
build a new RedBoot and install it. This will test if caching, and in |
particular the cache sync/flush operations, also work for ROM startup.</para> |
</listitem> |
|
<listitem> |
<para>Asynchronous breakpoints allow you to stop application execution |
and enter the debugger. Asynchronous breakpoint details are described |
in <!-- <xref linkend="hal-stubs-async-bps"> -->.</para> |
</listitem> |
|
</orderedlist> |
|
<para>You should now have a completed platform HAL port. Verify its |
stability and completeness by running all the eCos tests and fix any |
problems that show up (you have a working RedBoot now, remember! That |
means you can debug the code to see why it fails). |
</para> |
|
<para>Given the many configuration options in eCos, there may be hidden |
bugs or missing features that do not show up even if you run all the |
tests successfully with a default configuration. A comprehensive test |
of the entire system will take many configuration permutations and |
many many thousands of tests executed. |
</para> |
|
</section> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Hints --> |
|
<section> |
<title>Hints</title> |
|
<itemizedlist> |
|
<listitem> |
<para>JTAG or similar CPU debugging hardware can greatly reduce the time |
it takes to write a HAL port since you always have full visibility |
of what the CPU is doing. |
</para> |
</listitem> |
|
<listitem> |
<para>LEDs can be your friends if you don't have a JTAG |
device. Especially in the start of the porting effort if you don't |
already have a working ROM monitor on the target. Then you have to |
get a basic RedBoot working while basically being blindfolded. The |
LED can make it little easier, as you'll be able to do limited |
tracking of program flow and behavior by switching the LED on and |
off. If the board has multiple LEDs you can show a number (using |
binary notation with the LEDs) and sprinkle code which sets |
different numbers throughout the code.</para> |
</listitem> |
|
<listitem> |
<para>Debugging the interrupt processing is possible if you are |
careful with the way you program the very early interrupt entry |
handling. Write it so that as soon as possible in the interrupt |
path, taking a trap (exception) does not harm execution. See the |
SH vectors.S code for an example. Look for |
<literal>cyg_hal_default_interrupt_vsr</literal> and the label |
<literal>cyg_hal_default_interrupt_vsr_bp_safe</literal>, which |
marks the point after which traps/single-stepping is safe. |
</para> |
|
<para>Being able to display memory content, CPU registers, |
interrupt controller details at the time of an interrupt can save |
a lot of time.</para> |
</listitem> |
|
<listitem> |
<para>Using assertions is a good idea. They can sometimes reveal subtle |
bugs or missing features long before you would otherwise have |
found them, let alone notice them. |
</para> |
|
<para>The default eCos configuration does not use assertions, so you |
have to enable them by switching on the option <literal>CYGPKG_INFRA_DEBUG</literal> |
in the infra package.</para> |
</listitem> |
|
<listitem> |
<para>The idle loop can be used to help debug the system. |
</para> |
|
<para>Triggering clock from the idle loop is a neat trick for |
examining system behavior either before interrupts are fully |
working, or to speed up "the clock". |
</para> |
|
<para>Use the idle loop to monitor and/or print out variables or |
hardware registers.</para> |
</listitem> |
|
<listitem> |
<para><application>hal_mk_defs</application> is used in some of the |
HALs (ARM, SH) as a way to generate assembler symbol definitions from |
C header files without imposing an assembler/C syntax separation in |
the C header files.</para> |
</listitem> |
|
<!-- |
<listitem><para>Tracing using buffers [FIXME:TBD]</para> |
</listitem> |
--> |
|
</itemizedlist> |
|
</section> |
|
<!-- }}} --> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ CDL Requirements --> |
|
<section id="hal-porting-cdl-requirements"> |
<TITLE>HAL Platform CDL</TITLE> |
|
<para>The platform CDL both contains details necessary for the building |
of eCos, and platform-specific configuration options. For this reason |
the options differ between platforms, and the below is just a brief |
description of the most common options.</para> |
|
<para> See <!-- <xref linkend="???"> --> Components Writers Guide |
for more details on CDL. Also have a quick look around in |
existing platform CDL files to get an idea of what is possible and how |
various configuration issues can be represented with CDL.</para> |
|
<!-- {{{ eCos Database --> |
|
<section id="hal-porting-ecos-database"> |
<title>eCos Database</title> |
|
<para> |
The eCos configuration system is made aware of a package by |
adding a package description in <filename>ecos.db</filename>. As an |
example we use the <literal>TX39/JMR3904</literal> platform: |
</para> |
|
<programlisting> |
package CYGPKG_HAL_MIPS_TX39_JMR3904 { |
alias { "Toshiba JMR-TX3904 board" hal_tx39_jmr3904 tx39_jmr3904_hal } |
directory hal/mips/jmr3904 |
script hal_mips_tx39_jmr3904.cdl |
hardware |
description " |
The JMR3904 HAL package should be used when targeting the |
actual hardware. The same package can also be used when |
running on the full simulator, since this provides an |
accurate simulation of the hardware including I/O devices. |
To use the simulator in this mode the command |
`target sim --board=jmr3904' should be used from inside gdb." |
} |
</programlisting> |
|
<para>This contains the title and description presented in the |
Configuration Tool when the package is selected. It also specifies |
where in the tree the package files can be found (<literal>directory</literal>) |
and the name of the CDL file which contains the package details |
(<literal>script</literal>). |
</para> |
|
<para> |
To be able to build and test a configuration for the new target, there |
also needs to be a <literal>target</literal> entry in the |
<filename>ecos.db</filename> file. |
</para> |
|
<programlisting> |
target jmr3904 { |
alias { "Toshiba JMR-TX3904 board" jmr tx39 } |
packages { CYGPKG_HAL_MIPS |
CYGPKG_HAL_MIPS_TX39 |
CYGPKG_HAL_MIPS_TX39_JMR3904 |
} |
description " |
The jmr3904 target provides the packages needed to run |
eCos on a Toshiba JMR-TX3904 board. This target can also |
be used when running in the full simulator, since the simulator provides an |
accurate simulation of the hardware including I/O devices. |
To use the simulator in this mode the command |
`target sim --board=jmr3904' should be used from inside gdb." |
} |
</programlisting> |
|
|
<para> |
The important part here is the <literal>packages</literal> section |
which defines the various hardware specific packages that contribute |
to support for this target. In this case the MIPS architecture |
package, the TX39 variant package, and the JMR-TX3904 platform |
packages are selected. Other packages, for serial drivers, ethernet |
drivers and FLASH memory drivers may also appear here. |
</para> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ CDL File Layout --> |
|
<section> |
<title>CDL File Layout</title> |
|
<para> |
All the platform options are contained in a CDL package named |
<literal>CYGPKG_HAL_<architecture>_<variant>_<platform></literal>. |
They all share more or less the same <literal>cdl_package</literal> |
details: |
</para> |
|
<programlisting> |
cdl_package CYGPKG_HAL_MIPS_TX39_JMR3904 { |
display "JMR3904 evaluation board" |
parent CYGPKG_HAL_MIPS |
requires CYGPKG_HAL_MIPS_TX39 |
define_header hal_mips_tx39_jmr3904.h |
include_dir cyg/hal |
description " |
The JMR3904 HAL package should be used when targeting the |
actual hardware. The same package can also be used when |
running on the full simulator, since this provides an |
accurate simulation of the hardware including I/O devices. |
To use the simulator in this mode the command |
`target sim --board=jmr3904' should be used from inside gdb." |
|
compile platform.S plf_misc.c plf_stub.c |
|
define_proc { |
puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H <pkgconf/hal_mips_tx39.h>" |
puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H <pkgconf/hal_mips_tx39_jmr3904.h>" |
} |
|
... |
} |
</programlisting> |
|
<para>This specifies that the platform package should be parented under |
the MIPS packages, requires the TX39 variant HAL and all configuration |
settings should be saved in |
<filename>cyg/hal/hal_mips_tx39_jmt3904.h</filename>. |
</para> |
|
<para>The <literal>compile</literal> line specifies which files should be built |
when this package is enabled, and the <literal>define_proc</literal> defines |
some macros that are used to access the variant or architecture (the |
<literal>_TARGET_</literal> name is a bit of a misnomer) and platform |
configuration options. </para> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Startup Type --> |
|
<section> |
<title>Startup Type</title> |
|
<para>eCos uses an option to select between a set of valid startup |
configurations. These are normally RAM, ROM and possibly ROMRAM. This |
setting is used to select which linker map to use (i.e., where to link |
eCos and the application in the memory space), and how the startup |
code should behave.</para> |
|
<programlisting> |
cdl_component CYG_HAL_STARTUP { |
display "Startup type" |
flavor data |
legal_values {"RAM" "ROM"} |
default_value {"RAM"} |
no_define |
define -file system.h CYG_HAL_STARTUP |
description " |
When targeting the JMR3904 board it is possible to build |
the system for either RAM bootstrap, ROM bootstrap, or STUB |
bootstrap. RAM bootstrap generally requires that the board |
is equipped with ROMs containing a suitable ROM monitor or |
equivalent software that allows GDB to download the eCos |
application on to the board. The ROM bootstrap typically |
requires that the eCos application be blown into EPROMs or |
equivalent technology." |
} |
</programlisting> |
|
<para>The <literal>no_define</literal> and <literal>define</literal> |
pair is used to make the setting of this option appear in the file |
<filename>system.h</filename> instead of the default specified in the |
header.</para> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Build Options --> |
|
<section> |
<title>Build options</title> |
|
<para> |
A set of options under the components |
<literal>CYGBLD_GLOBAL_OPTIONS</literal> and |
<literal>CYGHWR_MEMORY_LAYOUT</literal> specify how eCos should be |
built: what tools and compiler options should be used, and which |
linker fragments should be used. |
</para> |
|
<programlisting> |
|
cdl_component CYGBLD_GLOBAL_OPTIONS { |
display "Global build options" |
flavor none |
parent CYGPKG_NONE |
description " |
Global build options including control over |
compiler flags, linker flags and choice of toolchain." |
|
|
cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { |
display "Global command prefix" |
flavor data |
no_define |
default_value { "mips-tx39-elf" } |
description " |
This option specifies the command prefix used when |
invoking the build tools." |
} |
|
cdl_option CYGBLD_GLOBAL_CFLAGS { |
display "Global compiler flags" |
flavor data |
no_define |
default_value { "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } |
description " |
This option controls the global compiler flags which |
are used to compile all packages by |
default. Individual packages may define |
options which override these global flags." |
} |
|
cdl_option CYGBLD_GLOBAL_LDFLAGS { |
display "Global linker flags" |
flavor data |
no_define |
default_value { "-g -nostdlib -Wl,--gc-sections -Wl,-static" } |
description " |
This option controls the global linker flags. Individual |
packages may define options which override these global flags." |
} |
} |
|
cdl_component CYGHWR_MEMORY_LAYOUT { |
display "Memory layout" |
flavor data |
no_define |
calculated { CYG_HAL_STARTUP == "RAM" ? "mips_tx39_jmr3904_ram" : \ |
"mips_tx39_jmr3904_rom" } |
|
cdl_option CYGHWR_MEMORY_LAYOUT_LDI { |
display "Memory layout linker script fragment" |
flavor data |
no_define |
define -file system.h CYGHWR_MEMORY_LAYOUT_LDI |
calculated { CYG_HAL_STARTUP == "RAM" ? "<pkgconf/mlt_mips_tx39_jmr3904_ram.ldi>" : \ |
"<pkgconf/mlt_mips_tx39_jmr3904_rom.ldi>" } |
} |
|
cdl_option CYGHWR_MEMORY_LAYOUT_H { |
display "Memory layout header file" |
flavor data |
no_define |
define -file system.h CYGHWR_MEMORY_LAYOUT_H |
calculated { CYG_HAL_STARTUP == "RAM" ? "<pkgconf/mlt_mips_tx39_jmr3904_ram.h>" : \ |
"<pkgconf/mlt_mips_tx39_jmr3904_rom.h>" } |
} |
} |
|
</programlisting> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Common Target Options --> |
|
<section> |
<title>Common Target Options</title> |
|
<para>All platforms also specify real-time clock details:</para> |
|
<programlisting> |
# Real-time clock/counter specifics |
cdl_component CYGNUM_HAL_RTC_CONSTANTS { |
display "Real-time clock constants." |
flavor none |
|
cdl_option CYGNUM_HAL_RTC_NUMERATOR { |
display "Real-time clock numerator" |
flavor data |
calculated 1000000000 |
} |
cdl_option CYGNUM_HAL_RTC_DENOMINATOR { |
display "Real-time clock denominator" |
flavor data |
calculated 100 |
} |
# Isn't a nice way to handle freq requirement! |
cdl_option CYGNUM_HAL_RTC_PERIOD { |
display "Real-time clock period" |
flavor data |
legal_values { 15360 20736 } |
calculated { CYGHWR_HAL_MIPS_CPU_FREQ == 50 ? 15360 : \ |
CYGHWR_HAL_MIPS_CPU_FREQ == 66 ? 20736 : 0 } |
} |
} |
</programlisting> |
|
<para> The <literal>NUMERATOR</literal> divided by the |
<literal>DENOMINATOR</literal> gives the number of nanoseconds per |
tick. The <literal>PERIOD</literal> is the divider to be programmed |
into a hardware timer that is driven from an appropriate hardware |
clock, such that the timer overflows once per tick (normally |
generating a CPU interrupt to mark the end of a tick). The tick |
default rate is typically 100Hz.</para> |
|
|
<para>Platforms that make use of the virtual vector |
ROM calling interface (see <xref linkend="hal-calling-if">) will also |
specify details necessary to define configuration channels (these |
options are from the SH/EDK7707 HAL) :</para> |
|
<programlisting> |
cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS { |
display "Number of communication channels on the board" |
flavor data |
calculated 1 |
} |
|
cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL { |
display "Debug serial port" |
flavor data |
legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 |
default_value 0 |
description " |
The EDK/7708 board has only one serial port. This option |
chooses which port will be used to connect to a host |
running GDB." |
} |
|
cdl_option CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL { |
display "Diagnostic serial port" |
flavor data |
legal_values 0 to CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS-1 |
default_value 0 |
description " |
The EDK/7708 board has only one serial port. This option |
chooses which port will be used for diagnostic output." |
} |
</programlisting> |
|
<para>The platform usually also specify an option controlling the ability |
to co-exist with a ROM monitor:</para> |
|
<programlisting> |
cdl_option CYGSEM_HAL_USE_ROM_MONITOR { |
display "Work with a ROM monitor" |
flavor booldata |
legal_values { "Generic" "CygMon" "GDB_stubs" } |
default_value { CYG_HAL_STARTUP == "RAM" ? "CygMon" : 0 } |
parent CYGPKG_HAL_ROM_MONITOR |
requires { CYG_HAL_STARTUP == "RAM" } |
description " |
Support can be enabled for three different varieties of ROM monitor. |
This support changes various eCos semantics such as the encoding |
of diagnostic output, or the overriding of hardware interrupt |
vectors. |
Firstly there is \"Generic\" support which prevents the HAL |
from overriding the hardware vectors that it does not use, to |
instead allow an installed ROM monitor to handle them. This is |
the most basic support which is likely to be common to most |
implementations of ROM monitor. |
\"CygMon\" provides support for the Cygnus ROM Monitor. |
And finally, \"GDB_stubs\" provides support when GDB stubs are |
included in the ROM monitor or boot ROM." |
} |
</programlisting> |
|
<para>Or the ability to be configured as a ROM monitor:</para> |
|
<programlisting> |
cdl_option CYGSEM_HAL_ROM_MONITOR { |
display "Behave as a ROM monitor" |
flavor bool |
default_value 0 |
parent CYGPKG_HAL_ROM_MONITOR |
requires { CYG_HAL_STARTUP == "ROM" } |
description " |
Enable this option if this program is to be used as a ROM monitor, |
i.e. applications will be loaded into RAM on the board, and this |
ROM monitor may process exceptions or interrupts generated from the |
application. This enables features such as utilizing a separate |
interrupt stack when exceptions are generated." |
} |
</programlisting> |
|
<para>The latter option is accompanied by a special build rule that |
extends the generic ROM monitor build rule in the common HAL:</para> |
|
<programlisting> |
cdl_option CYGBLD_BUILD_GDB_STUBS { |
display "Build GDB stub ROM image" |
default_value 0 |
requires { CYG_HAL_STARTUP == "ROM" } |
requires CYGSEM_HAL_ROM_MONITOR |
requires CYGBLD_BUILD_COMMON_GDB_STUBS |
requires CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS |
requires ! CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT |
requires ! CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT |
requires ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT |
requires ! CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM |
no_define |
description " |
This option enables the building of the GDB stubs for the |
board. The common HAL controls takes care of most of the |
build process, but the final conversion from ELF image to |
binary data is handled by the platform CDL, allowing |
relocation of the data if necessary." |
|
make -priority 320 { |
<PREFIX>/bin/gdb_module.bin : <PREFIX>/bin/gdb_module.img |
$(OBJCOPY) -O binary $< $@ |
} |
} |
</programlisting> |
|
<para> |
Most platforms support RedBoot, and some options are needed to |
configure for RedBoot. |
</para> |
|
<programlisting width=72> |
cdl_component CYGPKG_REDBOOT_HAL_OPTIONS { |
display "Redboot HAL options" |
flavor none |
no_define |
parent CYGPKG_REDBOOT |
active_if CYGPKG_REDBOOT |
description " |
This option lists the target's requirements for a valid Redboot |
configuration." |
|
cdl_option CYGBLD_BUILD_REDBOOT_BIN { |
display "Build Redboot ROM binary image" |
active_if CYGBLD_BUILD_REDBOOT |
default_value 1 |
no_define |
description "This option enables the conversion of the Redboot ELF |
image to a binary image suitable for ROM programming." |
|
make -priority 325 { |
<PREFIX>/bin/redboot.bin : <PREFIX>/bin/redboot.elf |
$(OBJCOPY) --strip-debug $< $(@:.bin=.img) |
$(OBJCOPY) -O srec $< $(@:.bin=.srec) |
$(OBJCOPY) -O binary $< $@ |
} |
} |
} |
</programlisting> |
|
<para> |
The important part here is the <literal>make</literal> command in the |
<literal>CYGBLD_BUILD_REDBOOT_BIN</literal> option which emits |
makefile commands to translate the <filename>.elf</filename> file |
generated by the link phase into both a binary file and an S-Record |
file. If a different format is required by a PROM programmer or ROM |
monitor, then different output formats would need to be generated here. |
</para> |
|
</section> |
|
<!-- }}} --> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Platform Memory Layout --> |
|
<section id="hal-porting-platform-memory-layout"> |
<TITLE>Platform Memory Layout</TITLE> |
|
<para>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 <pkgconf/hal_mips.h>" |
} |
|
compile var_misc.c |
|
make { |
<PREFIX>/lib/target.ld: <PACKAGE>/src/mips_vr4300.ld |
$(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(CFLAGS) -o $@ $< |
@echo $@ ": \\" > $(notdir $@).deps |
@tail +2 target.tmp >> $(notdir $@).deps |
@echo >> $(notdir $@).deps |
@rm target.tmp |
} |
|
cdl_option CYGBLD_LINKER_SCRIPT { |
display "Linker script" |
flavor data |
no_define |
calculated { "src/mips_vr4300.ld" } |
} |
|
} |
</programlisting> |
|
<para> |
The <literal>define_proc</literal> causes the architecture |
configuration file to be included into the configuration file for the |
variant. The <literal>compile</literal> causes the single source file |
for this variant, <filename>var_misc.c</filename> to be compiled. The |
<literal>make</literal> command emits makefile rules to combine the |
linker script with the <filename>.ldi</filename> file to generate |
<literal>target.ld</literal>. Finally, in the MIPS HALs, the main |
linker script is defined in the variant, rather than the architecture, |
so <literal>CYGBLD_LINKER_SCRIPT</literal> is defined here. |
</para> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Cache Support --> |
|
<section> |
<title>Cache Support</title> |
|
<para> |
The main area where the variant is likely to be involved is in cache |
support. Often the only thing that distinguishes one CPU variant from |
another is the size of its caches. |
</para> |
|
<para> |
In architectures such as the MIPS and PowerPC where cache instructions |
are part of the ISA, most of the actual cache operations are |
implemented in the architecture HAL. In this case the variant HAL only |
needs to define the cache dimensions. The following are the cache |
dimensions defined in the MIPS VR4300 variant |
<filename>var_cache.h</filename>. |
</para> |
|
<programlisting width=72> |
// Data cache |
#define HAL_DCACHE_SIZE (8*1024) // Size of data cache in bytes |
#define HAL_DCACHE_LINE_SIZE 16 // Size of a data cache line |
#define HAL_DCACHE_WAYS 1 // Associativity of the cache |
|
// Instruction cache |
#define HAL_ICACHE_SIZE (16*1024) // Size of cache in bytes |
#define HAL_ICACHE_LINE_SIZE 32 // Size of a cache line |
#define HAL_ICACHE_WAYS 1 // Associativity of the cache |
|
#define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS)) |
#define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS)) |
</programlisting> |
|
<para> |
Additional cache macros, or overrides for the defaults, may also |
appear in here. While some architectures have instructions for |
managing cache lines, overall enable/disable operations may be handled |
via variant specific registers. If so then |
<filename>var_cache.h</filename> should also define the |
<literal>HAL_XCACHE_ENABLE()</literal> and |
<literal>HAL_XCACHE_DISABLE()</literal> macros. |
</para> |
|
<para> |
If there are any generic features that the variant does not support |
(cache locking is a typical example) then |
<literal>var_cache.h</literal> may need to disable definitions of |
certain operations. It is architecture dependent exactly how this is |
done. |
</para> |
|
|
</section> |
|
<!-- }}} --> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Architecture HAL Porting --> |
|
<section id="hal-porting-architecture"> |
|
<title>Architecture HAL Porting</title> |
|
<para> |
A new architecture HAL is the most complex HAL to write, and it the |
least easily described. Hence this section is presently nothing more |
than a place holder for the future. |
</para> |
|
<!-- {{{ Porting Process --> |
|
<section> |
<TITLE>HAL Architecture Porting Process</TITLE> |
|
<para>The easiest way to make a new architecture HAL is simply to copy an |
existing architecture HAL of an, if possible, closely matching |
architecture and change all the files to match the new |
architecture. The MIPS architecture HAL should be used if possible, as |
it has the appropriate layout and coding conventions. Other HALs |
may deviate from that norm in various ways.</para> |
|
<note> |
<title>Note</title> |
<para> eCos is written for GCC. It requires C and C++ |
compiler support as well as a few compiler features introduced during |
eCos development - so compilers older than eCos may not provide these |
features. Note that there is no C++ support for any 8 or 16 bit |
CPUs. Before you can undertake an eCos port, you need the required |
compiler support. |
</para> |
</note> |
|
<para> |
The following gives a rough outline of the steps needed to create a |
new architecture HAL. The exact order and set of steps needed will |
vary greatly from architecture to architecture, so a lot of |
flexibility is required. And of course, if the architecture HAL is to |
be tested, it is necessary to do variant and platform ports for the |
initial target simultaneously. |
</para> |
|
<orderedlist> |
|
<listitem> |
<para> |
Make a new directory for the new architecture under the |
<filename>hal</filename> directory in the source repository. Make an |
<filename>arch</filename> directory under this and populate this with |
the standard set of package directories. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Copy the CDL file from an example HAL changing its name to match the |
new HAL. Edit the file, changing option names as appropriate. Delete |
any options that are specific to the original HAL, and and any new |
options that are necessary for the new architecture. This is likely to |
be a continuing process during the development of the HAL. See <xref |
linkend="hal-porting-architecture-cdl"> for more details. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Copy the <filename>hal_arch.h</filename> file from an example |
HAL. Within this file you need to change or define the following: |
</para> |
<itemizedlist> |
|
<listitem> |
<para> |
Define the <structname>HAL_SavedRegisters</structname> structure. This |
may need to reflect the save order of any group register save/restore |
instructions, the interrupt and exception save and restore formats, |
and the procedure calling conventions. It may also need to cater for |
optional FPUs and other functional units. It can be quite difficult to |
develop a layout that copes with all requirements. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define the bit manipulation routines, |
<literal>HAL_LSBIT_INDEX()</literal> and |
<literal>HAL_MSBIT_INDEX()</literal>. If the architecture contains |
instructions to perform these, or related, operations, then these |
should be defined as inline assembler fragments. Otherwise make them |
calls to functions. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define <literal>HAL_THREAD_INIT_CONTEXT()</literal>. This initializes |
a restorable CPU context onto a stack pointer so that a later call to |
<literal>HAL_THREAD_LOAD_CONTEXT()</literal> or |
<literal>HAL_THREAD_SWITCH_CONTEXT()</literal> will execute it |
correctly. This macro needs to take account of the same optional |
features of the architecture as the definition of |
<structname>HAL_SavedRegisters</structname>. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define <literal>HAL_THREAD_LOAD_CONTEXT()</literal> and |
<literal>HAL_THREAD_SWITCH_CONTEXT()</literal>. These should just be |
calls to functions in <filename>context.S</filename>. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define <literal>HAL_REORDER_BARRIER()</literal>. This prevents code |
being moved by the compiler and is necessary in some order-sensitive |
code. This macro is actually defined identically in all architecture, |
so it can just be copied. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define breakpoint support. The macro |
<literal>HAL_BREAKPOINT(label)</literal> needs to be an inline assembly |
fragment that invokes a breakpoint. The breakpoint instruction should |
be labeled with the <parameter>label</parameter> |
argument. <literal>HAL_BREAKINST</literal> and |
<literal>HAL_BREAKINST_SIZE</literal> define the breakpoint |
instruction for debugging purposes. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define GDB support. GDB views the registers of the target as a linear |
array, with each register having a well defined offset. This array may |
differ from the ordering defined in |
<structname>HAL_SavedRegisters</structname>. The macros |
<literal>HAL_GET_GDB_REGISTERS()</literal> and |
<literal>HAL_SET_GDB_REGISTERS()</literal> translate between the GDB |
array and the <structname>HAL_SavedRegisters</structname> structure. |
The <literal>HAL_THREAD_GET_SAVED_REGISTERS()</literal> translates a |
stack pointer saved by the context switch macros into a pointer to a |
<structname>HAL_SavedRegisters</structname> structure. Usually this is |
a one-to-one translation, but this macro allows it to differ if |
necessary. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define long jump support. The type <type>hal_jmp_buf</type> and the |
functions <function>hal_setjmp()</function> and |
<literal>hal_longjmp()</literal> provide the underlying implementation |
of the C library <function>setjmp()</function> and |
<function>longjmp()</function>. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define idle thread action. Generally the macro |
<literal>HAL_IDLE_THREAD_ACTION()</literal> is defined to call a |
function in <filename>hal_misc.c</filename>. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define stack sizes. The macros |
<literal>CYGNUM_HAL_STACK_SIZE_MINIMUM</literal> and |
<literal>CYGNUM_HAL_STACK_SIZE_TYPICAL</literal> should be defined to |
the minimum size for any thread stack and a reasonable default for |
most threads respectively. It is usually best to construct these out |
of component sizes for the CPU save state and procedure call stack |
usage. These definitions should not use anything other than numerical |
values since they can be used from assembly code in some HALs. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define memory access macros. These macros provide translation between |
cached and uncached and physical memory spaces. They usually consist |
of masking out bits of the supplied address and ORing in alternative |
address bits. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define global pointer save/restore macros. These really only need |
defining if the calling conventions of the architecture require a |
global pointer (as does the MIPS architecture), they may be empty |
otherwise. If it is necessary to define these, then take a look at the |
MIPS implementation for an example. |
</para> |
</listitem> |
|
</itemizedlist> |
|
</listitem> |
|
<listitem> |
<para> |
Copy <filename>hal_intr.h</filename> from an example HAL. Within this |
file you should change or define the following: |
</para> |
|
|
<itemizedlist> |
<listitem> |
<para> |
Define the exception vectors. These should be detailed in the |
architecture specification. Essentially for each exception entry point |
defined by the architecture there should be an entry in the VSR |
table. The offsets of these VSR table entries should be defined here |
by <literal>CYGNUM_HAL_VECTOR_*</literal> definitions. The size of the |
VSR table also needs to be defined here. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Map any hardware exceptions to standard names. There is a group of |
exception vector name of the form |
<literal>CYGNUM_HAL_EXCEPTION_*</literal> that define a wide variety |
of possible exceptions that many architectures raise. Generic code |
detects whether the architecture can raise a given exception by |
testing whether a given <literal>CYGNUM_HAL_EXCEPTION_*</literal> |
definition is present. If it is present then its value is the vector |
that raises that exception. This does not need to be a one-to-one |
correspondence, and several <literal>CYGNUM_HAL_EXCEPTION_*</literal> |
definitions may have the same value. |
</para> |
|
<para> |
Interrupt vectors are usually defined in the variant or platform |
HALs. The interrupt number space may either be continuous with the VSR |
number space, where they share a vector table (as in the i386) or may |
be a separate space where a separate decode stage is used (as in MIPS |
or PowerPC). |
</para> |
|
</listitem> |
|
<listitem> |
<para> |
Declare any static data used by the HAL to handle interrupts and |
exceptions. This is usually three vectors for interrupts: |
<literal>hal_interrupt_handlers[]</literal>, |
<literal>hal_interrupt_data[]</literal> and |
<literal>hal_interrupt_objects[]</literal>, which are sized according |
to the interrupt vector definitions. In addition a definition for the |
VSR table, <literal>hal_vsr_table[]</literal> should be made. These |
vectors are normally defined in either <filename>vectors.S</filename> |
or <filename>hal_misc.c</filename>. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define interrupt enable/disable macros. These are normally inline |
assembly fragments to execute the instructions, or manipulate the CPU |
register, that contains the CPU interrupt enable bit. |
</para> |
</listitem> |
|
<listitem> |
<para> |
A feature that many HALs support is the ability to execute DSRs on the |
interrupt stack. This is not an essential feature, and is better left |
unimplemented in the initial porting effort. If this is required, then |
the macro <literal>HAL_INTERRUPT_STACK_CALL_PENDING_DSRS()</literal> |
should be defined to call a function in |
<filename>vectors.S</filename>. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Define the interrupt and VSR attachment macros. If the same arrays as |
for other HALs have been used for VSR and interrupt vectors, then |
these macro can be copied across unchanged. |
</para> |
</listitem> |
|
</itemizedlist> |
|
</listitem> |
|
<listitem> |
<para> |
A number of other header files also need to be filled in: |
</para> |
<itemizedlist> |
<listitem> |
<para> |
<filename>basetype.h</filename>. This file defines the basic types |
used by eCos, together with the endianness and some other |
characteristics. This file only really needs to contain definitions |
if the architecture differs significantly from the defaults defined |
in <filename>cyg_type.h</filename> |
</para> |
</listitem> |
|
<listitem> |
<para> |
<filename>hal_io.h</filename>. This file contains macros for accessing |
device IO registers. If the architecture uses memory mapped IO, then |
these can be copied unchanged from an existing HAL such as MIPS. If |
the architecture uses special IO instructions, then these macros must |
be defined as inline assembler fragments. See the I386 HAL for an |
example. PCI bus access macros are usually defined in the variant or |
platform HALs. |
</para> |
</listitem> |
|
<listitem> |
<para> |
<filename>hal_cache.h</filename>. This file contains cache access |
macros. If the architecture defines cache instructions, or control |
registers, then the access macros should be defined here. Otherwise |
they must be defined in the variant or platform HAL. Usually the cache |
dimensions (total size, line size, ways etc.) are defined in the |
variant HAL. |
</para> |
</listitem> |
|
<listitem> |
<para> |
<filename>arch.inc</filename> and |
<filename><architecture>.inc</filename>. These files are |
assembler headers used by <filename>vectors.S</filename> and |
<filename>context.S</filename>. |
<filename><architecture>.inc</filename> is a general purpose |
header that should contain things like register aliases, ABI |
definitions and macros useful to general assembly |
code. If there are no such definitions, then this file need not be |
provided. <filename>arch.inc</filename> contains macros for performing |
various eCos related operations such as initializing the CPU, caches, |
FPU etc. The definitions here may often be configured or overridden by |
definitions in the variant or platform HALs. See the MIPS HAL for an |
example of this. |
</para> |
</listitem> |
|
</itemizedlist> |
|
</listitem> |
|
<listitem> |
<para> |
Write <filename>vectors.S</filename>. This is the most important file |
in the HAL. It contains the CPU initialization code, exception and |
interrupt handlers. While other HALs should be consulted for |
structures and techniques, there is very little here that can be |
copied over without major edits. |
</para> |
|
<para> |
The main pieces of code that need to be defined here are: |
</para> |
|
<itemizedlist> |
<listitem> |
<para> |
Reset vector. This usually need to be positioned at the start of the |
ROM or FLASH, so should be in a linker section of its own. It can then be |
placed correctly by the linker script. Normally this code is little |
more than a jump to the label <literal>_start</literal>. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Exception vectors. These are the trampoline routines connected to the |
hardware exception entry points that vector through the VSR table. In |
many architectures these are adjacent to the reset vector, and should |
occupy the same linker section. If the architecture allow the vectors |
to be moved then it may be necessary for these trampolines to be |
position independent so they can be relocated at runtime. |
</para> |
|
<para> |
The trampolines should do the minimum necessary to transfer control |
from the hardware vector to the VSR pointed to by the matching table |
entry. Exactly how this is done depends on the architecture. Usually |
the trampoline needs to get some working registers by either saving |
them to CPU special registers (e.g. PowerPC SPRs), using reserved |
general registers (MIPS K0 and K1), using only memory based |
operations (IA32), or just jumping directly (ARM). The VSR table index |
to be used is either implicit in the entry point taken (PowerPC, IA32, |
ARM), or must be determined from a CPU register (MIPS). |
</para> |
</listitem> |
|
<listitem> |
<para> |
Write kernel startup code. This is the location the reset vector jumps |
to, and can be in the main text section of the executable, rather than |
a special section. The code here should first initialize the CPU and other |
hardware subsystems. The best approach is to use a set of macro |
calls that are defined either in <filename>arch.inc</filename> or |
overridden in the variant or platform HALs. Other jobs that this code |
should do are: initialize stack pointer; copy the data section from |
ROM to RAM if necessary; zero the BSS; call variant and platform |
initializers; call <function>cyg_hal_invoke_constructors()</function>; |
call <function>initialize_stub()</function> if necessary. Finally it |
should call <function>cyg_start()</function>. See <xref |
linkend="hal-startup"> for details. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Write the default exception VSR. This VSR is installed in the VSR |
table for all synchronous exception vectors. See <xref |
linkend="hal-default-synchronous-exception-handling"> for details of |
what this VSR does. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Write the default interrupt VSR. This is installed in all VSR table |
entries that correspond to external interrupts. See <xref |
linkend="hal-default-synchronous-exception-handling"> for details of |
what this VSR does. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Write |
<function>hal_interrupt_stack_call_pending_dsrs()</function>. If this |
function is defined in <filename>hal_arch.h</filename> then it should |
appear here. The purpose of this function is to call DSRs on the |
interrupt stack rather than the current thread's stack. This is not an |
essential feature, and may be left until later. However it interacts |
with the stack switching that goes on in the interrupt VSR, so it may |
make sense to write these pieces of code at the same time to ensure |
consistency. |
</para> |
|
<para> |
When this function is implemented it should do the following: |
</para> |
|
<itemizedlist> |
<listitem> |
<para> |
Take a copy of the current SP and then switch to the interrupt stack. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Save the old SP, together with the CPU status register (or whatever |
register contains the interrupt enable status) and any other |
registers that may be corrupted by a function call (such as any link |
register) to locations in the interrupt stack. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Enable interrupts. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Call <function>cyg_interrupt_call_pending_DSRs()</function>. This is a |
kernel functions that actually calls any pending DSRs. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Retrieve saved registers from the interrupt stack and switch back to |
the current thread stack. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Merge the interrupt enable state recorded in the save CPU status |
register with the current value of the status register to restore the |
previous enable state. If the status register does not contain any |
other persistent state then this can be a simple restore of the |
register. However if the register contains other state bits that might |
have been changed by a DSR, then care must be taken not to disturb |
these. |
</para> |
</listitem> |
|
</itemizedlist> |
|
</listitem> |
|
|
<listitem> |
<para> |
Define any data items needed. Typically <filename>vectors.S</filename> |
may contain definitions for the VSR table, the interrupt tables and the |
interrupt stack. Sometimes these are only default definitions that may |
be overridden by the variant or platform HALs. |
</para> |
</listitem> |
|
</itemizedlist> |
|
</listitem> |
|
<listitem> |
<para> |
Write <filename>context.S</filename>. This file contains the context |
switch code. See <xref linkend="hal-context-switch"> for details of |
how these functions operate. This file may also contain the |
implementation of <function>hal_setjmp()</function> and |
<function>hal_longjmp()</function>. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Write <filename>hal_misc.c</filename>. This file contains any C |
data and functions needed by the HAL. These might include: |
</para> |
|
<itemizedlist> |
<listitem> |
<para> |
<varname>hal_interrupt_*[]</varname>. In some HALs, if these arrays |
are not defined in <filename>vectors.S</filename> then they must be |
defined here. |
</para> |
</listitem> |
|
<listitem> |
<para> |
<function>cyg_hal_exception_handler()</function>. This function is |
called from the exception VSR. It usually does extra decoding of the |
exception and invokes any special handlers for things like FPU traps, |
bus errors or memory exceptions. If there is nothing special to be |
done for an exception, then it either calls into the GDB stubs, by |
calling <function>__handle_exception()</function>, or |
invokes the kernel by calling |
<function>cyg_hal_deliver_exception()</function>. |
</para> |
</listitem> |
|
<listitem> |
<para> |
<function>hal_arch_default_isr()</function>. The |
<varname>hal_interrupt_handlers[]</varname> array is usually |
initialized with pointers to <filename>hal_default_isr()</filename>, |
which is defined in the common HAL. This function handles things like |
Ctrl-C processing, but if that is not relevant, then it will call |
<function>hal_arch_default_isr()</function>. Normally this function |
should just return zero. |
</para> |
</listitem> |
|
<listitem> |
<para> |
<function>cyg_hal_invoke_constructors()</function>. This calls the |
constructors for all static objects before the program starts. eCos |
relies on these being called in the correct order for it to function |
correctly. The exact way in which constructors are handled may differ |
between architectures, although most use a simple table of function |
pointers between labels <literal>__CTOR_LIST__</literal> and |
<literal>__CTOR_END__</literal> which must called in order from the |
top down. Generally, this function can be copied directly from an |
existing architecture HAL. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Bit indexing functions. If the macros |
<literal>HAL_LSBIT_INDEX()</literal> and |
<literal>HAL_MSBIT_INDEX()</literal> are defined as function calls, |
then the functions should appear here. The main reason for doing this |
is that the architecture does not have support for bit indexing and |
these functions must provide the functionality by conventional |
means. While the trivial implementation is a simple for loop, it is |
expensive and non-deterministic. Better, constant time, |
implementations can be found in several HALs (MIPS for example). |
</para> |
</listitem> |
|
<listitem> |
<para> |
<function>hal_delay_us()</function>. If the macro |
<literal>HAL_DELAY_US()</literal> is defined in <filename |
class="headerfile">hal_intr.h</filename> then it should be defined to |
call this function. While most of the time this function is called |
with very small values, occasionally (particularly in some ethernet |
drivers) it is called with values of several seconds. Hence the |
function should take care to avoid overflow in any calculations. |
</para> |
</listitem> |
|
<listitem> |
<para> |
<function>hal_idle_thread_action()</function>. This function is called |
from the idle thread via the |
<literal>HAL_IDLE_THREAD_ACTION()</literal> macro, if so |
defined. While normally this function does nothing, during development |
this is often a good place to report various important system |
parameters on LCDs, LED or other displays. This function can also |
monitor system state and report any anomalies. If the architecture |
supports a <literal>halt</literal> instruction then this is a good |
place to put an inline assembly fragment to execute it. It is also a |
good place to handle any power saving activity. |
</para> |
</listitem> |
|
</itemizedlist> |
</listitem> |
|
<listitem> |
<para> |
Create the <filename><architecture>.ld</filename> file. While |
this file may need to be moved to the variant HAL in the future, it |
should initially be defined here, and only moved if necessary. |
</para> |
<para> |
This file defines a set of macros that are used by the platform |
<literal>.ldi</literal> files to generate linker scripts. Most GCC |
toolchains are very similar so the correct approach is to copy the |
file from an existing architecture and edit it. The main things that |
will need editing are the <literal>OUTPUT_FORMAT()</literal> directive |
and maybe the creation or allocation of extra sections to various |
macros. Running the target linker with just the |
<literal>--verbose</literal> argument will cause it to output its |
default linker script. This can be compared with the |
<literal>.ld</literal> file and appropriate edits made. |
</para> |
</listitem> |
|
<listitem> |
<para> |
If GDB stubs are to be supported in RedBoot or eCos, then support must |
be included for these. The most important of these are <filename |
class="headerfile">include/<architecture>-stub.h</filename> and |
<filename>src/<architecture>-stub.c</filename>. In all existing |
architecture HALs these files, and any support files they need, have |
been derived from files supplied in <literal>libgloss</literal>, as |
part of the GDB toolchain package. If this is a totally new |
architecture, this may not have been done, and they must be created |
from scratch. |
</para> |
|
<para> |
<filename |
class="headerfile">include/<architecture>-stub.h</filename> |
contains definitions that are used by the GDB stubs to describe the |
size, type, number and names of CPU registers. This information is |
usually found in the GDB support files for the architecture. It also |
contains prototypes for the functions exported by |
<filename>src/<architecture>-stub.c</filename>; however, since |
this is common to all architectures, it can be copied from some other |
HAL. |
</para> |
|
<para> |
<filename>src/<architecture>-stub.c</filename> implements the |
functions exported by the header. Most of this is fairly straight |
forward: the implementation in existing HALs should show exactly what |
needs to be done. The only complex part is the support for |
single-stepping. This is used a lot by GDB, so it cannot be |
avoided. If the architecture has support for a trace or single-step |
trap then that can be used for this purpose. If it does not then this |
must be simulated by planting a breakpoint in the next |
instruction. This can be quite involved since it requires some |
analysis of the current instruction plus the state of the CPU to |
determine where execution is going to go next. |
</para> |
|
</listitem> |
|
</orderedlist> |
|
|
</section> |
|
<!-- }}} --> |
<!-- {{{ CDL Requirements --> |
|
<section id="hal-porting-architecture-cdl"> |
<title>CDL Requirements</title> |
|
<para> |
The CDL needed for any particular architecture HAL depends to a large |
extent on the needs of that architecture. This includes issues such as |
support for different variants, use of FPUs, MMUs and caches. The |
exact split between the architecture, variant and platform HALs for |
various features is also somewhat fluid. |
</para> |
|
<para> |
To give a rough idea about how the CDL for an architecture is |
structured, we will take as an example the I386 CDL. |
</para> |
|
<para> |
This first section introduces the CDL package and placed it under the |
main HAL package. Include files from this package will be put in the |
<filename>include/cyg/hal</filename> directory, and definitions from |
this file will be placed in |
<filename>include/pkgconf/hal_i386.h</filename>. The |
<literal>compile</literal> line specifies the files in the |
<filename>src</filename> directory that are to be compiled as part of |
this package. |
</para> |
|
<programlisting width=72> |
cdl_package CYGPKG_HAL_I386 { |
display "i386 architecture" |
parent CYGPKG_HAL |
hardware |
include_dir cyg/hal |
define_header hal_i386.h |
description " |
The i386 architecture HAL package provides generic |
support for this processor architecture. It is also |
necessary to select a specific target platform HAL |
package." |
|
compile hal_misc.c context.S i386_stub.c hal_syscall.c |
</programlisting> |
|
<para> |
Next we need to generate some files using non-standard make rules. The |
first is <filename>vectors.S</filename>, which is not put into the |
library, but linked explicitly with all applications. The second is |
the generation of the <filename>target.ld</filename> file from |
<filename>i386.ld</filename> and the startup-selected |
<filename>.ldi</filename> file. Both of these are essentially |
boilerplate code that can be copied and edited. |
</para> |
|
<programlisting width=72> |
|
make { |
<PREFIX>/lib/vectors.o : <PACKAGE>/src/vectors.S |
$(CC) -Wp,-MD,vectors.tmp $(INCLUDE_PATH) $(CFLAGS) -c -o $@ $< |
@echo $@ ": \\" > $(notdir $@).deps |
@tail +2 vectors.tmp >> $(notdir $@).deps |
@echo >> $(notdir $@).deps |
@rm vectors.tmp |
} |
|
make { |
<PREFIX>/lib/target.ld: <PACKAGE>/src/i386.ld |
$(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) $(CFLAGS) -o $@ $< |
@echo $@ ": \\" > $(notdir $@).deps |
@tail +2 target.tmp >> $(notdir $@).deps |
@echo >> $(notdir $@).deps |
@rm target.tmp |
} |
</programlisting> |
|
<para> |
The i386 is currently the only architecture that supports SMP. The |
following CDL simply enabled the HAL SMP support if |
required. Generally this will get enabled as a result of a |
<literal>requires</literal> statement in the kernel. The |
<literal>requires</literal> statement here turns off lazy FPU |
switching in the FPU support code, since it is inconsistent with SMP |
operation. |
</para> |
|
<programlisting width=72> |
|
cdl_component CYGPKG_HAL_SMP_SUPPORT { |
display "SMP support" |
default_value 0 |
requires { CYGHWR_HAL_I386_FPU_SWITCH_LAZY == 0 } |
|
cdl_option CYGPKG_HAL_SMP_CPU_MAX { |
display "Max number of CPUs supported" |
flavor data |
default_value 2 |
} |
} |
</programlisting> |
|
<para> |
The i386 HAL has optional FPU support, which is enabled by default. It |
can be disabled to improve system performance. There are two FPU |
support options: either to save and restore the FPU state on every |
context switch, or to only switch the FPU state when necessary. |
</para> |
|
<programlisting width=72> |
|
cdl_component CYGHWR_HAL_I386_FPU { |
display "Enable I386 FPU support" |
default_value 1 |
description "This component enables support for the |
I386 floating point unit." |
|
cdl_option CYGHWR_HAL_I386_FPU_SWITCH_LAZY { |
display "Use lazy FPU state switching" |
flavor bool |
default_value 1 |
|
description " |
This option enables lazy FPU state switching. |
The default behaviour for eCos is to save and |
restore FPU state on every thread switch, interrupt |
and exception. While simple and deterministic, this |
approach can be expensive if the FPU is not used by |
all threads. The alternative, enabled by this option, |
is to use hardware features that allow the FPU state |
of a thread to be left in the FPU after it has been |
descheduled, and to allow the state to be switched to |
a new thread only if it actually uses the FPU. Where |
only one or two threads use the FPU this can avoid a |
lot of unnecessary state switching." |
} |
} |
</programlisting> |
|
<para> |
The i386 HAL also has support for different classes of CPU. In |
particular, Pentium class CPUs have extra functional units, and some |
variants of GDB expect more registers to be reported. These options |
enable these features. Generally these are enabled by |
<literal>requires</literal> statements in variant or platform |
packages, or in <literal>.ecm</literal> files. |
</para> |
|
<programlisting width=72> |
|
cdl_component CYGHWR_HAL_I386_PENTIUM { |
display "Enable Pentium class CPU features" |
default_value 0 |
description "This component enables support for various |
features of Pentium class CPUs." |
|
cdl_option CYGHWR_HAL_I386_PENTIUM_SSE { |
display "Save/Restore SSE registers on context switch" |
flavor bool |
default_value 0 |
|
description " |
This option enables SSE state switching. The default |
behaviour for eCos is to ignore the SSE registers. |
Enabling this option adds SSE state information to |
every thread context." |
} |
|
cdl_option CYGHWR_HAL_I386_PENTIUM_GDB_REGS { |
display "Support extra Pentium registers in GDB stub" |
flavor bool |
default_value 0 |
|
description " |
This option enables support for extra Pentium registers |
in the GDB stub. These are registers such as CR0-CR4, and |
all MSRs. Not all GDBs support these registers, so the |
default behaviour for eCos is to not include them in the |
GDB stub support code." |
} |
} |
</programlisting> |
|
<para> |
In the i386 HALs, the linker script is provided by the architecture |
HAL. In other HALs, for example MIPS, it is provided in the variant |
HAL. The following option provides the name of the linker script to |
other elements in the configuration system. |
</para> |
|
<programlisting width=72> |
cdl_option CYGBLD_LINKER_SCRIPT { |
display "Linker script" |
flavor data |
no_define |
calculated { "src/i386.ld" } |
} |
</programlisting> |
|
<para> |
Finally, this interface indicates whether the platform supplied an |
implementation of the |
<function>hal_i386_mem_real_region_top()</function> function. If it |
does then it will contain a line of the form: <literal>implements |
CYGINT_HAL_I386_MEM_REAL_REGION_TOP</literal>. This allows packages |
such as RedBoot to detect the presence of this function so that they |
may call it. |
</para> |
|
<programlisting width=72> |
|
cdl_interface CYGINT_HAL_I386_MEM_REAL_REGION_TOP { |
display "Implementations of hal_i386_mem_real_region_top()" |
} |
|
} |
</programlisting> |
|
</section> |
|
<!-- }}} --> |
|
<!-- |
<para><a href="hal-arch-process.html">Porting process</a> |
<para><a href="hal-cache.html">HAL Cache Controls</a> |
<para><a href="hal-linking.html">Linker Script Macros</a> |
<para><a href="hal-arch-cdl.html">CDL requirements</a> |
|
--> |
|
</section> |
|
<!-- }}} --> |
|
</CHAPTER> |
|
<!-- |
|
Notes added by Nickg: |
|
The following are my notes from the HAL Porting course I did at |
Agilent in Feb 2002. It was my intention to incorporate some stuff |
from here into the Platform Porting section and to include some of |
the things I learned while doing the course. The main things I wanted |
to do were: to change the porting process to concentrate on getting |
RedBoot to run rather than the GDB stubs ROM; update the descriptions |
to match current practice - some of it is now quite old; remove all |
the TBDs and FIXMEs; mend the worst of Jesper's danglish :-) |
|
Also the variant and architecture porting guides are still in the |
incomplete state that Jesper left them; and there are some other bits |
and pieces in the original HTML porting guide that I have not yet |
moved over. |
|
The ridiculous demands of management to sacrifice quality to |
expediency mean that this is not now possible and this document has to |
be abandoned in mid-flux. So I'm just dumping this stuff here. Maybe |
one day someone will get around to doing it properly. |
|
|
|
|
Porting Principals |
================== |
|
Copy an existing HAL. |
- choose a HAL with which you are familiar and/or which is |
similar to the intended target. |
- copy the files |
- rename them appropriately |
- rename configuration variables |
- empty/reimplement platform specific code. |
- old code is a good indicator of what you need to do. |
- concentrate on getting it all to compile, so just commenting |
out the platform specific bits is often a good idea. |
|
Follow execution order. |
- gives a good indication of what to do next. |
|
Concentrate on RedBoot first. |
- simpler environment - no interrupts, no threads. |
|
|
CDL |
=== |
|
CDL changes made as part of the copy/edit above should be done. |
|
Need to add entries to ecos.db for the new packages. |
|
Platform: |
|
package CYGPKG_HAL_ARM_ARM9_XXXXXXXX { |
alias { "XXXXXXXX unit" hal_arm_arm9_xxxxxxxx xxxxxxxx } |
directory hal/arm/arm9/xxxxxxxx |
script hal_arm_arm9_xxxxxxxx.cdl |
hardware |
description " |
The XXXXXXXX HAL package provides the support needed to run |
eCos on an XXXXXXXX board." |
} |
|
Target: |
|
target xxxxxxxx { |
alias { "XXXXXXXX unit" aaed } |
packages { CYGPKG_HAL_ARM |
CYGPKG_HAL_ARM_ARM9 |
CYGPKG_HAL_ARM_ARM9_XXXXXXXX |
} |
description " |
The XXXXXXXX target provides the packages needed to run |
eCos on an XXXXXXXX board." |
} |
|
================================================================== |
|
Getting RedBoot Going |
===================== |
|
Startup |
======= |
|
1. Reset entry point. At location 0. |
Transfer control to ROM entry point: reset_vector. |
|
2. Here we call invoke PLATFORM_SETUP1 macro. This does the following: |
- disable interrupts |
- disable and clear caches |
- Init memory controllers. may involve discovery of what RAM is |
present. |
- Set up clock frequencies. |
- Init MMU table |
- sets up TTBR and DACR to default values |
- fills in MMU table to map |
- DRAM at 0x00000000 cacheable/buffered |
- Device registers elsewhere uncacheable/unbuffered usually 1-1 |
- DRAM at 0xF0000000 uncacheable/unbuffered (1-1 in aaed2000) |
- remap ROM at 0 elsewhere |
- Enable MMU |
- Relocate image to RAM for ROMRAM startup |
- Any other CPU setup required |
|
3. Jump to HAL startup. |
- Plant vector intructions at 0+ |
- copy .data section to RAM |
- Init CPSR and SPSR |
- Set SP |
- Clear .bss |
- Call hal_hardware_init() |
- call initialize_stub() if GDB stubs included |
- call hal_ctrlc_isr_init() |
- call cyg_hal_invoke_constructors() |
- call cyg_start() |
|
|
HAL Serial support |
================== |
|
Set up CDL in platform CDL file. |
CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS |
number of channels usually 0, 1 or 2 |
CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL |
channel to use for GDB |
CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL_BAUD |
initial baud rate |
CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL |
channel to use for console |
CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD |
initial baud rate |
CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_DEFAULT |
default console channel |
|
The code in hal_diag.c need to be converted to the new serial device. |
If this the same as a device already supported, copy that. |
|
Things that need to be written: |
|
struct channel_data_t; |
Structure containing base address, timeout and ISR vector |
number for each serial device. |
|
xxxx_ser_channels[]; |
Array of channel_data_t, initialized with parameters of each |
channel. |
|
void cyg_hal_plf_serial_init_channel(void *__ch_data) |
Initialize the serial device. parameter is a pointer to a |
channel_data_t. |
|
void cyg_hal_plf_serial_putc(void * __ch_data, char *c) |
Send a character to the serial device. |
Poll for ready, write the char. |
Maybe poll for char sent. |
|
bool cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) |
Look for a character and return it if available. |
If none available, return false. |
|
int cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t |
__func, ...) |
An IOCTL-like function for controlling various aspects of the |
serial device. |
May need to do some work in __COMMCTL_IRQ_ENABLE and |
__COMMCTL_IRQ_DISABLE cases to enable/disable interrupts. |
|
int cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, |
CYG_ADDRWORD __vector, CYG_ADDRWORD __data) |
Interrupt handler, specifically for dealing with Ctrl-C. |
- Check for an incoming character. |
- Read the character and call cyg_hal_is_break(). |
- If result is true, set *__ctrlc to 1. |
- return CYG_ISR_HANDLED; |
|
void cyg_hal_plf_serial_init() |
Initialize each of the serial channels. |
- call cyg_hal_plf_serial_init_channel() for each channel. |
- call CYGACC_COMM_IF_* macros for each channel - |
cut/paste/edit these. |
|
|
Interrupt Controller |
==================== |
|
ARM platforms have interrupt controller access in functions in variant |
or platform source file. |
|
void hal_interrupt_mask(int vector) |
Manipulate interrupt controller to mask the interrupt. |
|
void hal_interrupt_unmask(int vector) |
Manipulate interrupt controller to unmask the interrupt. |
|
void hal_interrupt_acknowledge(int vector) |
Manipulate interrupt controller to acknowledge the interrupt. |
May not be needed in some platforms. |
|
void hal_interrupt_configure(int vector, int level, int up) |
Set interrupt detection: level vs. edge; high/low |
rising/falling. |
Leave empty where not implemented. |
|
void hal_interrupt_set_level(int vector, int level) |
Set interrupt priority level. |
Leave empty where not implemented. |
|
|
Redboot Configuration |
===================== |
|
Having done all of the above, you should be in a position to get |
RedBoot running. |
|
If the platform you copied has redboot, there should be some .ecm |
files in the misc directory. Named redboot_<startup>.ecm. |
|
Choose a startup and edit the .ecm file. |
- remove any options that are not relevant |
- comment out FLASH, ETH and COMPRESS packages |
|
Configure for redboot: |
|
% setenv ECOS_REPOSITORY <path to source repository> |
% ecosconfig new xxxxxxxx redboot |
% ecosconfig import $ECOS_REPOSITORY/hal/arm/arm9/xxxxxxxx/current/misc/redboot_ROM.ecm |
% ecosconfig tree |
% make |
|
Repeat until successful. |
|
Load into hardware by either programming FLASH from existing ROM |
monitor, via JTAG or whatever. |
|
Run. Debug. Edit. Repeat. |
|
================================================================== |
|
Getting eCos Going |
================== |
|
Once RedBoot is up and running, it should be possible to configure and |
build eCos. |
|
Use the kernel template to start with. |
|
|
Clock Support |
============= |
|
We will use the RTC to test that interrupts are working. First step is |
to get RTC working. |
|
void hal_clock_initialize(cyg_uint32 period) |
Initialize the RTC device to interrupt every period ticks. The |
CDL should have defined period according to the frequency |
required. |
This should start the clock going. |
|
void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period) |
Perform any work to cause the clock to start another timing |
period. On many platforms this can be empty. On others the |
counter or compare register may need to be reloaded. |
|
void hal_clock_read(cyg_uint32 *pvalue) |
Returns the number of hardware ticks since the last interrupt. |
For count-up timers this is just the value of the timer. |
For count-down timers the result needs to be subtracted from the |
initial period. |
|
void hal_delay_us(cyg_int32 usecs) |
Busy delay for the given number of microseconds. |
Normally this works by polling the timer device until the |
required number of usecs has passed. |
Beware of timer wrap-around, resets, and arithmetic overflows. |
This function does not have to be very accurate - it's used |
mostly to provide short timing delays during hardware access. |
|
Interrupt Handling |
================== |
|
Quick overview of interrupt handling: |
|
|
1. Hardware interrupts are delivered to either the IRQ or FIQ vectors at |
0x18 and 0x1c respectively. |
|
2. These contain single instructions that load the contents of the memory |
location 0x20 later in memory and jump there. |
|
3. The code called is a VSR - Vector Service Routine. FIQ VSR fakes |
CPU state to make it look like an IRQ, then drops into IRQ. |
|
4. Switch back to supervisor mode. Save CPU state onto current stack. |
|
5. Switch to interrupt stack if not already there. |
|
6. Lock scheduler. |
|
7. Call hal_IRQ_handler(). This function inspects the interrupt |
controller and returns the number of the highest priority pending, |
unmasked interrupt. |
|
8. Use vector number to index hal_interrupt_handlers[] and |
hal_interrupt_data[] to get ISR and data. |
|
9. Call ISR. keep the return value. |
|
10. Switch back to original stack. |
|
11. Index hal_interrupt_objects[] with vector number to get interrupt |
object pointer. |
|
12. Call interrupt_end(isr_ret, *object, *save_regs). |
This will: |
- post the onterrupt object's DSR if CYG_ISR_CALL_DSR is set in |
return code. |
- Unlock scheduler. During this the following may happen: |
- Any pending DSRs may be called |
- The current thread may be preempted, either by a higher |
priority thread scheduled by a DSR, or it may be timesliced. |
|
13. The return from interrupt_end() may occur some time after the |
call: lots of threads may have run in the meantime. |
|
14. Restore CPU state and resume interrupted code. |
|
|
The only thing that needs doing in a platform port is to write |
hal_IRQ_handler(). |
|
|
|
Once the clock and IRQ code is done, eCos should be able to run all of |
the kernel tests. The best all-round test is tm_basic. Other tests |
that should be run are: |
clocktruth - tests accuracy of timer setup |
except1 - checks exception handling works |
timeslice - checks timeslicing works |
|
Run. Debug. Edit. Repeat. |
|
|
|
|
--> |
|
|
/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++. |
This is to permit the HAL the widest possible |
applicability.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>All interfaces to the HAL are implemented by |
CPP macros. This allows them to be implemented as inline |
C code, inline assembler or function calls to external C |
or assembler code. This allows the most efficient |
implementation to be selected without affecting the |
interface. It also allows them to be redefined if the |
platform or variant HAL needs to replace or enhance a definition |
from the architecture HAL.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>The HAL provides simple, portable mechanisms for dealing |
with the hardware of a wide range of architectures and platforms. |
It is always possible to bypass the HAL and program the hardware |
directly, but this may lead to a loss of portability. </PARA> |
</LISTITEM> |
</ORDEREDLIST> |
</CHAPTER> |
|
<!-- }}} --> |
<!-- {{{ HAL Interfaces --> |
|
<CHAPTER id="hal-interfaces"> |
<TITLE><!-- <index></index> --><!-- <xref> -->HAL Interfaces</TITLE> |
|
<para> |
This section describes the main HAL interfaces. |
</para> |
|
<!-- {{{ Base Definitions --> |
|
<SECTION id="hal-base-definitions"> |
<TITLE>Base Definitions</TITLE> |
|
<para> |
These are definitions that characterize the properties of the base |
architecture that are used to compile the portable parts of the |
kernel. They are concerned with such things a portable type |
definitions, endianness, and labeling. |
</para> |
|
<PARA> |
These definitions are supplied by the |
<filename>cyg/hal/basetype.h</filename> header file which is supplied |
by the architecture HAL. It is included automatically by |
<FILENAME>cyg/infra/cyg_type.h</FILENAME>. |
</PARA> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Byte order</TITLE> |
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM><VARNAME>CYG_BYTEORDER</VARNAME></TERM> |
<LISTITEM> |
<PARA> |
This defines the byte order of the target and must be set to either |
<varname>CYG_LSBFIRST</varname> or <varname>CYG_MSBFIRST</varname>. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Label Translation</TITLE> |
|
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM><FUNCTION>CYG_LABEL_NAME(name)</FUNCTION></TERM> |
<LISTITEM> |
|
<PARA> |
This is a wrapper used in some C and C++ files which |
use labels defined in assembly code or the linker script. |
It need only be defined if the default implementation in |
<filename>cyg/infra/cyg_type.h</filename>, which passes the name |
argument unaltered, is inadequate. It should be paired with |
<function>CYG_LABEL_DEFN()</function>. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
<VARLISTENTRY> |
<TERM><FUNCTION>CYG_LABEL_DEFN(name)</FUNCTION></TERM> |
<LISTITEM> |
|
<PARA> |
This is a wrapper used in assembler sources and linker scripts |
which define labels. It need only be defined if the default |
implementation in |
<filename>cyg/infra/cyg_type.h</filename>, which passes the name |
argument unaltered, is inadequate. The most usual alternative |
definition of this macro prepends an underscore to the label |
name. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
</SECTION> |
|
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Base types</TITLE> |
<PROGRAMLISTING> |
cyg_halint8 |
cyg_halint16 |
cyg_halint32 |
cyg_halint64 |
cyg_halcount8 |
cyg_halcount16 |
cyg_halcount32 |
cyg_halcount64 |
cyg_halbool |
</PROGRAMLISTING> |
<PARA> |
These macros define the C base types that should be used to define |
variables of the given size. They only need to be defined if the |
default types specified in <filename>cyg/infra/cyg_type.h</filename> |
cannot be used. Note that these are only the base types, they will be |
composed with <literal>signed</literal> and |
<literal>unsigned</literal> to form full type specifications. |
</PARA> |
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Atomic types</TITLE> |
<PROGRAMLISTING> |
cyg_halatomic CYG_ATOMIC |
</PROGRAMLISTING> |
<PARA> |
These types are guaranteed to be read or written in a single |
uninterruptible operation. It is architecture defined what size this |
type is, but it will be at least a byte. |
</PARA> |
</SECTION> |
|
</SECTION> |
|
<!-- }}} --> |
<!-- {{{ Architecture Characterization --> |
|
<SECTION id="hal-architecture-characterization"> |
<TITLE>Architecture Characterization</TITLE> |
|
<para> |
These are definition that are related to the basic architecture of the |
CPU. These include the CPU context save format, context switching, bit |
twiddling, breakpoints, stack sizes and address translation. |
</para> |
|
<PARA> |
Most of these definition are found in |
<filename>cyg/hal/hal_arch.h</filename>. This file is supplied by the |
architecture HAL. If there are variant or platform specific |
definitions then these will be found in |
<filename>cyg/hal/var_arch.h</filename> or |
<filename>cyg/hal/plf_arch.h</filename>. These files are include |
automatically by this header, so need not be included explicitly. |
</PARA> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Register Save Format</TITLE> |
<PROGRAMLISTING> |
typedef struct HAL_SavedRegisters |
{ |
/* architecture-dependent list of registers to be saved */ |
} HAL_SavedRegisters; |
</PROGRAMLISTING> |
<PARA> |
This structure describes the layout of a saved machine state on the |
stack. Such states are saved during thread context switches, |
interrupts and exceptions. Different quantities of state may be saved |
during each of these, but usually a thread context state is a subset |
of the interrupt state which is itself a subset of an exception state. |
For debugging purposes, the same structure is used for all three |
purposes, but where these states are significantly different, this |
structure may contain a union of the three states. |
</PARA> |
</SECTION> |
|
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Thread Context Initialization</TITLE> |
|
<PROGRAMLISTING> |
HAL_THREAD_INIT_CONTEXT( sp, arg, entry, id ) |
</PROGRAMLISTING> |
|
<PARA> |
This macro initializes a thread's context so that |
it may be switched to by <FUNCTION>HAL_THREAD_SWITCH_CONTEXT()</FUNCTION>. |
The arguments are: |
</PARA> |
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM>sp</TERM> |
<LISTITEM> |
<PARA> |
A location containing the current value of the thread's stack |
pointer. This should be a variable or a structure field. The SP |
value will be read out of here and an adjusted value written |
back. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>arg</TERM> |
<LISTITEM> |
<PARA> |
A value that is passed as the first argument to the entry |
point function. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
<VARLISTENTRY> |
<TERM>entry</TERM> |
<LISTITEM> |
<PARA> |
The address of an entry point function. This will be called |
according the C calling conventions, and the value of |
<parameter>arg</parameter> will be passed as the first |
argument. This function should have the following type signature |
<function>void entry(CYG_ADDRWORD arg)</function>. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
<VARLISTENTRY> |
<TERM>id</TERM> |
<LISTITEM> |
<PARA> |
A thread id value. This is only used for debugging purposes, |
it is ORed into the initialization pattern for unused registers |
and may be used to help identify the thread from its register dump. |
The least significant 16 bits of this value should be zero to allow |
space for a register identifier. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION id="hal-context-switch"> |
<TITLE>Thread Context Switching</TITLE> |
|
<PROGRAMLISTING> |
HAL_THREAD_LOAD_CONTEXT( to ) |
HAL_THREAD_SWITCH_CONTEXT( from, to ) |
</PROGRAMLISTING> |
<PARA> |
These macros implement the thread switch code. The arguments are: |
</PARA> |
|
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM>from</TERM> |
<LISTITEM> |
<PARA> |
A pointer to a location where the stack pointer of the current |
thread will be stored. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
<VARLISTENTRY> |
<TERM>to</TERM> |
<LISTITEM> |
<PARA> |
A pointer to a location from where the stack pointer of the next |
thread will be read. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
|
<para> |
For <function>HAL_THREAD_LOAD_CONTEXT()</function> the current CPU |
state is discarded and the state of the destination thread is |
loaded. This is only used once, to load the first thread when the |
scheduler is started. |
</para> |
|
<PARA> |
For <function>HAL_THREAD_SWITCH_CONTEXT()</function> the state of the |
current thread is saved onto its stack, using the current value of the |
stack pointer, and the address of the saved state placed in |
<parameter>*from</parameter>. The value in |
<parameter>*to</parameter> is then read and the state of the new |
thread is loaded from it. |
</PARA> |
|
<para> |
While these two operations may be implemented with inline assembler, |
they are normally implemented as calls to assembly code functions in |
the HAL. There are two advantages to doing it this way. First, the |
return link of the call provides a convenient PC value to be used in |
the saved context. Second, the calling conventions mean that the |
compiler will have already saved the caller-saved registers before the |
call, so the HAL need only save the callee-saved registers. |
</para> |
|
<para> |
The implementation of <function>HAL_THREAD_SWITCH_CONTEXT()</function> |
saves the current CPU state on the stack, including the current |
interrupt state (or at least the register that contains it). For |
debugging purposes it is useful to save the entire register set, but |
for performance only the ABI-defined callee-saved registers need be |
saved. If it is implemented, the option |
<literal>CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM</literal> controls |
how many registers are saved. |
</para> |
|
<para> |
The implementation of <function>HAL_THREAD_LOAD_CONTEXT()</function> |
loads a thread context, destroying the current context. With a little |
care this can be implemented by sharing code with |
<function>HAL_THREAD_SWITCH_CONTEXT()</function>. To load a thread |
context simply requires the saved registers to be restored from the |
stack and a jump or return made back to the saved PC. |
</para> |
|
<PARA> |
Note that interrupts are not disabled during this process, any |
interrupts that occur will be delivered onto the stack to which the |
current CPU stack pointer points. Hence the stack pointer |
should never be invalid, or loaded with a value that might cause the |
saved state to become corrupted by an interrupt. However, the current |
interrupt state is saved and restored as part of the thread |
context. If a thread disables interrupts and does something to cause a |
context switch, interrupts may be re-enabled on switching to another |
thread. Interrupts will be disabled again when the original thread |
regains control. |
</PARA> |
|
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Bit indexing</TITLE> |
|
<PROGRAMLISTING> |
HAL_LSBIT_INDEX( index, mask ) |
HAL_MSBIT_INDEX( index, mask ) |
</PROGRAMLISTING> |
|
<PARA> |
These macros place in <parameter>index</parameter> the bit index of |
the least significant bit in <parameter>mask</parameter>. Some |
architectures have instruction level support for one or other of these |
operations. If no architectural support is available, then these |
macros may call C functions to do the job. |
</PARA> |
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Idle thread activity</TITLE> |
|
<PROGRAMLISTING> |
HAL_IDLE_THREAD_ACTION( count ) |
</PROGRAMLISTING> |
|
<PARA> |
It may be necessary under some circumstances for the HAL to execute |
code in the kernel idle thread's loop. An example might be to execute |
a processor halt instruction. This macro provides a portable way of |
doing this. The argument is a copy of the idle thread's loop counter, |
and may be used to trigger actions at longer intervals than every |
loop. |
</PARA> |
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Reorder barrier</TITLE> |
|
<PROGRAMLISTING> |
HAL_REORDER_BARRIER() |
</PROGRAMLISTING> |
|
<PARA> |
When optimizing the compiler can reorder code. In some parts of |
multi-threaded systems, where the order of actions is vital, this can |
sometimes cause problems. This macro may be inserted into places where |
reordering should not happen and prevents code being migrated across |
it by the compiler optimizer. It should be placed between statements |
that must be executed in the order written in the code. |
</PARA> |
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Breakpoint support</TITLE> |
|
<PROGRAMLISTING> |
HAL_BREAKPOINT( label ) |
HAL_BREAKINST |
HAL_BREAKINST_SIZE |
</PROGRAMLISTING> |
|
<PARA> |
These macros provide support for breakpoints. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_BREAKPOINT()</FUNCTION> executes a breakpoint |
instruction. The label is defined at the breakpoint instruction so |
that exception code can detect which breakpoint was executed. |
</PARA> |
|
<PARA> |
<literal>HAL_BREAKINST</literal> contains the breakpoint instruction |
code as an integer value. <literal>HAL_BREAKINST_SIZE</literal> is |
the size of that breakpoint instruction in bytes. Together these |
may be used to place a breakpoint in any code. |
</PARA> |
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>GDB support</TITLE> |
|
<PROGRAMLISTING> |
HAL_THREAD_GET_SAVED_REGISTERS( sp, regs ) |
HAL_GET_GDB_REGISTERS( regval, regs ) |
HAL_SET_GDB_REGISTERS( regs, regval ) |
</PROGRAMLISTING> |
|
<PARA> |
These macros provide support for interfacing GDB to the HAL. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_THREAD_GET_SAVED_REGISTERS()</FUNCTION> extracts a |
pointer to a <STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure |
from a stack pointer value. The stack pointer passed in should be the |
value saved by the thread context macros. The macro will assign a |
pointer to the <STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure |
to the variable passed as the second argument. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_GET_GDB_REGISTERS()</FUNCTION> translates a register |
state as saved by the HAL and into a register dump in the format |
expected by GDB. It takes a pointer to a |
<STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure in the |
<parameter>regs</parameter> argument and a pointer to the memory to |
contain the GDB register dump in the <parameter>regval</parameter> |
argument. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_SET_GDB_REGISTERS()</FUNCTION> translates a GDB format |
register dump into a the format expected by the HAL. It takes a |
pointer to the memory containing the GDB register dump in the |
<parameter>regval</parameter> argument and a pointer to a |
<STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure |
in the <parameter>regs</parameter> argument. |
</PARA> |
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Setjmp and longjmp support</TITLE> |
|
<PROGRAMLISTING> |
CYGARC_JMP_BUF_SIZE |
hal_jmp_buf[CYGARC_JMP_BUF_SIZE] |
hal_setjmp( hal_jmp_buf env ) |
hal_longjmp( hal_jmp_buf env, int val ) |
</PROGRAMLISTING> |
|
<PARA> |
These functions provide support for the C |
<FUNCTION>setjmp()</FUNCTION> and <FUNCTION>longjmp()</FUNCTION> |
functions. Refer to the C library for further information. |
</PARA> |
|
</SECTION> |
|
<!-- =================================================================== --> |
|
<section> |
<title>Stack Sizes</title> |
<programlisting> |
CYGNUM_HAL_STACK_SIZE_MINIMUM |
CYGNUM_HAL_STACK_SIZE_TYPICAL |
</programlisting> |
|
<para> |
The values of these macros define the minimum and typical sizes of |
thread stacks. |
</para> |
|
<para> |
<literal>CYGNUM_HAL_STACK_SIZE_MINIMUM</literal> defines the minimum |
size of a thread stack. This is enough for the thread to function |
correctly within eCos and allows it to take interrupts and context |
switches. There should also be enough space for a simple thread entry |
function to execute and call basic kernel operations on objects like |
mutexes and semaphores. However there will not be enough room for much |
more than this. When creating stacks for their own threads, |
applications should determine the stack usage needed for application |
purposes and then add |
<literal>CYGNUM_HAL_STACK_SIZE_MINIMUM</literal>. |
</para> |
|
<para> |
<literal>CYGNUM_HAL_STACK_SIZE_TYPICAL</literal> is a reasonable increment over |
<literal>CYGNUM_HAL_STACK_SIZE_MINIMUM</literal>, usually about 1kB. This should be |
adequate for most modest thread needs. Only threads that need to |
define significant amounts of local data, or have very deep call trees |
should need to use a larger stack size. |
</para> |
|
</section> |
|
|
<!-- =================================================================== --> |
|
<section> |
<title>Address Translation</title> |
|
<programlisting> |
CYGARC_CACHED_ADDRESS(addr) |
CYGARC_UNCACHED_ADDRESS(addr) |
CYGARC_PHYSICAL_ADDRESS(addr) |
</programlisting> |
|
<para> |
These macros provide address translation between different views of |
memory. In many architectures a given memory location may be visible |
at different addresses in both cached and uncached forms. It is also |
possible that the MMU or some other address translation unit in the |
CPU presents memory to the program at a different virtual address to |
its physical address on the bus. |
</para> |
|
<para> |
<function>CYGARC_CACHED_ADDRESS()</function> translates the given |
address to its location in cached memory. This is typically where the |
application will access the memory. |
</para> |
|
<para> |
<function>CYGARC_UNCACHED_ADDRESS()</function> translates the given |
address to its location in uncached memory. This is typically where |
device drivers will access the memory to avoid cache problems. It may |
additionally be necessary for the cache to be flushed before the |
contents of this location is fully valid. |
</para> |
|
<para> |
<function>CYGARC_PHYSICAL_ADDRESS()</function> translates the given |
address to its location in the physical address space. This is |
typically the address that needs to be passed to device hardware such |
as a DMA engine, ethernet device or PCI bus bridge. The physical |
address may not be directly accessible to the program, it may be |
re-mapped by address translation. |
</para> |
|
</section> |
|
|
<!-- =================================================================== --> |
|
<section> |
<title>Global Pointer</title> |
|
<programlisting> |
CYGARC_HAL_SAVE_GP() |
CYGARC_HAL_RESTORE_GP() |
</programlisting> |
|
<para> |
These macros insert code to save and restore any global data pointer |
that the ABI uses. These are necessary when switching context between |
two eCos instances - for example between an eCos application and |
RedBoot. |
</para> |
|
</section> |
|
</SECTION> |
|
<!-- }}} --> |
<!-- {{{ Interrupt Handling --> |
|
<SECTION id="hal-interrupt-handling"> |
<TITLE>Interrupt Handling</TITLE> |
|
<para> |
These interfaces contain definitions related to interrupt |
handling. They include definitions of exception and interrupt numbers, |
interrupt enabling and masking, 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>+1. |
</PARA> |
|
</SECTION> |
|
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Interrupt state control</TITLE> |
|
<PROGRAMLISTING> |
CYG_INTERRUPT_STATE |
HAL_DISABLE_INTERRUPTS( old ) |
HAL_RESTORE_INTERRUPTS( old ) |
HAL_ENABLE_INTERRUPTS() |
HAL_QUERY_INTERRUPTS( state ) |
</PROGRAMLISTING> |
|
<PARA> |
These macros provide control over the state of the CPUs interrupt mask |
mechanism. They should normally manipulate a CPU status register to |
enable and disable interrupt delivery. They should not access an |
interrupt controller. |
</PARA> |
|
|
<para> |
<literal>CYG_INTERRUPT_STATE</literal> is a data type that should be |
used to store the interrupt state returned by |
<function>HAL_DISABLE_INTERRUPTS()</function> and |
<function>HAL_QUERY_INTERRUPTS()</function> and passed to |
<function>HAL_RESTORE_INTERRUPTS()</function>. |
</para> |
|
<PARA> |
<FUNCTION>HAL_DISABLE_INTERRUPTS()</FUNCTION> disables the delivery of |
interrupts and stores the original state of the interrupt mask in the |
variable passed in the <parameter>old</parameter> argument. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_RESTORE_INTERRUPTS()</FUNCTION> restores the state of |
the interrupt mask to that recorded in <parameter>old</parameter>. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_ENABLE_INTERRUPTS()</FUNCTION> simply enables interrupts |
regardless of the current state of the mask. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_QUERY_INTERRUPTS()</FUNCTION> stores the state of the |
interrupt mask in the variable passed in the <parameter> |
state</parameter> argument. The state stored here should also be |
capable of being passed to |
<function>HAL_RESTORE_INTERRUPTS()</function> at a later point. |
</PARA> |
|
<PARA> |
It is at the HAL implementer’s discretion exactly |
which interrupts are masked by this mechanism. Where a CPU has more |
than one interrupt type that may be masked separately (e.g. the |
ARM's IRQ and FIQ) only those that can raise DSRs need |
to be masked here. A separate architecture specific mechanism may |
then be used to control the other interrupt types. |
</PARA> |
|
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>ISR and VSR management</TITLE> |
|
<PROGRAMLISTING> |
HAL_INTERRUPT_IN_USE( vector, state ) |
HAL_INTERRUPT_ATTACH( vector, isr, data, object ) |
HAL_INTERRUPT_DETACH( vector, isr ) |
HAL_VSR_SET( vector, vsr, poldvsr ) |
HAL_VSR_GET( vector, pvsr ) |
HAL_VSR_SET_TO_ECOS_HANDLER( vector, poldvsr ) |
</PROGRAMLISTING> |
|
<PARA> |
These macros manage the attachment of interrupt and vector service |
routines to interrupt and exception vectors respectively. |
</PARA> |
|
<para> |
<function>HAL_INTERRUPT_IN_USE()</function> tests the state of the |
supplied interrupt vector and sets the value of the state parameter to |
either 1 or 0 depending on whether there is already an ISR attached to |
the vector. The HAL will only allow one ISR to be attached to each |
vector, so it is a good idea to use this function before using |
<function>HAL_INTERRUPT_ATTACH()</function>. |
</para> |
|
<PARA> |
<FUNCTION>HAL_INTERRUPT_ATTACH()</FUNCTION> attaches |
the ISR, data pointer and object pointer to the given |
<parameter>vector</parameter>. When an interrupt occurs on this |
vector the ISR is called using the C calling convention and the vector |
number and data pointer are passed to it as the first and second |
arguments respectively. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_INTERRUPT_DETACH()</FUNCTION> detaches the ISR from the |
vector. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_VSR_SET()</FUNCTION> replaces the VSR attached to the |
<parameter>vector</parameter> with the replacement supplied in |
<parameter>vsr</parameter>. The old VSR is returned in the location |
pointed to by <parameter>pvsr</parameter>. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_VSR_GET()</FUNCTION> assigns |
a copy of the VSR to the location pointed to by <parameter>pvsr</parameter>. |
</PARA> |
|
<para> |
<function>HAL_VSR_SET_TO_ECOS_HANDLER()</function> ensures that the |
VSR for a specific exception is pointing at the eCos exception VSR and |
not one for RedBoot or some other ROM monitor. The default when |
running under RedBoot is for exceptions to be handled by RedBoot and |
passed to GDB. This macro diverts the exception to eCos so that it may |
be handled by application code. The arguments are the VSR vector to be |
replaces, and a location in which to store the old VSR pointer, so |
that it may be replaced at a later point. |
</para> |
|
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Interrupt controller management</TITLE> |
|
<PROGRAMLISTING> |
HAL_INTERRUPT_MASK( vector ) |
HAL_INTERRUPT_UNMASK( vector ) |
HAL_INTERRUPT_ACKNOWLEDGE( vector ) |
HAL_INTERRUPT_CONFIGURE( vector, level, up ) |
HAL_INTERRUPT_SET_LEVEL( vector, level ) |
</PROGRAMLISTING> |
|
<PARA> |
These macros exert control over any prioritized interrupt |
controller that is present. If no priority controller exists, then |
these macros should be empty. |
</para> |
|
<note> |
<para> |
These macros may not be reentrant, so care should be taken to |
prevent them being called while interrupts are enabled. This means |
that they can be safely used in initialization code before |
interrupts are enabled, and in ISRs. In DSRs, ASRs and thread code, |
however, interrupts must be disabled before these macros are |
called. Here is an example for use in a DSR where the interrupt |
source is unmasked after data processing: |
</para> |
<PROGRAMLISTING> |
... |
HAL_DISABLE_INTERRUPTS(old); |
HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_ETH); |
HAL_RESTORE_INTERRUPTS(old); |
... |
</PROGRAMLISTING> |
</note> |
|
<PARA> |
<FUNCTION>HAL_INTERRUPT_MASK()</FUNCTION> causes the interrupt |
associated with the given vector to be blocked. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_INTERRUPT_UNMASK()</FUNCTION> causes the interrupt |
associated with the given vector to be unblocked. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_INTERRUPT_ACKNOWLEDGE()</FUNCTION> acknowledges the |
current interrupt from the given vector. This is usually executed from |
the ISR for this vector when it is prepared to allow further |
interrupts. Most interrupt controllers need some form of acknowledge |
action before the next interrupt is allowed through. Executing this |
macro may cause another interrupt to be delivered. Whether this |
interrupts the current code depends on the state of the CPU interrupt |
mask. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_INTERRUPT_CONFIGURE()</FUNCTION> provides |
control over how an interrupt signal is detected. The arguments |
are: |
</PARA> |
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM>vector</TERM> |
<LISTITEM> |
<PARA>The interrupt vector to be configured.</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>level</TERM> |
<LISTITEM> |
<PARA> |
Set to <varname>true</varname> if the interrupt is detected by |
level, and <varname>false</varname> if it is edge triggered. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>up</TERM> |
<LISTITEM> |
<PARA> |
If the interrupt is set to level detect, then if this is |
<VARNAME>true</VARNAME> it is detected by a high signal level, |
and if <VARNAME>false</VARNAME> by a low signal level. If the |
interrupt is set to edge triggered, then if this is |
<VARNAME>true</VARNAME> it is triggered by a rising edge and if |
<VARNAME>false</VARNAME> by a falling edge. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
|
<PARA> |
<FUNCTION>HAL_INTERRUPT_SET_LEVEL()</FUNCTION> provides control over |
the hardware priority of the interrupt. The arguments are: |
</PARA> |
|
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM>vector</TERM> |
<LISTITEM> |
<PARA>The interrupt whose level is to be set.</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>level</TERM> |
<LISTITEM> |
<PARA> |
The priority level to which the interrupt is to set. In some |
architectures the masking of an interrupt is achieved by |
changing its priority level. Hence this function, |
<FUNCTION>HAL_INTERRUPT_MASK()</FUNCTION> and |
<FUNCTION>HAL_INTERRUPT_UNMASK()</FUNCTION> may interfere with |
each other. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
|
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<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><cyg/hal/hal_cache.h></filename> in order to do this |
test and (maybe) use the macros. |
</PARA> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Cache Dimensions</TITLE> |
|
<PROGRAMLISTING> |
HAL_XCACHE_SIZE |
HAL_XCACHE_LINE_SIZE |
HAL_XCACHE_WAYS |
HAL_XCACHE_SETS |
</PROGRAMLISTING> |
<PARA> |
These macros define the size and dimensions of the Instruction |
and Data caches. |
</PARA> |
|
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM>HAL_XCACHE_SIZE </TERM> |
<LISTITEM> |
<PARA>Defines the total size of the cache in bytes.</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_LINE_SIZE </TERM> |
<LISTITEM> |
<PARA>Defines the cache line size in bytes.</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_WAYS </TERM> |
<LISTITEM> |
<PARA> |
Defines the number of ways in each set and defines its level |
of associativity. This would be 1 for a direct mapped |
cache, 2 for a 2-way cache, 4 for 4-way and so on. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_SETS </TERM> |
<LISTITEM> |
<PARA> |
Defines the number of sets in the cache, and is calculated from |
the previous values. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
|
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Global Cache Control</TITLE> |
|
<PROGRAMLISTING> |
HAL_XCACHE_ENABLE() |
HAL_XCACHE_DISABLE() |
HAL_XCACHE_INVALIDATE_ALL() |
HAL_XCACHE_SYNC() |
HAL_XCACHE_BURST_SIZE( size ) |
HAL_DCACHE_WRITE_MODE( mode ) |
HAL_XCACHE_LOCK( base, size ) |
HAL_XCACHE_UNLOCK( base, size ) |
HAL_XCACHE_UNLOCK_ALL() |
</PROGRAMLISTING> |
|
<PARA> |
These macros affect the state of the entire cache, or a large part of |
it. |
</PARA> |
|
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM>HAL_XCACHE_ENABLE() and HAL_XCACHE_DISABLE()</TERM> |
<LISTITEM> |
<PARA>Enable and disable the cache.</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_INVALIDATE_ALL()</TERM> |
<LISTITEM> |
<PARA> |
Causes the entire contents of the cache to be invalidated. |
Depending on the hardware, this may require the cache to be disabled |
during the invalidation process. If so, the implementation must |
use <function>HAL_XCACHE_IS_ENABLED()</function> to save and |
restore the previous state. |
</PARA> |
<note> |
<para> |
If this macro is called after |
<function>HAL_XCACHE_SYNC()</function> with the intention of clearing |
the cache (invalidating the cache after writing dirty data back to |
memory), you must prevent interrupts from happening between the two |
calls: |
</para> |
<PROGRAMLISTING> |
... |
HAL_DISABLE_INTERRUPTS(old); |
HAL_XCACHE_SYNC(); |
HAL_XCACHE_INVALIDATE_ALL(); |
HAL_RESTORE_INTERRUPTS(old); |
... |
</PROGRAMLISTING> |
<para> |
Since the operation may take a very long time, real-time |
responsiveness could be affected, so only do this when it is |
absolutely required and you know the delay will not interfere |
with the operation of drivers or the application. |
</para> |
</note> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_SYNC()</TERM> |
<LISTITEM> |
<PARA> |
Causes the contents of the cache to be brought into synchronization |
with the contents of memory. In some implementations this may be |
equivalent to <function>HAL_XCACHE_INVALIDATE_ALL()</function>. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_BURST_SIZE()</TERM> |
<LISTITEM> |
<PARA> |
Allows the size of cache to/from memory bursts to |
be controlled. This macro will only be defined if this functionality |
is available. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_DCACHE_WRITE_MODE()</TERM> |
<LISTITEM> |
<PARA> |
Controls the way in which data cache lines are written back to |
memory. There will be definitions for the possible |
modes. Typical definitions are |
<literal>HAL_DCACHE_WRITEBACK_MODE</literal> and |
<literal>HAL_DCACHE_WRITETHRU_MODE</literal>. This macro will |
only be defined if this functionality is available. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_LOCK()</TERM> |
<LISTITEM> |
<PARA> |
Causes data to be locked into the cache. The base and size |
arguments define the memory region that will be locked into the |
cache. It is architecture dependent whether more than one locked |
region is allowed at any one time, and whether this operation |
causes the cache to cease acting as a cache for addresses |
outside the region during the duration of the lock. This macro |
will only be defined if this functionality is available. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_UNLOCK()</TERM> |
<LISTITEM> |
<PARA> |
Cancels the locking of the memory region given. This should |
normally correspond to a region supplied in a matching lock |
call. This macro will only be defined if this functionality is |
available. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_UNLOCK_ALL()</TERM> |
<LISTITEM> |
<PARA> |
Cancels all existing locked memory regions. This may be required |
as part of the cache initialization on some architectures. This |
macro will only be defined if this functionality is available. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
|
</SECTION> |
|
<!-- =================================================================== --> |
|
<SECTION> |
<TITLE>Cache Line Control</TITLE> |
|
<PROGRAMLISTING> |
HAL_DCACHE_ALLOCATE( base , size ) |
HAL_DCACHE_FLUSH( base , size ) |
HAL_XCACHE_INVALIDATE( base , size ) |
HAL_DCACHE_STORE( base , size ) |
HAL_DCACHE_READ_HINT( base , size ) |
HAL_DCACHE_WRITE_HINT( base , size ) |
HAL_DCACHE_ZERO( base , size ) |
</PROGRAMLISTING> |
|
<PARA> |
All of these macros apply a cache operation to all cache lines that |
match the memory address region defined by the base and size |
arguments. These macros will only be defined if the described |
functionality is available. Also, it is not guaranteed that the cache |
function will only be applied to just the described regions, in some |
architectures it may be applied to the whole cache. |
</PARA> |
|
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM>HAL_DCACHE_ALLOCATE()</TERM> |
<LISTITEM> |
<PARA> |
Allocates lines in the cache for the given region without |
reading their contents from memory, hence the contents of the lines |
is undefined. This is useful for preallocating lines which are to |
be completely overwritten, for example in a block copy |
operation. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_DCACHE_FLUSH()</TERM> |
<LISTITEM> |
<PARA> |
Invalidates all cache lines in the region after writing any |
dirty lines to memory. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_XCACHE_INVALIDATE() </TERM> |
<LISTITEM> |
<PARA> |
Invalidates all cache lines in the region. Any dirty lines |
are invalidated without being written to memory. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_DCACHE_STORE() </TERM> |
<LISTITEM> |
<PARA> |
Writes all dirty lines in the region to memory, but does not |
invalidate any lines. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_DCACHE_READ_HINT() </TERM> |
<LISTITEM> |
<PARA> |
Hints to the cache that the region is going to be read from |
in the near future. This may cause the region to be speculatively |
read into the cache. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_DCACHE_WRITE_HINT() </TERM> |
<LISTITEM> |
<PARA> |
Hints to the cache that the region is going to be written |
to in the near future. This may have the identical behavior to |
HAL_DCACHE_READ_HINT(). |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>HAL_DCACHE_ZERO()</TERM> |
<LISTITEM> |
<PARA> |
Allocates and zeroes lines in the cache for the given |
region without reading memory. This is useful if a large area of |
memory is to be cleared. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
|
</SECTION> |
</SECTION> |
|
<!-- }}} --> |
<!-- {{{ Linker Scripts --> |
|
<SECTION id="hal-linker-scripts"> |
<TITLE><!-- <xref> -->Linker Scripts</TITLE> |
|
<para> |
When an eCos application is linked it must be done under the control |
of a linker script. This script defines the memory areas, addresses |
and sized, into which the code and data are to be put, and allocates |
the various sections generated by the compiler to these. |
</para> |
|
<para> |
The linker script actually used is in |
<filename>lib/target.ld</filename> in the install directory. This is |
actually manufactured out of two other files: a base linker script and |
an <literal>.ldi</literal> file that was generated by the memory |
layout tool. |
</para> |
|
<para> |
The base linker script is usually supplied either by the architecture |
HAL or the variant HAL. It consists of a set of linker script |
fragments, in the form of C preprocessor macros, that define the major |
output sections to be generated by the link operation. The |
<literal>.ldi</literal> file, which is <literal>#include'ed</literal> |
by the base linker script, uses these macro definitions to assign the |
output sections to the required memory areas and link addresses. |
</para> |
|
<para> |
The <literal>.ldi</literal> file is supplied by the platform HAL, and |
contains knowledge of the memory layout of the target platform. These |
files generally conform to a standard naming convention, each file |
being of the form: |
</para> |
<para> |
<filename>pkgconf/mlt_<architecture>_<variant>_<platform>_<startup>.ldi</filename> |
</para> |
<para> |
where <literal><architecture></literal>, |
<literal><variant></literal> and |
<literal><platform></literal> are the respective HAL package |
names and <literal><startup></literal> is the startup type which |
is usually one of <literal>ROM</literal>, <literal>RAM</literal> or |
<literal>ROMRAM</literal>. |
</para> |
|
<para> |
In addition to the <literal>.ldi</literal> file, there is also a |
congruously name <literal>.h</literal> file. This may be used by the |
application to access information defined in the |
<literal>.ldi</literal> file. Specifically it contains the memory |
layout defined there, together with any additional section names |
defined by the user. Examples of the latter are heap areas or PCI bus |
memory access windows. |
</para> |
|
<para> |
The <literal>.ldi</literal> is manufactured by the <application>Memory |
Layout Tool</application> (MLT). The <application>MLT</application> saves the memory |
configuration into a file named |
</para> |
<para> |
<filename>include/pkgconf/mlt_<architecture>_<variant>_<platform>_<startup>.mlt</filename> |
</para> |
<para> |
in the platform HAL. This file is used by the |
<application>MLT</application> to manufacture both the |
<literal>.ldi</literal> and <literal>.h</literal> files. Users should |
beware that direct edits the either of these files may be overwritten |
if the <application>MLT</application> is run and regenerates them from the |
<literal>.mlt</literal> file. |
</para> |
|
<para> |
The names of the <literal>.ldi</literal> and <literal>.h</literal> |
files are defined by macro definitions in |
<FILENAME>pkgconf/system.h</FILENAME>. These are |
<literal>CYGHWR_MEMORY_LAYOUT_LDI</literal> and |
<literal>CYGHWR_MEMORY_LAYOUT_H</literal> respectively. While there |
will be little need for the application to refer to the |
<literal>.ldi</literal> file directly, it may include the |
<literal>.h</literal> file as follows: |
</para> |
|
<programlisting> |
#include CYGHWR_MEMORY_LAYOUT_H |
</programlisting> |
|
</SECTION> |
|
<!-- }}} --> |
<!-- {{{ Diagnostic Support --> |
|
<SECTION id="hal-diagnostic-support"> |
<TITLE>Diagnostic Support</TITLE> |
|
<para> |
The HAL provides support for low level diagnostic IO. This is |
particularly useful during early development as an aid to bringing up |
a new platform. Usually this diagnostic channel is a UART or some |
other serial IO device, but it may equally be a a memory |
buffer, a simulator supported output channel, a ROM emulator virtual |
UART, and LCD panel, a memory mapped video buffer or any other output |
device. |
</para> |
|
<PARA> |
<FUNCTION>HAL_DIAG_INIT()</FUNCTION> performs any initialization |
required on the device being used to generate diagnostic output. This |
may include, for a UART, setting baud rate, and stop, parity and |
character bits. For other devices it may include initializing a |
controller or establishing contact with a remote device. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_DIAG_WRITE_CHAR(c)</FUNCTION> writes |
the character supplied to the diagnostic output device. |
</PARA> |
|
<PARA> |
<FUNCTION>HAL_DIAG_READ_CHAR(c)</FUNCTION> reads a character from the |
diagnostic device into the supplied variable. This is not supported |
for all diagnostic devices. |
</PARA> |
|
<para> |
These macros are defined in the header file |
<filename>cyg/hal/hal_diag.h</filename>. This file is usually supplied |
by the variant or platform HAL, depending on where the IO device being |
used is located. For example for on-chip UARTs it would be in the |
variant HAL, but for a board-level LCD panel it would be in the |
platform HAL. |
</para> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ SMP Support --> |
|
<section id="hal-smp-support"> |
<TITLE>SMP Support</TITLE> |
|
<para> |
eCos contains support for limited Symmetric Multi-Processing |
(SMP). This is only available on selected architectures and platforms. |
</para> |
|
<section> |
<title>Target Hardware Limitations</title> |
|
<para> |
To allow a reasonable implementation of SMP, and to reduce the |
disruption to the existing source base, a number of assumptions have |
been made about the features of the target hardware. |
</para> |
|
<itemizedlist> |
<listitem> |
<para> |
Modest multiprocessing. The typical number of CPUs supported is two |
to four, with an upper limit around eight. While there are no |
inherent limits in the code, hardware and algorithmic limitations |
will probably become significant beyond this point. |
</para> |
</listitem> |
|
<listitem> |
<para> |
SMP synchronization support. The hardware must supply a mechanism to |
allow software on two CPUs to synchronize. This is normally provided |
as part of the instruction set in the form of test-and-set, |
compare-and-swap or load-link/store-conditional instructions. An |
alternative approach is the provision of hardware semaphore |
registers which can be used to serialize implementations of these |
operations. Whatever hardware facilities are available, they are |
used in eCos to implement spinlocks. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Coherent caches. It is assumed that no extra effort will be required |
to access shared memory from any processor. This means that either |
there are no caches, they are shared by all processors, or are |
maintained in a coherent state by the hardware. It would be too |
disruptive to the eCos sources if every memory access had to be |
bracketed by cache load/flush operations. Any hardware that requires |
this is not supported. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Uniform addressing. It is assumed that all memory that is |
shared between CPUs is addressed at the same location from all |
CPUs. Like non-coherent caches, dealing with CPU-specific address |
translation is considered too disruptive to the eCos source |
base. This does not, however, preclude systems with non-uniform |
access costs for different CPUs. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Uniform device addressing. As with access to memory, it is assumed |
that all devices are equally accessible to all CPUs. Since device |
access is often made from thread contexts, it is not possible to |
restrict access to device control registers to certain CPUs, since |
there is currently no support for binding or migrating threads to CPUs. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Interrupt routing. The target hardware must have an interrupt |
controller that can route interrupts to specific CPUs. It is |
acceptable for all interrupts to be delivered to just one CPU, or |
for some interrupts to be bound to specific CPUs, or for some |
interrupts to be local to each CPU. At present dynamic routing, |
where a different CPU may be chosen each time an interrupt is |
delivered, is not supported. ECos cannot support hardware where all |
interrupts are delivered to all CPUs simultaneously with the |
expectation that software will resolve any conflicts. |
</para> |
</listitem> |
|
<listitem> |
<para> |
Inter-CPU interrupts. A mechanism to allow one CPU to interrupt |
another is needed. This is necessary so that events on one CPU can |
cause rescheduling on other CPUs. |
</para> |
</listitem> |
|
<listitem> |
<para> |
CPU Identifiers. Code running on a CPU must be able to determine |
which CPU it is running on. The CPU Id is usually provided either in |
a CPU status register, or in a register associated with the |
inter-CPU interrupt delivery subsystem. ECos expects CPU Ids to be |
small positive integers, although alternative representations, such |
as bitmaps, can be converted relatively easily. Complex mechanisms |
for getting the CPU Id cannot be supported. Getting the CPU Id must |
be a cheap operation, since it is done often, and in performance |
critical places such as interrupt handlers and the scheduler. |
</para> |
</listitem> |
</itemizedlist> |
|
</section> |
|
<section> |
<title>HAL Support</title> |
|
<para> |
SMP support in any platform depends on the HAL supplying the |
appropriate operations. All HAL SMP support is defined in the |
<filename>cyg/hal/hal_smp.h</filename> header. Variant and platform |
specific definitions will be in <filename>cyg/hal/var_smp.h</filename> |
and <filename>cyg/hal/plf_smp.h</filename> respectively. These files |
are include automatically by this header, so need not be included |
explicitly. |
</para> |
|
<para> |
SMP support falls into a number of functional groups. |
</para> |
|
<section> |
<title>CPU Control</title> |
|
<para> |
This group consists of descriptive and control macros for managing the |
CPUs in an SMP system. |
</para> |
|
<variablelist> |
<varlistentry> |
<term><literal>HAL_SMP_CPU_TYPE</literal></term> |
<listitem> |
<para> |
A type that can contain a CPU id. A CPU id is |
usually a small integer that is used to index |
arrays of variables that are managed on an |
per-CPU basis. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_CPU_MAX</literal></term> |
<listitem> |
<para> |
The maximum number of CPUs that can be |
supported. This is used to provide the size of |
any arrays that have an element per CPU. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_CPU_COUNT()</literal></term> |
<listitem> |
<para> |
Returns the number of CPUs currently |
operational. This may differ from |
HAL_SMP_CPU_MAX depending on the runtime |
environment. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_CPU_THIS()</literal></term> |
<listitem> |
<para> |
Returns the CPU id of the current CPU. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_CPU_NONE</literal></term> |
<listitem> |
<para> |
A value that does not match any real CPU |
id. This is uses where a CPU type variable |
must be set to a null value. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_CPU_START( cpu )</literal></term> |
<listitem> |
<para> |
Starts the given CPU executing at a defined |
HAL entry point. After performing any HAL |
level initialization, the CPU calls up into |
the kernel at <function>cyg_kernel_cpu_startup()</function>. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_CPU_RESCHEDULE_INTERRUPT( cpu, wait )</literal></term> |
<listitem> |
<para> |
Sends the CPU a reschedule interrupt, and if |
<parameter>wait</parameter> is non-zero, waits for an |
acknowledgment. The interrupted CPU should call |
<function>cyg_scheduler_set_need_reschedule()</function> in its DSR to |
cause the reschedule to occur. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_CPU_TIMESLICE_INTERRUPT( cpu, wait )</literal></term> |
<listitem> |
<para> |
Sends the CPU a timeslice interrupt, and if |
<parameter>wait</parameter> is non-zero, waits for an |
acknowledgment. The interrupted CPU should call |
<function>cyg_scheduler_timeslice_cpu()</function> to cause the |
timeslice event to be processed. |
</para> |
</listitem> |
</varlistentry> |
</variablelist> |
</section> |
|
|
<section> |
<title>Test-and-set Support</title> |
|
<para> |
Test-and-set is the foundation of the SMP synchronization |
mechanisms. |
</para> |
|
<variablelist> |
<varlistentry> |
<term><literal>HAL_TAS_TYPE</literal></term> |
<listitem> |
<para> |
The type for all test-and-set variables. The |
test-and-set macros only support operations on |
a single bit (usually the least significant |
bit) of this location. This allows for maximum |
flexibility in the implementation. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_TAS_SET( tas, oldb )</literal></term> |
<listitem> |
<para> |
Performs a test and set operation on the |
location <parameter>tas</parameter>. <parameter>oldb</parameter> will contain <literal>true</literal> if |
the location was already set, and <literal>false</literal> if |
it was clear. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_TAS_CLEAR( tas, oldb )</literal></term> |
<listitem> |
<para> |
Performs a test and clear operation on the |
location <parameter>tas</parameter>. <parameter>oldb</parameter> will contain <literal>true</literal> if |
the location was already set, and <literal>false</literal> if |
it was clear. |
</para> |
</listitem> |
</varlistentry> |
</variablelist> |
</section> |
<section> |
|
<title>Spinlocks</title> |
|
<para> |
Spinlocks provide inter-CPU locking. Normally they will be implemented |
on top of the test-and-set mechanism above, but may also be |
implemented by other means if, for example, the hardware has more |
direct support for spinlocks. |
</para> |
|
<variablelist> |
<varlistentry> |
<term><literal>HAL_SPINLOCK_TYPE</literal></term> |
<listitem> |
<para> |
The type for all spinlock variables. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SPINLOCK_INIT_CLEAR</literal></term> |
<listitem> |
<para> |
A value that may be assigned to a spinlock |
variable to initialize it to clear. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SPINLOCK_INIT_SET</literal></term> |
<listitem> |
<para> |
A value that may be assigned to a spinlock |
variable to initialize it to set. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SPINLOCK_SPIN( lock )</literal></term> |
<listitem> |
<para> |
The caller spins in a busy loop waiting for |
the lock to become clear. It then sets it and |
continues. This is all handled atomically, so |
that there are no race conditions between CPUs. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SPINLOCK_CLEAR( lock )</literal></term> |
<listitem> |
<para> |
The caller clears the lock. One of any waiting |
spinners will then be able to proceed. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SPINLOCK_TRY( lock, val )</literal></term> |
<listitem> |
<para> |
Attempts to set the lock. The value put in |
<parameter>val</parameter> will be <literal>true</literal> if the lock was |
claimed successfully, and <literal>false</literal> if it was |
not. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SPINLOCK_TEST( lock, val )</literal></term> |
<listitem> |
<para> |
Tests the current value of the lock. The value |
put in <parameter>val</parameter> will be <literal>true</literal> if the lock is |
claimed and <literal>false</literal> of it is clear. |
</para> |
</listitem> |
</varlistentry> |
</variablelist> |
</section> |
<section> |
|
<title>Scheduler Lock</title> |
|
<para> |
The scheduler lock is the main protection for all kernel data |
structures. By default the kernel implements the scheduler lock itself |
using a spinlock. However, if spinlocks cannot be supported by the |
hardware, or there is a more efficient implementation available, the |
HAL may provide macros to implement the scheduler lock. |
</para> |
|
<variablelist> |
<varlistentry> |
<term><literal>HAL_SMP_SCHEDLOCK_DATA_TYPE</literal></term> |
<listitem> |
<para> |
A data type, possibly a structure, that |
contains any data items needed by the |
scheduler lock implementation. A variable of |
this type will be instantiated as a static |
member of the Cyg_Scheduler_SchedLock class |
and passed to all the following macros. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_SCHEDLOCK_INIT( lock, data )</literal></term> |
<listitem> |
<para> |
Initialize the scheduler lock. The <parameter>lock</parameter> |
argument is the scheduler lock counter and the |
<parameter>data</parameter> argument is a variable of |
HAL_SMP_SCHEDLOCK_DATA_TYPE type. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_SCHEDLOCK_INC( lock, data )</literal></term> |
<listitem> |
<para> |
Increment the scheduler lock. The first |
increment of the lock from zero to one for any |
CPU may cause it to wait until the lock is |
zeroed by another CPU. Subsequent increments |
should be less expensive since this CPU |
already holds the lock. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_SCHEDLOCK_ZERO( lock, data )</literal></term> |
<listitem> |
<para> |
Zero the scheduler lock. This operation will |
also clear the lock so that other CPUs may |
claim it. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_SMP_SCHEDLOCK_SET( lock, data, new )</literal></term> |
<listitem> |
<para> |
Set the lock to a different value, in |
<parameter>new</parameter>. This is only called when the lock is |
already known to be owned by the current CPU. It is never called to |
zero the lock, or to increment it from zero. |
</para> |
</listitem> |
</varlistentry> |
|
</variablelist> |
</section> |
<section> |
|
<title>Interrupt Routing</title> |
|
<para> |
The routing of interrupts to different CPUs is supported by two new |
interfaces in hal_intr.h. |
</para> |
|
<para> |
Once an interrupt has been routed to a new CPU, the existing vector |
masking and configuration operations should take account of the CPU |
routing. For example, if the operation is not invoked on the |
destination CPU itself, then the HAL may need to arrange to transfer |
the operation to the destination CPU for correct application. |
</para> |
|
<variablelist> |
<varlistentry> |
<term><literal>HAL_INTERRUPT_SET_CPU( vector, cpu )</literal></term> |
<listitem> |
<para> |
Route the interrupt for the given <parameter>vector</parameter> to |
the given <parameter>cpu</parameter>. |
</para> |
</listitem> |
</varlistentry> |
|
<varlistentry> |
<term><literal>HAL_INTERRUPT_GET_CPU( vector, cpu )</literal></term> |
<listitem> |
<para> |
Set <parameter>cpu</parameter> to the id of the CPU to which this |
vector is routed. |
</para> |
</listitem> |
</varlistentry> |
</variablelist> |
|
</section> |
|
</section> |
|
|
</section> |
|
<!-- }}} --> |
|
</CHAPTER> |
|
<!-- }}} --> |
<!-- {{{ Exception Handling --> |
|
<CHAPTER id="hal-exception-handling"> |
<TITLE>Exception Handling</TITLE> |
|
<!-- {{{ Intro --> |
|
<para> |
Most of the HAL consists of simple macros or functions that are |
called via the interfaces described in the previous section. These |
just perform whatever operation is required by accessing the hardware |
and then return. The exception to this is the handling of exceptions: |
either synchronous hardware traps or asynchronous device |
interrupts. Here control is passed first to the HAL, which then passed |
it on to eCos or the application. After eCos has finished with it, |
control is then passed back to the HAL for it to tidy up the CPU state |
and resume processing from the point at which the exception occurred. |
</para> |
|
<PARA> |
The HAL exceptions handling code is usually found in the file |
<FILENAME>vectors.S</FILENAME> in the architecture HAL. Since the |
reset entry point is usually implemented as one of these it also deals |
with system startup. |
</PARA> |
|
<PARA> |
The exact implementation of this code is under the control of the HAL |
implementer. So long as it interacts correctly with the interfaces |
defined previously it may take any form. However, all current |
implementation follow the same pattern, and there should be a very |
good reason to break with this. The rest of this section describes |
these operate. |
</PARA> |
|
<para> |
Exception handling normally deals with the following broad areas of |
functionality: |
</para> |
|
<ITEMIZEDLIST> |
<LISTITEM> |
<PARA>Startup and initialization.</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA>Hardware exception delivery.</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA>Default handling of synchronous exceptions.</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA>Default handling of asynchronous interrupts.</PARA> |
</LISTITEM> |
</ITEMIZEDLIST> |
|
<!-- }}} --> |
<!-- {{{ HAL Startup --> |
|
<SECTION id="hal-startup"> |
<TITLE><!-- <index></index> --><!-- <xref> -->HAL Startup</TITLE> |
|
<PARA> |
Execution normally begins at the reset vector with |
the machine in a minimal startup state. From here the HAL needs to get |
the machine running, set up the execution environment for the |
application, and finally invoke its entry point. |
</PARA> |
|
<PARA> |
The following is a list of the jobs that need to be done in |
approximately the order in which they should be accomplished. Many |
of these will not be needed in some configurations. |
</PARA> |
|
<ITEMIZEDLIST> |
<listitem> |
<para> |
Initialize the hardware. This may involve initializing several |
subsystems in both the architecture, variant and platform |
HALs. These include: |
</para> |
<itemizedlist> |
<LISTITEM> |
<PARA> |
Initialize various CPU status registers. Most importantly, the CPU |
interrupt mask should be set to disable interrupts. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Initialize the MMU, if it is used. On many platforms it is |
only possible to control the cacheability of address ranges |
via the MMU. Also, it may be necessary to remap RAM and device |
registers to locations other than their defaults. However, for |
simplicity, the mapping should be kept as close to one-to-one |
physical-to-virtual as possible. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Set up the memory controller to access RAM, ROM and I/O devices |
correctly. Until this is done it may not be possible to access |
RAM. If this is a ROMRAM startup then the program code can |
now be copied to its RAM address and control transferred to it. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Set up any bus bridges and support chips. Often access to |
device registers needs to go through various bus bridges and |
other intermediary devices. In many systems these are combined |
with the memory controller, so it makes sense to set these up |
together. This is particularly important if early diagnostic |
output needs to go through one of these devices. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Set up diagnostic mechanisms. If the platform includes an LED or |
LCD output device, it often makes sense to output progress |
indications on this during startup. This helps with diagnosing |
hardware and software errors. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Initialize floating point and other extensions such as SIMD |
and multimedia engines. It is usually necessary to enable |
these and maybe initialize control and exception registers for |
these extensions. |
</PARA> |
</LISTITEM> |
|
|
<LISTITEM> |
<PARA> |
Initialize interrupt controller. At the very least, it should |
be configured to mask all interrupts. It may also be necessary |
to set up the mapping from the interrupt controller's vector |
number space to the CPU's exception number space. Similar |
mappings may need to be set up between primary and secondary |
interrupt controllers. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Disable and initialize the caches. The caches should not |
normally be enabled at this point, but it may be necessary to |
clear or initialize them so that they can be enabled |
later. Some architectures require that the caches be |
explicitly reinitialized after a power-on reset. |
</PARA> |
</LISTITEM> |
|
|
<LISTITEM> |
<PARA> |
Initialize the timer, clock etc. While the timer used for RTC |
interrupts will be initialized later, it may be necessary to |
set up the clocks that drive it here. |
</PARA> |
</LISTITEM> |
|
</itemizedlist> |
<para> |
The exact order in which these initializations is done is |
architecture or variant specific. It is also often not necessary |
to do anything at all for some of these options. These fragments |
of code should concentrate on getting the target up and running so |
that C function calls can be made and code can be run. More |
complex initializations that cannot be done in assembly code may |
be postponed until calls to |
<function>hal_variant_init()</function> or |
<function>hal_platform_init()</function> are made. |
</para> |
|
<para> |
Not all of these initializations need to be done for all startup |
types. In particular, RAM startups can reasonably assume that the |
ROM monitor or loader has already done most of this work. |
</para> |
|
</listitem> |
|
<LISTITEM> |
<PARA> |
Set up the stack pointer, this allows subsequent initialization |
code to make proper procedure calls. Usually the interrupt stack |
is used for this purpose since it is available, large enough, and |
will be reused for other purposes later. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Initialize any global pointer register needed for access to |
globally defined variables. This allows subsequent initialization |
code to access global variables. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
If the system is starting from ROM, copy the ROM template of the |
<filename>.data</filename> section out to its correct position in |
RAM. (<xref linkend="hal-linker-scripts">). |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Zero the <filename>.bss</filename> section. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Create a suitable C call stack frame. This may involve making |
stack space for call frames, and arguments, and initializing the |
back pointers to halt a GDB backtrace operation. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Call <function>hal_variant_init()</function> and |
<function>hal_platform_init()</function>. These will perform any |
additional initialization needed by the variant and platform. This |
typically includes further initialization of the interrupt |
controller, PCI bus bridges, basic IO devices and enabling the |
caches. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Call <FUNCTION>cyg_hal_invoke_constructors()</FUNCTION> to run any |
static constructors. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Call <FUNCTION>cyg_start()</FUNCTION>. If |
<FUNCTION>cyg_start()</FUNCTION> returns, drop into an infinite |
loop. |
</PARA> |
</LISTITEM> |
</ITEMIZEDLIST> |
|
</SECTION> |
|
<!-- }}} --> |
<!-- {{{ Vectors and VSRs --> |
|
<SECTION id="hal-vectors-and-vsrs"><!-- <index></index> --> |
<TITLE>Vectors and VSRs</TITLE> |
|
<PARA> |
The CPU delivers all <!-- <index></index> --> exceptions, whether |
synchronous faults or asynchronous interrupts, to a set of hardware |
defined vectors. Depending on the architecture, these may be |
implemented in a number of different ways. Examples of existing |
mechanisms are: |
</PARA> |
|
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM>PowerPC</TERM> |
<LISTITEM> |
<PARA> |
Exceptions are vectored to locations 256 bytes apart starting at |
either zero or <literal>0xFFF00000</literal>. There are 16 such |
vectors defined by the basic architecture and extra vectors may |
be defined by specific variants. One of the base vectors is for |
all external interrupts, and another is for the architecture |
defined timer. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>MIPS</TERM> |
<LISTITEM> |
<PARA> |
Most exceptions and all interrupts are vectored to a single |
address at either <literal>0x80000000</literal> or |
<literal>0xBFC00180</literal>. Software is responsible for |
reading the exception code from the CPU <literal>cause</literal> |
register to discover its true source. Some TLB and debug |
exceptions are delivered to different vector addresses, but |
these are not used currently by eCos. One of the exception codes |
in the <literal>cause</literal> register indicates an external |
interrupt. Additional bits in the <literal>cause</literal> |
register provide a first-level decode for the interrupt source, |
one of which represents an architecture defined timer. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>IA32</TERM> |
<LISTITEM> |
<PARA> |
Exceptions are delivered via an Interrupt Descriptor Table (IDT) |
which is essentially an indirection table indexed by exception |
number. The IDT may be placed anywhere in memory. In PC hardware |
the standard interrupt controller can be programmed to deliver |
the external interrupts to a block of 16 vectors at any offset |
in the IDT. There is no hardware supplied mechanism for |
determining the vector taken, other than from the address jumped |
to. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>ARM</TERM> |
<LISTITEM> |
<PARA> |
All exceptions, including the FIQ and IRQ interrupts, are |
vectored to locations four bytes apart starting at zero. There |
is only room for one instruction here, which must immediately |
jump out to handling code higher in memory. Interrupt sources |
have to be decoded entirely from the interrupt controller. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
|
|
<para> |
With such a wide variety of hardware approaches, it is not possible to |
provide a generic mechanism for the substitution of exception vectors |
directly. Therefore, eCos translates all of these mechanisms in to a |
common approach that can be used by portable code on all platforms. |
</para> |
|
<para> |
The mechanism implemented is to attach to each hardware vector a short |
piece of trampoline code that makes an indirect jump via a table to |
the actual handler for the exception. This handler is called the |
Vector Service Routine (VSR) and the table is called the VSR table. |
</para> |
|
<para> |
The trampoline code performs the absolute minimum processing necessary |
to identify the exception source, and jump to the VSR. The VSR is then |
responsible for saving the CPU state and taking the necessary actions |
to handle the exception or interrupt. The entry conditions for the VSR |
are as close to the raw hardware exception entry state as possible - |
although on some platforms the trampoline will have had to move or |
reorganize some registers to do its job. |
</para> |
|
<para> |
To make this more concrete, consider how the trampoline code operates |
in each of the architectures described above: |
</para> |
|
|
<VARIABLELIST> |
<VARLISTENTRY> |
<TERM>PowerPC</TERM> |
<LISTITEM> |
<PARA> |
A separate trampoline is contained in each of the vector |
locations. This code saves a few work registers away to the |
special purposes registers available, loads the exception number |
into a register and then uses that to index the VSR table and |
jump to the VSR. The VSR is entered with some registers move to |
the SPRs, and one of the data register containing the number of |
the vector taken. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>MIPS</TERM> |
<LISTITEM> |
<PARA> |
A single trampoline routine attached to the common vector reads |
the exception code out of the <literal>cause</literal> register |
and uses that value to index the VSR table and jump to the VSR. |
The trampoline uses the two registers defined in the ABI for |
kernel use to do this, one of these will contain the exception |
vector number for the VSR. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>IA32</TERM> |
<LISTITEM> |
<PARA> |
There is a separate 3 or 4 instruction trampoline pointed to by |
each active IDT table entry. The trampoline for exceptions that |
also have an error code pop it from the stack and put it into a |
memory location. Trampolines for non-error-code exceptions just |
zero the memory location. Then all trampolines push an |
interrupt/exception number onto the stack, and take an indirect |
jump through a precalculated offset in the VSR table. This is |
all done without saving any registers, using memory-only |
operations. The VSR is entered with the vector number pushed |
onto the stack on top of the standard hardware saved state. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
|
<VARLISTENTRY> |
<TERM>ARM</TERM> |
<LISTITEM> |
<PARA> |
The trampoline consists solely of the single instruction at the |
exception entry point. This is an indirect jump via a location |
32 bytes higher in memory. These locations, from |
<literal>0x20</literal> up, form the VSR table. Since each VSR |
is entered in a different CPU mode |
(<literal>SVC,UNDEF,ABORT,IRQ or FIQ</literal>) there has to be a |
different VSR for each exception that knows how to save the CPU |
state correctly. |
</PARA> |
</LISTITEM> |
</VARLISTENTRY> |
</VARIABLELIST> |
|
</section> |
|
<!-- }}} --> |
<!-- {{{ Synchronous Exception Handling --> |
|
<SECTION id="hal-default-synchronous-exception-handling"> |
<TITLE><!-- <index></index> -->Default Synchronous Exception Handling</TITLE> |
|
<PARA> |
Most synchronous exception VSR table entries will point to a default |
exception VSR which is responsible for handling all exceptions in a |
generic manner. The default VSR simply saves the CPU state, makes any |
adjustments to the CPU state that is necessary, and calls |
<function>cyg_hal_exception_handler()</function>. |
</PARA> |
|
<PARA> |
<function>cyg_hal_exception_handler()</function> needs to pass the |
exception on to some handling code. There are two basic destinations: |
enter GDB or pass the exception up to eCos. Exactly which |
destination is taken depends on the configuration. When the GDB stubs are |
included then the exception is passed to them, otherwise it is passed |
to eCos. |
</PARA> |
|
<para> |
If an eCos application has been loaded by RedBoot then the VSR table |
entries will all point into RedBoot's exception VSR, and will |
therefore enter GDB if an exception occurs. If the eCos application |
wants to handle an exception itself, it needs to replace the the VSR |
table entry with one pointing to its own VSR. It can do this with the |
<function>HAL_VSR_SET_TO_ECOS_HANDLER()</function> macro. |
</para> |
|
</SECTION> |
|
<!-- }}} --> |
<!-- {{{ Interrupt Handling --> |
|
<SECTION id="hal-default-interrupt-handling"> |
<TITLE><!-- <index></index> -->Default Interrupt Handling</TITLE> |
|
<PARA> |
Most asynchronous external interrupt vectors will point to a default |
interrupt VSR which decodes the actual interrupt being delivered from |
the interrupt controller and invokes the appropriate ISR. |
</PARA> |
|
<PARA> |
The default interrupt VSR has a number of responsibilities if it is |
going to interact with the Kernel cleanly and allow interrupts to |
cause thread preemption. |
</PARA> |
|
<PARA> |
To support this VSR an ISR vector table is needed. For each valid |
vector three pointers need to be stored: the ISR, its data pointer and |
an opaque (to the HAL) interrupt object pointer needed by the |
kernel. It is implementation defined whether these are stored in a |
single table of triples, or in three separate tables. |
</PARA> |
|
<PARA> |
The VSR follows the following approximate plan: |
</PARA> |
|
<ORDEREDLIST> |
<LISTITEM> |
<PARA> |
Save the CPU state. In non-debug configurations, it may be |
possible to get away with saving less than the entire machine |
state. The option |
<literal>CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT</literal> |
is supported in some targets to do this. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Increment the kernel scheduler lock. This is a static member of |
the Cyg_Scheduler class, however it has also been aliased to |
<literal>cyg_scheduler_sched_lock</literal> so that it can be |
accessed from assembly code. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
(Optional) Switch to an interrupt stack if not already running on |
it. This allows nested interrupts to be delivered without needing |
every thread to have a stack large enough to take the maximum |
possible nesting. It is implementation defined how to detect |
whether this is a nested interrupt but there are two basic |
techniques. The first is to inspect the stack pointer and switch |
only if it is not currently within the interrupt stack range; the |
second is to maintain a counter of the interrupt nesting level and |
switch only if it is zero. The option |
<literal>CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK</literal> |
controls whether this happens. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Decode the actual external interrupt being delivered from |
the interrupt controller. This will yield the ISR vector |
number. The code to do this usually needs to come from the |
variant or platform HAL, so is usually present in the form of a |
macro or procedure callout. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
(Optional) Re-enable interrupts to permit nesting. At this point |
we can potentially allow higher priority interrupts to occur. It |
depends on the interrupt architecture of the CPU and platform |
whether more interrupts will occur at this point, or whether they |
will only be delivered after the current interrupt has been |
acknowledged (by a call to |
<function>HAL_INTERRUPT_ACKNOWLEDGE()</function> in the ISR). |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Using the ISR vector number as an index, retrieve the |
ISR pointer and its data pointer from the ISR vector table. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Construct a C call stack frame. This may involve making stack |
space for call frames, and arguments, and initializing the back |
pointers to halt a GDB backtrace operation. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Call the ISR, passing the vector number and data pointer. The |
vector number and a pointer to the saved state should be preserved |
across this call, preferably by storing them in registers that are |
defined to be callee-saved by the calling conventions. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
If this is an un-nested interrupt and a separate interrupt |
stack is being used, switch back to the interrupted thread's |
own stack. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Use the saved ISR vector number to get the interrupt object |
pointer from the ISR vector table. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
Call <FUNCTION>interrupt_end()</FUNCTION> passing it the return |
value from the ISR, the interrupt object pointer and a pointer to |
the saved CPU state. This function is implemented by the Kernel |
and is responsible for finishing off the interrupt |
handling. Specifically, it may post a DSR depending on the ISR |
return value, and will decrement the scheduler lock. If the lock |
is zeroed by this operation then any posted DSRs may be called and |
may in turn result in a thread context switch. |
</PARA> |
</LISTITEM> |
|
<LISTITEM> |
<PARA> |
The return from <FUNCTION>interrupt_end()</FUNCTION> may occur |
some time after the call. Many other threads may have executed in |
the meantime. So here all we may do is restore the machine state |
and resume execution of the interrupted thread. Depending on the |
architecture, it may be necessary to disable interrupts again for |
part of this. |
</PARA> |
</LISTITEM> |
|
</ORDEREDLIST> |
|
<PARA> |
The detailed order of these steps may vary slightly depending on the |
architecture, in particular where interrupts are enabled and disabled. |
</PARA> |
|
</SECTION> |
|
<!-- }}} --> |
|
</CHAPTER> |
|
<!-- }}} --> |
<!-- {{{ Porting Guide --> |
|
&hal-common-porting-sgml; |
|
<!-- }}} --> |
<!-- {{{ Future Developments --> |
|
<CHAPTER id="hal-future-developments"> |
<TITLE><!-- <index></index> --><!-- <xref> -->Future developments</TITLE> |
|
<PARA> |
The HAL is not complete, and will evolve and increase over |
time. Among the intended developments are: |
</PARA> |
<ITEMIZEDLIST> |
<LISTITEM> |
<PARA>Common macros for interpreting the contents of a saved |
machine context. These would allow portable code, such as debug |
stubs, to extract such values as the program counter and stack pointer |
from a state without having to interpret a <STRUCTNAME>HAL_SavedRegisters</STRUCTNAME> structure |
directly.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>Debugging support. Macros to set and clear hardware and |
software breakpoints. Access to other areas of machine state may |
also be supported.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>Static initialization support. The current HAL provides a |
dynamic interface to things like thread context initialization and ISR |
attachment. We also need to be able to define the system entirely |
statically so that it is ready to go on restart, without needing to |
run code. This will require extra macros to define these |
initializations. Such support may have a consequential effect on the |
current HAL specification.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>CPU state control. Many CPUs have both kernel and user |
states. Although it is not intended to run any code in user state |
for the foreseeable future, it is possible that this may happen |
eventually. If this is the case, then some minor changes may be needed |
to the current HAL API to accommodate this. These should mostly |
be extensions, but minor changes in semantics may also be required.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>Physical memory management. Many embedded systems have |
multiple memory areas with varying properties such as base address, |
size, speed, bus width, cacheability and persistence. An API is |
needed to support the discovery of this information about the machine's |
physical memory map.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>Memory management control. Some embedded processors have |
a memory management unit. In some cases this must be enabled to |
allow the cache to be controlled, particularly if different regions |
of memory must have different caching properties. For some purposes, |
in some systems, it will be useful to manipulate the MMU settings |
dynamically.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>Power management. Macros to access and control any power |
management mechanisms available on the CPU implementation. These |
would provide a substrate for a more general power management system |
that also involved device drivers and other hardware components.</PARA> |
</LISTITEM> |
<LISTITEM> |
<PARA>Generic serial line macros. Most serial line devices operate |
in the same way, the only real differences being exactly which bits |
in which registers perform the standard functions. It should be |
possible to develop a set of HAL macros that provide basic serial |
line services such as baud rate setting, enabling interrupts, polling |
for transmit or receive ready, transmitting and receiving data etc. |
Given these it should be possible to create a generic serial line |
device driver that will allow rapid bootstrapping on any new platform. |
It may be possible to extend this mechanism to other device types.</PARA> |
</LISTITEM> |
</ITEMIZEDLIST> |
</CHAPTER> |
|
<!-- }}} --> |
|
</part> |
/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 = ®isters[0] ; |
break ; |
case 1 : |
/* copy the saved registers into the backup registers */ |
stub_copy_registers(alt_registers,registers) ; |
/* The OS will now update the values it has in a saved process context*/ |
if (dbg_getthreadreg(&id,NUMREGS,&alt_registers[0])) |
{ |
/* switch the registers pointer */ |
_registers = &alt_registers[0] ; |
outbuf = stub_pack_ack(outbuf) ; |
} |
else |
outbuf = stub_pack_nak(outbuf) ; |
break ; |
case 2 : |
/* switch to interrupted context */ |
outbuf = stub_pack_ack(outbuf) ; |
break ; |
default: |
outbuf = stub_pack_nak(outbuf) ; |
break ; |
} |
*outbuf = '\0' ; /* Terminate response pkt */ |
} /* stub_pkt_changethread */ |
|
|
/* ---- STUB_PKT_GETTHREADLIST ------------------------------- */ |
/* Get a portion of the threadlist or process list */ |
/* This may be part of a multipacket transaction */ |
/* It would be hard to tell in the response packet the difference |
between the end of list and an error in threadid encoding. |
*/ |
|
void stub_pkt_getthreadlist(char * inbuf, |
char * outbuf, |
int bufmax) |
{ |
char * count_ptr ; |
char * done_ptr ; |
char * limit ; |
int start_flag , batchsize , result , count ; |
static threadref lastthread, nextthread ; |
|
#if PKT_DEBUG |
char * r_base = outbuf ; |
#endif |
PKT_TRACE("pkt_getthreadlist: ",inbuf) ; |
|
count = 0 ; |
inbuf = unpack_nibble(inbuf,&start_flag) ; |
inbuf = unpack_byte(inbuf,&batchsize) ; |
inbuf = unpack_threadid(inbuf,&lastthread) ; /* even if startflag */ |
|
/* Start building response packet */ |
limit = outbuf + (bufmax - BUFTHREADIDSIZ - 10) ; /* id output packing limit */ |
*outbuf++ = 'Q' ; |
*outbuf++ = 'M' ; |
|
/* Default values for count and done fields, save ptr to repatch */ |
count_ptr = outbuf ; /* save to repatch count */ |
outbuf = pack_hex_byte(outbuf,0) ; |
done_ptr = outbuf ; /* Backpatched later */ |
*outbuf++ = '0' ; /* Done = 0 by default */ |
outbuf = pack_threadid(outbuf,&lastthread) ; |
|
/* Loop through the threadid packing */ |
while ((outbuf < limit) && (count < batchsize)) |
{ |
result = dbg_threadlist(start_flag,&lastthread,&nextthread) ; |
start_flag = 0 ; /* redundant but effective */ |
if (!result) |
{ *done_ptr = '1' ; /* pack the done flag */ |
break ; |
} |
#if 0 /* DEBUG */ |
if (threadmatch(&lastthread,&nextthread)) |
{ |
output_string("FAIL: Threadlist, not incrementing\n") ; |
*done_ptr = '1' ; |
break ; |
} |
#endif |
count++ ; |
outbuf = pack_threadid(outbuf,&nextthread) ; |
copy_threadref(&lastthread,&nextthread) ; |
} |
pack_hex_byte(count_ptr,count) ;/* backpatch, Pack the count field */ |
*outbuf = '\0' ; |
PKT_TRACE("pkt_getthreadlist(resp) ",r_base) ; |
} /* pkt_getthreadlist */ |
|
|
|
|
/* ----- STUB_PKT_GETTHREADINFO ---------------------------------------- */ |
/* Get the detailed information about a specific thread or process */ |
|
/* |
Encoding: |
'Q':8,'P':8,mask:16 |
|
Mask Fields |
threadid:1, # always request threadid |
context_exists:2, |
display:4, |
unique_name:8, |
more_display:16 |
*/ |
|
void stub_pkt_getthreadinfo( |
char * inbuf, |
char * outbuf, |
int bufmax) |
{ |
int mask ; |
int result ; |
threadref thread ; |
struct cygmon_thread_debug_info info ; |
|
info.context_exists = 0 ; |
info.thread_display = 0 ; |
info.unique_thread_name = 0 ; |
info.more_display = 0 ; |
|
/* Assume the packet identification chars have already been |
discarded by the packet demultiples routines */ |
PKT_TRACE("PKT getthreadinfo",inbuf) ; |
|
inbuf = unpack_int(inbuf,&mask) ; |
inbuf = unpack_threadid(inbuf,&thread) ; |
|
result = dbg_threadinfo(&thread,&info) ; /* Make system call */ |
|
if (result) |
{ |
*outbuf++ = 'q' ; |
*outbuf++ = 'p' ; |
outbuf = pack_int(outbuf,mask) ; |
outbuf = pack_threadid(outbuf,&info.thread_id) ; /* echo threadid */ |
if (mask & 2) /* context-exists */ |
{ |
outbuf = pack_int(outbuf,2) ; /* tag */ |
outbuf = pack_hex_byte(outbuf,2) ; /* length */ |
outbuf = pack_hex_byte(outbuf,info.context_exists) ; |
} |
if ((mask & 4) && info.thread_display)/* display */ |
{ |
outbuf = pack_int(outbuf,4) ; /* tag */ |
outbuf = pack_string(outbuf,info.thread_display) ; |
} |
if ((mask & 8) && info.unique_thread_name) /* unique_name */ |
{ |
outbuf = pack_int(outbuf,8) ; |
outbuf = pack_string(outbuf,info.unique_thread_name) ; |
} |
if ((mask & 16) && info.more_display) /* more display */ |
{ |
outbuf = pack_int(outbuf,16) ; /* tag 16 */ |
outbuf = pack_string(outbuf,info.more_display) ; |
} |
} |
else |
{ |
PKT_TRACE("FAIL: dbg_threadinfo\n", "") ; |
outbuf = stub_pack_nak(outbuf) ; |
} |
*outbuf = '\0' ; |
} /* stub_pkt_getthreadinfo */ |
|
int stub_lock_scheduler(int lock, /* 0 to unlock, 1 to lock */ |
int mode, /* 0 for step, 1 for continue */ |
long id) /* current thread */ |
{ |
threadref thread; |
|
int_to_threadref(&thread, id) ; |
return dbg_scheduler(&thread, lock, mode) ; |
} |
|
|
#if GDB_MOCKUP |
/* ------ MATCHED GDB SIDE PACKET ENCODING AND PARSING ----------------- */ |
|
char * pack_nibble(char * buf, int nibble) |
{ |
*buf++ = hexchars[(nibble & 0x0f)] ; |
return buf ; |
} /* pack_nibble */ |
|
#if 0 |
static char * unpack_short(char * buf,int * value) |
{ |
*value = stub_unpack_int(buf,4) ; |
return buf + 4 ; |
} |
|
static char * pack_short( |
char * buf, |
unsigned int value) |
{ |
buf = pack_hex_byte(buf,(value >> 8) & 0xff) ; |
buf = pack_hex_byte(buf,(value & 0xff)) ; |
return buf ; |
} /* pack_short */ |
#endif |
|
|
/* Generally, I dont bury xmit and receive calls inside packet formatters |
and parsers |
*/ |
|
|
|
|
/* ----- PACK_SETTHREAD_REQUEST ------------------------------------- */ |
/* Encoding: ??? decode gdb/remote.c |
'Q':8,'p':8,idefined:8,threadid:32 ; |
*/ |
|
char * pack_setthread_request( |
char * buf, |
char fmt, /* c,g or, p */ |
int idformat , |
threadref * threadid ) |
{ |
*buf++ = fmt ; |
|
if (fmt == 'p') |
{ /* pack the long form */ |
buf = pack_nibble(buf,idformat) ; |
buf = pack_threadid(buf,threadid) ; |
} |
else |
{ /* pack the shorter form - Serious truncation */ |
/* There are reserved identifieds 0 , -1 */ |
int quickref = threadref_to_int(threadid) ; |
buf = pack_varlen_hex(buf,quickref) ; |
} |
*buf++ = '\0' ; /* end_of_packet */ |
return buf ; |
} /* pack_setthread_request */ |
|
|
|
/* -------- PACK_THREADLIST-REQUEST --------------------------------- */ |
/* Format: i'Q':8,i"L":8,initflag:8,batchsize:16,lastthreadid:32 */ |
|
|
char * pack_threadlist_request( |
char * pkt, |
int startflag, |
int threadcount, |
threadref * nextthread |
) |
{ |
*pkt++ = 'q' ; |
*pkt++ = 'L' ; |
pkt = pack_nibble(pkt,startflag) ; /* initflag 1 bytes */ |
pkt = pack_hex_byte(pkt,threadcount) ; /* threadcount 2 bytes */ |
pkt = pack_threadid(pkt,nextthread) ; /* 64 bit thread identifier */ |
*pkt = '\0' ; |
return pkt ; |
} /* remote_threadlist_request */ |
|
|
|
|
/* ---------- PARSE_THREADLIST_RESPONSE ------------------------------------ */ |
/* Encoding: 'q':8,'M':8,count:16,done:8,argthreadid:64,(threadid:64)* */ |
|
int parse_threadlist_response( |
char * pkt, |
threadref * original_echo, |
threadref * resultlist, |
int * doneflag) |
{ |
char * limit ; |
int count, resultcount , done ; |
resultcount = 0 ; |
|
/* assume the 'q' and 'M chars have been stripped */ |
PKT_TRACE("parse-threadlist-response ",pkt) ; |
limit = pkt + (STUB_BUF_MAX - BUFTHREADIDSIZ) ; /* done parse past here */ |
pkt = unpack_byte(pkt,&count) ; /* count field */ |
pkt = unpack_nibble(pkt,&done) ; |
/* The first threadid is the argument threadid */ |
pkt = unpack_threadid(pkt,original_echo) ; /* should match query packet */ |
while ((count-- > 0) && (pkt < limit)) |
{ |
pkt = unpack_threadid(pkt,resultlist++) ; |
resultcount++ ; |
} |
if (doneflag) *doneflag = done ; |
return resultcount ; /* successvalue */ |
} /* parse_threadlist_response */ |
|
struct gdb_ext_thread_info |
{ |
threadref threadid ; |
int active ; |
char display[256] ; |
char shortname[32] ; |
char more_display[256] ; |
} ; |
|
|
/* ----- PACK_THREAD_INFO_REQUEST -------------------------------- */ |
|
/* |
threadid:1, # always request threadid |
context_exists:2, |
display:4, |
unique_name:8, |
more_display:16 |
*/ |
|
/* Encoding: 'Q':8,'P':8,mask:32,threadid:64 */ |
|
char * pack_threadinfo_request(char * pkt, |
int mode, |
threadref * id |
) |
{ |
*pkt++ = 'Q' ; |
*pkt++ = 'P' ; |
pkt = pack_int(pkt,mode) ; /* mode */ |
pkt = pack_threadid(pkt,id) ; /* threadid */ |
*pkt = '\0' ; /* terminate */ |
return pkt ; |
} /* pack_thread_info_request */ |
|
|
|
static char * unpack_string( |
char * src, |
char * dest, |
int length) |
{ |
while (length--) *dest++ = *src++ ; |
*dest = '\0' ; |
return src ; |
} /* unpack_string */ |
|
|
void output_threadid(char * title,threadref * ref) |
{ |
char hexid[20] ; |
pack_threadid(&hexid[0],ref) ; /* Convert threead id into hex */ |
hexid[16] = 0 ; |
output_string(title) ; |
output_string(&hexid[0]) ; |
output_string("\n") ; |
} |
|
/* ------ REMOTE_UPK_THREAD_INFO_RESPONSE ------------------------------- */ |
/* Unpack the response of a detailed thread info packet */ |
/* Encoding: i'Q':8,i'R':8,argmask:16,threadid:64,(tag:8,length:16,data:x)* */ |
|
#define TAG_THREADID 1 |
#define TAG_EXISTS 2 |
#define TAG_DISPLAY 4 |
#define TAG_THREADNAME 8 |
#define TAG_MOREDISPLAY 16 |
|
|
int remote_upk_thread_info_response( |
char * pkt, |
threadref * expectedref , |
struct gdb_ext_thread_info * info) |
{ |
int mask, length ; |
unsigned int tag ; |
threadref ref ; |
char * limit = pkt + 500 ; /* plausable parsing limit */ |
int retval = 1 ; |
|
PKT_TRACE("upk-threadinfo ",pkt) ; |
|
/* info->threadid = 0 ; FIXME: implement zero_threadref */ |
info->active = 0 ; |
info->display[0] = '\0' ; |
info->shortname[0] = '\0' ; |
info->more_display[0] = '\0' ; |
|
/* Assume the characters indicating the packet type have been stripped */ |
pkt = unpack_int(pkt,&mask) ; /* arg mask */ |
pkt = unpack_threadid(pkt , &ref) ; |
|
if (! threadmatch(&ref,expectedref)) |
{ /* This is an answer to a different request */ |
output_string("FAIL Thread mismatch\n") ; |
output_threadid("ref ",&ref) ; |
output_threadid("expected ",expectedref) ; |
return 0 ; |
} |
copy_threadref(&info->threadid,&ref) ; |
|
/* Loop on tagged fields , try to bail if somthing goes wrong */ |
if (mask==0) output_string("OOPS NO MASK \n") ; |
|
while ((pkt < limit) && mask && *pkt) /* packets are terminated with nulls */ |
{ |
pkt = unpack_int(pkt,&tag) ; /* tag */ |
pkt = unpack_byte(pkt,&length) ; /* length */ |
if (! (tag & mask)) /* tags out of synch with mask */ |
{ |
output_string("FAIL: threadinfo tag mismatch\n") ; |
retval = 0 ; |
break ; |
} |
if (tag == TAG_THREADID) |
{ |
output_string("unpack THREADID\n") ; |
if (length != 16) |
{ |
output_string("FAIL: length of threadid is not 16\n") ; |
retval = 0 ; |
break ; |
} |
pkt = unpack_threadid(pkt,&ref) ; |
mask = mask & ~ TAG_THREADID ; |
continue ; |
} |
if (tag == TAG_EXISTS) |
{ |
info->active = stub_unpack_int(pkt,length) ; |
pkt += length ; |
mask = mask & ~(TAG_EXISTS) ; |
if (length > 8) |
{ |
output_string("FAIL: 'exists' length too long\n") ; |
retval = 0 ; |
break ; |
} |
continue ; |
} |
if (tag == TAG_THREADNAME) |
{ |
pkt = unpack_string(pkt,&info->shortname[0],length) ; |
mask = mask & ~TAG_THREADNAME ; |
continue ; |
} |
if (tag == TAG_DISPLAY) |
{ |
pkt = unpack_string(pkt,&info->display[0],length) ; |
mask = mask & ~TAG_DISPLAY ; |
continue ; |
} |
if (tag == TAG_MOREDISPLAY) |
{ |
pkt = unpack_string(pkt,&info->more_display[0],length) ; |
mask = mask & ~TAG_MOREDISPLAY ; |
continue ; |
} |
output_string("FAIL: unknown info tag\n") ; |
break ; /* Not a tag we know about */ |
} |
return retval ; |
} /* parse-thread_info_response */ |
|
|
/* ---- REMOTE_PACK_CURRTHREAD_REQUEST ---------------------------- */ |
/* This is a request to emit the T packet */ |
|
/* FORMAT: 'q':8,'C' */ |
|
char * remote_pack_currthread_request(char * pkt ) |
{ |
*pkt++ = 'q' ; |
*pkt++ = 'C' ; |
*pkt = '\0' ; |
return pkt ; |
} /* remote_pack_currthread_request */ |
|
|
/* ------- REMOTE_UPK_CURTHREAD_RESPONSE ----------------------- */ |
/* Unpack the interesting part of a T packet */ |
|
|
int remote_upk_currthread_response( |
char * pkt, |
int *thr ) /* Parse a T packet */ |
{ |
int retval = 0 ; |
PKT_TRACE("upk-currthreadresp ",pkt) ; |
|
#if 0 |
{ |
static char threadtag[8] = "thread" ; |
int retval = 0 ; |
int i , found ; |
char ch ; |
int quickid ; |
|
/* Unpack as a t packet */ |
while (((ch = *pkt++) != ':') /* scan for : thread */ |
&& (ch != '\0')) /* stop at end of packet */ |
|
{ |
found = 0 ; |
i = 0 ; |
while ((ch = *pkt++) == threadtag[i++]) ; |
if (i == 8) /* string match "thread" */ |
{ |
pkt = unpack_varlen_hex(pkt,&quickid) ; |
retval = 1; |
break ; |
} |
retval = 0 ; |
} |
} |
#else |
pkt = unpack_threadid(pkt, thr) ; |
retval = 1 ; |
#endif |
return retval ; |
} /* remote_upk_currthread_response */ |
|
|
/* -------- REMOTE_UPK-SIMPLE_ACK --------------------------------- */ |
/* Decode a response which is eother "OK" or "Enn" |
fillin error code, fillin pkfag-1== undef, 0==nak, 1 == ack ; |
return advanced packet pointer */ |
|
|
char * remote_upk_simple_ack( |
char * buf, |
int * pkflag, |
int * errcode) |
{ |
int lclerr = 0 ; |
char ch = *buf++ ; |
int retval = -1 ; /* Undefined ACK , a protocol error */ |
if (ch == 'E') /* NAK */ |
{ |
buf = unpack_byte(buf,&lclerr) ; |
retval = 0 ; /* transaction failed, explicitly */ |
} |
else |
if ((ch == 'O') && (*buf++ == 'K')) /* ACK */ |
retval = 1 ; /* transaction succeeded */ |
*pkflag = retval ; |
*errcode = lclerr ; |
return buf ; |
} /* remote-upk_simple_ack */ |
|
|
/* -------- PACK_THREADALIVE_REQUEST ------------------------------- */ |
|
char * pack_threadalive_request( |
char * buf, |
threadref * threadid) |
{ |
*buf++ = 'T' ; |
buf = pack_threadid(buf,threadid) ; |
*buf = '\0' ; |
return buf ; |
} /* pack_threadalive_request */ |
|
#endif /* GDB_MOCKUP */ |
|
/* ---------------------------------------------------------------------- */ |
/* UNIT_TESTS SUBSECTION */ |
/* ---------------------------------------------------------------------- */ |
|
|
#if UNIT_TEST |
extern void output_string(char * message) ; |
static char test_req[400] ; |
static char t_response[400] ; |
|
|
|
/* ----- DISPLAY_THREAD_INFO ---------------------------------------------- */ |
/* Use local cygmon string output utiities */ |
|
void display_thread_info(struct gdb_ext_thread_info * info) |
{ |
|
output_threadid("Threadid: ",&info->threadid) ; |
/* short name */ |
output_string("Name: ") ; output_string(info->shortname) ; output_string("\n"); |
/* format display state */ |
output_string("State: ") ; output_string(info->display) ; output_string("\n") ; |
/* additional data */ |
output_string("other: ");output_string(info->more_display); |
output_string("\n\n"); |
} /* display_thread_info */ |
|
|
/* --- CURRTHREAD-TEST -------------------------------------------- */ |
static int currthread_test(threadref * thread) |
{ |
int result ; |
int threadid ; |
output_string("TEST: currthread\n") ; |
remote_pack_currthread_request(test_req) ; |
stub_pkt_currthread(test_req+2,t_response,STUB_BUF_MAX) ; |
result = remote_upk_currthread_response(t_response+2, &threadid) ; |
if (result) |
{ |
output_string("PASS getcurthread\n") ; |
/* FIXME: print the thread */ |
} |
else |
output_string("FAIL getcurrthread\n") ; |
return result ; |
} /* currthread_test */ |
|
/* ------ SETTHREAD_TEST ------------------------------------------- */ |
/* use a known thread from previous test */ |
|
static int setthread_test(threadref * thread) |
{ |
int result, errcode ; |
output_string("TEST: setthread\n") ; |
|
pack_setthread_request(test_req,'p',1,thread) ; |
stub_pkt_changethread(test_req,t_response,STUB_BUF_MAX) ; |
remote_upk_simple_ack(t_response,&result,&errcode) ; |
switch (result) |
{ |
case 0 : |
output_string("FAIL setthread\n") ; |
break ; |
case 1 : |
output_string("PASS setthread\n") ; |
break ; |
default : |
output_string("FAIL setthread -unrecognized response\n") ; |
break ; |
} |
return result ; |
} /* setthread_test */ |
|
|
/* ------ THREADACTIVE_TEST ---------------------- */ |
/* use known thread */ |
/* pack threadactive packet */ |
/* process threadactive packet */ |
/* parse threadactive response */ |
/* check results */ |
|
|
int threadactive_test(threadref * thread) |
{ |
int result ; |
int errcode ; |
output_string("TEST: threadactive\n") ; |
pack_threadalive_request(test_req,thread) ; |
stub_pkt_thread_alive(test_req+1,t_response,STUB_BUF_MAX); |
remote_upk_simple_ack(t_response,&result,&errcode) ; |
switch (result) |
{ |
case 0 : |
output_string("FAIL threadalive\n") ; |
break ; |
case 1 : |
output_string("PASS threadalive\n") ; |
break ; |
default : |
output_string("FAIL threadalive -unrecognized response\n") ; |
break ; |
} |
return result ; |
} /* threadactive_test */ |
|
/* ------ REMOTE_GET_THREADINFO -------------------------------------- */ |
int remote_get_threadinfo( |
threadref * threadid, |
int fieldset , /* TAG mask */ |
struct gdb_ext_thread_info * info |
) |
{ |
int result ; |
pack_threadinfo_request(test_req,fieldset,threadid) ; |
stub_pkt_getthreadinfo(test_req+2,t_response,STUB_BUF_MAX) ; |
result = remote_upk_thread_info_response(t_response+2,threadid,info) ; |
return result ; |
} /* remote_get-thrreadinfo */ |
|
|
static struct gdb_ext_thread_info test_info ; |
|
static int get_and_display_threadinfo(threadref * thread) |
{ |
int mode ; |
int result ; |
/* output_string("TEST: get and display threadinfo\n") ; */ |
|
mode = TAG_THREADID | TAG_EXISTS | TAG_THREADNAME |
| TAG_MOREDISPLAY | TAG_DISPLAY ; |
result = remote_get_threadinfo(thread,mode,&test_info) ; |
if (result) display_thread_info(&test_info) ; |
#if 0 /* silent subtest */ |
if (result) |
output_string("PASS: get_and_display threadinfo\n") ; |
else |
output_string("FAIL: get_and_display threadinfo\n") ; |
#endif |
return result ; |
} /* get-and-display-threadinfo */ |
|
|
|
/* ----- THREADLIST_TEST ------------------------------------------ */ |
#define TESTLISTSIZE 16 |
#define TLRSIZ 2 |
static threadref test_threadlist[TESTLISTSIZE] ; |
|
static int threadlist_test(void) |
{ |
int done, i , result_count ; |
int startflag = 1 ; |
int result = 1 ; |
int loopcount = 0 ; |
static threadref nextthread ; |
static threadref echo_nextthread ; |
|
output_string("TEST: threadlist\n") ; |
|
done = 0 ; |
while (! done) |
{ |
if (loopcount++ > 10) |
{ |
result = 0 ; |
output_string("FAIL: Threadlist test -infinite loop-\n") ; |
break ; |
} |
pack_threadlist_request(test_req,startflag,TLRSIZ,&nextthread) ; |
startflag = 0 ; /* clear for later iterations */ |
stub_pkt_getthreadlist(test_req+2,t_response,STUB_BUF_MAX); |
result_count = parse_threadlist_response(t_response+2, |
&echo_nextthread, |
&test_threadlist[0],&done) ; |
if (! threadmatch(&echo_nextthread,&nextthread)) |
{ |
output_string("FAIL: threadlist did not echo arg thread\n"); |
result = 0 ; |
break ; |
} |
if (result_count <= 0) |
{ |
if (done != 0) |
{ output_string("FAIL threadlist_test, failed to get list"); |
result = 0 ; |
} |
break ; |
} |
if (result_count > TLRSIZ) |
{ |
output_string("FAIL: threadlist response longer than requested\n") ; |
result = 0 ; |
break ; |
} |
/* Setup to resume next batch of thread references , set nestthread */ |
copy_threadref(&nextthread,&test_threadlist[result_count-1]) ; |
/* output_threadid("last-of-batch",&nextthread) ; */ |
i = 0 ; |
while (result_count--) |
{ |
if (0) /* two display alternatives */ |
output_threadid("truncatedisplay",&test_threadlist[i++]) ; |
else |
get_and_display_threadinfo(&test_threadlist[i++]) ; |
} |
|
} |
if (!result) |
output_string("FAIL: threadlist test\n") ; |
else output_string("PASS: Threadlist test\n") ; |
return result ; |
} /* threadlist_test */ |
|
|
static threadref testthread ; |
|
|
int test_thread_support(void) |
{ |
int result = 1 ; |
output_string("TESTING Thread support infrastructure\n") ; |
stub_pack_Tpkt_threadid(test_req) ; |
PKT_TRACE("packing the threadid -> ",test_req) ; |
result &= currthread_test(&testthread) ; |
result &= get_and_display_threadinfo(&testthread) ; |
result &= threadlist_test() ; |
result &= setthread_test(&testthread) ; |
if (result) |
output_string("PASS: UNITTEST Thread support\n") ; |
else |
output_string("FAIL: UNITTEST Thread support\n") ; |
return result ; |
} /* test-thread_support */ |
#endif /* UNIT_TEST */ |
|
// #ifdef __ECOS__ |
#endif // ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT... |
// #endif // __ECOS__ |
/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(®isters[0], _hal_registers); |
_registers = ®isters[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 = ®isters[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, ®isters[0]); |
|
interruptible(1); |
} |
|
|
//----------------------------------------------------------------------------- |
// Initialization. |
|
// Signal handler. |
int |
cyg_hal_process_signal (int signal) |
{ |
// We don't care about the signal (atm). |
return 0; |
} |
|
// Install the standard set of trap handlers for the stub. |
void |
__install_traps (void) |
{ |
// Set signal handling vector so we can treat 'C<signum>' as 'c'. |
__process_signal_vec = &cyg_hal_process_signal; |
__process_exit_vec = &handle_exception_exit; |
|
__cleanup_vec = &handle_exception_cleanup; |
__init_vec = &handle_exception_init; |
|
#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away |
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT |
// Control of GDB interrupts. |
__interruptible_control = HAL_STUB_PLATFORM_INTERRUPTIBLE; |
#endif |
#endif |
|
// Nothing further to do, handle_exception will be called when an |
// exception occurs. |
} |
|
// Initialize the hardware. |
void |
initHardware (void) |
{ |
static int initialized = 0; |
|
if (initialized) |
return; |
initialized = 1; |
|
// Get serial port initialized. |
HAL_STUB_PLATFORM_INIT_SERIAL(); |
|
#ifdef HAL_STUB_PLATFORM_INIT |
// If the platform defines any initialization code, call it here. |
HAL_STUB_PLATFORM_INIT(); |
#endif |
|
#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this should go away |
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT |
// Get interrupt handler initialized. |
HAL_STUB_PLATFORM_INIT_BREAK_IRQ(); |
#endif |
#endif // !CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT |
} |
|
// Reset the board. |
void |
__reset (void) |
{ |
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT |
__call_if_reset_t *__rom_reset = CYGACC_CALL_IF_RESET_GET(); |
if (__rom_reset) |
(*__rom_reset)(); |
#else |
HAL_PLATFORM_RESET(); |
#endif |
} |
|
//----------------------------------------------------------------------------- |
// Breakpoint support. |
|
#ifndef CYGPKG_HAL_ARM |
// This function will generate a breakpoint exception. It is used at |
// the beginning of a program to sync up with a debugger and can be |
// used otherwise as a quick means to stop program execution and |
// "break" into the debugger. |
void |
breakpoint() |
{ |
HAL_BREAKPOINT(_breakinst); |
} |
|
// This function returns the opcode for a 'trap' instruction. |
unsigned long |
__break_opcode () |
{ |
return HAL_BREAKINST; |
} |
#endif |
|
//----------------------------------------------------------------------------- |
// Write the 'T' packet in BUFFER. SIGVAL is the signal the program received. |
void |
__build_t_packet (int sigval, char *buf) |
{ |
target_register_t addr; |
char *ptr = buf; |
target_register_t extend_val = 0; |
|
*ptr++ = 'T'; |
*ptr++ = __tohex (sigval >> 4); |
*ptr++ = __tohex (sigval); |
|
#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT |
// Include thread ID if thread manipulation is required. |
{ |
int id = dbg_currthread_id (); |
|
if (id != 0) { |
*ptr++ = 't'; |
*ptr++ = 'h'; |
*ptr++ = 'r'; |
*ptr++ = 'e'; |
*ptr++ = 'a'; |
*ptr++ = 'd'; |
*ptr++ = ':'; |
|
#if (CYG_BYTEORDER == CYG_LSBFIRST) |
// FIXME: Temporary workaround for PR 18903. Thread ID must be |
// big-endian in the T packet. |
{ |
unsigned char* bep = (unsigned char*)&id; |
int be_id; |
|
be_id = id; |
*bep++ = (be_id >> 24) & 0xff ; |
*bep++ = (be_id >> 16) & 0xff ; |
*bep++ = (be_id >> 8) & 0xff ; |
*bep++ = (be_id & 0xff) ; |
} |
#endif |
ptr = __mem2hex((char *)&id, ptr, sizeof(id), 0); |
*ptr++ = ';'; |
} |
} |
#endif |
|
#ifdef HAL_STUB_HW_WATCHPOINT |
switch(_hw_stop_reason) { |
case HAL_STUB_HW_STOP_WATCH: |
case HAL_STUB_HW_STOP_RWATCH: |
case HAL_STUB_HW_STOP_AWATCH: |
#ifdef HAL_STUB_HW_SEND_STOP_REASON_TEXT |
// Not all GDBs understand this. |
strcpy(ptr, _hw_stop_str[_hw_stop_reason]); |
ptr += strlen(_hw_stop_str[_hw_stop_reason]); |
#endif |
*ptr++ = ':'; |
// Send address MSB first |
ptr += __intToHex(ptr, (target_register_t)_watch_data_addr, |
sizeof(_watch_data_addr) * 8); |
*ptr++ = ';'; |
break; |
default: |
break; |
} |
#endif |
|
*ptr++ = __tohex (PC >> 4); |
*ptr++ = __tohex (PC); |
*ptr++ = ':'; |
addr = get_register (PC); |
if (sizeof(addr) < REGSIZE(PC)) |
{ |
// GDB is expecting REGSIZE(PC) number of bytes. |
// We only have sizeof(addr) number. Let's fill |
// the appropriate number of bytes intelligently. |
#ifdef CYGARC_SIGN_EXTEND_REGISTERS |
{ |
unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 |
target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); |
if ((addr & sign_bit_mask) == sign_bit_mask) |
extend_val = ~0; |
} |
#endif |
} |
#if (CYG_BYTEORDER == CYG_MSBFIRST) |
ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0); |
#endif |
ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); |
#if (CYG_BYTEORDER == CYG_LSBFIRST) |
ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(PC) - sizeof(addr), 0); |
#endif |
*ptr++ = ';'; |
|
*ptr++ = __tohex (SP >> 4); |
*ptr++ = __tohex (SP); |
*ptr++ = ':'; |
addr = (target_register_t) get_register (SP); |
if (sizeof(addr) < REGSIZE(SP)) |
{ |
// GDB is expecting REGSIZE(SP) number of bytes. |
// We only have sizeof(addr) number. Let's fill |
// the appropriate number of bytes intelligently. |
extend_val = 0; |
#ifdef CYGARC_SIGN_EXTEND_REGISTERS |
{ |
unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 |
target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); |
if ((addr & sign_bit_mask) == sign_bit_mask) |
extend_val = ~0; |
} |
#endif |
ptr = __mem2hex((char *)&extend_val, ptr, REGSIZE(SP) - sizeof(addr), 0); |
} |
ptr = __mem2hex((char *)&addr, ptr, sizeof(addr), 0); |
*ptr++ = ';'; |
|
HAL_STUB_ARCH_T_PACKET_EXTRAS(ptr); |
|
*ptr++ = 0; |
} |
|
|
//----------------------------------------------------------------------------- |
// Cache functions. |
|
// Perform the specified operation on the instruction cache. |
// Returns 1 if the cache is enabled, 0 otherwise. |
int |
__instruction_cache (cache_control_t request) |
{ |
int state = 1; |
|
switch (request) { |
case CACHE_ENABLE: |
HAL_ICACHE_ENABLE(); |
break; |
case CACHE_DISABLE: |
HAL_ICACHE_DISABLE(); |
state = 0; |
break; |
case CACHE_FLUSH: |
HAL_ICACHE_SYNC(); |
break; |
case CACHE_NOOP: |
/* fall through */ |
default: |
break; |
} |
|
#ifdef HAL_ICACHE_IS_ENABLED |
HAL_ICACHE_IS_ENABLED(state); |
#endif |
|
return state; |
} |
|
// Perform the specified operation on the data cache. |
// Returns 1 if the cache is enabled, 0 otherwise. |
int |
__data_cache (cache_control_t request) |
{ |
int state = 1; |
|
switch (request) { |
case CACHE_ENABLE: |
HAL_DCACHE_ENABLE(); |
break; |
case CACHE_DISABLE: |
HAL_DCACHE_DISABLE(); |
state = 0; |
break; |
case CACHE_FLUSH: |
HAL_DCACHE_SYNC(); |
break; |
case CACHE_NOOP: |
/* fall through */ |
default: |
break; |
} |
#ifdef HAL_DCACHE_IS_ENABLED |
HAL_DCACHE_IS_ENABLED(state); |
#endif |
|
return state; |
} |
|
//----------------------------------------------------------------------------- |
// Memory accessor functions. |
|
// The __mem_fault_handler pointer is volatile since it is only |
// set/cleared by the function below - which does not rely on any |
// other functions, so the compiler may decide to not bother updating |
// the pointer at all. If any of the memory accesses cause an |
// exception, the pointer must be set to ensure the exception handler |
// can make use of it. |
|
void* volatile __mem_fault_handler = (void *)0; |
|
/* These are the "arguments" to __do_read_mem and __do_write_mem, |
which are passed as globals to avoid squeezing them thru |
__set_mem_fault_trap. */ |
|
static volatile target_register_t memCount; |
|
static void |
__do_copy_mem (unsigned char* src, unsigned char* dst) |
{ |
unsigned long *long_dst; |
unsigned long *long_src; |
unsigned short *short_dst; |
unsigned short *short_src; |
|
// Zero memCount is not really an error, but the goto is necessary to |
// keep some compilers from reordering stuff across the 'err' label. |
if (memCount == 0) goto err; |
|
__mem_fault = 1; /* Defaults to 'fail'. Is cleared */ |
/* when the copy loop completes. */ |
__mem_fault_handler = &&err; |
|
// See if it's safe to do multi-byte, aligned operations |
while (memCount) { |
if ((memCount >= sizeof(long)) && |
(((target_register_t)dst & (sizeof(long)-1)) == 0) && |
(((target_register_t)src & (sizeof(long)-1)) == 0)) { |
|
long_dst = (unsigned long *)dst; |
long_src = (unsigned long *)src; |
|
*long_dst++ = *long_src++; |
memCount -= sizeof(long); |
|
dst = (unsigned char *)long_dst; |
src = (unsigned char *)long_src; |
} else if ((memCount >= sizeof(short)) && |
(((target_register_t)dst & (sizeof(short)-1)) == 0) && |
(((target_register_t)src & (sizeof(short)-1)) == 0)) { |
|
short_dst = (unsigned short *)dst; |
short_src = (unsigned short *)src; |
|
*short_dst++ = *short_src++; |
memCount -= sizeof(short); |
|
dst = (unsigned char *)short_dst; |
src = (unsigned char *)short_src; |
} else { |
*dst++ = *src++; |
memCount--; |
} |
} |
|
__mem_fault = 0; |
|
err: |
__mem_fault_handler = (void *)0; |
} |
|
/* |
* __read_mem_safe: |
* Get contents of target memory, abort on error. |
*/ |
|
int |
__read_mem_safe (void *dst, void *src, int count) |
{ |
if( !CYG_HAL_STUB_PERMIT_DATA_READ( src, count ) ) |
return 0; |
|
memCount = count; |
__do_copy_mem((unsigned char*) src, (unsigned char*) dst); |
return count - memCount; // return number of bytes successfully read |
} |
|
/* |
* __write_mem_safe: |
* Set contents of target memory, abort on error. |
*/ |
|
int |
__write_mem_safe (void *src, void *dst, int count) |
{ |
if( !CYG_HAL_STUB_PERMIT_DATA_READ( dst, count ) ) |
return 0; |
|
memCount = count; |
__do_copy_mem((unsigned char*) src, (unsigned char*) dst); |
return count - memCount; // return number of bytes successfully written |
} |
|
#ifdef TARGET_HAS_HARVARD_MEMORY |
static void |
__do_copy_from_progmem (unsigned char* src, unsigned char* dst) |
{ |
unsigned long *long_dst; |
unsigned long *long_src; |
unsigned short *short_dst; |
unsigned short *short_src; |
|
// Zero memCount is not really an error, but the goto is necessary to |
// keep some compilers from reordering stuff across the 'err' label. |
if (memCount == 0) goto err; |
|
__mem_fault = 1; /* Defaults to 'fail'. Is cleared */ |
/* when the copy loop completes. */ |
__mem_fault_handler = &&err; |
|
// See if it's safe to do multi-byte, aligned operations |
while (memCount) { |
if ((memCount >= sizeof(long)) && |
(((target_register_t)dst & (sizeof(long)-1)) == 0) && |
(((target_register_t)src & (sizeof(long)-1)) == 0)) { |
|
long_dst = (unsigned long *)dst; |
long_src = (unsigned long *)src; |
|
*long_dst++ = __read_prog_uint32(long_src++); |
memCount -= sizeof(long); |
|
dst = (unsigned char *)long_dst; |
src = (unsigned char *)long_src; |
} else if ((memCount >= sizeof(short)) && |
(((target_register_t)dst & (sizeof(short)-1)) == 0) && |
(((target_register_t)src & (sizeof(short)-1)) == 0)) { |
|
short_dst = (unsigned short *)dst; |
short_src = (unsigned short *)src; |
|
*short_dst++ = __read_prog_uint16(short_src++); |
memCount -= sizeof(short); |
|
dst = (unsigned char *)short_dst; |
src = (unsigned char *)short_src; |
} else { |
*dst++ = __read_prog_uint8(src++); |
memCount--; |
} |
} |
|
__mem_fault = 0; |
|
err: |
__mem_fault_handler = (void *)0; |
} |
|
static void |
__do_copy_to_progmem (unsigned char* src, unsigned char* dst) |
{ |
unsigned long *long_dst; |
unsigned long *long_src; |
unsigned short *short_dst; |
unsigned short *short_src; |
|
// Zero memCount is not really an error, but the goto is necessary to |
// keep some compilers from reordering stuff across the 'err' label. |
if (memCount == 0) goto err; |
|
__mem_fault = 1; /* Defaults to 'fail'. Is cleared */ |
/* when the copy loop completes. */ |
__mem_fault_handler = &&err; |
|
// See if it's safe to do multi-byte, aligned operations |
while (memCount) { |
if ((memCount >= sizeof(long)) && |
(((target_register_t)dst & (sizeof(long)-1)) == 0) && |
(((target_register_t)src & (sizeof(long)-1)) == 0)) { |
|
long_dst = (unsigned long *)dst; |
long_src = (unsigned long *)src; |
|
__write_prog_uint32(long_dst++, *long_src++); |
memCount -= sizeof(long); |
|
dst = (unsigned char *)long_dst; |
src = (unsigned char *)long_src; |
} else if ((memCount >= sizeof(short)) && |
(((target_register_t)dst & (sizeof(short)-1)) == 0) && |
(((target_register_t)src & (sizeof(short)-1)) == 0)) { |
|
short_dst = (unsigned short *)dst; |
short_src = (unsigned short *)src; |
|
__write_prog_uint16(short_dst++, *short_src++); |
memCount -= sizeof(short); |
|
dst = (unsigned char *)short_dst; |
src = (unsigned char *)short_src; |
} else { |
__write_prog_uint8(dst++, *src++); |
memCount--; |
} |
} |
|
__mem_fault = 0; |
|
err: |
__mem_fault_handler = (void *)0; |
} |
|
/* |
* __read_progmem_safe: |
* Get contents of target memory, abort on error. |
*/ |
|
int |
__read_progmem_safe (void *dst, void *src, int count) |
{ |
if( !CYG_HAL_STUB_PERMIT_CODE_READ( src, count ) ) |
return 0; |
|
memCount = count; |
__do_copy_from_progmem((unsigned char*) src, (unsigned char*) dst); |
return count - memCount; // return number of bytes successfully read |
} |
|
/* |
* __write_progmem_safe: |
* Set contents of target memory, abort on error. |
*/ |
|
int |
__write_progmem_safe (void *src, void *dst, int count) |
{ |
if( !CYG_HAL_STUB_PERMIT_CODE_WRITE( dst, count ) ) |
return 0; |
|
memCount = count; |
__do_copy_to_progmem((unsigned char*) src, (unsigned char*) dst); |
return count - memCount; // return number of bytes successfully written |
} |
#endif |
|
//----------------------------------------------------------------------------- |
// Target extras?! |
int |
__process_target_query(char * pkt, char * out, int maxOut) |
{ return 0 ; } |
int |
__process_target_set(char * pkt, char * out, int maxout) |
{ return 0 ; } |
int |
__process_target_packet(char * pkt, char * out, int maxout) |
{ return 0 ; } |
|
// GDB string output, making sure interrupts are disabled. |
// This function gets used by some diag output functions. |
void |
hal_output_gdb_string(target_register_t str, int string_len) |
{ |
unsigned long __state; |
HAL_DISABLE_INTERRUPTS(__state); |
__output_gdb_string(str, string_len); |
HAL_RESTORE_INTERRUPTS(__state); |
} |
|
#endif // CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS |
/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, ®no)) |
{ |
sr = regno; |
er = regno + 1; |
} |
else |
{ |
strcpy (ptr, "INVALID"); |
return; |
} |
} |
|
for (regnum = sr; regnum < er; regnum++) |
{ |
/* We need to compensate for the value offset within the |
register. */ |
char dummyDat[32]; |
target_register_t addr; |
char *vptr; |
int reg_valid = 1; |
|
#ifdef TARGET_HAS_LARGE_REGISTERS |
if (sizeof (target_register_t) < REGSIZE (regnum)) { |
get_register_as_bytes (regnum, dummyDat); |
vptr = dummyDat; |
} else |
#endif |
{ |
if (_get_trace_register_hook) |
reg_valid = _get_trace_register_hook (regnum, &addr); |
else |
{ |
addr = get_register (regnum); |
#ifdef CYGHWR_REGISTER_VALIDITY_CHECKING |
reg_valid = get_register_valid (regnum); |
#endif |
} |
vptr = ((char *) &addr); |
if (sizeof (addr) > REGSIZE(regnum)) { |
/* May need to cope with endian-ness */ |
|
#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN) |
vptr += sizeof (addr) - REGSIZE (regnum); |
#endif |
} else if (sizeof (addr) < REGSIZE (regnum)) { |
int off = REGSIZE (regnum) - sizeof (addr); |
int x; |
char extend_val = 0; |
|
#ifdef CYGARC_SIGN_EXTEND_REGISTERS |
{ |
unsigned long bits_in_addr = (sizeof(addr) << 3); // ie Size in bytes * 8 |
target_register_t sign_bit_mask = (1 << (bits_in_addr - 1)); |
if ((addr & sign_bit_mask) == sign_bit_mask) |
extend_val = ~0; |
} |
#endif |
|
#if defined(__LITTLE_ENDIAN__) || defined(_LITTLE_ENDIAN) |
for (x = 0; x < off; x++) |
dummyDat[x + sizeof(addr)] = extend_val; |
_memcpy (dummyDat, &addr, sizeof (addr)); |
#else |
for (x = 0; x < off; x++) |
dummyDat[x] = extend_val; |
_memcpy (dummyDat + off, &addr, sizeof (addr)); |
#endif |
vptr = dummyDat; |
} |
} |
if (reg_valid) { /* we have a valid reg value */ |
ptr = __mem2hex (vptr, ptr, REGSIZE (regnum), 0); |
} else { |
/* Trace component returned a failure code. |
This means that the register value is not available. |
We'll fill it with 'x's, and GDB will understand. */ |
_memset (ptr, 'x', 2 * REGSIZE (regnum)); |
ptr += 2 * REGSIZE (regnum); |
} |
} |
} |
|
void |
stub_update_registers(char *in_ptr, char *out_ptr) |
{ |
char *ptr = &in_ptr[1]; |
int x; |
int sr = 0, er = NUMREGS_GDB; |
|
if (*in_ptr == 'P') { |
target_register_t regno; |
|
if (__hexToInt (&ptr, ®no) && (*ptr++ == '=')) { |
|
sr = regno; |
er = regno + 1; |
} else { |
strcpy (out_ptr, "P01"); |
return; |
} |
} |
|
for (x = sr; x < er; x++) { |
target_register_t value = 0; |
char *vptr; |
|
#ifdef TARGET_HAS_LARGE_REGISTERS |
if (sizeof (target_register_t) < REGSIZE (x)) { |
char dummyDat [32]; |
|
__hex2mem (ptr, dummyDat, REGSIZE (x), 0); |
put_register_as_bytes (x, dummyDat); |
} else |
#endif |
{ |
vptr = ((char *) &value); |
#if !defined(__LITTLE_ENDIAN__) && !defined(_LITTLE_ENDIAN) |
vptr += sizeof (value) - REGSIZE (x); |
#endif |
__hex2mem (ptr, vptr, REGSIZE (x), 0); |
put_register (x, value); |
} |
ptr += REGSIZE (x) * 2; |
} |
|
strcpy (out_ptr, "OK"); |
} |
|
int |
__process_packet (char *packet) |
{ |
int is_binary = 0; |
#if defined(CYGNUM_HAL_BREAKPOINT_LIST_SIZE) |
int is_Z = 0; |
#endif |
|
__remcomOutBuffer[0] = 0; |
switch (packet[0]) |
{ |
case '?': |
{ |
int sigval = __computeSignal (__get_trap_number ()); |
__remcomOutBuffer[0] = 'S'; |
__remcomOutBuffer[1] = hexchars[(sigval >> 4) & 0xf]; |
__remcomOutBuffer[2] = hexchars[sigval & 0xf]; |
__remcomOutBuffer[3] = 0; |
break; |
} |
|
#ifdef __ECOS__ |
#if !defined(CYG_HAL_STARTUP_RAM) // Only for ROM based stubs |
#if 0 // Disable to avoid conflict with stub-breakpoint z/Z-packets |
case 'z': |
/* report IO buffer sizes so download can achieve optimal |
download speed */ |
{ |
int i; |
i = __intToHex (__remcomOutBuffer, BUFMAX, 32); |
__remcomOutBuffer[i] = 0; |
break; |
} |
#endif |
case 'd': |
/* toggle debug flag */ |
strcpy(__remcomOutBuffer, GDB_stubs_version); |
break; |
#endif |
#endif // __ECOS__ |
|
case 'q': |
/* general query packet */ |
process_query (&packet[1]); |
break; |
|
case 'Q': |
/* general set packet */ |
process_set (&packet[1]); |
break; |
|
case 'p': /* return the value of a single CPU register */ |
case 'g': /* return the value of the CPU registers */ |
{ |
stub_format_registers(&packet[0], __remcomOutBuffer); |
break; |
} |
|
case 'A': /* set program arguments */ |
{ |
#ifdef CYGSEM_ECOS_SUPPORTS_PROGRAM_ARGS |
if (packet[1] == '\0') |
{ |
__free_program_args (); |
strcpy (__remcomOutBuffer, "OK"); |
} |
else |
{ |
target_register_t arglen, argnum; |
char *ptr = &packet[1]; |
|
while (1) |
{ |
if (__hexToInt (&ptr, &arglen) |
&& (*ptr++ == ',') |
&& __hexToInt (&ptr, &argnum) |
&& (*ptr++ == ',')) |
{ |
if (arglen > 0) |
{ |
char *s = __add_program_arg (argnum, arglen); |
if (s != NULL) |
{ |
__hex2mem (ptr, s, arglen, 0); |
} |
ptr += arglen * 2; |
} |
|
if (*ptr == ',') |
ptr++; |
else |
break; |
} |
else |
break; |
} |
if (*ptr == '\0') |
strcpy (__remcomOutBuffer, "OK"); |
else |
strcpy (__remcomOutBuffer, "E01"); |
} |
#else |
strcpy (__remcomOutBuffer, "E01"); |
#endif |
} |
break; |
|
case 'P': |
case 'G': /* set the value of the CPU registers - return OK */ |
{ |
char *in_ptr = &packet[0]; |
char *out_ptr = __remcomOutBuffer; |
stub_update_registers(in_ptr, out_ptr); |
break; |
} |
|
case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ |
/* Try to read %x,%x. */ |
{ |
target_register_t length; |
char *ptr = &packet[1]; |
target_addr_t addr; |
|
if (__hexToAddr (&ptr, &addr) |
&& *ptr++ == ',' |
&& __hexToInt (&ptr, &length)) |
{ |
if (__mem2hex_safe (addr, __remcomOutBuffer, length)) |
break; |
|
strcpy (__remcomOutBuffer, "E03"); |
} |
else |
strcpy (__remcomOutBuffer, "E01"); |
break; |
} |
|
case 'X': |
/* XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA */ |
is_binary = 1; |
/* fall through */ |
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ |
/* Try to read '%x,%x:'. */ |
{ |
target_register_t length; |
char *ptr = &packet[1], buf[128]; |
int i; |
target_addr_t addr; |
|
if (__hexToAddr (&ptr, &addr) |
&& *ptr++ == ',' |
&& __hexToInt (&ptr, &length) |
&& *ptr++ == ':') |
{ |
/* GDB sometimes sends an impossible length */ |
if (length < 0 || length >= BUFMAX) |
strcpy (__remcomOutBuffer, "E01"); |
|
else if (is_binary) |
{ |
while (length > 0) |
{ |
for (i = 0; i < sizeof(buf) && i < length; i++) |
if ((buf[i] = *ptr++) == 0x7d) |
buf[i] = 0x20 | (*ptr++ & 0xff); |
|
#ifdef TARGET_HAS_HARVARD_MEMORY |
if (TARGET_ADDR_IS_PROGMEM(addr)) { |
if (__write_progmem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i) |
break; |
} else |
#endif |
if (__write_mem_safe (buf, (void *)TARGET_ADDR_TO_PTR(addr), i) != i) |
break; |
|
|
length -= i; |
addr += i; |
} |
if (length <= 0) |
strcpy (__remcomOutBuffer, "OK"); |
else |
strcpy (__remcomOutBuffer, "E03"); |
} |
else |
{ |
if (__hex2mem_safe (ptr, addr, length) != NULL) |
strcpy (__remcomOutBuffer, "OK"); |
else |
strcpy (__remcomOutBuffer, "E03"); |
} |
} |
else |
strcpy (__remcomOutBuffer, "E02"); |
break; |
} |
|
case 'S': |
case 's': /* sAA..AA Step from address AA..AA (optional) */ |
case 'C': |
case 'c': /* cAA..AA Continue at address AA..AA (optional) */ |
/* try to read optional parameter, pc unchanged if no parm */ |
|
{ |
char *ptr = &packet[1]; |
target_addr_t addr; |
target_register_t sigval = 0; |
|
if (packet[0] == 'C' || packet[0] == 'S') |
{ |
__hexToInt (&ptr, &sigval); |
if (*ptr == ';') |
ptr++; |
} |
|
if (__hexToAddr (&ptr, &addr)) |
set_pc ((target_register_t)TARGET_ADDR_TO_PTR(addr)); |
|
/* Need to flush the instruction cache here, as we may have |
deposited a breakpoint, and the icache probably has no way of |
knowing that a data ref to some location may have changed |
something that is in the instruction cache. */ |
|
#ifdef __ECOS__ |
__data_cache (CACHE_FLUSH) ; |
#endif |
__instruction_cache (CACHE_FLUSH) ; |
|
/* If we have a function to handle signals, call it. */ |
if (sigval != 0 && __process_signal_vec != NULL) |
{ |
/* If 0 is returned, we either ignored the signal or invoked a user |
handler. Otherwise, the user program should die. */ |
if (! __process_signal_vec (sigval)) |
sigval = 0; |
} |
|
if (sigval != 0) |
{ |
sigval = SIGKILL; /* Always nuke the program */ |
__kill_program (sigval); |
return 0; |
} |
|
#ifdef __ECOS__ |
// CASE 102327 - watchpoints fight with output, so do not step |
// through $O packet output routines. |
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT |
if ( cyg_hal_gdb_break_is_set() ) { |
packet[0] = 'c'; // Force it to be a "continue" instead of step. |
cyg_hal_gdb_running_step = 1; // And tell the hal_stub... |
} |
#endif |
#endif |
|
/* Set machine state to force a single step. */ |
if (packet[0] == 's' || packet[0] == 'S') |
{ |
lock_thread_scheduler (0); /* 0 == single-step */ |
#ifdef __ECOS__ |
// PR 19845 workaround: |
// Make sure the single-step magic affects the correct registers. |
_registers = ®isters[0]; |
#endif |
__single_step (); |
} |
else |
{ |
lock_thread_scheduler (1); /* 1 == continue */ |
} |
|
#ifdef __ECOS__ |
/* Need to flush the data and instruction cache here, as we may have |
deposited a breakpoint in __single_step. */ |
|
__data_cache (CACHE_FLUSH) ; |
__instruction_cache (CACHE_FLUSH) ; |
hal_flush_output(); |
#endif |
|
return -1; |
} |
|
case 'D' : /* detach */ |
__putpacket (__remcomOutBuffer); |
/* fall through */ |
case 'k' : /* kill the program */ |
#ifdef __ECOS__ |
hal_flush_output(); |
#endif |
#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#### |
//=========================================================================== |