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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [common/] [v2_0/] [doc/] [hal.sgml] - Diff between revs 27 and 174

Only display areas with differences | Details | Blame | View Log

Rev 27 Rev 174
The eCos Hardware Abstraction Layer (HAL)
The eCos Hardware Abstraction Layer (HAL)
Introduction
Introduction
This is an initial specification of the eCos Hardware Abstraction Layer (HAL). The HAL abstracts
 -->Hardware Abstraction Layer (HAL). The HAL abstracts
the underlying hardware of a processor architecture and/or the
the underlying hardware of a processor architecture and/or the
platform to a level sufficient for the eCos kernel to be ported onto
platform to a level sufficient for the eCos kernel to be ported onto
that platform.
that platform.
Caveat
Caveat
This document is an informal description of the HAL capabilities and
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
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
source for such. It also describes the HAL as it is currently
implemented for the architectures targeted in this release. It most
implemented for the architectures targeted in this release. It most
closely describes the HALs for the MIPS, I386 and PowerPC HALs. Other
closely describes the HALs for the MIPS, I386 and PowerPC HALs. Other
architectures are similar but may not be organized precisely as
architectures are similar but may not be organized precisely as
described here.
described here.
Architecture, Variant and Platform
Architecture, Variant and Platform
We have identified three levels at which the HAL must operate.
We have identified three levels at which the HAL must operate.
  
  
    
    
    The architecture
    The architecture
    HAL abstracts the basic CPU architecture and includes
    HAL abstracts the basic CPU architecture and includes
    things like interrupt delivery, context switching, CPU startup
    things like interrupt delivery, context switching, CPU startup
    etc.
    etc.
    
    
  
  
  
  
    
    
    The  variant HAL
    The  variant HAL
    encapsulates features of the CPU variant such as caches, MMU and
    encapsulates features of the CPU variant such as caches, MMU and
    FPU features. It also deals with any on-chip peripherals such as
    FPU features. It also deals with any on-chip peripherals such as
    memory and interrupt controllers. For architectural variations,
    memory and interrupt controllers. For architectural variations,
    the actual implementation of the variation is often in the
    the actual implementation of the variation is often in the
    architectural HAL, and the variant HAL simply provides the correct
    architectural HAL, and the variant HAL simply provides the correct
    configuration definitions.
    configuration definitions.
    
    
  
  
    
    
    
    
    The platform HAL
    The platform HAL
    abstracts the properties of the current platform and includes
    abstracts the properties of the current platform and includes
    things like platform startup, timer devices, I/O register access
    things like platform startup, timer devices, I/O register access
    and interrupt controllers.
    and interrupt controllers.
    
    
  
  
The boundaries between these three HAL levels are necessarily blurred
The boundaries between these three HAL levels are necessarily blurred
since functionality shifts between levels on a target-by-target basis.
since functionality shifts between levels on a target-by-target basis.
For example caches and MMU may be either an architecture feature or a
For example caches and MMU may be either an architecture feature or a
variant feature. Similarly, memory and interrupt controllers may be
variant feature. Similarly, memory and interrupt controllers may be
on-chip and in the variant HAL, or off-chip and in the platform HAL.
on-chip and in the variant HAL, or off-chip and in the platform HAL.
Generally there is a separate package for each of the architecture,
Generally there is a separate package for each of the architecture,
variant and package HALs for a target. For some of the older targets,
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.
or where it would be essentially empty, the variant HAL is omitted.
General principles
General principles
The HAL has been implemented according to the following general
The HAL has been implemented according to the following general
principles:
principles:
              The HAL is implemented in C and assembler, although the
              The HAL is implemented in C and assembler, although the
              eCos kernel is largely implemented in C++.
              eCos kernel is largely implemented in C++.
              This is to permit the HAL the widest possible
              This is to permit the HAL the widest possible
              applicability.
              applicability.
All interfaces to the HAL are implemented by
All interfaces to the HAL are implemented by
              CPP macros. This allows them to be implemented as inline
              CPP macros. This allows them to be implemented as inline
              C code, inline assembler or function calls to external C
              C code, inline assembler or function calls to external C
              or assembler code. This allows the most efficient
              or assembler code. This allows the most efficient
              implementation to be selected without affecting the
              implementation to be selected without affecting the
              interface. It also allows them to be redefined if the
              interface. It also allows them to be redefined if the
              platform or variant HAL needs to replace or enhance a definition
              platform or variant HAL needs to replace or enhance a definition
              from the architecture HAL.
              from the architecture HAL.
The HAL provides simple, portable mechanisms for dealing
The HAL provides simple, portable mechanisms for dealing
with the hardware of a wide range of architectures and platforms.
with the hardware of a wide range of architectures and platforms.
It is always possible to bypass the HAL and program the hardware
It is always possible to bypass the HAL and program the hardware
directly, but this may lead to a loss of portability. 
directly, but this may lead to a loss of portability. 
<!-- <index></index> --><!-- <xref> -->HAL Interfaces
<!-- <index></index> --><!-- <xref> -->HAL Interfaces
This section describes the main HAL interfaces.
This section describes the main HAL interfaces.
Base Definitions
Base Definitions
These are definitions that characterize the properties of the base
These are definitions that characterize the properties of the base
architecture that are used to compile the portable parts of the
architecture that are used to compile the portable parts of the
kernel. They are concerned with such things a portable type
kernel. They are concerned with such things a portable type
definitions, endianness, and labeling.
definitions, endianness, and labeling.
These definitions are supplied by the
These definitions are supplied by the
cyg/hal/basetype.h header file which is supplied
cyg/hal/basetype.h header file which is supplied
by the architecture HAL. It is included automatically by
by the architecture HAL. It is included automatically by
cyg/infra/cyg_type.h.
cyg/infra/cyg_type.h.
Byte order
Byte order
  
  
    CYG_BYTEORDER
    CYG_BYTEORDER
    
    
      
      
      This defines the byte order of the target and must be set to either
      This defines the byte order of the target and must be set to either
      CYG_LSBFIRST or CYG_MSBFIRST.
      CYG_LSBFIRST or CYG_MSBFIRST.
      
      
    
    
  
  
Label Translation
Label Translation
  
  
    CYG_LABEL_NAME(name)
    CYG_LABEL_NAME(name)
    
    
      
      
      This is a wrapper used in some C and C++ files which
      This is a wrapper used in some C and C++ files which
      use labels defined in assembly code or the linker script.
      use labels defined in assembly code or the linker script.
      It need only be defined if the default implementation in
      It need only be defined if the default implementation in
      cyg/infra/cyg_type.h, which passes the name
      cyg/infra/cyg_type.h, which passes the name
      argument unaltered, is inadequate. It should be paired with
      argument unaltered, is inadequate. It should be paired with
      CYG_LABEL_DEFN().
      CYG_LABEL_DEFN().
      
      
    
    
  
  
  
  
    CYG_LABEL_DEFN(name)
    CYG_LABEL_DEFN(name)
    
    
      
      
      This is a wrapper used in assembler sources and linker scripts
      This is a wrapper used in assembler sources and linker scripts
      which define labels.  It need only be defined if the default
      which define labels.  It need only be defined if the default
      implementation in
      implementation in
      cyg/infra/cyg_type.h, which passes the name
      cyg/infra/cyg_type.h, which passes the name
      argument unaltered, is inadequate. The most usual alternative
      argument unaltered, is inadequate. The most usual alternative
      definition of this macro prepends an underscore to the label
      definition of this macro prepends an underscore to the label
      name.
      name.
      
      
    
    
  
  
Base types
Base types
        cyg_halint8
        cyg_halint8
        cyg_halint16
        cyg_halint16
        cyg_halint32
        cyg_halint32
        cyg_halint64
        cyg_halint64
        cyg_halcount8
        cyg_halcount8
        cyg_halcount16
        cyg_halcount16
        cyg_halcount32
        cyg_halcount32
        cyg_halcount64
        cyg_halcount64
        cyg_halbool
        cyg_halbool
These macros define the C base types that should be used to define
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
variables of the given size. They only need to be defined if the
default types specified in cyg/infra/cyg_type.h
default types specified in cyg/infra/cyg_type.h
cannot be used. Note that these are only the base types, they will be
cannot be used. Note that these are only the base types, they will be
composed with signed and
composed with signed and
unsigned to form full type specifications.
unsigned to form full type specifications.
Atomic types
Atomic types
        cyg_halatomic CYG_ATOMIC
        cyg_halatomic CYG_ATOMIC
These types are guaranteed to be read or written in a single
These types are guaranteed to be read or written in a single
uninterruptible operation. It is architecture defined what size this
uninterruptible operation. It is architecture defined what size this
type is, but it will be at least a byte.
type is, but it will be at least a byte.
Architecture Characterization
Architecture Characterization
These are definition that are related to the basic architecture of the
These are definition that are related to the basic architecture of the
CPU. These include the CPU context save format, context switching, bit
CPU. These include the CPU context save format, context switching, bit
twiddling, breakpoints, stack sizes and address translation.
twiddling, breakpoints, stack sizes and address translation.
Most of these definition are found in
Most of these definition are found in
cyg/hal/hal_arch.h.  This file is supplied by the
cyg/hal/hal_arch.h.  This file is supplied by the
architecture HAL. If there are variant or platform specific
architecture HAL. If there are variant or platform specific
definitions then these will be found in
definitions then these will be found in
cyg/hal/var_arch.h or
cyg/hal/var_arch.h or
cyg/hal/plf_arch.h. These files are include
cyg/hal/plf_arch.h. These files are include
automatically by this header, so need not be included explicitly.
automatically by this header, so need not be included explicitly.
Register Save Format
Register Save Format
typedef struct HAL_SavedRegisters
typedef struct HAL_SavedRegisters
{
{
    /* architecture-dependent list of registers to be saved */
    /* architecture-dependent list of registers to be saved */
} HAL_SavedRegisters;
} HAL_SavedRegisters;
This structure describes the layout of a saved machine state on the
This structure describes the layout of a saved machine state on the
stack. Such states are saved during thread context switches,
stack. Such states are saved during thread context switches,
interrupts and exceptions. Different quantities of state may be saved
interrupts and exceptions. Different quantities of state may be saved
during each of these, but usually a thread context state is a subset
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.
of the interrupt state which is itself a subset of an exception state.
For debugging purposes, the same structure is used for all three
For debugging purposes, the same structure is used for all three
purposes, but where these states are significantly different, this
purposes, but where these states are significantly different, this
structure may contain a union of the three states.
structure may contain a union of the three states.
Thread Context Initialization
Thread Context Initialization
HAL_THREAD_INIT_CONTEXT( sp, arg, entry, id )
HAL_THREAD_INIT_CONTEXT( sp, arg, entry, id )
This macro initializes a thread's context so that
This macro initializes a thread's context so that
it may be switched to by HAL_THREAD_SWITCH_CONTEXT().
it may be switched to by HAL_THREAD_SWITCH_CONTEXT().
The arguments are:
The arguments are:
  
  
    sp
    sp
    
    
      
      
      A location containing the current value of the thread's stack
      A location containing the current value of the thread's stack
      pointer. This should be a variable or a structure field. The SP
      pointer. This should be a variable or a structure field. The SP
      value will be read out of here and an adjusted value written
      value will be read out of here and an adjusted value written
      back.
      back.
      
      
    
    
  
  
  
  
    arg
    arg
    
    
      
      
      A value that is passed as the first argument to the entry
      A value that is passed as the first argument to the entry
      point function.
      point function.
      
      
    
    
  
  
  
  
    entry
    entry
    
    
      
      
      The address of an entry point function. This will be called
      The address of an entry point function. This will be called
      according the C calling conventions, and the value of
      according the C calling conventions, and the value of
      arg will be passed as the first
      arg will be passed as the first
      argument. This function should have the following type signature
      argument. This function should have the following type signature
      void entry(CYG_ADDRWORD arg).
      void entry(CYG_ADDRWORD arg).
      
      
    
    
  
  
  
  
    id
    id
    
    
      
      
      A thread id value. This is only used for debugging purposes,
      A thread id value. This is only used for debugging purposes,
      it is ORed into the initialization pattern for unused registers
      it is ORed into the initialization pattern for unused registers
      and may be used to help identify the thread from its register dump.
      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
      The least significant 16 bits of this value should be zero to allow
      space for a register identifier.
      space for a register identifier.
      
      
    
    
  
  
Thread Context Switching
Thread Context Switching
HAL_THREAD_LOAD_CONTEXT( to )
HAL_THREAD_LOAD_CONTEXT( to )
HAL_THREAD_SWITCH_CONTEXT( from, to )
HAL_THREAD_SWITCH_CONTEXT( from, to )
These macros implement the thread switch code. The arguments are:
These macros implement the thread switch code. The arguments are:
  
  
    from
    from
    
    
      
      
      A pointer to a location where the stack pointer of the current
      A pointer to a location where the stack pointer of the current
      thread will be stored.
      thread will be stored.
      
      
    
    
  
  
  
  
    to
    to
    
    
      
      
      A pointer to a location from where the stack pointer of the next
      A pointer to a location from where the stack pointer of the next
      thread will be read.
      thread will be read.
      
      
    
    
  
  
For HAL_THREAD_LOAD_CONTEXT() the current CPU
For HAL_THREAD_LOAD_CONTEXT() the current CPU
state is discarded and the state of the destination thread is
state is discarded and the state of the destination thread is
loaded. This is only used once, to load the first thread when the
loaded. This is only used once, to load the first thread when the
scheduler is started.
scheduler is started.
For HAL_THREAD_SWITCH_CONTEXT() the state of the
For HAL_THREAD_SWITCH_CONTEXT() the state of the
current thread is saved onto its stack, using the current value 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
stack pointer, and the address of the saved state placed in
*from.  The value in
*from.  The value in
*to is then read and the state of the new
*to is then read and the state of the new
thread is loaded from it.
thread is loaded from it.
While these two operations may be implemented with inline assembler,
While these two operations may be implemented with inline assembler,
they are normally implemented as calls to assembly code functions in
they are normally implemented as calls to assembly code functions in
the HAL. There are two advantages to doing it this way. First, the
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
return link of the call provides a convenient PC value to be used in
the saved context. Second, the calling conventions mean that the
the saved context. Second, the calling conventions mean that the
compiler will have already saved the caller-saved registers before the
compiler will have already saved the caller-saved registers before the
call, so the HAL need only save the callee-saved registers.
call, so the HAL need only save the callee-saved registers.
The implementation of HAL_THREAD_SWITCH_CONTEXT()
The implementation of HAL_THREAD_SWITCH_CONTEXT()
saves the current CPU state on the stack, including the current
saves the current CPU state on the stack, including the current
interrupt state (or at least the register that contains it). For
interrupt state (or at least the register that contains it). For
debugging purposes it is useful to save the entire register set, but
debugging purposes it is useful to save the entire register set, but
for performance only the ABI-defined callee-saved registers need be
for performance only the ABI-defined callee-saved registers need be
saved. If it is implemented, the option
saved. If it is implemented, the option
CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM controls
CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM controls
how many registers are saved.
how many registers are saved.
The implementation of HAL_THREAD_LOAD_CONTEXT()
The implementation of HAL_THREAD_LOAD_CONTEXT()
loads a thread context, destroying the current context. With a little
loads a thread context, destroying the current context. With a little
care this can be implemented by sharing code with
care this can be implemented by sharing code with
HAL_THREAD_SWITCH_CONTEXT(). To load a thread
HAL_THREAD_SWITCH_CONTEXT(). To load a thread
context simply requires the saved registers to be restored from the
context simply requires the saved registers to be restored from the
stack and a jump or return made back to the saved PC.
stack and a jump or return made back to the saved PC.
Note that interrupts are not disabled during this process, any
Note that interrupts are not disabled during this process, any
interrupts that occur will be delivered onto the stack to which the
interrupts that occur will be delivered onto the stack to which the
current CPU stack pointer points. Hence the stack pointer
current CPU stack pointer points. Hence the stack pointer
should never be invalid, or loaded with a value that might cause the
should never be invalid, or loaded with a value that might cause the
saved state to become corrupted by an interrupt. However, the current
saved state to become corrupted by an interrupt. However, the current
interrupt state is saved and restored as part of the thread
interrupt state is saved and restored as part of the thread
context. If a thread disables interrupts and does something to cause a
context. If a thread disables interrupts and does something to cause a
context switch, interrupts may be re-enabled on switching to another
context switch, interrupts may be re-enabled on switching to another
thread. Interrupts will be disabled again when the original thread
thread. Interrupts will be disabled again when the original thread
regains control.
regains control.
Bit indexing
Bit indexing
HAL_LSBIT_INDEX( index, mask )
HAL_LSBIT_INDEX( index, mask )
HAL_MSBIT_INDEX( index, mask )
HAL_MSBIT_INDEX( index, mask )
These macros place in index the bit index of
These macros place in index the bit index of
the least significant bit in mask. Some
the least significant bit in mask. Some
architectures have instruction level support for one or other of these
architectures have instruction level support for one or other of these
operations. If no architectural support is available, then these
operations. If no architectural support is available, then these
macros may call C functions to do the job.
macros may call C functions to do the job.
Idle thread activity
Idle thread activity
HAL_IDLE_THREAD_ACTION( count )
HAL_IDLE_THREAD_ACTION( count )
It may be necessary under some circumstances for the HAL to execute
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
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
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,
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
and may be used to trigger actions at longer intervals than every
loop.
loop.
Reorder barrier
Reorder barrier
HAL_REORDER_BARRIER()
HAL_REORDER_BARRIER()
When optimizing the compiler can reorder code. In some parts of
When optimizing the compiler can reorder code. In some parts of
multi-threaded systems, where the order of actions is vital, this can
multi-threaded systems, where the order of actions is vital, this can
sometimes cause problems. This macro may be inserted into places where
sometimes cause problems. This macro may be inserted into places where
reordering should not happen and prevents code being migrated across
reordering should not happen and prevents code being migrated across
it by the compiler optimizer. It should be placed between statements
it by the compiler optimizer. It should be placed between statements
that must be executed in the order written in the code.
that must be executed in the order written in the code.
Breakpoint support
Breakpoint support
HAL_BREAKPOINT( label )
HAL_BREAKPOINT( label )
HAL_BREAKINST
HAL_BREAKINST
HAL_BREAKINST_SIZE
HAL_BREAKINST_SIZE
These macros provide support for breakpoints.
These macros provide support for breakpoints.
HAL_BREAKPOINT() executes a breakpoint
HAL_BREAKPOINT() executes a breakpoint
instruction. The label is defined at the breakpoint instruction so
instruction. The label is defined at the breakpoint instruction so
that exception code can detect which breakpoint was executed.
that exception code can detect which breakpoint was executed.
HAL_BREAKINST contains the breakpoint instruction
HAL_BREAKINST contains the breakpoint instruction
code as an integer value. HAL_BREAKINST_SIZE is
code as an integer value. HAL_BREAKINST_SIZE is
the size of that breakpoint instruction in bytes. Together these
the size of that breakpoint instruction in bytes. Together these
may be used to place a breakpoint in any code.
may be used to place a breakpoint in any code.
GDB support
GDB support
HAL_THREAD_GET_SAVED_REGISTERS( sp, regs )
HAL_THREAD_GET_SAVED_REGISTERS( sp, regs )
HAL_GET_GDB_REGISTERS( regval, regs )
HAL_GET_GDB_REGISTERS( regval, regs )
HAL_SET_GDB_REGISTERS( regs, regval )
HAL_SET_GDB_REGISTERS( regs, regval )
These macros provide support for interfacing GDB to the HAL.
These macros provide support for interfacing GDB to the HAL.
HAL_THREAD_GET_SAVED_REGISTERS() extracts a
HAL_THREAD_GET_SAVED_REGISTERS() extracts a
pointer to a HAL_SavedRegisters structure
pointer to a HAL_SavedRegisters structure
from a stack pointer value. The stack pointer passed in should be the
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
value saved by the thread context macros. The macro will assign a
pointer to the HAL_SavedRegisters structure
pointer to the HAL_SavedRegisters structure
to the variable passed as the second argument.
to the variable passed as the second argument.
HAL_GET_GDB_REGISTERS() translates a register
HAL_GET_GDB_REGISTERS() translates a register
state as saved by the HAL and into a register dump in the format
state as saved by the HAL and into a register dump in the format
expected by GDB. It takes a pointer to a
expected by GDB. It takes a pointer to a
HAL_SavedRegisters structure in the
HAL_SavedRegisters structure in the
regs argument and a pointer to the memory to
regs argument and a pointer to the memory to
contain the GDB register dump in the regval
contain the GDB register dump in the regval
argument.
argument.
HAL_SET_GDB_REGISTERS() translates a GDB format
HAL_SET_GDB_REGISTERS() translates a GDB format
register dump into a the format expected by the HAL.  It takes a
register dump into a the format expected by the HAL.  It takes a
pointer to the memory containing the GDB register dump in the
pointer to the memory containing the GDB register dump in the
regval argument and a pointer to a
regval argument and a pointer to a
HAL_SavedRegisters structure
HAL_SavedRegisters structure
in the regs argument.
in the regs argument.
Setjmp and longjmp support
Setjmp and longjmp support
CYGARC_JMP_BUF_SIZE
CYGARC_JMP_BUF_SIZE
hal_jmp_buf[CYGARC_JMP_BUF_SIZE]
hal_jmp_buf[CYGARC_JMP_BUF_SIZE]
hal_setjmp( hal_jmp_buf env )
hal_setjmp( hal_jmp_buf env )
hal_longjmp( hal_jmp_buf env, int val )
hal_longjmp( hal_jmp_buf env, int val )
These functions provide support for the C
These functions provide support for the C
setjmp() and longjmp()
setjmp() and longjmp()
functions.  Refer to the C library for further information.
functions.  Refer to the C library for further information.
Stack Sizes
Stack Sizes
CYGNUM_HAL_STACK_SIZE_MINIMUM
CYGNUM_HAL_STACK_SIZE_MINIMUM
CYGNUM_HAL_STACK_SIZE_TYPICAL
CYGNUM_HAL_STACK_SIZE_TYPICAL
The values of these macros define the minimum and typical sizes of
The values of these macros define the minimum and typical sizes of
thread stacks.
thread stacks.
CYGNUM_HAL_STACK_SIZE_MINIMUM defines the minimum
CYGNUM_HAL_STACK_SIZE_MINIMUM defines the minimum
size of a thread stack. This is enough for the thread to function
size of a thread stack. This is enough for the thread to function
correctly within eCos and allows it to take interrupts and context
correctly within eCos and allows it to take interrupts and context
switches. There should also be enough space for a simple thread entry
switches. There should also be enough space for a simple thread entry
function to execute and call basic kernel operations on objects like
function to execute and call basic kernel operations on objects like
mutexes and semaphores. However there will not be enough room for much
mutexes and semaphores. However there will not be enough room for much
more than this. When creating stacks for their own threads,
more than this. When creating stacks for their own threads,
applications should determine the stack usage needed for application
applications should determine the stack usage needed for application
purposes and then add
purposes and then add
CYGNUM_HAL_STACK_SIZE_MINIMUM.
CYGNUM_HAL_STACK_SIZE_MINIMUM.
CYGNUM_HAL_STACK_SIZE_TYPICAL is a reasonable increment over
CYGNUM_HAL_STACK_SIZE_TYPICAL is a reasonable increment over
CYGNUM_HAL_STACK_SIZE_MINIMUM, usually about 1kB. This should be
CYGNUM_HAL_STACK_SIZE_MINIMUM, usually about 1kB. This should be
adequate for most modest thread needs. Only threads that need to
adequate for most modest thread needs. Only threads that need to
define significant amounts of local data, or have very deep call trees
define significant amounts of local data, or have very deep call trees
should need to use a larger stack size.
should need to use a larger stack size.
Address Translation
Address Translation
CYGARC_CACHED_ADDRESS(addr)
CYGARC_CACHED_ADDRESS(addr)
CYGARC_UNCACHED_ADDRESS(addr)
CYGARC_UNCACHED_ADDRESS(addr)
CYGARC_PHYSICAL_ADDRESS(addr)
CYGARC_PHYSICAL_ADDRESS(addr)
These macros provide address translation between different views of
These macros provide address translation between different views of
memory. In many architectures a given memory location may be visible
memory. In many architectures a given memory location may be visible
at different addresses in both cached and uncached forms. It is also
at different addresses in both cached and uncached forms. It is also
possible that the MMU or some other address translation unit in the
possible that the MMU or some other address translation unit in the
CPU presents memory to the program at a different virtual address to
CPU presents memory to the program at a different virtual address to
its physical address on the bus.
its physical address on the bus.
CYGARC_CACHED_ADDRESS() translates the given
CYGARC_CACHED_ADDRESS() translates the given
address to its location in cached memory. This is typically where the
address to its location in cached memory. This is typically where the
application will access the memory.
application will access the memory.
CYGARC_UNCACHED_ADDRESS() translates the given
CYGARC_UNCACHED_ADDRESS() translates the given
address to its location in uncached memory. This is typically where
address to its location in uncached memory. This is typically where
device drivers will access the memory to avoid cache problems. It may
device drivers will access the memory to avoid cache problems. It may
additionally be necessary for the cache to be flushed before the
additionally be necessary for the cache to be flushed before the
contents of this location is fully valid.
contents of this location is fully valid.
CYGARC_PHYSICAL_ADDRESS() translates the given
CYGARC_PHYSICAL_ADDRESS() translates the given
address to its location in the physical address space. This is
address to its location in the physical address space. This is
typically the address that needs to be passed to device hardware such
typically the address that needs to be passed to device hardware such
as a DMA engine, ethernet device or PCI bus bridge. The physical
as a DMA engine, ethernet device or PCI bus bridge. The physical
address may not be directly accessible to the program, it may be
address may not be directly accessible to the program, it may be
re-mapped by address translation.
re-mapped by address translation.
Global Pointer
Global Pointer
CYGARC_HAL_SAVE_GP()
CYGARC_HAL_SAVE_GP()
CYGARC_HAL_RESTORE_GP()
CYGARC_HAL_RESTORE_GP()
These macros insert code to save and restore any global data pointer
These macros insert code to save and restore any global data pointer
that the ABI uses. These are necessary when switching context between
that the ABI uses. These are necessary when switching context between
two eCos instances - for example between an eCos application and
two eCos instances - for example between an eCos application and
RedBoot.
RedBoot.
Interrupt Handling
Interrupt Handling
These interfaces contain definitions related to interrupt
These interfaces contain definitions related to interrupt
handling. They include definitions of exception and interrupt numbers,
handling. They include definitions of exception and interrupt numbers,
interrupt enabling and masking, and realtime clock operations.
interrupt enabling and masking, and realtime clock operations.
These definitions are normally found in
These definitions are normally found in
cyg/hal/hal_intr.h.  This file is supplied by the
cyg/hal/hal_intr.h.  This file is supplied by the
architecture HAL.  Any variant or platform specific definitions will
architecture HAL.  Any variant or platform specific definitions will
be found in cyg/hal/var_intr.h,
be found in cyg/hal/var_intr.h,
cyg/hal/plf_intr.h or
cyg/hal/plf_intr.h or
cyg/hal/hal_platform_ints.h in the variant or platform
cyg/hal/hal_platform_ints.h in the variant or platform
HAL, depending on the exact target. These files are include
HAL, depending on the exact target. These files are include
automatically by this header, so need not be included explicitly.
automatically by this header, so need not be included explicitly.
Vector numbers
Vector numbers
CYGNUM_HAL_VECTOR_XXXX
CYGNUM_HAL_VECTOR_XXXX
CYGNUM_HAL_VSR_MIN
CYGNUM_HAL_VSR_MIN
CYGNUM_HAL_VSR_MAX
CYGNUM_HAL_VSR_MAX
CYGNUM_HAL_VSR_COUNT
CYGNUM_HAL_VSR_COUNT
CYGNUM_HAL_INTERRUPT_XXXX
CYGNUM_HAL_INTERRUPT_XXXX
CYGNUM_HAL_ISR_MIN
CYGNUM_HAL_ISR_MIN
CYGNUM_HAL_ISR_MAX
CYGNUM_HAL_ISR_MAX
CYGNUM_HAL_ISR_COUNT
CYGNUM_HAL_ISR_COUNT
CYGNUM_HAL_EXCEPTION_XXXX
CYGNUM_HAL_EXCEPTION_XXXX
CYGNUM_HAL_EXCEPTION_MIN
CYGNUM_HAL_EXCEPTION_MIN
CYGNUM_HAL_EXCEPTION_MAX
CYGNUM_HAL_EXCEPTION_MAX
CYGNUM_HAL_EXCEPTION_COUNT
CYGNUM_HAL_EXCEPTION_COUNT
All possible VSR, interrupt and exception vectors are specified here,
All possible VSR, interrupt and exception vectors are specified here,
together with maximum and minimum values for range checking. While the
together with maximum and minimum values for range checking. While the
VSR and exception numbers will be defined in this file, the interrupt
VSR and exception numbers will be defined in this file, the interrupt
numbers will normally be defined in the variant or platform HAL file
numbers will normally be defined in the variant or platform HAL file
that is included by this header.
that is included by this header.
There are two ranges of numbers, those for the vector service
There are two ranges of numbers, those for the vector service
routines and those for the interrupt service routines. The relationship
routines and those for the interrupt service routines. The relationship
between these two ranges is undefined, and no equivalence should
between these two ranges is undefined, and no equivalence should
be assumed if vectors from the two ranges coincide.
be assumed if vectors from the two ranges coincide.
The VSR vectors correspond to the set of exception vectors that can be
The VSR vectors correspond to the set of exception vectors that can be
delivered by the CPU architecture, many of these will be internal
delivered by the CPU architecture, many of these will be internal
exception traps. The ISR vectors correspond to the set of external
exception traps. The ISR vectors correspond to the set of external
interrupts that can be delivered and are usually determined by extra
interrupts that can be delivered and are usually determined by extra
decoding of the interrupt controller by the interrupt VSR.
decoding of the interrupt controller by the interrupt VSR.
Where a CPU supports synchronous exceptions, the range of such
Where a CPU supports synchronous exceptions, the range of such
exceptions allowed are defined by CYGNUM_HAL_EXCEPTION_MIN and
exceptions allowed are defined by CYGNUM_HAL_EXCEPTION_MIN and
CYGNUM_HAL_EXCEPTION_MAX. The
CYGNUM_HAL_EXCEPTION_MAX. The
CYGNUM_HAL_EXCEPTION_XXXX definitions are
CYGNUM_HAL_EXCEPTION_XXXX definitions are
standard names used by target independent code to test for the
standard names used by target independent code to test for the
presence of particular exceptions in the architecture. The actual
presence of particular exceptions in the architecture. The actual
exception numbers will normally correspond to the VSR exception
exception numbers will normally correspond to the VSR exception
range. In future other exceptions generated by the system software
range. In future other exceptions generated by the system software
(such as stack overflow) may be added.
(such as stack overflow) may be added.
CYGNUM_HAL_ISR_COUNT, CYGNUM_HAL_VSR_COUNT and
CYGNUM_HAL_ISR_COUNT, CYGNUM_HAL_VSR_COUNT and
CYGNUM_HAL_EXCEPTION_COUNT define the number of
CYGNUM_HAL_EXCEPTION_COUNT define the number of
ISRs, VSRs and EXCEPTIONs respectively for the purposes of defining
ISRs, VSRs and EXCEPTIONs respectively for the purposes of defining
arrays etc. There might be a translation from the supplied vector
arrays etc. There might be a translation from the supplied vector
numbers into array offsets. Hence
numbers into array offsets. Hence
CYGNUM_HAL_XXX_COUNT may not simply be
CYGNUM_HAL_XXX_COUNT may not simply be
CYGNUM_HAL_XXX_MAX - CYGNUM_HAL_XXX_MIN or CYGNUM_HAL_XXX_MAX+1.
CYGNUM_HAL_XXX_MAX - CYGNUM_HAL_XXX_MIN or CYGNUM_HAL_XXX_MAX+1.
Interrupt state control
Interrupt state control
CYG_INTERRUPT_STATE
CYG_INTERRUPT_STATE
HAL_DISABLE_INTERRUPTS( old )
HAL_DISABLE_INTERRUPTS( old )
HAL_RESTORE_INTERRUPTS( old )
HAL_RESTORE_INTERRUPTS( old )
HAL_ENABLE_INTERRUPTS()
HAL_ENABLE_INTERRUPTS()
HAL_QUERY_INTERRUPTS( state )
HAL_QUERY_INTERRUPTS( state )
These macros provide control over the state of the CPUs interrupt mask
These macros provide control over the state of the CPUs interrupt mask
mechanism. They should normally manipulate a CPU status register to
mechanism. They should normally manipulate a CPU status register to
enable and disable interrupt delivery. They should not access an
enable and disable interrupt delivery. They should not access an
interrupt controller.
interrupt controller.
CYG_INTERRUPT_STATE is a data type that should be
CYG_INTERRUPT_STATE is a data type that should be
used to store the interrupt state returned by
used to store the interrupt state returned by
HAL_DISABLE_INTERRUPTS() and
HAL_DISABLE_INTERRUPTS() and
HAL_QUERY_INTERRUPTS() and passed to
HAL_QUERY_INTERRUPTS() and passed to
HAL_RESTORE_INTERRUPTS().
HAL_RESTORE_INTERRUPTS().
HAL_DISABLE_INTERRUPTS() disables the delivery of
HAL_DISABLE_INTERRUPTS() disables the delivery of
interrupts and stores the original state of the interrupt mask in the
interrupts and stores the original state of the interrupt mask in the
variable passed in the old argument.
variable passed in the old argument.
HAL_RESTORE_INTERRUPTS() restores the state of
HAL_RESTORE_INTERRUPTS() restores the state of
the interrupt mask to that recorded in old.
the interrupt mask to that recorded in old.
HAL_ENABLE_INTERRUPTS() simply enables interrupts
HAL_ENABLE_INTERRUPTS() simply enables interrupts
regardless of the current state of the mask.
regardless of the current state of the mask.
HAL_QUERY_INTERRUPTS() stores the state of the
HAL_QUERY_INTERRUPTS() stores the state of the
interrupt mask in the variable passed in the 
interrupt mask in the variable passed in the 
state argument. The state stored here should also be
state argument. The state stored here should also be
capable of being passed to
capable of being passed to
HAL_RESTORE_INTERRUPTS() at a later point.
HAL_RESTORE_INTERRUPTS() at a later point.
It is at the HAL implementer’s discretion exactly
It is at the HAL implementer’s discretion exactly
which interrupts are masked by this mechanism. Where a CPU has more
which interrupts are masked by this mechanism. Where a CPU has more
than one interrupt type that may be masked separately (e.g. the
than one interrupt type that may be masked separately (e.g. the
ARM's IRQ and FIQ) only those that can raise DSRs need
ARM's IRQ and FIQ) only those that can raise DSRs need
to be masked here. A separate architecture specific mechanism may
to be masked here. A separate architecture specific mechanism may
then be used to control the other interrupt types.
then be used to control the other interrupt types.
ISR and VSR management
ISR and VSR management
HAL_INTERRUPT_IN_USE( vector, state )
HAL_INTERRUPT_IN_USE( vector, state )
HAL_INTERRUPT_ATTACH( vector, isr, data, object )
HAL_INTERRUPT_ATTACH( vector, isr, data, object )
HAL_INTERRUPT_DETACH( vector, isr )
HAL_INTERRUPT_DETACH( vector, isr )
HAL_VSR_SET( vector, vsr, poldvsr )
HAL_VSR_SET( vector, vsr, poldvsr )
HAL_VSR_GET( vector, pvsr )
HAL_VSR_GET( vector, pvsr )
HAL_VSR_SET_TO_ECOS_HANDLER( vector, poldvsr )
HAL_VSR_SET_TO_ECOS_HANDLER( vector, poldvsr )
These macros manage the attachment of interrupt and vector service
These macros manage the attachment of interrupt and vector service
routines to interrupt and exception vectors respectively.
routines to interrupt and exception vectors respectively.
HAL_INTERRUPT_IN_USE() tests the state of the
HAL_INTERRUPT_IN_USE() tests the state of the
supplied interrupt vector and sets the value of the state parameter to
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
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
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
vector, so it is a good idea to use this function before using
HAL_INTERRUPT_ATTACH().
HAL_INTERRUPT_ATTACH().
HAL_INTERRUPT_ATTACH() attaches
HAL_INTERRUPT_ATTACH() attaches
the ISR, data pointer and object pointer to the given
the ISR, data pointer and object pointer to the given
vector. When an interrupt occurs on this
vector. When an interrupt occurs on this
vector the ISR is called using the C calling convention and the vector
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
number and data pointer are passed to it as the first and second
arguments respectively.
arguments respectively.
HAL_INTERRUPT_DETACH() detaches the ISR from the
HAL_INTERRUPT_DETACH() detaches the ISR from the
vector.
vector.
HAL_VSR_SET() replaces the VSR attached to the
HAL_VSR_SET() replaces the VSR attached to the
vector with the replacement supplied in
vector with the replacement supplied in
vsr. The old VSR is returned in the location
vsr. The old VSR is returned in the location
pointed to by pvsr.
pointed to by pvsr.
HAL_VSR_GET() assigns
HAL_VSR_GET() assigns
a copy of the VSR to the location pointed to by pvsr.
a copy of the VSR to the location pointed to by pvsr.
HAL_VSR_SET_TO_ECOS_HANDLER() ensures that the
HAL_VSR_SET_TO_ECOS_HANDLER() ensures that the
VSR for a specific exception is pointing at the eCos exception VSR and
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
not one for RedBoot or some other ROM monitor. The default when
running under RedBoot is for exceptions to be handled by RedBoot and
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
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
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
replaces, and a location in which to store the old VSR pointer, so
that it may be replaced at a later point.
that it may be replaced at a later point.
Interrupt controller management
Interrupt controller management
HAL_INTERRUPT_MASK( vector )
HAL_INTERRUPT_MASK( vector )
HAL_INTERRUPT_UNMASK( vector )
HAL_INTERRUPT_UNMASK( vector )
HAL_INTERRUPT_ACKNOWLEDGE( vector )
HAL_INTERRUPT_ACKNOWLEDGE( vector )
HAL_INTERRUPT_CONFIGURE( vector, level, up )
HAL_INTERRUPT_CONFIGURE( vector, level, up )
HAL_INTERRUPT_SET_LEVEL( vector, level )
HAL_INTERRUPT_SET_LEVEL( vector, level )
These macros exert control over any prioritized interrupt
These macros exert control over any prioritized interrupt
controller that is present. If no priority controller exists, then
controller that is present. If no priority controller exists, then
these macros should be empty.
these macros should be empty.
  
  
  These macros may not be reentrant, so care should be taken to
  These macros may not be reentrant, so care should be taken to
  prevent them being called while interrupts are enabled. This means
  prevent them being called while interrupts are enabled. This means
  that they can be safely used in initialization code before
  that they can be safely used in initialization code before
  interrupts are enabled, and in ISRs. In DSRs, ASRs and thread code,
  interrupts are enabled, and in ISRs. In DSRs, ASRs and thread code,
  however, interrupts must be disabled before these macros are
  however, interrupts must be disabled before these macros are
  called. Here is an example for use in a DSR where the interrupt
  called. Here is an example for use in a DSR where the interrupt
  source is unmasked after data processing:
  source is unmasked after data processing:
  
  
 ...
 ...
 HAL_DISABLE_INTERRUPTS(old);
 HAL_DISABLE_INTERRUPTS(old);
 HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_ETH);
 HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_ETH);
 HAL_RESTORE_INTERRUPTS(old);
 HAL_RESTORE_INTERRUPTS(old);
 ...
 ...
HAL_INTERRUPT_MASK() causes the interrupt
HAL_INTERRUPT_MASK() causes the interrupt
associated with the given vector to be blocked.
associated with the given vector to be blocked.
HAL_INTERRUPT_UNMASK() causes the interrupt
HAL_INTERRUPT_UNMASK() causes the interrupt
associated with the given vector to be unblocked.
associated with the given vector to be unblocked.
HAL_INTERRUPT_ACKNOWLEDGE() acknowledges the
HAL_INTERRUPT_ACKNOWLEDGE() acknowledges the
current interrupt from the given vector. This is usually executed from
current interrupt from the given vector. This is usually executed from
the ISR for this vector when it is prepared to allow further
the ISR for this vector when it is prepared to allow further
interrupts.  Most interrupt controllers need some form of acknowledge
interrupts.  Most interrupt controllers need some form of acknowledge
action before the next interrupt is allowed through. Executing this
action before the next interrupt is allowed through. Executing this
macro may cause another interrupt to be delivered. Whether this
macro may cause another interrupt to be delivered. Whether this
interrupts the current code depends on the state of the CPU interrupt
interrupts the current code depends on the state of the CPU interrupt
mask.
mask.
HAL_INTERRUPT_CONFIGURE() provides
HAL_INTERRUPT_CONFIGURE() provides
control over how an interrupt signal is detected. The arguments
control over how an interrupt signal is detected. The arguments
are:
are:
  
  
    vector
    vector
    
    
      The interrupt vector to be configured.
      The interrupt vector to be configured.
    
    
  
  
  
  
    level
    level
    
    
      
      
      Set to true if the interrupt is detected by
      Set to true if the interrupt is detected by
      level, and false if it is edge triggered.
      level, and false if it is edge triggered.
      
      
    
    
  
  
  
  
    up
    up
    
    
      
      
      If the interrupt is set to level detect, then if this is
      If the interrupt is set to level detect, then if this is
      true it is detected by a high signal level,
      true it is detected by a high signal level,
      and if false by a low signal level. If the
      and if false by a low signal level. If the
      interrupt is set to edge triggered, then if this is
      interrupt is set to edge triggered, then if this is
      true it is triggered by a rising edge and if
      true it is triggered by a rising edge and if
      false by a falling edge.
      false by a falling edge.
      
      
    
    
  
  
HAL_INTERRUPT_SET_LEVEL() provides control over
HAL_INTERRUPT_SET_LEVEL() provides control over
the hardware priority of the interrupt. The arguments are:
the hardware priority of the interrupt. The arguments are:
  
  
    vector
    vector
    
    
      The interrupt whose level is to be set.
      The interrupt whose level is to be set.
    
    
  
  
  
  
    level
    level
    
    
      
      
      The priority level to which the interrupt is to set. In some
      The priority level to which the interrupt is to set. In some
      architectures the masking of an interrupt is achieved by
      architectures the masking of an interrupt is achieved by
      changing its priority level. Hence this function,
      changing its priority level. Hence this function,
      HAL_INTERRUPT_MASK() and
      HAL_INTERRUPT_MASK() and
      HAL_INTERRUPT_UNMASK() may interfere with
      HAL_INTERRUPT_UNMASK() may interfere with
      each other.
      each other.
      
      
    
    
  
  
Clock control
Clock control
HAL_CLOCK_INITIALIZE( period )
HAL_CLOCK_INITIALIZE( period )
HAL_CLOCK_RESET( vector, period )
HAL_CLOCK_RESET( vector, period )
HAL_CLOCK_READ( pvalue )
HAL_CLOCK_READ( pvalue )
These macros provide control over a clock or timer device that may be
These macros provide control over a clock or timer device that may be
used by the kernel to provide time-out, delay and scheduling
used by the kernel to provide time-out, delay and scheduling
services. The clock is assumed to be implemented by some form of
services. The clock is assumed to be implemented by some form of
counter that is incremented or decremented by some external source and
counter that is incremented or decremented by some external source and
which raises an interrupt when it reaches a predetermined value.
which raises an interrupt when it reaches a predetermined value.
HAL_CLOCK_INITIALIZE() initializes the timer
HAL_CLOCK_INITIALIZE() initializes the timer
device to interrupt at the given period. The period is essentially the
device to interrupt at the given period. The period is essentially the
value used to initialize the timer counter and must be calculated from
value used to initialize the timer counter and must be calculated from
the timer frequency and the desired interrupt rate. The timer device
the timer frequency and the desired interrupt rate. The timer device
should generate an interrupt every period cycles.
should generate an interrupt every period cycles.
HAL_CLOCK_RESET() re-initializes the timer to
HAL_CLOCK_RESET() re-initializes the timer to
provoke the next interrupt. This macro is only really necessary when
provoke the next interrupt. This macro is only really necessary when
the timer device needs to be reset in some way after each interrupt.
the timer device needs to be reset in some way after each interrupt.
HAL_CLOCK_READ() reads the current value of the
HAL_CLOCK_READ() reads the current value of the
timer counter and puts the value in the location pointed to by
timer counter and puts the value in the location pointed to by
pvalue. The value stored will always be the
pvalue. The value stored will always be the
number of timer cycles since the last interrupt, and hence ranges
number of timer cycles since the last interrupt, and hence ranges
between zero and the initial period value. If this is a count-down
between zero and the initial period value. If this is a count-down
cyclic timer, some arithmetic may be necessary to generate this value.
cyclic timer, some arithmetic may be necessary to generate this value.
Microsecond Delay
Microsecond Delay
HAL_DELAY_US(us)
HAL_DELAY_US(us)
This is an optional definition. If defined the macro implements a busy
This is an optional definition. If defined the macro implements a busy
loop delay for the given number of microseconds. This is usually
loop delay for the given number of microseconds. This is usually
implemented by waiting for the required number of hardware timer ticks
implemented by waiting for the required number of hardware timer ticks
to pass.
to pass.
This operation should normally be used when a very short delay is
This operation should normally be used when a very short delay is
needed when controlling hardware, programming FLASH devices and similar
needed when controlling hardware, programming FLASH devices and similar
situations where a wait/timeout loop would otherwise be used. Since it
situations where a wait/timeout loop would otherwise be used. Since it
may disable interrupts, and is implemented by busy waiting, it should
may disable interrupts, and is implemented by busy waiting, it should
not be used in code that is sensitive to interrupt or context switch
not be used in code that is sensitive to interrupt or context switch
latencies.
latencies.
HAL I/O
HAL I/O
This section contains definitions for supporting access
This section contains definitions for supporting access
to device control registers in an architecture neutral
to device control registers in an architecture neutral
fashion.
fashion.
These definitions are normally found in the header file
These definitions are normally found in the header file
cyg/hal/hal_io.h.  This file itself contains
cyg/hal/hal_io.h.  This file itself contains
macros that are generic to the architecture. If there are variant or
macros that are generic to the architecture. If there are variant or
platform specific IO access macros then these will be found in
platform specific IO access macros then these will be found in
cyg/hal/var_io.h and
cyg/hal/var_io.h and
cyg/hal/plf_io.h in the variant or platform HALs
cyg/hal/plf_io.h in the variant or platform HALs
respectively. These files are include automatically by this header, so
respectively. These files are include automatically by this header, so
need not be included explicitly.
need not be included explicitly.
This header (or more likely cyg/hal/plf_io.h) also
This header (or more likely cyg/hal/plf_io.h) also
defines the PCI access macros. For more information on these see 
defines the PCI access macros. For more information on these see 
linkend="pci-library-reference">.
linkend="pci-library-reference">.
Register address
Register address
HAL_IO_REGISTER
HAL_IO_REGISTER
This type is used to store the address of an I/O register. It will
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
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
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
address space plus offset pair into a single word, or may represent it
as a structure.
as a structure.
Values of variables and constants of this type will usually be
Values of variables and constants of this type will usually be
supplied by configuration mechanisms or in target specific headers.
supplied by configuration mechanisms or in target specific headers.
Register read
Register read
HAL_READ_XXX( register, value )
HAL_READ_XXX( register, value )
HAL_READ_XXX_VECTOR( register, buffer, count, stride )
HAL_READ_XXX_VECTOR( register, buffer, count, stride )
These macros support the reading of I/O registers in various
These macros support the reading of I/O registers in various
sizes. The XXX component of the name may be
sizes. The XXX component of the name may be
UINT8, UINT16,
UINT8, UINT16,
UINT32.
UINT32.
HAL_READ_XXX() reads the appropriately sized
HAL_READ_XXX() reads the appropriately sized
value from the register and stores it in the variable passed as the
value from the register and stores it in the variable passed as the
second argument.
second argument.
HAL_READ_XXX_VECTOR() reads
HAL_READ_XXX_VECTOR() reads
count values of the appropriate size into
count values of the appropriate size into
buffer. The stride
buffer. The stride
controls how the pointer advances through the register space. A stride
controls how the pointer advances through the register space. A stride
of zero will read the same register repeatedly, and a stride of one
of zero will read the same register repeatedly, and a stride of one
will read adjacent registers of the given size. Greater strides will
will read adjacent registers of the given size. Greater strides will
step by larger amounts, to allow for sparsely mapped registers for
step by larger amounts, to allow for sparsely mapped registers for
example.
example.
Register write
Register write
HAL_WRITE_XXX( register, value )
HAL_WRITE_XXX( register, value )
HAL_WRITE_XXX_VECTOR( register, buffer,count, stride )
HAL_WRITE_XXX_VECTOR( register, buffer,count, stride )
These macros support the writing of I/O registers in various
These macros support the writing of I/O registers in various
sizes. The XXX component of the name may be
sizes. The XXX component of the name may be
UINT8, UINT16,
UINT8, UINT16,
UINT32.
UINT32.
HAL_WRITE_XXX() writes
HAL_WRITE_XXX() writes
the appropriately sized value from the variable passed as the second argument
the appropriately sized value from the variable passed as the second argument
stored it in the register.
stored it in the register.
HAL_WRITE_XXX_VECTOR() writes
HAL_WRITE_XXX_VECTOR() writes
count values of the appropriate size from 
count values of the appropriate size from 
buffer. The stride controls
buffer. The stride controls
how the pointer advances through the register space. A stride of
how the pointer advances through the register space. A stride of
zero will write the same register repeatedly, and a stride of one
zero will write the same register repeatedly, and a stride of one
will write adjacent registers of the given size. Greater strides
will write adjacent registers of the given size. Greater strides
will step by larger amounts, to allow for sparsely mapped registers
will step by larger amounts, to allow for sparsely mapped registers
for example.
for example.
Cache Control
Cache Control
This section contains definitions for supporting control
This section contains definitions for supporting control
of the caches on the CPU.
of the caches on the CPU.
These definitions are usually found in the header file
These definitions are usually found in the header file
cyg/hal/hal_cache.h.  This file may be defined in
cyg/hal/hal_cache.h.  This file may be defined in
the architecture, variant or platform HAL, depending on where the
the architecture, variant or platform HAL, depending on where the
caches are implemented for the target. Often there will be a generic
caches are implemented for the target. Often there will be a generic
implementation of the cache control macros in the architecture HAL
implementation of the cache control macros in the architecture HAL
with the ability to override or undefine them in the variant or
with the ability to override or undefine them in the variant or
platform HAL. Even when the implementation of the cache macros is in
platform HAL. Even when the implementation of the cache macros is in
the architecture HAL, the cache dimensions will be defined in the
the architecture HAL, the cache dimensions will be defined in the
variant or platform HAL. As with other files, the variant or platform
variant or platform HAL. As with other files, the variant or platform
specific definitions are usually found in
specific definitions are usually found in
cyg/hal/var_cache.h and
cyg/hal/var_cache.h and
cyg/hal/plf_cache.h respectively.  These files
cyg/hal/plf_cache.h respectively.  These files
are include automatically by this header, so need not be included
are include automatically by this header, so need not be included
explicitly.
explicitly.
There are versions of the macros defined here for both the Data and
There are versions of the macros defined here for both the Data and
Instruction caches. these are distinguished by the use of either
Instruction caches. these are distinguished by the use of either
DCACHE or ICACHE in the macro
DCACHE or ICACHE in the macro
names. Some architectures have a unified cache, where both data and
names. Some architectures have a unified cache, where both data and
instruction share the same cache. In these cases the control macros
instruction share the same cache. In these cases the control macros
use UCACHE and the DCACHE and
use UCACHE and the DCACHE and
ICACHE macros will just be calls to the
ICACHE macros will just be calls to the
UCACHE version. In the following descriptions,
UCACHE version. In the following descriptions,
XCACHE is used to stand for any of these. Where
XCACHE is used to stand for any of these. Where
there are issues specific to a particular cache, this will be
there are issues specific to a particular cache, this will be
explained in the text.
explained in the text.
There might be target specific restrictions on the use of some of the
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
macros which it is the user's responsibility to comply with. Such
restrictions are documented in the header file with the macro
restrictions are documented in the header file with the macro
definition.
definition.
Note that destructive cache macros should be used with caution.
Note that destructive cache macros should be used with caution.
Preceding a cache invalidation with a cache synchronization is not
Preceding a cache invalidation with a cache synchronization is not
safe in itself since an interrupt may happen after the synchronization
safe in itself since an interrupt may happen after the synchronization
but before the invalidation. This might cause the state of dirty data
but before the invalidation. This might cause the state of dirty data
lines created during the interrupt to be lost.
lines created during the interrupt to be lost.
Depending on the architecture's capabilities, it may be possible to
Depending on the architecture's capabilities, it may be possible to
temporarily disable the cache while doing the synchronization and
temporarily disable the cache while doing the synchronization and
invalidation which solves the problem (no new data would be cached
invalidation which solves the problem (no new data would be cached
during an interrupt). Otherwise it is necessary to disable interrupts
during an interrupt). Otherwise it is necessary to disable interrupts
while manipulating the cache which may take a long time.
while manipulating the cache which may take a long time.
Some platform HALs now support a pair of cache state query
Some platform HALs now support a pair of cache state query
macros: HAL_ICACHE_IS_ENABLED( x ) and
macros: HAL_ICACHE_IS_ENABLED( x ) and
HAL_DCACHE_IS_ENABLED( x ) which set the argument
HAL_DCACHE_IS_ENABLED( x ) which set the argument
to true if the instruction or data cache is enabled,
to true if the instruction or data cache is enabled,
respectively. Like most cache control macros, these are optional,
respectively. Like most cache control macros, these are optional,
because the capabilities of different targets and boards can vary
because the capabilities of different targets and boards can vary
considerably. Code which uses them, if it is to be considered
considerably. Code which uses them, if it is to be considered
portable, should test for their existence first by means of
portable, should test for their existence first by means of
#ifdef.  Be sure to include
#ifdef.  Be sure to include
<cyg/hal/hal_cache.h> in order to do this
<cyg/hal/hal_cache.h> in order to do this
test and (maybe) use the macros.
test and (maybe) use the macros.
Cache Dimensions
Cache Dimensions
HAL_XCACHE_SIZE
HAL_XCACHE_SIZE
HAL_XCACHE_LINE_SIZE
HAL_XCACHE_LINE_SIZE
HAL_XCACHE_WAYS
HAL_XCACHE_WAYS
HAL_XCACHE_SETS
HAL_XCACHE_SETS
These macros define the size and dimensions of the Instruction
These macros define the size and dimensions of the Instruction
and Data caches.
and Data caches.
  
  
    HAL_XCACHE_SIZE     
    HAL_XCACHE_SIZE     
    
    
      Defines the total size of the cache in bytes.
      Defines the total size of the cache in bytes.
    
    
  
  
  
  
    HAL_XCACHE_LINE_SIZE        
    HAL_XCACHE_LINE_SIZE        
    
    
      Defines the cache line size in bytes.
      Defines the cache line size in bytes.
    
    
  
  
  
  
    HAL_XCACHE_WAYS     
    HAL_XCACHE_WAYS     
    
    
      
      
      Defines the number of ways in each set and defines its level
      Defines the number of ways in each set and defines its level
      of associativity. This would be 1 for a direct mapped
      of associativity. This would be 1 for a direct mapped
      cache, 2 for a 2-way cache, 4 for 4-way and so on.
      cache, 2 for a 2-way cache, 4 for 4-way and so on.
      
      
    
    
  
  
  
  
    HAL_XCACHE_SETS     
    HAL_XCACHE_SETS     
    
    
      
      
      Defines the number of sets in the cache, and is calculated from
      Defines the number of sets in the cache, and is calculated from
      the previous values.
      the previous values.
      
      
    
    
  
  
Global Cache Control
Global Cache Control
HAL_XCACHE_ENABLE()
HAL_XCACHE_ENABLE()
HAL_XCACHE_DISABLE()
HAL_XCACHE_DISABLE()
HAL_XCACHE_INVALIDATE_ALL()
HAL_XCACHE_INVALIDATE_ALL()
HAL_XCACHE_SYNC()
HAL_XCACHE_SYNC()
HAL_XCACHE_BURST_SIZE( size )
HAL_XCACHE_BURST_SIZE( size )
HAL_DCACHE_WRITE_MODE( mode )
HAL_DCACHE_WRITE_MODE( mode )
HAL_XCACHE_LOCK( base, size )
HAL_XCACHE_LOCK( base, size )
HAL_XCACHE_UNLOCK( base, size )
HAL_XCACHE_UNLOCK( base, size )
HAL_XCACHE_UNLOCK_ALL()
HAL_XCACHE_UNLOCK_ALL()
These macros affect the state of the entire cache, or a large part of
These macros affect the state of the entire cache, or a large part of
it.
it.
  
  
    HAL_XCACHE_ENABLE() and HAL_XCACHE_DISABLE()
    HAL_XCACHE_ENABLE() and HAL_XCACHE_DISABLE()
    
    
      Enable and disable the cache.
      Enable and disable the cache.
    
    
  
  
  
  
    HAL_XCACHE_INVALIDATE_ALL()
    HAL_XCACHE_INVALIDATE_ALL()
    
    
      
      
      Causes the entire contents of the cache to be invalidated.
      Causes the entire contents of the cache to be invalidated.
      Depending on the hardware, this may require the cache to be disabled
      Depending on the hardware, this may require the cache to be disabled
      during the invalidation process. If so, the implementation must
      during the invalidation process. If so, the implementation must
      use HAL_XCACHE_IS_ENABLED() to save and
      use HAL_XCACHE_IS_ENABLED() to save and
      restore the previous state.
      restore the previous state.
      
      
      
      
        
        
        If this macro is called after
        If this macro is called after
        HAL_XCACHE_SYNC() with the intention of clearing
        HAL_XCACHE_SYNC() with the intention of clearing
        the cache (invalidating the cache after writing dirty data back to
        the cache (invalidating the cache after writing dirty data back to
        memory), you must prevent interrupts from happening between the two
        memory), you must prevent interrupts from happening between the two
        calls:
        calls:
        
        
 ...
 ...
 HAL_DISABLE_INTERRUPTS(old);
 HAL_DISABLE_INTERRUPTS(old);
 HAL_XCACHE_SYNC();
 HAL_XCACHE_SYNC();
 HAL_XCACHE_INVALIDATE_ALL();
 HAL_XCACHE_INVALIDATE_ALL();
 HAL_RESTORE_INTERRUPTS(old);
 HAL_RESTORE_INTERRUPTS(old);
 ...
 ...
        
        
        Since the operation may take a very long time, real-time
        Since the operation may take a very long time, real-time
        responsiveness could be affected, so only do this when it is
        responsiveness could be affected, so only do this when it is
        absolutely required and you know the delay will not interfere
        absolutely required and you know the delay will not interfere
        with the operation of drivers or the application.
        with the operation of drivers or the application.
        
        
      
      
    
    
  
  
  
  
    HAL_XCACHE_SYNC()
    HAL_XCACHE_SYNC()
    
    
      
      
      Causes the contents of the cache to be brought into synchronization
      Causes the contents of the cache to be brought into synchronization
      with the contents of memory. In some implementations this may be
      with the contents of memory. In some implementations this may be
      equivalent to HAL_XCACHE_INVALIDATE_ALL().
      equivalent to HAL_XCACHE_INVALIDATE_ALL().
      
      
    
    
  
  
  
  
    HAL_XCACHE_BURST_SIZE()
    HAL_XCACHE_BURST_SIZE()
    
    
      
      
      Allows the size of cache to/from memory bursts to
      Allows the size of cache to/from memory bursts to
      be controlled. This macro will only be defined if this functionality
      be controlled. This macro will only be defined if this functionality
      is available.
      is available.
      
      
    
    
  
  
  
  
    HAL_DCACHE_WRITE_MODE()
    HAL_DCACHE_WRITE_MODE()
    
    
      
      
      Controls the way in which data cache lines are written back to
      Controls the way in which data cache lines are written back to
      memory. There will be definitions for the possible
      memory. There will be definitions for the possible
      modes. Typical definitions are
      modes. Typical definitions are
      HAL_DCACHE_WRITEBACK_MODE and
      HAL_DCACHE_WRITEBACK_MODE and
      HAL_DCACHE_WRITETHRU_MODE. This macro will
      HAL_DCACHE_WRITETHRU_MODE. This macro will
      only be defined if this functionality is available.
      only be defined if this functionality is available.
      
      
    
    
  
  
  
  
    HAL_XCACHE_LOCK()
    HAL_XCACHE_LOCK()
    
    
      
      
      Causes data to be locked into the cache. The base and size
      Causes data to be locked into the cache. The base and size
      arguments define the memory region that will be locked into the
      arguments define the memory region that will be locked into the
      cache. It is architecture dependent whether more than one locked
      cache. It is architecture dependent whether more than one locked
      region is allowed at any one time, and whether this operation
      region is allowed at any one time, and whether this operation
      causes the cache to cease acting as a cache for addresses
      causes the cache to cease acting as a cache for addresses
      outside the region during the duration of the lock. This macro
      outside the region during the duration of the lock. This macro
      will only be defined if this functionality is available.
      will only be defined if this functionality is available.
      
      
    
    
  
  
  
  
    HAL_XCACHE_UNLOCK()
    HAL_XCACHE_UNLOCK()
    
    
      
      
      Cancels the locking of the memory region given. This should
      Cancels the locking of the memory region given. This should
      normally correspond to a region supplied in a matching lock
      normally correspond to a region supplied in a matching lock
      call.  This macro will only be defined if this functionality is
      call.  This macro will only be defined if this functionality is
      available.
      available.
      
      
    
    
  
  
  
  
    HAL_XCACHE_UNLOCK_ALL()
    HAL_XCACHE_UNLOCK_ALL()
    
    
      
      
      Cancels all existing locked memory regions. This may be required
      Cancels all existing locked memory regions. This may be required
      as part of the cache initialization on some architectures. This
      as part of the cache initialization on some architectures. This
      macro will only be defined if this functionality is available.
      macro will only be defined if this functionality is available.
      
      
    
    
  
  
Cache Line Control
Cache Line Control
HAL_DCACHE_ALLOCATE( base , size )
HAL_DCACHE_ALLOCATE( base , size )
HAL_DCACHE_FLUSH( base , size )
HAL_DCACHE_FLUSH( base , size )
HAL_XCACHE_INVALIDATE( base , size )
HAL_XCACHE_INVALIDATE( base , size )
HAL_DCACHE_STORE( base , size )
HAL_DCACHE_STORE( base , size )
HAL_DCACHE_READ_HINT( base , size )
HAL_DCACHE_READ_HINT( base , size )
HAL_DCACHE_WRITE_HINT( base , size )
HAL_DCACHE_WRITE_HINT( base , size )
HAL_DCACHE_ZERO( base , size )
HAL_DCACHE_ZERO( base , size )
All of these macros apply a cache operation to all cache lines that
All of these macros apply a cache operation to all cache lines that
match the memory address region defined by the base and size
match the memory address region defined by the base and size
arguments. These macros will only be defined if the described
arguments. These macros will only be defined if the described
functionality is available. Also, it is not guaranteed that the cache
functionality is available. Also, it is not guaranteed that the cache
function will only be applied to just the described regions, in some
function will only be applied to just the described regions, in some
architectures it may be applied to the whole cache.
architectures it may be applied to the whole cache.
  
  
    HAL_DCACHE_ALLOCATE()
    HAL_DCACHE_ALLOCATE()
    
    
      
      
      Allocates lines in the cache for the given region without
      Allocates lines in the cache for the given region without
      reading their contents from memory, hence the contents of the lines
      reading their contents from memory, hence the contents of the lines
      is undefined. This is useful for preallocating lines which are to
      is undefined. This is useful for preallocating lines which are to
      be completely overwritten, for example in a block copy
      be completely overwritten, for example in a block copy
      operation.
      operation.
      
      
    
    
  
  
  
  
    HAL_DCACHE_FLUSH()
    HAL_DCACHE_FLUSH()
    
    
      
      
      Invalidates all cache lines in the region after writing any
      Invalidates all cache lines in the region after writing any
      dirty lines to memory.
      dirty lines to memory.
      
      
    
    
  
  
  
  
    HAL_XCACHE_INVALIDATE() 
    HAL_XCACHE_INVALIDATE() 
    
    
      
      
      Invalidates all cache lines in the region. Any dirty lines
      Invalidates all cache lines in the region. Any dirty lines
      are invalidated without being written to memory.
      are invalidated without being written to memory.
      
      
    
    
  
  
  
  
    HAL_DCACHE_STORE() 
    HAL_DCACHE_STORE() 
    
    
      
      
      Writes all dirty lines in the region to memory, but does not
      Writes all dirty lines in the region to memory, but does not
      invalidate any lines.
      invalidate any lines.
      
      
    
    
  
  
  
  
    HAL_DCACHE_READ_HINT() 
    HAL_DCACHE_READ_HINT() 
    
    
      
      
      Hints to the cache that the region is going to be read from
      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
      in the near future. This may cause the region to be speculatively
      read into the cache.
      read into the cache.
      
      
    
    
  
  
  
  
    HAL_DCACHE_WRITE_HINT() 
    HAL_DCACHE_WRITE_HINT() 
    
    
      
      
      Hints to the cache that the region is going to be written
      Hints to the cache that the region is going to be written
      to in the near future. This may have the identical behavior to
      to in the near future. This may have the identical behavior to
      HAL_DCACHE_READ_HINT().
      HAL_DCACHE_READ_HINT().
      
      
    
    
  
  
  
  
    HAL_DCACHE_ZERO()
    HAL_DCACHE_ZERO()
    
    
      
      
      Allocates and zeroes lines in the cache for the given
      Allocates and zeroes lines in the cache for the given
      region without reading memory. This is useful if a large area of
      region without reading memory. This is useful if a large area of
      memory is to be cleared.
      memory is to be cleared.
      
      
    
    
  
  
<!-- <xref> -->Linker Scripts
<!-- <xref> -->Linker Scripts
When an eCos application is linked it must be done under the control
When an eCos application is linked it must be done under the control
of a linker script. This script defines the memory areas, addresses
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
and sized, into which the code and data are to be put, and allocates
the various sections generated by the compiler to these.
the various sections generated by the compiler to these.
The linker script actually used is in
The linker script actually used is in
lib/target.ld in the install directory. This is
lib/target.ld in the install directory. This is
actually manufactured out of two other files: a base linker script and
actually manufactured out of two other files: a base linker script and
an .ldi file that was generated by the memory
an .ldi file that was generated by the memory
layout tool.
layout tool.
The base linker script is usually supplied either by the architecture
The base linker script is usually supplied either by the architecture
HAL or the variant HAL. It consists of a set of linker script
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
fragments, in the form of C preprocessor macros, that define the major
output sections to be generated by the link operation. The
output sections to be generated by the link operation. The
.ldi file, which is #include'ed
.ldi file, which is #include'ed
by the base linker script, uses these macro definitions to assign the
by the base linker script, uses these macro definitions to assign the
output sections to the required memory areas and link addresses.
output sections to the required memory areas and link addresses.
The .ldi file is supplied by the platform HAL, and
The .ldi file is supplied by the platform HAL, and
contains knowledge of the memory layout of the target platform. These
contains knowledge of the memory layout of the target platform. These
files generally conform to a standard naming convention, each file
files generally conform to a standard naming convention, each file
being of the form:
being of the form:
pkgconf/mlt_<architecture>_<variant>_<platform>_<startup>.ldi
pkgconf/mlt_<architecture>_<variant>_<platform>_<startup>.ldi
where <architecture>,
where <architecture>,
<variant> and
<variant> and
<platform> are the respective HAL package
<platform> are the respective HAL package
names and <startup> is the startup type which
names and <startup> is the startup type which
is usually one of ROM, RAM or
is usually one of ROM, RAM or
ROMRAM.
ROMRAM.
In addition to the .ldi file, there is also a
In addition to the .ldi file, there is also a
congruously name .h file. This may be used by the
congruously name .h file. This may be used by the
application to access information defined in the
application to access information defined in the
.ldi file. Specifically it contains the memory
.ldi file. Specifically it contains the memory
layout defined there, together with any additional section names
layout defined there, together with any additional section names
defined by the user. Examples of the latter are heap areas or PCI bus
defined by the user. Examples of the latter are heap areas or PCI bus
memory access windows.
memory access windows.
The .ldi is manufactured by the Memory
The .ldi is manufactured by the Memory
Layout Tool (MLT). The MLT saves the memory
Layout Tool (MLT). The MLT saves the memory
configuration into a file named
configuration into a file named
include/pkgconf/mlt_<architecture>_<variant>_<platform>_<startup>.mlt
include/pkgconf/mlt_<architecture>_<variant>_<platform>_<startup>.mlt
in the platform HAL. This file is used by the
in the platform HAL. This file is used by the
MLT to manufacture both the
MLT to manufacture both the
.ldi and .h files. Users should
.ldi and .h files. Users should
beware that direct edits the either of these files may be overwritten
beware that direct edits the either of these files may be overwritten
if the MLT is run and regenerates them from the
if the MLT is run and regenerates them from the
.mlt file.
.mlt file.
The names of the .ldi and .h
The names of the .ldi and .h
files are defined by macro definitions in
files are defined by macro definitions in
pkgconf/system.h. These are
pkgconf/system.h. These are
CYGHWR_MEMORY_LAYOUT_LDI and
CYGHWR_MEMORY_LAYOUT_LDI and
CYGHWR_MEMORY_LAYOUT_H respectively. While there
CYGHWR_MEMORY_LAYOUT_H respectively. While there
will be little need for the application to refer to the
will be little need for the application to refer to the
.ldi file directly, it may include the
.ldi file directly, it may include the
.h file as follows:
.h file as follows:
#include CYGHWR_MEMORY_LAYOUT_H
#include CYGHWR_MEMORY_LAYOUT_H
Diagnostic Support
Diagnostic Support
The HAL provides support for low level diagnostic IO. This is
The HAL provides support for low level diagnostic IO. This is
particularly useful during early development as an aid to bringing up
particularly useful during early development as an aid to bringing up
a new platform. Usually this diagnostic channel is a UART or some
a new platform. Usually this diagnostic channel is a UART or some
other serial IO device, but it may equally be a a memory
other serial IO device, but it may equally be a a memory
buffer, a simulator supported output channel, a ROM emulator virtual
buffer, a simulator supported output channel, a ROM emulator virtual
UART, and LCD panel, a memory mapped video buffer or any other output
UART, and LCD panel, a memory mapped video buffer or any other output
device.
device.
HAL_DIAG_INIT() performs any initialization
HAL_DIAG_INIT() performs any initialization
required on the device being used to generate diagnostic output. This
required on the device being used to generate diagnostic output. This
may include, for a UART, setting baud rate, and stop, parity and
may include, for a UART, setting baud rate, and stop, parity and
character bits. For other devices it may include initializing a
character bits. For other devices it may include initializing a
controller or establishing contact with a remote device.
controller or establishing contact with a remote device.
HAL_DIAG_WRITE_CHAR(c) writes
HAL_DIAG_WRITE_CHAR(c) writes
the character supplied to the diagnostic output device.
the character supplied to the diagnostic output device.
HAL_DIAG_READ_CHAR(c) reads a character from the
HAL_DIAG_READ_CHAR(c) reads a character from the
diagnostic device into the supplied variable. This is not supported
diagnostic device into the supplied variable. This is not supported
for all diagnostic devices.
for all diagnostic devices.
These macros are defined in the header file
These macros are defined in the header file
cyg/hal/hal_diag.h. This file is usually supplied
cyg/hal/hal_diag.h. This file is usually supplied
by the variant or platform HAL, depending on where the IO device being
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
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
variant HAL, but for a board-level LCD panel it would be in the
platform HAL.
platform HAL.
SMP Support
SMP Support
eCos contains support for limited Symmetric Multi-Processing
eCos contains support for limited Symmetric Multi-Processing
(SMP). This is only available on selected architectures and platforms.
(SMP). This is only available on selected architectures and platforms.
Target Hardware Limitations
Target Hardware Limitations
To allow a reasonable implementation of SMP, and to reduce the
To allow a reasonable implementation of SMP, and to reduce the
disruption to the existing source base, a number of assumptions have
disruption to the existing source base, a number of assumptions have
been made about the features of the target hardware.
been made about the features of the target hardware.
Modest multiprocessing. The typical number of CPUs supported is two
Modest multiprocessing. The typical number of CPUs supported is two
to four, with an upper limit around eight. While there are no
to four, with an upper limit around eight. While there are no
inherent limits in the code, hardware and algorithmic limitations
inherent limits in the code, hardware and algorithmic limitations
will probably become significant beyond this point.
will probably become significant beyond this point.
SMP synchronization support. The hardware must supply a mechanism to
SMP synchronization support. The hardware must supply a mechanism to
allow software on two CPUs to synchronize. This is normally provided
allow software on two CPUs to synchronize. This is normally provided
as part of the instruction set in the form of test-and-set,
as part of the instruction set in the form of test-and-set,
compare-and-swap or load-link/store-conditional instructions. An
compare-and-swap or load-link/store-conditional instructions. An
alternative approach is the provision of hardware semaphore
alternative approach is the provision of hardware semaphore
registers which can be used to serialize implementations of these
registers which can be used to serialize implementations of these
operations. Whatever hardware facilities are available, they are
operations. Whatever hardware facilities are available, they are
used in eCos to implement spinlocks.
used in eCos to implement spinlocks.
Coherent caches. It is assumed that no extra effort will be required
Coherent caches. It is assumed that no extra effort will be required
to access shared memory from any processor. This means that either
to access shared memory from any processor. This means that either
there are no caches, they are shared by all processors, or are
there are no caches, they are shared by all processors, or are
maintained in a coherent state by the hardware. It would be too
maintained in a coherent state by the hardware. It would be too
disruptive to the eCos sources if every memory access had to be
disruptive to the eCos sources if every memory access had to be
bracketed by cache load/flush operations. Any hardware that requires
bracketed by cache load/flush operations. Any hardware that requires
this is not supported.
this is not supported.
Uniform addressing. It is assumed that all memory that is
Uniform addressing. It is assumed that all memory that is
shared between CPUs is addressed at the same location from all
shared between CPUs is addressed at the same location from all
CPUs. Like non-coherent caches, dealing with CPU-specific address
CPUs. Like non-coherent caches, dealing with CPU-specific address
translation is considered too disruptive to the eCos source
translation is considered too disruptive to the eCos source
base. This does not, however, preclude systems with non-uniform
base. This does not, however, preclude systems with non-uniform
access costs for different CPUs.
access costs for different CPUs.
Uniform device addressing. As with access to memory, it is assumed
Uniform device addressing. As with access to memory, it is assumed
that all devices are equally accessible to all CPUs. Since device
that all devices are equally accessible to all CPUs. Since device
access is often made from thread contexts, it is not possible to
access is often made from thread contexts, it is not possible to
restrict access to device control registers to certain CPUs, since
restrict access to device control registers to certain CPUs, since
there is currently no support for binding or migrating threads to CPUs.
there is currently no support for binding or migrating threads to CPUs.
Interrupt routing. The target hardware must have an interrupt
Interrupt routing. The target hardware must have an interrupt
controller that can route interrupts to specific CPUs. It is
controller that can route interrupts to specific CPUs. It is
acceptable for all interrupts to be delivered to just one CPU, or
acceptable for all interrupts to be delivered to just one CPU, or
for some interrupts to be bound to specific CPUs, or for some
for some interrupts to be bound to specific CPUs, or for some
interrupts to be local to each CPU. At present dynamic routing,
interrupts to be local to each CPU. At present dynamic routing,
where a different CPU may be chosen each time an interrupt is
where a different CPU may be chosen each time an interrupt is
delivered, is not supported. ECos cannot support hardware where all
delivered, is not supported. ECos cannot support hardware where all
interrupts are delivered to all CPUs simultaneously with the
interrupts are delivered to all CPUs simultaneously with the
expectation that software will resolve any conflicts.
expectation that software will resolve any conflicts.
Inter-CPU interrupts. A mechanism to allow one CPU to interrupt
Inter-CPU interrupts. A mechanism to allow one CPU to interrupt
another is needed. This is necessary so that events on one CPU can
another is needed. This is necessary so that events on one CPU can
cause rescheduling on other CPUs.
cause rescheduling on other CPUs.
CPU Identifiers. Code running on a CPU must be able to determine
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
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
a CPU status register, or in a register associated with the
inter-CPU interrupt delivery subsystem. ECos expects CPU Ids to be
inter-CPU interrupt delivery subsystem. ECos expects CPU Ids to be
small positive integers, although alternative representations, such
small positive integers, although alternative representations, such
as bitmaps, can be converted relatively easily. Complex mechanisms
as bitmaps, can be converted relatively easily. Complex mechanisms
for getting the CPU Id cannot be supported. Getting the CPU Id must
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
be a cheap operation, since it is done often, and in performance
critical places such as interrupt handlers and the scheduler.
critical places such as interrupt handlers and the scheduler.
HAL Support
HAL Support
SMP support in any platform depends on the HAL supplying the
SMP support in any platform depends on the HAL supplying the
appropriate operations. All HAL SMP support is defined in the
appropriate operations. All HAL SMP support is defined in the
cyg/hal/hal_smp.h header. Variant and platform
cyg/hal/hal_smp.h header. Variant and platform
specific definitions will be in cyg/hal/var_smp.h
specific definitions will be in cyg/hal/var_smp.h
and cyg/hal/plf_smp.h respectively. These files
and cyg/hal/plf_smp.h respectively. These files
are include automatically by this header, so need not be included
are include automatically by this header, so need not be included
explicitly.
explicitly.
SMP support falls into a number of functional groups.
SMP support falls into a number of functional groups.
CPU Control
CPU Control
This group consists of descriptive and control macros for managing the
This group consists of descriptive and control macros for managing the
CPUs in an SMP system.
CPUs in an SMP system.
HAL_SMP_CPU_TYPE
HAL_SMP_CPU_TYPE
A type that can contain a CPU id. A CPU id is
A type that can contain a CPU id. A CPU id is
usually a small integer that is used to index
usually a small integer that is used to index
arrays of variables that are managed on an
arrays of variables that are managed on an
per-CPU basis.
per-CPU basis.
HAL_SMP_CPU_MAX
HAL_SMP_CPU_MAX
The maximum number of CPUs that can be
The maximum number of CPUs that can be
supported. This is used to provide the size of
supported. This is used to provide the size of
any arrays that have an element per CPU.
any arrays that have an element per CPU.
HAL_SMP_CPU_COUNT()
HAL_SMP_CPU_COUNT()
Returns the number of CPUs currently
Returns the number of CPUs currently
operational. This may differ from
operational. This may differ from
HAL_SMP_CPU_MAX depending on the runtime
HAL_SMP_CPU_MAX depending on the runtime
environment.
environment.
HAL_SMP_CPU_THIS()
HAL_SMP_CPU_THIS()
Returns the CPU id of the current CPU.
Returns the CPU id of the current CPU.
HAL_SMP_CPU_NONE
HAL_SMP_CPU_NONE
A value that does not match any real CPU
A value that does not match any real CPU
id. This is uses where a CPU type variable
id. This is uses where a CPU type variable
must be set to a null value.
must be set to a null value.
HAL_SMP_CPU_START( cpu )
HAL_SMP_CPU_START( cpu )
Starts the given CPU executing at a defined
Starts the given CPU executing at a defined
HAL entry point. After performing any HAL
HAL entry point. After performing any HAL
level initialization, the CPU calls up into
level initialization, the CPU calls up into
the kernel at cyg_kernel_cpu_startup().
the kernel at cyg_kernel_cpu_startup().
HAL_SMP_CPU_RESCHEDULE_INTERRUPT( cpu, wait )
HAL_SMP_CPU_RESCHEDULE_INTERRUPT( cpu, wait )
Sends the CPU a reschedule interrupt, and if
Sends the CPU a reschedule interrupt, and if
wait is non-zero, waits for an
wait is non-zero, waits for an
acknowledgment. The interrupted CPU should call
acknowledgment. The interrupted CPU should call
cyg_scheduler_set_need_reschedule() in its DSR to
cyg_scheduler_set_need_reschedule() in its DSR to
cause the reschedule to occur.
cause the reschedule to occur.
HAL_SMP_CPU_TIMESLICE_INTERRUPT( cpu, wait )
HAL_SMP_CPU_TIMESLICE_INTERRUPT( cpu, wait )
Sends the CPU a timeslice interrupt, and if
Sends the CPU a timeslice interrupt, and if
wait is non-zero, waits for an
wait is non-zero, waits for an
acknowledgment. The interrupted CPU should call
acknowledgment. The interrupted CPU should call
cyg_scheduler_timeslice_cpu() to cause the
cyg_scheduler_timeslice_cpu() to cause the
timeslice event to be processed.
timeslice event to be processed.
Test-and-set Support
Test-and-set Support
Test-and-set is the foundation of the SMP synchronization
Test-and-set is the foundation of the SMP synchronization
mechanisms.
mechanisms.
HAL_TAS_TYPE
HAL_TAS_TYPE
The type for all test-and-set variables. The
The type for all test-and-set variables. The
test-and-set macros only support operations on
test-and-set macros only support operations on
a single bit (usually the least significant
a single bit (usually the least significant
bit) of this location. This allows for maximum
bit) of this location. This allows for maximum
flexibility in the implementation.
flexibility in the implementation.
HAL_TAS_SET( tas, oldb )
HAL_TAS_SET( tas, oldb )
Performs a test and set operation on the
Performs a test and set operation on the
location tas. oldb will contain true if
location tas. oldb will contain true if
the location was already set, and false if
the location was already set, and false if
it was clear.
it was clear.
HAL_TAS_CLEAR( tas, oldb )
HAL_TAS_CLEAR( tas, oldb )
Performs a test and clear operation on the
Performs a test and clear operation on the
location tas. oldb will contain true if
location tas. oldb will contain true if
the location was already set, and false if
the location was already set, and false if
it was clear.
it was clear.
Spinlocks
Spinlocks
Spinlocks provide inter-CPU locking. Normally they will be implemented
Spinlocks provide inter-CPU locking. Normally they will be implemented
on top of the test-and-set mechanism above, but may also be
on top of the test-and-set mechanism above, but may also be
implemented by other means if, for example, the hardware has more
implemented by other means if, for example, the hardware has more
direct support for spinlocks.
direct support for spinlocks.
HAL_SPINLOCK_TYPE
HAL_SPINLOCK_TYPE
The type for all spinlock variables.
The type for all spinlock variables.
HAL_SPINLOCK_INIT_CLEAR
HAL_SPINLOCK_INIT_CLEAR
A value that may be assigned to a spinlock
A value that may be assigned to a spinlock
variable to initialize it to clear.
variable to initialize it to clear.
HAL_SPINLOCK_INIT_SET
HAL_SPINLOCK_INIT_SET
A value that may be assigned to a spinlock
A value that may be assigned to a spinlock
variable to initialize it to set.
variable to initialize it to set.
HAL_SPINLOCK_SPIN( lock )
HAL_SPINLOCK_SPIN( lock )
The caller spins in a busy loop waiting for
The caller spins in a busy loop waiting for
the lock to become clear. It then sets it and
the lock to become clear. It then sets it and
continues. This is all handled atomically, so
continues. This is all handled atomically, so
that there are no race conditions between CPUs.
that there are no race conditions between CPUs.
HAL_SPINLOCK_CLEAR( lock )
HAL_SPINLOCK_CLEAR( lock )
The caller clears the lock. One of any waiting
The caller clears the lock. One of any waiting
spinners will then be able to proceed.
spinners will then be able to proceed.
HAL_SPINLOCK_TRY( lock, val )
HAL_SPINLOCK_TRY( lock, val )
Attempts to set the lock. The value put in
Attempts to set the lock. The value put in
val will be true if the lock was
val will be true if the lock was
claimed successfully, and false if it was
claimed successfully, and false if it was
not.
not.
HAL_SPINLOCK_TEST( lock, val )
HAL_SPINLOCK_TEST( lock, val )
Tests the current value of the lock. The value
Tests the current value of the lock. The value
put in val will be true if the lock is
put in val will be true if the lock is
claimed and false of it is clear.
claimed and false of it is clear.
Scheduler Lock
Scheduler Lock
The scheduler lock is the main protection for all kernel data
The scheduler lock is the main protection for all kernel data
structures. By default the kernel implements the scheduler lock itself
structures. By default the kernel implements the scheduler lock itself
using a spinlock. However, if spinlocks cannot be supported by the
using a spinlock. However, if spinlocks cannot be supported by the
hardware, or there is a more efficient implementation available, the
hardware, or there is a more efficient implementation available, the
HAL may provide macros to implement the scheduler lock.
HAL may provide macros to implement the scheduler lock.
HAL_SMP_SCHEDLOCK_DATA_TYPE
HAL_SMP_SCHEDLOCK_DATA_TYPE
A data type, possibly a structure, that
A data type, possibly a structure, that
contains any data items needed by the
contains any data items needed by the
scheduler lock implementation. A variable of
scheduler lock implementation. A variable of
this type will be instantiated as a static
this type will be instantiated as a static
member of the Cyg_Scheduler_SchedLock class
member of the Cyg_Scheduler_SchedLock class
and passed to all the following macros.
and passed to all the following macros.
HAL_SMP_SCHEDLOCK_INIT( lock, data )
HAL_SMP_SCHEDLOCK_INIT( lock, data )
Initialize the scheduler lock. The lock
Initialize the scheduler lock. The lock
argument is the scheduler lock counter and the
argument is the scheduler lock counter and the
data argument is a variable of
data argument is a variable of
HAL_SMP_SCHEDLOCK_DATA_TYPE type.
HAL_SMP_SCHEDLOCK_DATA_TYPE type.
HAL_SMP_SCHEDLOCK_INC( lock, data )
HAL_SMP_SCHEDLOCK_INC( lock, data )
Increment the scheduler lock. The first
Increment the scheduler lock. The first
increment of the lock from zero to one for any
increment of the lock from zero to one for any
CPU may cause it to wait until the lock is
CPU may cause it to wait until the lock is
zeroed by another CPU. Subsequent increments
zeroed by another CPU. Subsequent increments
should be less expensive since this CPU
should be less expensive since this CPU
already holds the lock.
already holds the lock.
HAL_SMP_SCHEDLOCK_ZERO( lock, data )
HAL_SMP_SCHEDLOCK_ZERO( lock, data )
Zero the scheduler lock. This operation will
Zero the scheduler lock. This operation will
also clear the lock so that other CPUs may
also clear the lock so that other CPUs may
claim it.
claim it.
HAL_SMP_SCHEDLOCK_SET( lock, data, new )
HAL_SMP_SCHEDLOCK_SET( lock, data, new )
Set the lock to a different value, in
Set the lock to a different value, in
new. This is only called when the lock is
new. This is only called when the lock is
already known to be owned by the current CPU. It is never called to
already known to be owned by the current CPU. It is never called to
zero the lock, or to increment it from zero.
zero the lock, or to increment it from zero.
Interrupt Routing
Interrupt Routing
The routing of interrupts to different CPUs is supported by two new
The routing of interrupts to different CPUs is supported by two new
interfaces in hal_intr.h.
interfaces in hal_intr.h.
Once an interrupt has been routed to a new CPU, the existing vector
Once an interrupt has been routed to a new CPU, the existing vector
masking and configuration operations should take account of the CPU
masking and configuration operations should take account of the CPU
routing. For example, if the operation is not invoked on the
routing. For example, if the operation is not invoked on the
destination CPU itself, then the HAL may need to arrange to transfer
destination CPU itself, then the HAL may need to arrange to transfer
the operation to the destination CPU for correct application.
the operation to the destination CPU for correct application.
HAL_INTERRUPT_SET_CPU( vector, cpu )
HAL_INTERRUPT_SET_CPU( vector, cpu )
Route the interrupt for the given vector to
Route the interrupt for the given vector to
the given cpu.
the given cpu.
HAL_INTERRUPT_GET_CPU( vector, cpu )
HAL_INTERRUPT_GET_CPU( vector, cpu )
Set cpu to the id of the CPU to which this
Set cpu to the id of the CPU to which this
vector is routed.
vector is routed.
Exception Handling
Exception Handling
Most of the HAL consists of simple macros or functions that are
Most of the HAL consists of simple macros or functions that are
called via the interfaces described in the previous section. These
called via the interfaces described in the previous section. These
just perform whatever operation is required by accessing the hardware
just perform whatever operation is required by accessing the hardware
and then return. The exception to this is the handling of exceptions:
and then return. The exception to this is the handling of exceptions:
either synchronous hardware traps or asynchronous device
either synchronous hardware traps or asynchronous device
interrupts. Here control is passed first to the HAL, which then passed
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,
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
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.
and resume processing from the point at which the exception occurred.
The HAL exceptions handling code is usually found in the file
The HAL exceptions handling code is usually found in the file
vectors.S in the architecture HAL.  Since the
vectors.S in the architecture HAL.  Since the
reset entry point is usually implemented as one of these it also deals
reset entry point is usually implemented as one of these it also deals
with system startup.
with system startup.
The exact implementation of this code is under the control of the HAL
The exact implementation of this code is under the control of the HAL
implementer. So long as it interacts correctly with the interfaces
implementer. So long as it interacts correctly with the interfaces
defined previously it may take any form.  However, all current
defined previously it may take any form.  However, all current
implementation follow the same pattern, and there should be a very
implementation follow the same pattern, and there should be a very
good reason to break with this. The rest of this section describes
good reason to break with this. The rest of this section describes
these operate.
these operate.
Exception handling normally deals with the following broad areas of
Exception handling normally deals with the following broad areas of
functionality:
functionality:
  
  
    Startup and initialization.
    Startup and initialization.
  
  
  
  
    Hardware exception delivery.
    Hardware exception delivery.
  
  
  
  
    Default handling of synchronous exceptions.
    Default handling of synchronous exceptions.
  
  
  
  
    Default handling of asynchronous interrupts.
    Default handling of asynchronous interrupts.
  
  
<!-- <index></index> --><!-- <xref> -->HAL Startup
<!-- <index></index> --><!-- <xref> -->HAL Startup
Execution normally begins at the reset vector with
Execution normally begins at the reset vector with
the machine in a minimal startup state. From here the HAL needs to get
the machine in a minimal startup state. From here the HAL needs to get
the machine running, set up the execution environment for the
the machine running, set up the execution environment for the
application, and finally invoke its entry point.
application, and finally invoke its entry point.
The following is a list of the jobs that need to be done in
The following is a list of the jobs that need to be done in
approximately the order in which they should be accomplished. Many
approximately the order in which they should be accomplished. Many
of these will not be needed in some configurations.
of these will not be needed in some configurations.
  
  
  
  
  Initialize the hardware. This may involve initializing several
  Initialize the hardware. This may involve initializing several
  subsystems in both the architecture, variant and platform
  subsystems in both the architecture, variant and platform
  HALs. These include:
  HALs. These include:
  
  
    
    
      
      
        
        
        Initialize various CPU status registers. Most importantly, the CPU
        Initialize various CPU status registers. Most importantly, the CPU
        interrupt mask should be set to disable interrupts.
        interrupt mask should be set to disable interrupts.
        
        
      
      
      
      
        
        
        Initialize the MMU, if it is used. On many platforms it is
        Initialize the MMU, if it is used. On many platforms it is
        only possible to control the cacheability of address ranges
        only possible to control the cacheability of address ranges
        via the MMU. Also, it may be necessary to remap RAM and device
        via the MMU. Also, it may be necessary to remap RAM and device
        registers to locations other than their defaults. However, for
        registers to locations other than their defaults. However, for
        simplicity, the mapping should be kept as close to one-to-one
        simplicity, the mapping should be kept as close to one-to-one
        physical-to-virtual as possible.
        physical-to-virtual as possible.
        
        
      
      
      
      
        
        
        Set up the memory controller to access RAM, ROM and I/O devices
        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
        correctly. Until this is done it may not be possible to access
        RAM. If this is a ROMRAM startup then the program code can
        RAM. If this is a ROMRAM startup then the program code can
        now be copied to its RAM address and control transferred to it.
        now be copied to its RAM address and control transferred to it.
        
        
      
      
      
      
        
        
        Set up any bus bridges and support chips. Often access to
        Set up any bus bridges and support chips. Often access to
        device registers needs to go through various bus bridges and
        device registers needs to go through various bus bridges and
        other intermediary devices. In many systems these are combined
        other intermediary devices. In many systems these are combined
        with the memory controller, so it makes sense to set these up
        with the memory controller, so it makes sense to set these up
        together. This is particularly important if early diagnostic
        together. This is particularly important if early diagnostic
        output needs to go through one of these devices.
        output needs to go through one of these devices.
        
        
      
      
      
      
        
        
        Set up diagnostic mechanisms. If the platform includes an LED or
        Set up diagnostic mechanisms. If the platform includes an LED or
        LCD output device, it often makes sense to output progress
        LCD output device, it often makes sense to output progress
        indications on this during startup. This helps with diagnosing
        indications on this during startup. This helps with diagnosing
        hardware and software errors.
        hardware and software errors.
        
        
      
      
      
      
        
        
        Initialize floating point and other extensions such as SIMD
        Initialize floating point and other extensions such as SIMD
        and multimedia engines. It is usually necessary to enable
        and multimedia engines. It is usually necessary to enable
        these and maybe initialize control and exception registers for
        these and maybe initialize control and exception registers for
        these extensions.
        these extensions.
        
        
      
      
      
      
        
        
        Initialize interrupt controller. At the very least, it should
        Initialize interrupt controller. At the very least, it should
        be configured to mask all interrupts. It may also be necessary
        be configured to mask all interrupts. It may also be necessary
        to set up the mapping from the interrupt controller's vector
        to set up the mapping from the interrupt controller's vector
        number space to the CPU's exception number space. Similar
        number space to the CPU's exception number space. Similar
        mappings may need to be set up between primary and secondary
        mappings may need to be set up between primary and secondary
        interrupt controllers.
        interrupt controllers.
        
        
      
      
      
      
        
        
        Disable and initialize the caches. The caches should not
        Disable and initialize the caches. The caches should not
        normally be enabled at this point, but it may be necessary to
        normally be enabled at this point, but it may be necessary to
        clear or initialize them so that they can be enabled
        clear or initialize them so that they can be enabled
        later. Some architectures require that the caches be
        later. Some architectures require that the caches be
        explicitly reinitialized after a power-on reset.
        explicitly reinitialized after a power-on reset.
        
        
      
      
      
      
        
        
        Initialize the timer, clock etc. While the timer used for RTC
        Initialize the timer, clock etc. While the timer used for RTC
        interrupts will be initialized later, it may be necessary to
        interrupts will be initialized later, it may be necessary to
        set up the clocks that drive it here.
        set up the clocks that drive it here.
        
        
      
      
    
    
    
    
    The exact order in which these initializations is done is
    The exact order in which these initializations is done is
    architecture or variant specific. It is also often not necessary
    architecture or variant specific. It is also often not necessary
    to do anything at all for some of these options. These fragments
    to do anything at all for some of these options. These fragments
    of code should concentrate on getting the target up and running so
    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
    that C function calls can be made and code can be run. More
    complex initializations that cannot be done in assembly code may
    complex initializations that cannot be done in assembly code may
    be postponed until calls to
    be postponed until calls to
    hal_variant_init() or
    hal_variant_init() or
    hal_platform_init() are made.
    hal_platform_init() are made.
    
    
    
    
    Not all of these initializations need to be done for all startup
    Not all of these initializations need to be done for all startup
    types. In particular, RAM startups can reasonably assume that the
    types. In particular, RAM startups can reasonably assume that the
    ROM monitor or loader has already done most of this work.
    ROM monitor or loader has already done most of this work.
    
    
  
  
  
  
    
    
    Set up the stack pointer, this allows subsequent initialization
    Set up the stack pointer, this allows subsequent initialization
    code to make proper procedure calls. Usually the interrupt stack
    code to make proper procedure calls. Usually the interrupt stack
    is used for this purpose since it is available, large enough, and
    is used for this purpose since it is available, large enough, and
    will be reused for other purposes later.
    will be reused for other purposes later.
    
    
  
  
  
  
    
    
    Initialize any global pointer register needed for access to
    Initialize any global pointer register needed for access to
    globally defined variables. This allows subsequent initialization
    globally defined variables. This allows subsequent initialization
    code to access global variables.
    code to access global variables.
    
    
  
  
  
  
    
    
    If the system is starting from ROM, copy the ROM template of the
    If the system is starting from ROM, copy the ROM template of the
    .data section out to its correct position in
    .data section out to its correct position in
    RAM. ().
    RAM. ().
    
    
  
  
  
  
    
    
    Zero the .bss section.
    Zero the .bss section.
    
    
  
  
  
  
    
    
    Create a suitable C call stack frame. This may involve making
    Create a suitable C call stack frame. This may involve making
    stack space for call frames, and arguments, and initializing the
    stack space for call frames, and arguments, and initializing the
    back pointers to halt a GDB backtrace operation.
    back pointers to halt a GDB backtrace operation.
    
    
  
  
  
  
    
    
    Call hal_variant_init() and
    Call hal_variant_init() and
    hal_platform_init(). These will perform any
    hal_platform_init(). These will perform any
    additional initialization needed by the variant and platform. This
    additional initialization needed by the variant and platform. This
    typically includes further initialization of the interrupt
    typically includes further initialization of the interrupt
    controller, PCI bus bridges, basic IO devices and enabling the
    controller, PCI bus bridges, basic IO devices and enabling the
    caches.
    caches.
    
    
  
  
  
  
    
    
    Call cyg_hal_invoke_constructors() to run any
    Call cyg_hal_invoke_constructors() to run any
    static constructors.
    static constructors.
    
    
  
  
  
  
    
    
    Call cyg_start(). If
    Call cyg_start(). If
    cyg_start() returns, drop into an infinite
    cyg_start() returns, drop into an infinite
    loop.
    loop.
    
    
  
  
Vectors and VSRs
Vectors and VSRs
The CPU delivers all  exceptions, whether
The CPU delivers all  exceptions, whether
synchronous faults or asynchronous interrupts, to a set of hardware
synchronous faults or asynchronous interrupts, to a set of hardware
defined vectors. Depending on the architecture, these may be
defined vectors. Depending on the architecture, these may be
implemented in a number of different ways. Examples of existing
implemented in a number of different ways. Examples of existing
mechanisms are:
mechanisms are:
  
  
    PowerPC
    PowerPC
    
    
      
      
      Exceptions are vectored to locations 256 bytes apart starting at
      Exceptions are vectored to locations 256 bytes apart starting at
      either zero or 0xFFF00000. There are 16 such
      either zero or 0xFFF00000. There are 16 such
      vectors defined by the basic architecture and extra vectors may
      vectors defined by the basic architecture and extra vectors may
      be defined by specific variants. One of the base vectors is for
      be defined by specific variants. One of the base vectors is for
      all external interrupts, and another is for the architecture
      all external interrupts, and another is for the architecture
      defined timer.
      defined timer.
      
      
    
    
  
  
  
  
    MIPS
    MIPS
    
    
      
      
      Most exceptions and all interrupts are vectored to a single
      Most exceptions and all interrupts are vectored to a single
      address at either 0x80000000 or
      address at either 0x80000000 or
      0xBFC00180. Software is responsible for
      0xBFC00180. Software is responsible for
      reading the exception code from the CPU cause
      reading the exception code from the CPU cause
      register to discover its true source. Some TLB and debug
      register to discover its true source. Some TLB and debug
      exceptions are delivered to different vector addresses, but
      exceptions are delivered to different vector addresses, but
      these are not used currently by eCos. One of the exception codes
      these are not used currently by eCos. One of the exception codes
      in the cause register indicates an external
      in the cause register indicates an external
      interrupt. Additional bits in the cause
      interrupt. Additional bits in the cause
      register provide a first-level decode for the interrupt source,
      register provide a first-level decode for the interrupt source,
      one of which represents an architecture defined timer.
      one of which represents an architecture defined timer.
      
      
    
    
  
  
  
  
    IA32
    IA32
    
    
      
      
      Exceptions are delivered via an Interrupt Descriptor Table (IDT)
      Exceptions are delivered via an Interrupt Descriptor Table (IDT)
      which is essentially an indirection table indexed by exception
      which is essentially an indirection table indexed by exception
      number. The IDT may be placed anywhere in memory. In PC hardware
      number. The IDT may be placed anywhere in memory. In PC hardware
      the standard interrupt controller can be programmed to deliver
      the standard interrupt controller can be programmed to deliver
      the external interrupts to a block of 16 vectors at any offset
      the external interrupts to a block of 16 vectors at any offset
      in the IDT. There is no hardware supplied mechanism for
      in the IDT. There is no hardware supplied mechanism for
      determining the vector taken, other than from the address jumped
      determining the vector taken, other than from the address jumped
      to.
      to.
      
      
    
    
  
  
  
  
    ARM
    ARM
    
    
      
      
      All exceptions, including the FIQ and IRQ interrupts, are
      All exceptions, including the FIQ and IRQ interrupts, are
      vectored to locations four bytes apart starting at zero. There
      vectored to locations four bytes apart starting at zero. There
      is only room for one instruction here, which must immediately
      is only room for one instruction here, which must immediately
      jump out to handling code higher in memory. Interrupt sources
      jump out to handling code higher in memory. Interrupt sources
      have to be decoded entirely from the interrupt controller.
      have to be decoded entirely from the interrupt controller.
      
      
    
    
  
  
With such a wide variety of hardware approaches, it is not possible to
With such a wide variety of hardware approaches, it is not possible to
provide a generic mechanism for the substitution of exception vectors
provide a generic mechanism for the substitution of exception vectors
directly. Therefore, eCos translates all of these mechanisms in to a
directly. Therefore, eCos translates all of these mechanisms in to a
common approach that can be used by portable code on all platforms.
common approach that can be used by portable code on all platforms.
The mechanism implemented is to attach to each hardware vector a short
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
piece of trampoline code that makes an indirect jump via a table to
the actual handler for the exception. This handler is called the
the actual handler for the exception. This handler is called the
Vector Service Routine (VSR) and the table is called the VSR table.
Vector Service Routine (VSR) and the table is called the VSR table.
The trampoline code performs the absolute minimum processing necessary
The trampoline code performs the absolute minimum processing necessary
to identify the exception source, and jump to the VSR. The VSR is then
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
responsible for saving the CPU state and taking the necessary actions
to handle the exception or interrupt. The entry conditions for the VSR
to handle the exception or interrupt. The entry conditions for the VSR
are as close to the raw hardware exception entry state as possible -
are as close to the raw hardware exception entry state as possible -
although on some platforms the trampoline will have had to move or
although on some platforms the trampoline will have had to move or
reorganize some registers to do its job.
reorganize some registers to do its job.
To make this more concrete, consider how the trampoline code operates
To make this more concrete, consider how the trampoline code operates
in each of the architectures described above:
in each of the architectures described above:
  
  
    PowerPC
    PowerPC
    
    
      
      
      A separate trampoline is contained in each of the vector
      A separate trampoline is contained in each of the vector
      locations. This code saves a few work registers away to the
      locations. This code saves a few work registers away to the
      special purposes registers available, loads the exception number
      special purposes registers available, loads the exception number
      into a register and then uses that to index the VSR table and
      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
      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 SPRs, and one of the data register containing the number of
      the vector taken.
      the vector taken.
      
      
    
    
  
  
  
  
    MIPS
    MIPS
    
    
      
      
      A single trampoline routine attached to the common vector reads
      A single trampoline routine attached to the common vector reads
      the exception code out of the cause register
      the exception code out of the cause register
      and uses that value to index the VSR table and jump to the VSR.
      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
      The trampoline uses the two registers defined in the ABI for
      kernel use to do this, one of these will contain the exception
      kernel use to do this, one of these will contain the exception
      vector number for the VSR.
      vector number for the VSR.
      
      
    
    
  
  
  
  
    IA32
    IA32
    
    
      
      
      There is a separate 3 or 4 instruction trampoline pointed to by
      There is a separate 3 or 4 instruction trampoline pointed to by
      each active IDT table entry. The trampoline for exceptions that
      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
      also have an error code pop it from the stack and put it into a
      memory location. Trampolines for non-error-code exceptions just
      memory location. Trampolines for non-error-code exceptions just
      zero the memory location. Then all trampolines push an
      zero the memory location. Then all trampolines push an
      interrupt/exception number onto the stack, and take an indirect
      interrupt/exception number onto the stack, and take an indirect
      jump through a precalculated offset in the VSR table. This is
      jump through a precalculated offset in the VSR table. This is
      all done without saving any registers, using memory-only
      all done without saving any registers, using memory-only
      operations. The VSR is entered with the vector number pushed
      operations. The VSR is entered with the vector number pushed
      onto the stack on top of the standard hardware saved state.
      onto the stack on top of the standard hardware saved state.
      
      
    
    
  
  
  
  
    ARM
    ARM
    
    
      
      
      The trampoline consists solely of the single instruction at the
      The trampoline consists solely of the single instruction at the
      exception entry point. This is an indirect jump via a location
      exception entry point. This is an indirect jump via a location
      32 bytes higher in memory. These locations, from
      32 bytes higher in memory. These locations, from
      0x20 up, form the VSR table. Since each VSR
      0x20 up, form the VSR table. Since each VSR
      is entered in a different CPU mode
      is entered in a different CPU mode
      (SVC,UNDEF,ABORT,IRQ or FIQ) there has to be a
      (SVC,UNDEF,ABORT,IRQ or FIQ) there has to be a
      different VSR for each exception that knows how to save the CPU
      different VSR for each exception that knows how to save the CPU
      state correctly.
      state correctly.
      
      
    
    
  
  
<!-- <index></index> -->Default Synchronous Exception Handling
<!-- <index></index> -->Default Synchronous Exception Handling
Most synchronous exception VSR table entries will point to a default
Most synchronous exception VSR table entries will point to a default
exception VSR which is responsible for handling all exceptions in a
exception VSR which is responsible for handling all exceptions in a
generic manner. The default VSR simply saves the CPU state, makes any
generic manner. The default VSR simply saves the CPU state, makes any
adjustments to the CPU state that is necessary, and calls
adjustments to the CPU state that is necessary, and calls
cyg_hal_exception_handler().
cyg_hal_exception_handler().
cyg_hal_exception_handler() needs to pass the
cyg_hal_exception_handler() needs to pass the
exception on to some handling code.  There are two basic destinations:
exception on to some handling code.  There are two basic destinations:
enter GDB or pass the exception up to eCos. Exactly which
enter GDB or pass the exception up to eCos. Exactly which
destination is taken depends on the configuration. When the GDB stubs are
destination is taken depends on the configuration. When the GDB stubs are
included then the exception is passed to them, otherwise it is passed
included then the exception is passed to them, otherwise it is passed
to eCos.
to eCos.
If an eCos application has been loaded by RedBoot then the VSR table
If an eCos application has been loaded by RedBoot then the VSR table
entries will all point into RedBoot's exception VSR, and will
entries will all point into RedBoot's exception VSR, and will
therefore enter GDB if an exception occurs. If the eCos application
therefore enter GDB if an exception occurs. If the eCos application
wants to handle an exception itself, it needs to replace the the VSR
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
table entry with one pointing to its own VSR. It can do this with the
HAL_VSR_SET_TO_ECOS_HANDLER() macro.
HAL_VSR_SET_TO_ECOS_HANDLER() macro.
<!-- <index></index> -->Default Interrupt Handling
<!-- <index></index> -->Default Interrupt Handling
Most asynchronous external interrupt vectors will point to a default
Most asynchronous external interrupt vectors will point to a default
interrupt VSR which decodes the actual interrupt being delivered from
interrupt VSR which decodes the actual interrupt being delivered from
the interrupt controller and invokes the appropriate ISR.
the interrupt controller and invokes the appropriate ISR.
The default interrupt VSR has a number of responsibilities if it is
The default interrupt VSR has a number of responsibilities if it is
going to interact with the Kernel cleanly and allow interrupts to
going to interact with the Kernel cleanly and allow interrupts to
cause thread preemption.
cause thread preemption.
To support this VSR an ISR vector table is needed. For each valid
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
vector three pointers need to be stored: the ISR, its data pointer and
an opaque (to the HAL) interrupt object pointer needed by the
an opaque (to the HAL) interrupt object pointer needed by the
kernel. It is implementation defined whether these are stored in a
kernel. It is implementation defined whether these are stored in a
single table of triples, or in three separate tables.
single table of triples, or in three separate tables.
The VSR follows the following approximate plan:
The VSR follows the following approximate plan:
  
  
    
    
    Save the CPU state. In non-debug configurations, it may be
    Save the CPU state. In non-debug configurations, it may be
    possible to get away with saving less than the entire machine
    possible to get away with saving less than the entire machine
    state. The option
    state. The option
    CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
    CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT
    is supported in some targets to do this.
    is supported in some targets to do this.
    
    
  
  
  
  
    
    
    Increment the kernel scheduler lock. This is a static member of
    Increment the kernel scheduler lock. This is a static member of
    the Cyg_Scheduler class, however it has also been aliased to
    the Cyg_Scheduler class, however it has also been aliased to
    cyg_scheduler_sched_lock so that it can be
    cyg_scheduler_sched_lock so that it can be
    accessed from assembly code.
    accessed from assembly code.
    
    
  
  
  
  
    
    
    (Optional) Switch to an interrupt stack if not already running on
    (Optional) Switch to an interrupt stack if not already running on
    it. This allows nested interrupts to be delivered without needing
    it. This allows nested interrupts to be delivered without needing
    every thread to have a stack large enough to take the maximum
    every thread to have a stack large enough to take the maximum
    possible nesting. It is implementation defined how to detect
    possible nesting. It is implementation defined how to detect
    whether this is a nested interrupt but there are two basic
    whether this is a nested interrupt but there are two basic
    techniques. The first is to inspect the stack pointer and switch
    techniques. The first is to inspect the stack pointer and switch
    only if it is not currently within the interrupt stack range; the
    only if it is not currently within the interrupt stack range; the
    second is to maintain a counter of the interrupt nesting level and
    second is to maintain a counter of the interrupt nesting level and
    switch only if it is zero. The option
    switch only if it is zero. The option
    CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
    CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
    controls whether this happens.
    controls whether this happens.
    
    
  
  
  
  
    
    
    Decode the actual external interrupt being delivered from
    Decode the actual external interrupt being delivered from
    the interrupt controller. This will yield the ISR vector
    the interrupt controller. This will yield the ISR vector
    number. The code to do this usually needs to come from the
    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
    variant or platform HAL, so is usually present in the form of a
    macro or procedure callout.
    macro or procedure callout.
    
    
  
  
  
  
    
    
    (Optional) Re-enable interrupts to permit nesting. At this point
    (Optional) Re-enable interrupts to permit nesting. At this point
    we can potentially allow higher priority interrupts to occur. It
    we can potentially allow higher priority interrupts to occur. It
    depends on the interrupt architecture of the CPU and platform
    depends on the interrupt architecture of the CPU and platform
    whether more interrupts will occur at this point, or whether they
    whether more interrupts will occur at this point, or whether they
    will only be delivered after the current interrupt has been
    will only be delivered after the current interrupt has been
    acknowledged (by a call to
    acknowledged (by a call to
    HAL_INTERRUPT_ACKNOWLEDGE() in the ISR).
    HAL_INTERRUPT_ACKNOWLEDGE() in the ISR).
    
    
  
  
  
  
    
    
    Using the ISR vector number as an index, retrieve the
    Using the ISR vector number as an index, retrieve the
    ISR pointer and its data pointer from the ISR vector table.
    ISR pointer and its data pointer from the ISR vector table.
    
    
  
  
  
  
    
    
    Construct a C call stack frame. This may involve making stack
    Construct a C call stack frame. This may involve making stack
    space for call frames, and arguments, and initializing the back
    space for call frames, and arguments, and initializing the back
    pointers to halt a GDB backtrace operation.
    pointers to halt a GDB backtrace operation.
    
    
  
  
  
  
    
    
    Call the ISR, passing the vector number and data pointer.  The
    Call the ISR, passing the vector number and data pointer.  The
    vector number and a pointer to the saved state should be preserved
    vector number and a pointer to the saved state should be preserved
    across this call, preferably by storing them in registers that are
    across this call, preferably by storing them in registers that are
    defined to be callee-saved by the calling conventions.
    defined to be callee-saved by the calling conventions.
    
    
  
  
  
  
    
    
    If this is an un-nested interrupt and a separate interrupt
    If this is an un-nested interrupt and a separate interrupt
    stack is being used, switch back to the interrupted thread's
    stack is being used, switch back to the interrupted thread's
    own stack.
    own stack.
    
    
  
  
  
  
    
    
    Use the saved ISR vector number to get the interrupt object
    Use the saved ISR vector number to get the interrupt object
    pointer from the ISR vector table.
    pointer from the ISR vector table.
    
    
  
  
  
  
    
    
    Call interrupt_end() passing it the return
    Call interrupt_end() passing it the return
    value from the ISR, the interrupt object pointer and a pointer to
    value from the ISR, the interrupt object pointer and a pointer to
    the saved CPU state. This function is implemented by the Kernel
    the saved CPU state. This function is implemented by the Kernel
    and is responsible for finishing off the interrupt
    and is responsible for finishing off the interrupt
    handling. Specifically, it may post a DSR depending on the ISR
    handling. Specifically, it may post a DSR depending on the ISR
    return value, and will decrement the scheduler lock. If the lock
    return value, and will decrement the scheduler lock. If the lock
    is zeroed by this operation then any posted DSRs may be called and
    is zeroed by this operation then any posted DSRs may be called and
    may in turn result in a thread context switch.
    may in turn result in a thread context switch.
    
    
  
  
  
  
    
    
    The return from interrupt_end() may occur
    The return from interrupt_end() may occur
    some time after the call. Many other threads may have executed in
    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
    the meantime. So here all we may do is restore the machine state
    and resume execution of the interrupted thread. Depending on the
    and resume execution of the interrupted thread. Depending on the
    architecture, it may be necessary to disable interrupts again for
    architecture, it may be necessary to disable interrupts again for
    part of this.
    part of this.
    
    
  
  
The detailed order of these steps may vary slightly depending on the
The detailed order of these steps may vary slightly depending on the
architecture, in particular where interrupts are enabled and disabled.
architecture, in particular where interrupts are enabled and disabled.
&hal-common-porting-sgml;
&hal-common-porting-sgml;
<!-- <index></index> --><!-- <xref> -->Future developments
<!-- <index></index> --><!-- <xref> -->Future developments
The HAL is not complete, and will evolve and increase over
The HAL is not complete, and will evolve and increase over
time. Among the intended developments are:
time. Among the intended developments are:
Common macros for interpreting the contents of a saved
Common macros for interpreting the contents of a saved
machine context. These would allow portable code, such as debug
machine context. These would allow portable code, such as debug
stubs, to extract such values as the program counter and stack pointer
stubs, to extract such values as the program counter and stack pointer
from a state without having to interpret a HAL_SavedRegisters structure
from a state without having to interpret a HAL_SavedRegisters structure
directly.
directly.
Debugging support. Macros to set and clear hardware and
Debugging support. Macros to set and clear hardware and
software breakpoints. Access to other areas of machine state may
software breakpoints. Access to other areas of machine state may
also be supported.
also be supported.
Static initialization support. The current HAL provides a
Static initialization support. The current HAL provides a
dynamic interface to things like thread context initialization and ISR
dynamic interface to things like thread context initialization and ISR
attachment. We also need to be able to define the system entirely
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
statically so that it is ready to go on restart, without needing to
run code. This will require extra macros to define these
run code. This will require extra macros to define these
initializations.  Such support may have a consequential effect on the
initializations.  Such support may have a consequential effect on the
current HAL specification.
current HAL specification.
CPU state control. Many CPUs have both kernel and user
CPU state control. Many CPUs have both kernel and user
states. Although it is not intended to run any code in user state
states. Although it is not intended to run any code in user state
for the foreseeable future, it is possible that this may happen
for the foreseeable future, it is possible that this may happen
eventually. If this is the case, then some minor changes may be needed
eventually. If this is the case, then some minor changes may be needed
to the current HAL API to accommodate this. These should mostly
to the current HAL API to accommodate this. These should mostly
be extensions, but minor changes in semantics may also be required.
be extensions, but minor changes in semantics may also be required.
Physical memory management. Many embedded systems have
Physical memory management. Many embedded systems have
multiple memory areas with varying properties such as base address,
multiple memory areas with varying properties such as base address,
size, speed, bus width, cacheability and persistence. An API is
size, speed, bus width, cacheability and persistence. An API is
needed to support the discovery of this information about the machine's
needed to support the discovery of this information about the machine's
physical memory map.
physical memory map.
Memory management control. Some embedded processors have
Memory management control. Some embedded processors have
a memory management unit. In some cases this must be enabled to
a memory management unit. In some cases this must be enabled to
allow the cache to be controlled, particularly if different regions
allow the cache to be controlled, particularly if different regions
of memory must have different caching properties. For some purposes,
of memory must have different caching properties. For some purposes,
in some systems, it will be useful to manipulate the MMU settings
in some systems, it will be useful to manipulate the MMU settings
dynamically.
dynamically.
Power management. Macros to access and control any power
Power management. Macros to access and control any power
management mechanisms available on the CPU implementation. These
management mechanisms available on the CPU implementation. These
would provide a substrate for a more general power management system
would provide a substrate for a more general power management system
that also involved device drivers and other hardware components.
that also involved device drivers and other hardware components.
Generic serial line macros. Most serial line devices operate
Generic serial line macros. Most serial line devices operate
in the same way, the only real differences being exactly which bits
in the same way, the only real differences being exactly which bits
in which registers perform the standard functions. It should be
in which registers perform the standard functions. It should be
possible to develop a set of HAL macros that provide basic serial
possible to develop a set of HAL macros that provide basic serial
line services such as baud rate setting, enabling interrupts, polling
line services such as baud rate setting, enabling interrupts, polling
for transmit or receive ready, transmitting and receiving data etc.
for transmit or receive ready, transmitting and receiving data etc.
Given these it should be possible to create a generic serial line
Given these it should be possible to create a generic serial line
device driver that will allow rapid bootstrapping on any new platform.
device driver that will allow rapid bootstrapping on any new platform.
It may be possible to extend this mechanism to other device types.
It may be possible to extend this mechanism to other device types.
 
 

powered by: WebSVN 2.1.0

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