M68000 Architectural SupportOverviewOvervieweCos Support for the M68K Family of ProcessorsDescription
The original Motorola 68000 processor was released in 1979, and
featured the following:
Eight general purpose 32-bit data registers, %D0 to %D7. Seven 32-bit
address registers %A0 to %A6, with %A7 dedicated as the stack pointer.
A 16-bit status register.
A linear address space, limited to 24-bits because the chip package
only had 24 address pins. Hence the processor could address 16
megabytes of memory.
No separate address space for I/O operations. Instead devices are
accessed just like memory via the main address and data buses.
16-bit external data bus, even though the data registers were 32 bits
wide.
A CISC variable-length instruction set with no less than 14 different
addressing modes (although of course the terms RISC and CISC were not
yet in common use).
Separate supervisor and user modes. The processor actually has two
distinct stack pointer registers %A7, and the mode determines which one
gets used.
An interrupt subsystem with support for vectored and prioritized
interrupts.
The 68000 processor was used in several microcomputers of its time,
including the original Apple Macintosh, the Commodore Amiga, and the
Atari ST. Over the years numerous variants have been developed. The
core instruction set has remained essentially unchanged. Some of the
variants have additional instructions. The development of MMUs led to
changes in exception handling. In more recent variants, notably the
Freescale ColdFire family, some infrequently used instructions and
addressing modes have been removed.
The 68008 reduced the widths of the external data and address buses to
8 bits and 20 bits respectively, giving the processor slow access to
only one megabyte.
The 68010 (1982) added virtual memory support.
In the 68020 (1984) both the address and data buses were made 32-bits wide. A
256-byte instruction cache was added, as were some new instructions
and addressing modes.
The 68030 (1987) included an on-chip mmu and a 256-byte data cache.
The 68040 (1991) added hardware floating point (previous processors relied on
an external coprocessor or on software emulation). It also had larger
caches and an improved mmu.
The 68060 (1994) involved an internally very different superscalar
implementation of the architecture, but few changes at the interface
level. It also contained support for power management.
There have been numerous 683xx variants for embedded use, with
on-chip peripherals like UARTs and timers. The cpu core of these
variants is also known as cpu32.
The MCFxxxx ColdFire series (1995) resembles a stripped-down 68060,
with some instructions and addressing modes removed to allow for a
much smaller and more efficient implementation. Various hardware units
such as the and FPU and MMU have become optional.
eCos only provides support for some of these variants, although it
should be possible to add support for additional variants with few or
no changes to the architectural HAL package.
The architectural HAL provides support for those features which are
common to all members of the 68000 and ColdFire families, and for
certain features which are present on some but not all members. A
typical eCos configuration will also contain: a variant HAL package
with support code for a family of processors, for example MCFxxxx;
possibly a processor HAL package with support for one specific
processor, for example the MCF5272; and a platform HAL
which contains the code needed for a specific hardware platform such
as the m5272c3.
ConfigurationOptionsConfiguring the M68K Architectural PackageLoading and Unloading the Package
The M68K architectural HAL package CYGPKG_HAL_M68K
should be loaded automatically when eCos is configured for M68K-based
target hardware. It should never be necessary to load this package
explicitly. Unloading the package should only happen as a side effect
of switching target hardware. CYGPKG_HAL_M68K
serves primarily as a container for lower-level HALs and has only a
small number of configuration options.
Stacks
By default the architectural HAL provides a single block of memory to
act as both the startup stack and the interrupt stack. The variant,
processor or platform HAL may override this. For example if there are
several banks of RAM with different performance characteristics it may
be desirable to place the interrupt stack in fast RAM rather than in
ordinary RAM.
The assembler startup code sets the stack pointer to the startup stack
before switching to C code. This stack used for all HAL
initialization, running any C++ static constructors defined either by
eCos or by the application, and the cyg_start
entry point. In configurations containing the eCos kernel
cyg_start will enable interrupts, activate the
scheduler and threads will then run on their own stacks. In non-kernel
single-threaded applications the whole system continues to run on the
startup stack.
When an interrupt occurs the default behaviour is to switch to a
separate interrupt stack. This behaviour is controlled by the common
HAL configuration option
CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK.
It reduces the stack requirements of all threads in the system, at the
cost of some extra instructions during interrupt handling. In kernel
configurations the startup stack is no longer used once the scheduler
starts running so its memory can be reused for the interrupt stack. To
handle the possibility of nested interrupts the interrupt handling
code will detect if it is already on the interrupt stack, so in
non-kernel configurations it is also safe to use the same area of
memory for both startup and interrupt stacks. This leads to the
following scenarios:
If interrupt stacks are enabled via
CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
and the interrupt stack is not provided by the variant, processor or
platform HAL then a single block of memory will be used for both
startup and interrupt stacks. The size of this block is determined by
the common HAL configuration option
CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE, with a
default value
CYGNUM_HAL_DEFAULT_INTERRUPT_STACK_SIZE provided by
the M68K architectural HAL.
If the use of an interrupt stack is disabled then the M68K
architectural HAL will provide just the startup stack, unless this is
done by the variant, processor or platform HAL. The size of the
startup stack is controlled by
CYGNUM_HAL_M68K_STARTUP_STACK_SIZE.
Otherwise the interrupt and/or startup stacks are provided by other
packages and it is up to those packages to provide configuration
options for setting the sizes.
Floating Point Support
There are many variants of the basic M68K architecture. Some of these
have hardware floating point support. Originally this came in the form
of a separate 68881 coprocessor, but with modern variants it will be
part of the main processor chip. If the processor does not have
hardware floating point then software emulation will be used instead.
If the processor on the target hardware has a floating point unit then
the variant or processor HAL will implement the CDL interface
CYGINT_HAL_M68K_VARIANT_FPU. This allows the
architectural HAL and other packages to do the right thing on
different hardware.
Saving and restoring hardware floating point context increases
interrupt and dispatch latency, code size, and data size. If the
application does not actually use floating point then these overheads
are unnecessary, and can be suppressed by disabling the configuration
option CYGIMP_HAL_M68K_FPU_SAVE. Some applications
do use floating point but only in one thread. In that scenario it is
also unnecessary to save the floating point context during interrupts
and context switches, so the configuration option can be disabled.
The exact behaviour of the hardware floating point unit is determined
by the floating point control register %fpcr. By
default this is initialized to 0, giving IEE754 standard behaviour,
but another initial value can be specified using the configuration
option CYGNUM_HAL_M68K_FPU_CR_DEFAULT. For details
of the various bits in this control register see appropriate hardware
documentation. eCos assumes that the control register does not change
on a per-thread basis and hence the register is not saved or restored
during interrupt handling or a context switch.
At the time of writing eCos has not run on an M68K processor with
hardware floating point so the support for this is untested.
Other Options
There are configuration options to change the compiler flags used for
building this packages.
The M68K architectural HAL package does not define any other
configuration options that can be manipulated by the user. It does
define a number of interfaces such as
CYGINT_HAL_M68K_USE_STANDARD_PLATFORM_STUB_SUPPORT
which can be used by lower levels of the M68K HAL hierarchy to enable
certain functionality within the architectural package. Usually these
are of no interest to application developers.
The HAL PortHAL PortImplementation DetailsDescription
This documentation explains how the eCos HAL specification has been
mapped onto M68K hardware, and should be read in conjunction with
that specification. It also describes how variant, processor and
platform HALs can modify the default behaviour.
eCos support for any given target will involve either three or four
HAL packages: the architectural HAL, the platform HAL, the variant
HAL, and optionally a processor HAL. This package, the architectural
HAL, provides code and definitions that are applicable to all M68K
processors. The platform HAL provides support for one specific
board, for example an M5272C3 evaluation board, or possibly for a
number of almost-identical boards. The processor HAL, if present,
serves mainly to provide details of on-chip peripherals including the
interrupt controller. The variant HAL provides functionality that is
common to a group of processors, for example all MCFxxxx processors
have very similar UARTs and hence can share HAL diagnostic code.
There is no fixed specification of what should go into the variant HAL
versus the processor HAL. For simplicity the description below only
refers to variant HALs, but the work may actually happen in a
processor HAL instead.
As a design goal lower-level HALs can always override functionality
that is normally provided higher up. For example the architectural HAL
will provide the required eCos HAL_LSBIT_INDEX
and HAL_MSBIT_INDEX macros, but these can be
provided lower down instead. Many but not all ColdFire processors have
the ff1 and bitrev instructions
which allow for a more efficient implementation than the default
architectural ones. In some areas such as handling context switching
the architectural HAL will usually provide the basic functionality but
it may be extended by lower HALs, for example to add support for the
multiply-accumulate units present in certain ColdFire processors.
The architectural HAL provides header files cyg/hal/hal_arch.h, cyg/hal/hal_intr.h, cyg/hal/hal_cache.h, cyg/hal/hal_io.h and cyg/hal/arch.inc. These automatically
include an equivalent header file from the variant HAL, for example
cyg/hal/var_arch.h. The
variant HAL header will in turn include processor and
platform-specific headers. This means that application developers and
other packages can simply include the architectural HAL headers
without needing to know about variants or platforms. It also allows
the variant and platform HALs to override architectural settings.
The port assumes that eCos and application code always runs in
supervisor mode, with full access to all hardware and special
registers.
Data Types
For eCos purposes all M68K processors are big-endian and 32-bit, so
the default data types in cyg/infra/cyg_type.h are used. Some
variants have external bus widths less than 32-bit, but this does not
affect the architectural HAL.
When porting to another variant it is possible to override some or all
of the type definitions. The variant HAL needs to implement the CDL
interface CYGINT_HAL_M68K_VARIANT_TYPES and provide
a header file cyg/hal/var_basetype.h.
Startup and Exception Vectors
The conventional bootstrap mechanism involves a table of exception
vectors at the base of memory. The first two words of this table give
the initial program counter and stack pointer. In a typical embedded
system the hardware is arranged such that non-volatile flash memory is
found at location 0x0 so it is the start of flash that contains the
exception vectors and the boot code. The table of exception vectors is
used subsequently for interrupt handling and for hardware exceptions
such as attempts to execute an illegal instruction. There are a number
of common scenarios:
On systems with very limited memory flash may remain mapped at
location 0 and the table of exception vectors remains mapped there as
well. The M68K architecture defines the table to have 256 entries and
hence it occupies 1K of memory, but in reality many of the entries are
unused so part of the table may get used for code instead. Since the
whole exception vector table is in read-only memory parts of the eCos
interrupt and exception handling mechanisms have to be statically
initialized and macros like HAL_VSR_SET are not
available.
As a minor variation of the previous case, flash remains at location 0
but the table of exception vectors gets remapped elsewhere in the
address space, usually RAM. This allows
HAL_VSR_SET to operate normally but at the cost
of increased memory usage. The exception vector table in flash only
contains two entries, for the initial program counter and stack
pointer. The exception vector table in RAM typically gets initialized
at run-time.
On systems with more memory it is conventional to rearrange the
address map during bootstrap. The flash gets relocated, typically to
near the end of the address space, and RAM gets placed at location 0
instead. The exception vector table stays at location 0 but is now in
RAM and gets initialized at run-time. The bootstrap exception vector
table in flash again only needs two entries. A variation places the
RAM elsewhere in the address space and moves the exception vector
table there, leaving location 0 unused. This provides some protection
against null pointer accesses in errant code.
As a further complication, larger systems typically support different
startup types. The application can be linked against a ROM startup
configuration and placed directly in flash, as before. Alternatively
there may be a ROM monitor such as RedBoot in the flash, taking care
of initial bootstrap. The user's application is linked against a RAM
startup configuration, loaded into RAM via the ROM monitor, and
debugged using functionality provided by the ROM monitor. Yet another
possibility involves a RAM startup application but it gets loaded and
run via a hardware debug technology such as BDM, and the ROM monitor
is either missing or not used.
The exact hardware details, the various startup types, the steps
needed for low-level hardware initialization, and so on are not known
to the architectural HAL. Hence although the architectural HAL does
provide the basic framework for startup, much of the work is done via
macros provided by lower-level HAL packages and those macros are
likely to depend on various configuration options. Rather than try to
enumerate all the various combinations here it is better to look at
the actual code in vectors.S and in appropriate
variant, processor or platform HALs. vectors.S is
responsible for any low-level initialization that needs to happen.
This includes setting up a standard C environment with the stack
pointer set to the startup stack in working RAM, making sure all
statically initialized global variables have the correct values, and
that all uninitialized global variables are zeroed. Once the C
environment has been set up the code jumps to
hal_m68k_c_startup in file
hal_m68k.c which completes the initialization and
jumps to the application entry point.
Interrupt Handling
The M68K architecture reserves a 1K area of memory for 256 exception
vectors. These are used for internal and external interrupts,
exceptions, software traps, and special operations such as reset
handling. Some of the vectors have well-defined uses. However when it
comes to interrupt handling the details will depend on the processor
variant and on the platform, and the appropriate package documentation
should be consulted for full details. Most platforms will not use the
full set of 256 vectors, instead re-using some of this memory for
other purposes.
By default the exception vectors are located at location 0, but some
variants allow the vectors to be located elsewhere. This is managed by
an M68K-specific macro CYG_HAL_VSR_TABLE. The
default value is 0, but a variant HAL can provide an alternative value.
The standard eCos macros HAL_VSR_GET and
HAL_VSR_SET just manipulate one of the 256
entries in the table of exception vectors. Hence it is usually
possible to replace the default handlers for exceptions and traps in
addition to interrupt handlers.
hal_intr.h
provides #define's for the more common exception
vectors, and additional ones can be provided by the platform or
variant. It is the responsibility of the platform or variant HAL to
initialize the table, and to provide the
HAL_VSR_SET_TO_ECOS_HANDLER macro since that
requires knowledge of the default table entries.
It should be noted that in some configurations the table of exception
vectors may reside in read-only memory so entries cannot be changed.
If so then the HAL_VSR_SET and
HAL_VSR_SET_TO_ECOS_HANDLER macros will not be
defined. Portable code may need to consider this possibility and test
for the existence of these macros before using them.
The architectural HAL provides an entry point
hal_m68k_interrupt_vsr in the file
hal_arch.S. When an interrupt occurs the original
68000 pushed the program counter and the status register on to the
stack, and then called the VSR via the exception table. On newer
variants some additional information is pushed, including details of
the interrupt source. hal_m68k_interrupt_vsr
assumes the latter and can be used directly as the VSR on these newer
variants. On older variants a small trampoline is needed which pushes
the additional information and then jumps to the generic VSR.
Interpreting the additional information is handled via an assembler
macro hal_context_extract_isr_vector_shl2
which should be defined by the variant, matching the behaviour of the
hardware or the trampoline.
At the architecture level there is no fixed mapping between VSR and
ISR vectors. Instead that is left to the variant or platform HAL. The
architectural HAL does provide default implementations of
HAL_INTERRUPT_ATTACH,
HAL_INTERRUPT_DETACH and
HAL_INTERRUPT_IN_USE since these just involve
updating a static table.
By default the interrupt state control macros
HAL_DISABLE_INTERRUPTS,
HAL_RESTORE_INTERRUPTS,
HAL_ENABLE_INTERRUPTS and
HAL_QUERY_INTERRUPTS are implemented by the
architectural HAL, and simply involve updating the status register.
Disabling interrupts involves setting the three IPL bits to 0x07.
Enabling interrupts involves setting those bits to a smaller value,
CYGNUM_HAL_INTERRUPT_DEFAULT_IPL_LEVEL, which
defaults to 0.
HAL_DISABLE_INTERRUPTS has no effect on
non-maskable interrupts. This causes a problem because parts of the
system assume that all normal interrupt sources are affected by this
macro. If the target hardware can raise non-maskable interrupts then
it is the responsibility of application code to install a suitable VSR
and handle non-maskable interrupts entirely within the application,
bypassing the usual eCos ISR and DSR mechanisms.
The architectural HAL does not provide any support for the interrupt
controller management macros like
HAL_INTERRUPT_MASK. These can only be implemented
on a per-variant, per-processor or per-platform basis.
Exception Handling
Synchronous exception handling is done in much the same way as
interrupt handling. The architectural HAL provides a generic entry
point hal_m68k_exception_vsr. On some variants
this can be used directly as the exception VSR, on others it will be
called via a small trampoline.
The details of exception handling vary widely from one variant to the
next. Some variants push a great deal of additional information on to
the stack for certain exceptions, but not all. The pushed program
counter may correspond to the specific instruction that caused the
exception, or the next instruction, or there may be only a loose
correlation because of buffered writes. The architectural HAL makes no
attempt to cope with all these differences, although some variants may
provide more advanced support. Otherwise if an exception needs to be
handled in a very specific way then it is up to the application to
install a suitable VSR and handle the exception directly.
Stacks and Stack Sizescyg/hal/hal_arch.h defines
values for minimal and recommended thread stack sizes,
CYGNUM_HAL_STACK_SIZE_MINIMUM and
CYGNUM_HAL_STACK_SIZE_TYPICAL. These values are
specific to the current configuration, and are affected mainly by
options related to interrupt handling.
By default eCos uses a separate interrupt stack, although this can be
disabled through the configuration option
CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK.
When an interrupt or exception occurs eCos will save the context on
the current stack and then switch to the interrupt stack before
calling the appropriate ISR interrupt handler. This means that thread
stacks can be significantly smaller because there is no need to worry
about interrupt handling overheads, just the thread context. However
switching the stack does require some extra work and hence increases
the interrupt latency. Disabling the interrupt stack removes this
processing overhead but requires larger stack sizes. It depends on
the application whether or not this is a sensible trade off.
By default eCos does not allow nested interrupts, but this can be
controlled via the configuration option
CYGSEM_HAL_COMMON_INTERRUPTS_ALLOW_NESTING.
Supporting nested interrupts requires larger thread stacks, especially
if the separate interrupt stack is also disabled.
Although the M68K has enough registers for typical operation, the
calling conventions are memory-oriented. In particular all arguments
are pushed on the stack rather than held in registers, and the return
address is also pushed rather than ending up in a link register. To
allow for this the recommended minimum stack sizes are a little bit
larger than for some other architectures. Variant HALs cannot directly
affect these stack sizes. However the sizes do depend in part on the
size of a thread context, so if for example the processor supports
hardware floating point and support for that is enabled then the stack
sizes will increase.
Usually the M68K architectural HAL will provide a single block of
memory which acts as both the startup and interrupt stack, and there
are configuration options to
control the size of this block. Alternatively a variant, processor or
platform HAL may define either or both of
_HAL_M68K_STARTUP_STACK_ and
_HAL_M68K_INTERRUPT_STACK_BASE_ if for some reason
the stacks should not be placed in ordinary RAM.
Thread Contexts and Setjmp/Longjmp
A typical thread context consists of the following:
The integer context. This consists of the data registers
%d0 to %d7 and the address
registers %a0 to %a6, The stack
pointer register %a7 does not have to be saved
explicitly since it is implicit in the pointer to the saved context.
The caller-save registers are %d0,
%d1, %a0,
%a1, %a7 and the status
register. The remaining registers are callee-save. Function arguments
are always passed on the stack. The result is held in
%d0.
Floating point context, consisting of eight 64-bit floating point
registers %fp0 to %fp7 and two
support registers %fpsr and
%fpiar. Support for this is only relevant if the
processor variant has a hardware floating point unit, and even then
saving floating point context is optional and can be disabled using a
configuration option CYGIMP_HAL_M68K_FPU_SAVE. The
control register %fpcr is not saved as part of the
context. It is assumed that a single %fpcr value,
usually 0, will be used throughout the application.
The architectural HAL provides support for the hardware floating point
unit. The variant or processor HAL should implement the CDL interface
CYGINT_HAL_M68K_VARIANT_FPU if this hardware unit
is actually present.
Some M68K variants have additional hardware units, for example the
multiply-accumulate units in certain ColdFire processors. The
architectural HAL allows the context to be extended through various
macros such as HAL_CONTEXT_OTHER.
The status register %sr and the program counter.
These are special because when an interrupt occurs the hardware
automatically pushes these onto the stack, but exactly what gets
pushed depends on the variant.
setjmp and longjmp only deal
with the integer and fpu contexts. It is assumed that any special
hardware units will only be used by application code, not by the
compiler. Hence it is the responsibility of application code to
define and implement appropriate setjmp semantics for these units.
The variant HAL package can override the default implementations if
necessary.
When porting to a new M68K variant, if this has a hardware floating
point unit then the variant HAL should implement the CDL interface
CYGINT_HAL_M68K_VARIANT_FPU, thus enabling support
provided by the architectural HAL. If the variant has additional
hardware units involving state that should be preserved during a
context switch or when an interrupt occurs, the variant HAL should
define a number of macros. The header file cyg/hal/var_arch.h should define
HAL_CONTEXT_OTHER,
HAL_CONTEXT_OTHER_SIZE, and
HAL_CONTEXT_OTHER_INIT, either directly or via
cyg/hal/proc_arch.h. The
assembler header file cyg/hal/var.inc should define a number
of macros such as hal_context_other_save_caller.
For details of these macros see the architectural
hal_arch.S file.
Variants also need to define exactly how the status register and
program counter are saved onto the stack when an interrupt or
exception occurs. This is handled through C macros
HAL_CONTEXT_PCSR_SIZE,
HAL_CONTEXT_PCSR_RTE_ADJUST, and
HAL_CONTEXT_PCSR_INIT, and a number of assembler
macros such as hal_context_pcsr_save_sr. Again
the architectural files cyg/hal/hal_arch.h and
hal_arch.S provide more details of these.
Bit Indexing
For performance reasons the HAL_LSBIT_INDEX and
HAL_MSBIT_INDEX macros are implemented using
assembler functions. A variant HAL can override the default
definitions if, for example, the variant has special instructions to
perform these operations.
Idle Thread Processing
The default HAL_IDLE_THREAD_ACTION implementation
is a no-op. A variant HAL may override this, for example to put the
processor into sleep mode. Alternative implementations should consider
exactly how this macro gets used in eCos kernel code.
Clock Support
The architectural HAL cannot provide the required clock support
because it does not know what timer hardware may be available on the
target hardware. Instead this is left to either the variant or
platform HAL, depending on whether the processor has a suitable
on-chip timer or whether an off-chip timer has to be used.
HAL I/O
The M68K architecture does not have a separate I/O bus. Instead all
hardware is assumed to be memory-mapped. Further it is assumed that
all peripherals on the memory bus are wired appropriately for a
big-endian processor and that there is no need for any byte swapping.
Hence the various HAL macros for performing I/O simply involve
pointers to volatile memory.
The variant, processor and platform equivalents of the cyg/hal/hal_io.h header will typically
also provide details of some or all of the peripherals, for example
register offsets and the meaning of various bits in those registers.
Cache Handling
If the processor has a cache then the variant HAL should implement the
CDL interface CYGINT_HAL_M68K_VARIANT_CACHE. This
causes the architectural header cyg/hal/hal_cache.h to pick up
appropriate definitions from cyg/hal/var_cache.h. The architectural
header will provide null defaults for anything not defined by the
variant.
Linker Scripts
The architectural HAL will generate the linker script for eCos
applications. This involves the architectural file
m68k.ld and a .ldi memory
layout file provided lower down, typically by the platform HAL. It is
the LDI file which specifies the types and amount of memory available
and which places code and data in appropriate places, but most of the
hard work is done via macros provided by the architectural
m68k.ld file.
Diagnostic Support
The architectural HAL does not implement diagnostic support. Instead
this is left to the variant or platform HAL, depending on whether
suitable peripherals are available on-chip or off-chip.
SMP Support
The M68K port does not have SMP support.
Debug Support
The M68K architectural HAL package provides basic support only for gdb
stubs. There is no support for more advanced debug features like
hardware watchpoints.
The generic gdb support in the common HAL requires a platform header
<cyg/hal/plf_stub.h. In
practice there is rarely any need for the contents of this file to
change between platforms so the architectural HAL can provide a
suitable default. It will do so if the CDL interface
CYGINT_HAL_M68K_USE_STANDARD_PLATFORM_STUB_SUPPORT
is implemented.
HAL_DELAY_US Macro
The architectural HAL provides a default implementation of the
standard HAL_DELAY_US macro using a simply busy
loop. To use this support a lower-level HAL should define
_HAL_M68K_DELAY_US_LOOPS_, typically a small number
of about 20 but it will need to be calibrated during the porting
process. If the processor has a cache then the lower-level HAL may
also define _HAL_M68K_DELAY_US_LOOPS_UNCACHED_ for
the case when a delay loop is triggered while the cache is disabled.
Profiling Support
The M68K architectural HAL implements the mcount
function, allowing profiling tools like
gprof to determine the application's call
graph. It does not implement the profiling timer. Instead that
functionality needs to be provided by the variant or platform HAL.
The implementation of mcount requires a dedicated
frame pointer register so code should be compiled without the
flag.
Other Functionality
The M68K architectural HAL only implements the functionality provided
by the eCos HAL specification and does not export any extra
functionality.