📄 hal-porting-architecture.html
字号:
>Define interrupt enable/disable macros. These are normally inline
assembly fragments to execute the instructions, or manipulate the CPU
register, that contains the CPU interrupt enable bit.</P
></LI
><LI
><P
>A feature that many HALs support is the ability to execute DSRs on the
interrupt stack. This is not an essential feature, and is better left
unimplemented in the initial porting effort. If this is required, then
the macro <TT
CLASS="LITERAL"
>HAL_INTERRUPT_STACK_CALL_PENDING_DSRS()</TT
>
should be defined to call a function in
<TT
CLASS="FILENAME"
>vectors.S</TT
>.</P
></LI
><LI
><P
>Define the interrupt and VSR attachment macros. If the same arrays as
for other HALs have been used for VSR and interrupt vectors, then
these macro can be copied across unchanged.</P
></LI
></UL
></LI
><LI
><P
>A number of other header files also need to be filled in:</P
><P
></P
><UL
><LI
><P
><TT
CLASS="FILENAME"
>basetype.h</TT
>. This file defines the basic types
used by eCos, together with the endianness and some other
characteristics. This file only really needs to contain definitions
if the architecture differs significantly from the defaults defined
in <TT
CLASS="FILENAME"
>cyg_type.h</TT
></P
></LI
><LI
><P
><TT
CLASS="FILENAME"
>hal_io.h</TT
>. This file contains macros for accessing
device IO registers. If the architecture uses memory mapped IO, then
these can be copied unchanged from an existing HAL such as MIPS. If
the architecture uses special IO instructions, then these macros must
be defined as inline assembler fragments. See the I386 HAL for an
example. PCI bus access macros are usually defined in the variant or
platform HALs.</P
></LI
><LI
><P
><TT
CLASS="FILENAME"
>hal_cache.h</TT
>. This file contains cache access
macros. If the architecture defines cache instructions, or control
registers, then the access macros should be defined here. Otherwise
they must be defined in the variant or platform HAL. Usually the cache
dimensions (total size, line size, ways etc.) are defined in the
variant HAL.</P
></LI
><LI
><P
><TT
CLASS="FILENAME"
>arch.inc</TT
> and
<TT
CLASS="FILENAME"
><architecture>.inc</TT
>. These files are
assembler headers used by <TT
CLASS="FILENAME"
>vectors.S</TT
> and
<TT
CLASS="FILENAME"
>context.S</TT
>.
<TT
CLASS="FILENAME"
><architecture>.inc</TT
> is a general purpose
header that should contain things like register aliases, ABI
definitions and macros useful to general assembly
code. If there are no such definitions, then this file need not be
provided. <TT
CLASS="FILENAME"
>arch.inc</TT
> contains macros for performing
various eCos related operations such as initializing the CPU, caches,
FPU etc. The definitions here may often be configured or overridden by
definitions in the variant or platform HALs. See the MIPS HAL for an
example of this.</P
></LI
></UL
></LI
><LI
><P
>Write <TT
CLASS="FILENAME"
>vectors.S</TT
>. This is the most important file
in the HAL. It contains the CPU initialization code, exception and
interrupt handlers. While other HALs should be consulted for
structures and techniques, there is very little here that can be
copied over without major edits.</P
><P
>The main pieces of code that need to be defined here are:</P
><P
></P
><UL
><LI
><P
>Reset vector. This usually need to be positioned at the start of the
ROM or FLASH, so should be in a linker section of its own. It can then be
placed correctly by the linker script. Normally this code is little
more than a jump to the label <TT
CLASS="LITERAL"
>_start</TT
>.</P
></LI
><LI
><P
>Exception vectors. These are the trampoline routines connected to the
hardware exception entry points that vector through the VSR table. In
many architectures these are adjacent to the reset vector, and should
occupy the same linker section. If the architecture allow the vectors
to be moved then it may be necessary for these trampolines to be
position independent so they can be relocated at runtime.</P
><P
>The trampolines should do the minimum necessary to transfer control
from the hardware vector to the VSR pointed to by the matching table
entry. Exactly how this is done depends on the architecture. Usually
the trampoline needs to get some working registers by either saving
them to CPU special registers (e.g. PowerPC SPRs), using reserved
general registers (MIPS K0 and K1), using only memory based
operations (IA32), or just jumping directly (ARM). The VSR table index
to be used is either implicit in the entry point taken (PowerPC, IA32,
ARM), or must be determined from a CPU register (MIPS).</P
></LI
><LI
><P
>Write kernel startup code. This is the location the reset vector jumps
to, and can be in the main text section of the executable, rather than
a special section. The code here should first initialize the CPU and other
hardware subsystems. The best approach is to use a set of macro
calls that are defined either in <TT
CLASS="FILENAME"
>arch.inc</TT
> or
overridden in the variant or platform HALs. Other jobs that this code
should do are: initialize stack pointer; copy the data section from
ROM to RAM if necessary; zero the BSS; call variant and platform
initializers; call <TT
CLASS="FUNCTION"
>cyg_hal_invoke_constructors()</TT
>;
call <TT
CLASS="FUNCTION"
>initialize_stub()</TT
> if necessary. Finally it
should call <TT
CLASS="FUNCTION"
>cyg_start()</TT
>. See <A
HREF="hal-exception-handling.html#HAL-STARTUP"
>the Section called <I
>HAL Startup</I
> in Chapter 10</A
> for details.</P
></LI
><LI
><P
>Write the default exception VSR. This VSR is installed in the VSR
table for all synchronous exception vectors. See <A
HREF="hal-default-synchronous-exception-handling.html"
>the Section called <I
>Default Synchronous Exception Handling</I
> in Chapter 10</A
> for details of
what this VSR does.</P
></LI
><LI
><P
>Write the default interrupt VSR. This is installed in all VSR table
entries that correspond to external interrupts. See <A
HREF="hal-default-synchronous-exception-handling.html"
>the Section called <I
>Default Synchronous Exception Handling</I
> in Chapter 10</A
> for details of
what this VSR does.</P
></LI
><LI
><P
>Write
<TT
CLASS="FUNCTION"
>hal_interrupt_stack_call_pending_dsrs()</TT
>. If this
function is defined in <TT
CLASS="FILENAME"
>hal_arch.h</TT
> then it should
appear here. The purpose of this function is to call DSRs on the
interrupt stack rather than the current thread's stack. This is not an
essential feature, and may be left until later. However it interacts
with the stack switching that goes on in the interrupt VSR, so it may
make sense to write these pieces of code at the same time to ensure
consistency.</P
><P
>When this function is implemented it should do the following:</P
><P
></P
><UL
><LI
><P
>Take a copy of the current SP and then switch to the interrupt stack.</P
></LI
><LI
><P
>Save the old SP, together with the CPU status register (or whatever
register contains the interrupt enable status) and any other
registers that may be corrupted by a function call (such as any link
register) to locations in the interrupt stack.</P
></LI
><LI
><P
>Enable interrupts.</P
></LI
><LI
><P
>Call <TT
CLASS="FUNCTION"
>cyg_interrupt_call_pending_DSRs()</TT
>. This is a
kernel functions that actually calls any pending DSRs.</P
></LI
><LI
><P
>Retrieve saved registers from the interrupt stack and switch back to
the current thread stack.</P
></LI
><LI
><P
>Merge the interrupt enable state recorded in the save CPU status
register with the current value of the status register to restore the
previous enable state. If the status register does not contain any
other persistent state then this can be a simple restore of the
register. However if the register contains other state bits that might
have been changed by a DSR, then care must be taken not to disturb
these.</P
></LI
></UL
></LI
><LI
><P
>Define any data items needed. Typically <TT
CLASS="FILENAME"
>vectors.S</TT
>
may contain definitions for the VSR table, the interrupt tables and the
interrupt stack. Sometimes these are only default definitions that may
be overridden by the variant or platform HALs.</P
></LI
></UL
></LI
><LI
><P
>Write <TT
CLASS="FILENAME"
>context.S</TT
>. This file contains the context
switch code. See <A
HREF="hal-architecture-characterization.html#HAL-CONTEXT-SWITCH"
>the Section called <I
>Thread Context Switching</I
> in Chapter 9</A
> for details of
how these functions operate. This file may also contain the
implementation of <TT
CLASS="FUNCTION"
>hal_setjmp()</TT
> and
<TT
CLASS="FUNCTION"
>hal_longjmp()</TT
>.</P
></LI
><LI
><P
>Write <TT
CLASS="FILENAME"
>hal_misc.c</TT
>. This file contains any C
data and functions needed by the HAL. These might include:</P
><P
></P
><UL
><LI
><P
><TT
CLASS="VARNAME"
>hal_interrupt_*[]</TT
>. In some HALs, if these arrays
are not defined in <TT
CLASS="FILENAME"
>vectors.S</TT
> then they must be
defined here.</P
></LI
><LI
><P
><TT
CLASS="FUNCTION"
>cyg_hal_exception_handler()</TT
>. This function is
called from the exception VSR. It usually does extra decoding of the
exception and invokes any special handlers for things like FPU traps,
bus errors or memory exceptions. If there is nothing special to be
done for an exception, then it either calls into the GDB stubs, by
calling <TT
CLASS="FUNCTION"
>__handle_exception()</TT
>, or
invokes the kernel by calling
<TT
CLASS="FUNCTION"
>cyg_hal_deliver_exception()</TT
>.</P
></LI
><LI
><P
><TT
CLASS="FUNCTION"
>hal_arch_default_isr()</TT
>. The
<TT
CLASS="VARNAME"
>hal_interrupt_handlers[]</TT
> array is usually
initialized with pointers to <TT
CLASS="FILENAME"
>hal_default_isr()</TT
>,
which is defined in the common HAL. This function handles things like
Ctrl-C processing, but if that is not relevant, then it will call
<TT
CLASS="FUNCTION"
>hal_arch_default_isr()</TT
>. Normally this function
should just return zero.</P
></LI
><LI
><P
><TT
CLASS="FUNCTION"
>cyg_hal_invoke_constructors()</TT
>. This calls the
constructors for all static objects before the program starts. eCos
relies on these being called in the correct order for it to function
correctly. The exact way in which constructors are handled may differ
between architectures, although most use a simple table of function
pointers between labels <TT
CLASS="LITERAL"
>__CTOR_LIST__</TT
> and
<TT
CLASS="LITERAL"
>__CTOR_END__</TT
> which must called in order from the
top down. Generally, this function can be copied directly from an
existing architecture HAL.</P
></LI
><LI
><P
>Bit indexing functions. If the macros
<TT
CLASS="LITERAL"
>HAL_LSBIT_INDEX()</TT
> and
<TT
CLASS="LITERAL"
>HAL_MSBIT_INDEX()</TT
> are defined as function calls,
then the functions should appear here. The main reason for doing this
is that the architecture does not have support for bit indexing and
these functions must provide the functionality by conventional
means. While the trivial implementation is a simple for loop, it is
expensive and non-deterministic. Better, constant time,
implementations can be found in several HALs (MIPS for example).</P
></LI
><LI
><P
><TT
CLASS="FUNCTION"
>hal_delay_us()</TT
>. If the macro
<TT
CLASS="LITERAL"
>HAL_DELAY_US()</TT
> is defined in <TT
CLASS="FILENAME"
>hal_intr.h</TT
> then it should be defined to
call this function. While most of the time this function is called
with very small values, occasionally (particularly in some ethernet
drivers) it is called with values of several seconds. Hence the
function should take care to avoid overflow in any calculations.</P
></LI
><LI
><P
><TT
CLASS="FUNCTION"
>hal_idle_thread_action()</TT
>. This function is called
from the idle thread via the
<TT
CLASS="LITERAL"
>HAL_IDLE_THREAD_ACTION()</TT
> macro, if so
defined. While normally this function does nothing, during development
this is often a good place to report various important system
parameters on LCDs, LED or other displays. This function can also
monitor system state and report any anomalies. If the architecture
supports a <TT
CLASS="LITERAL"
>halt</TT
> instruction then this is a good
place to put an inline assembly fragment to execute it. It is also a
good place to handle any power saving activity.</P
></LI
></UL
></LI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -