mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-11-09 08:37:58 +08:00
New manual. First version to CVS. Just starting to see if it builds.
This commit is contained in:
1 parent
b9fcbd0fc8
commit
33cd2d43a1
13 files changed
+1846
No files matched your search
@@ -0,0 +1,117 @@
|
||||
#
|
||||
# COPYRIGHT (c) 1988-1998.
|
||||
# On-Line Applications Research Corporation (OAR).
|
||||
# All rights reserved.
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
PROJECT=porting
|
||||
|
||||
include ../Make.config
|
||||
|
||||
all: html info ps pdf
|
||||
|
||||
dirs:
|
||||
$(make-dirs)
|
||||
|
||||
COMMON_FILES=../common/cpright.texi
|
||||
FILES=preface.texi developtools.texi sourcecode.texi cpumodels.texi \
|
||||
cpuinit.texi interrupts.texi taskcontext.texi idlethread.texi \
|
||||
prioritybitmap.texi codetuning.texi miscellaneous.texi $(COMMON_FILES)
|
||||
|
||||
GENERATED_FILES=preface.texi developtools.texi sourcecode.texi cpumodels.texi \
|
||||
cpuinit.texi interrupts.texi taskcontext.texi idlethread.texi \
|
||||
prioritybitmap.texi codetuning.texi miscellaneous.texi
|
||||
|
||||
|
||||
INFOFILES=$(wildcard $(PROJECT) $(PROJECT)-*)
|
||||
|
||||
info: dirs $(PROJECT)
|
||||
cp $(PROJECT) $(PROJECT)-* $(INFO_INSTALL)
|
||||
|
||||
$(PROJECT): $(FILES)
|
||||
$(MAKEINFO) $(PROJECT).texi
|
||||
|
||||
dvi: $(PROJECT).dvi
|
||||
ps: dirs $(PROJECT).ps
|
||||
pdf: dirs $(PROJECT).pdf
|
||||
|
||||
$(PROJECT).pdf: $(FILES)
|
||||
$(TEXI2PDF) $(PROJECT).texi
|
||||
cp $(PROJECT).pdf $(PDF_INSTALL)
|
||||
|
||||
$(PROJECT).ps: $(PROJECT).dvi
|
||||
dvips -o $(PROJECT).ps $(PROJECT).dvi
|
||||
cp $(PROJECT).ps $(PS_INSTALL)
|
||||
|
||||
$(PROJECT).dvi: $(FILES)
|
||||
# $(TEXI2DVI) $(PROJECT).texi
|
||||
texi2dvi -V $(PROJECT).texi
|
||||
|
||||
html: dirs $(FILES)
|
||||
-mkdir -p $(WWW_INSTALL)/$(PROJECT)
|
||||
cp rtemsarc.png rtemspie.png states.png $(WWW_INSTALL)/$(PROJECT)
|
||||
$(TEXI2WWW) $(TEXI2WWW_ARGS) -dir $(WWW_INSTALL)/$(PROJECT) \
|
||||
$(PROJECT).texi
|
||||
|
||||
clean:
|
||||
rm -f *.o $(PROG) *.txt core *.html *.pdf
|
||||
rm -f *.dvi *.ps *.log *.aux *.cp *.fn *.ky *.pg *.toc *.tp *.vr $(BASE)
|
||||
rm -f $(PROJECT) $(PROJECT)-* _* $(GENERATED_FILES)
|
||||
|
||||
preface.texi: preface.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
developtools.texi: developtools.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
sourcecode.texi: sourcecode.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
cpumodels.texi: cpumodels.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
cpuinit.texi: cpuinit.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
interrupts.texi: interrupts.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
taskcontext.texi: taskcontext.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
idlethread.texi: idlethread.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
prioritybitmap.texi: prioritybitmap.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
codetuning.texi: codetuning.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
miscellaneous.texi: miscellaneous.t
|
||||
$(BMENU) -p "" \
|
||||
-u "Top" \
|
||||
-n "" .t
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
@chapter Code Tuning Parameters
|
||||
|
||||
@subsection Inline Thread_Enable_dispatch
|
||||
|
||||
Should the calls to _Thread_Enable_dispatch be inlined?
|
||||
|
||||
If TRUE, then they are inlined.
|
||||
|
||||
If FALSE, then a subroutine call is made.
|
||||
|
||||
|
||||
Basically this is an example of the classic trade-off of size versus
|
||||
speed. Inlining the call (TRUE) typically increases the size of RTEMS
|
||||
while speeding up the enabling of dispatching.
|
||||
|
||||
[NOTE: In general, the _Thread_Dispatch_disable_level will only be 0 or 1
|
||||
unless you are in an interrupt handler and that interrupt handler invokes
|
||||
the executive.] When not inlined something calls _Thread_Enable_dispatch
|
||||
which in turns calls _Thread_Dispatch. If the enable dispatch is inlined,
|
||||
then one subroutine call is avoided entirely.]
|
||||
|
||||
@example
|
||||
#define CPU_INLINE_ENABLE_DISPATCH FALSE
|
||||
@end example
|
||||
|
||||
@subsection Inline Thread_queue_Enqueue_priority
|
||||
|
||||
Should the body of the search loops in _Thread_queue_Enqueue_priority be
|
||||
unrolled one time? In unrolled each iteration of the loop examines two
|
||||
"nodes" on the chain being searched. Otherwise, only one node is examined
|
||||
per iteration.
|
||||
|
||||
If TRUE, then the loops are unrolled.
|
||||
|
||||
If FALSE, then the loops are not unrolled.
|
||||
|
||||
The primary factor in making this decision is the cost of disabling and
|
||||
enabling interrupts (_ISR_Flash) versus the cost of rest of the body of
|
||||
the loop. On some CPUs, the flash is more expensive than one iteration of
|
||||
the loop body. In this case, it might be desirable to unroll the loop.
|
||||
It is important to note that on some CPUs, this code is the longest
|
||||
interrupt disable period in RTEMS. So it is necessary to strike a balance
|
||||
when setting this parameter.
|
||||
|
||||
@example
|
||||
#define CPU_UNROLL_ENQUEUE_PRIORITY TRUE
|
||||
@end example
|
||||
|
||||
|
||||
@subsection Structure Alignment Optimization
|
||||
|
||||
The following macro may be defined to the attribute setting used to force
|
||||
alignment of critical RTEMS structures. On some processors it may make
|
||||
sense to have these aligned on tighter boundaries than the minimum
|
||||
requirements of the compiler in order to have as much of the critical data
|
||||
area as possible in a cache line. This ensures that the first access of
|
||||
an element in that structure fetches most, if not all, of the data
|
||||
structure and places it in the data cache. Modern CPUs often have cache
|
||||
lines of at least 16 bytes and thus a single access implicitly fetches
|
||||
some surrounding data and places that unreferenced data in the cache.
|
||||
Taking advantage of this allows RTEMS to essentially prefetch critical
|
||||
data elements.
|
||||
|
||||
The placement of this macro in the declaration of the variables is based
|
||||
on the syntactically requirements of the GNU C "__attribute__" extension.
|
||||
For another toolset, the placement of this macro could be incorrect. For
|
||||
example with GNU C, use the following definition of
|
||||
CPU_STRUCTURE_ALIGNMENT to force a structures to a 32 byte boundary.
|
||||
|
||||
#define CPU_STRUCTURE_ALIGNMENT __attribute__ ((aligned (32)))
|
||||
|
||||
To benefit from using this, the data must be heavily used so it will stay
|
||||
in the cache and used frequently enough in the executive to justify
|
||||
turning this on. NOTE: Because of this, only the Priority Bit Map table
|
||||
currently uses this feature.
|
||||
|
||||
The following illustrates how the CPU_STRUCTURE_ALIGNMENT is defined on
|
||||
ports which require no special alignment for optimized access to data
|
||||
structures:
|
||||
|
||||
@example
|
||||
#define CPU_STRUCTURE_ALIGNMENT
|
||||
@end example
|
||||
|
||||
@subsection Data Alignment Requirements
|
||||
|
||||
@subsection Data Element Alignment
|
||||
|
||||
The CPU_ALIGNMENT macro should be set to the CPU's worst alignment
|
||||
requirement for data types on a byte boundary. This is typically the
|
||||
alignment requirement for a C double. This alignment does not take into
|
||||
account the requirements for the stack.
|
||||
|
||||
The following sets the CPU_ALIGNMENT macro to 8 which indicates that there
|
||||
is a basic C data type for this port which much be aligned to an 8 byte
|
||||
boundary.
|
||||
|
||||
@example
|
||||
#define CPU_ALIGNMENT 8
|
||||
@end example
|
||||
|
||||
@subsection Heap Element Alignment
|
||||
|
||||
The CPU_HEAP_ALIGNMENT macro is set to indicate the byte alignment
|
||||
requirement for data allocated by the RTEMS Code Heap Handler. This
|
||||
alignment requirement may be stricter than that for the data types
|
||||
alignment specified by CPU_ALIGNMENT. It is common for the heap to follow
|
||||
the same alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is
|
||||
strict enough for the heap, then this should be set to CPU_ALIGNMENT. This
|
||||
macro is necessary to ensure that allocated memory is properly aligned for
|
||||
use by high level language routines.
|
||||
|
||||
The following example illustrates how the CPU_HEAP_ALIGNMENT macro is set
|
||||
when the required alignment for elements from the heap is the same as the
|
||||
basic CPU alignment requirements.
|
||||
|
||||
@example
|
||||
#define CPU_HEAP_ALIGNMENT CPU_ALIGNMENT
|
||||
@end example
|
||||
|
||||
NOTE: This does not have to be a power of 2. It does have to be greater
|
||||
or equal to than CPU_ALIGNMENT.
|
||||
|
||||
@subsection Partition Element Alignment
|
||||
|
||||
The CPU_PARTITION_ALIGNMENT macro is set to indicate the byte alignment
|
||||
requirement for memory buffers allocated by the RTEMS Partition Manager
|
||||
that is part of the Classic API. This alignment requirement may be
|
||||
stricter than that for the data types alignment specified by
|
||||
CPU_ALIGNMENT. It is common for the partition to follow the same
|
||||
alignment requirement as CPU_ALIGNMENT. If the CPU_ALIGNMENT is strict
|
||||
enough for the partition, then this should be set to CPU_ALIGNMENT. This
|
||||
macro is necessary to ensure that allocated memory is properly aligned for
|
||||
use by high level language routines.
|
||||
|
||||
The following example illustrates how the CPU_PARTITION_ALIGNMENT macro is
|
||||
set when the required alignment for elements from the RTEMS Partition
|
||||
Manager is the same as the basic CPU alignment requirements.
|
||||
|
||||
|
||||
@example
|
||||
#define CPU_PARTITION_ALIGNMENT CPU_ALIGNMENT
|
||||
@end example
|
||||
|
||||
NOTE: This does not have to be a power of 2. It does have to be greater
|
||||
or equal to than CPU_ALIGNMENT.
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
@chapter CPU Initialization
|
||||
|
||||
This section describes the general CPU and system initialization sequence
|
||||
as it pertains to the CPU dependent code.
|
||||
|
||||
@section Introduction
|
||||
|
||||
XXX general startup sequence description rewritten to make it more
|
||||
applicable to CPU depdent code in executive
|
||||
|
||||
@section CPU Dependent Configuration Table
|
||||
|
||||
The CPU Dependent Configuration Table contains information which tailors
|
||||
the behavior of RTEMS base Some of the fields in this table are required
|
||||
to be present in all ports of RTEMS. These fields appear at the beginning
|
||||
of the data structure. Fields past this point may be CPU family and CPU
|
||||
model dependent. For example, a port may add a field to specify the
|
||||
default value for an interrupt mask register on the CPU. This table is
|
||||
initialized by the Board Support Package and passed to the
|
||||
rtems_initialize_executive or rtems_initialize_executive_early directive.
|
||||
|
||||
@example
|
||||
typedef struct @{
|
||||
void (*pretasking_hook)( void );
|
||||
void (*predriver_hook)( void );
|
||||
void (*postdriver_hook)( void );
|
||||
void (*idle_task)( void );
|
||||
boolean do_zero_of_workspace;
|
||||
unsigned32 idle_task_stack_size;
|
||||
unsigned32 interrupt_stack_size;
|
||||
unsigned32 extra_mpci_receive_server_stack;
|
||||
void * (*stack_allocate_hook)( unsigned32 );
|
||||
void (*stack_free_hook)( void* );
|
||||
/* end of fields required on all CPUs */
|
||||
|
||||
unsigned32 some_other_cpu_dependent_info;
|
||||
@} rtems_cpu_table;
|
||||
@end example
|
||||
|
||||
XXX copy the descriptions of the fields from another CPU supplement
|
||||
|
||||
@section Initializing the CPU
|
||||
|
||||
The _CPU_Initialize routine performs processor dependent initialization.
|
||||
|
||||
@example
|
||||
void _CPU_Initialize(
|
||||
rtems_cpu_table *cpu_table,
|
||||
void (*thread_dispatch) /* may be ignored */
|
||||
)
|
||||
@end example
|
||||
|
||||
The thread_dispatch argument is the address of the entry point for the
|
||||
routine called at the end of an ISR once it has been decided a context
|
||||
switch is necessary. On some compilation systems it is difficult to call
|
||||
a high-level language routine from assembly. Providing the address of the
|
||||
_Thread_ISR_Dispatch routine allows the porter an easy way to obtain this
|
||||
critical address and thus provides an easy way to work around this
|
||||
limitation on these systems.
|
||||
|
||||
If you encounter this problem save the entry point in a CPU dependent
|
||||
variable as shown below:
|
||||
|
||||
@example
|
||||
_CPU_Thread_dispatch_pointer = thread_dispatch;
|
||||
@end example
|
||||
|
||||
|
||||
During the initialization of the context for tasks with floating point,
|
||||
the CPU dependent code is responsible for initializing the floating point
|
||||
context. If there is not an easy way to initialize the FP context during
|
||||
Context_Initialize, then it is usually easier to save an "uninitialized"
|
||||
FP context here and copy it to the task's during Context_Initialize. If
|
||||
this technique is used to initialize the FP contexts, then it is important
|
||||
to ensure that the state of the floating point unit is in a coherent,
|
||||
initialized state.
|
||||
|
||||
Finally, this routine is responsible for copying the application's CPU
|
||||
Table into a locally accessible and modifiable area. This is shown below:
|
||||
|
||||
@example
|
||||
_CPU_Table = *cpu_table;
|
||||
@end example
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
@chapter CPU Model Variations
|
||||
|
||||
XXX copy some description of the portability model discussion from the
|
||||
France97 paper
|
||||
XXX enhance thatusing portability presentation from class
|
||||
|
||||
@section Introduction
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
@chapter Development Tools
|
||||
|
||||
When porting RTEMS to a new CPU architecture, one will have to have a
|
||||
development environment including compiler, assembler, linker, and
|
||||
debugger. The GNU development tool suite used by RTEMS supports most
|
||||
modern CPU families. Often all that is required is to add RTEMS
|
||||
configurations for the target CPU family. RTEMS targets for the GNU tools
|
||||
usually start life as little more than aliases for existing embedded
|
||||
configurations. At this point in time, ELF is supported on most of the
|
||||
CPU families with a tool target of the form CPU-elf. If this target is
|
||||
not supported by all of the GNU tools, then it will be necessary to
|
||||
determine the configuration that makes the best starting point regardless
|
||||
of the target object format.
|
||||
|
||||
Porting and retargetting the GNU tools is beyond the scope of this manual.
|
||||
The best advice that can be offered is to look at the existing RTEMS
|
||||
targets in the tool source and use that as a guideline.
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
@chapter IDLE Thread
|
||||
|
||||
@section Does Idle Thread Have a Floating Point Context?
|
||||
|
||||
The setting of the macro CPU_IDLE_TASK_IS_FP is based on the answer to the
|
||||
question: Should the IDLE task have a floating point context? If the
|
||||
answer to this question is TRUE, then the IDLE task has a floating point
|
||||
context associated. This is equivalent to creating a task in the Classic
|
||||
API (using rtems_task_create) as a RTEMS_FLOATING_POINT task. If
|
||||
CPU_IDLE_TASK_IS_FP is set to TRUE, then a floating point context switch
|
||||
occurs when the IDLE task is switched in and out. This adds to the
|
||||
execution overhead of the system but is necessary on some ports.
|
||||
|
||||
If FALSE, then the IDLE task does not have a floating point context.
|
||||
|
||||
NOTE: Setting CPU_IDLE_TASK_IS_FP to TRUE negatively impacts the time
|
||||
required to preempt the IDLE task from an interrupt because the floating
|
||||
point context must be saved as part of the preemption.
|
||||
|
||||
The following illustrates how to set this macro:
|
||||
|
||||
@example
|
||||
#define CPU_IDLE_TASK_IS_FP FALSE
|
||||
@end example
|
||||
|
||||
@section CPU Dependent Idle Thread Body
|
||||
|
||||
@subsection CPU_PROVIDES_IDLE_THREAD_BODY Macro Setting
|
||||
|
||||
The CPU_PROVIDES_IDLE_THREAD_BODY macro setting is based upon the answer
|
||||
to the question: Does this port provide a CPU dependent IDLE task
|
||||
implementation? If the answer to this question is yes, then the
|
||||
CPU_PROVIDES_IDLE_THREAD_BODY macro should be set to TRUE, and the routine
|
||||
_CPU_Thread_Idle_body must be provided. This routine overrides the
|
||||
default IDLE thread body of _Thread_Idle_body. If the
|
||||
CPU_PROVIDES_IDLE_THREAD_BODY macro is set to FALSE, then the generic
|
||||
_Thread_Idle_body is the default IDLE thread body for this port.
|
||||
Regardless of whether or not a CPU dependent IDLE thread implementation is
|
||||
provided, the BSP can still override it.
|
||||
|
||||
This is intended to allow for supporting processors which have a low power
|
||||
or idle mode. When the IDLE thread is executed, then the CPU can be
|
||||
powered down when the processor is idle.
|
||||
|
||||
The order of precedence for selecting the IDLE thread body is:
|
||||
|
||||
@enumerate
|
||||
@item BSP provided
|
||||
|
||||
@item CPU dependent (if provided)
|
||||
|
||||
@item generic (if no BSP and no CPU dependent)
|
||||
|
||||
@end itemize
|
||||
|
||||
The following illustrates setting the CPU_PROVIDES_IDLE_THREAD_BODY macro:
|
||||
|
||||
@example
|
||||
#define CPU_PROVIDES_IDLE_THREAD_BODY TRUE
|
||||
@end example
|
||||
|
||||
Implementation details of a CPU model specific IDLE thread body are in the
|
||||
next section.
|
||||
|
||||
@subsection Idle Thread Body
|
||||
|
||||
The _CPU_Thread_Idle_body routine only needs to be provided if the porter
|
||||
wishes to include a CPU dependent IDLE thread body. If the port includes
|
||||
a CPU dependent implementation of the IDLE thread body, then the
|
||||
CPU_PROVIDES_IDLE_THREAD_BODY macro should be defined to TRUE. This
|
||||
routine is prototyped as follows:
|
||||
|
||||
@example
|
||||
void _CPU_Thread_Idle_body( void );
|
||||
@end example
|
||||
|
||||
As mentioned above, RTEMS does not require that a CPU dependent IDLE
|
||||
thread body be provided as part of the port. If
|
||||
CPU_PROVIDES_IDLE_THREAD_BODY is defined to FALSE, then the CPU
|
||||
independent algorithm is used. This algorithm consists of a "branch to
|
||||
self" which is implemented in the XXX routine as follows.
|
||||
|
||||
@example
|
||||
XXX check name and exact implementation
|
||||
void _Thread_Idle_body( void )
|
||||
@{
|
||||
while( 1 ) ;
|
||||
@}
|
||||
@end example
|
||||
|
||||
If the CPU dependent IDLE thread body is implementation centers upon using
|
||||
a "halt", "idle", or "shutdown" instruction, then don't forget to put it
|
||||
in an infinite loop as the CPU will have to reexecute this instruction
|
||||
each time the IDLE thread is dispatched.
|
||||
|
||||
@example
|
||||
void _CPU_Thread_Idle_body( void )
|
||||
@{
|
||||
|
||||
for( ; ; )
|
||||
/* insert your "halt" instruction here */ ;
|
||||
@}
|
||||
@end example
|
||||
|
||||
Be warned. Some processors with onboard DMA have been known to stop the
|
||||
DMA if the CPU were put in IDLE mode. This might also be a problem with
|
||||
other on-chip peripherals. So use this hook with caution.
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,162 @@
|
||||
@chapter Miscellaneous
|
||||
|
||||
@section Fatal Error Default Handler
|
||||
|
||||
The _CPU_Fatal_halt routine is the default fatal error handler. This
|
||||
routine copies _error into a known place -- typically a stack location or
|
||||
a register, optionally disables interrupts, and halts/stops the CPU. It
|
||||
is prototyped as follows and is often implemented as a macro:
|
||||
|
||||
@example
|
||||
void _CPU_Fatal_halt(
|
||||
unsigned32 _error
|
||||
);
|
||||
@end example
|
||||
|
||||
@section Processor Endianness
|
||||
|
||||
Endianness refers to the order in which numeric values are stored in
|
||||
memory by the microprocessor. Big endian architectures store the most
|
||||
significant byte of a multi-byte numeric value in the byte with the lowest
|
||||
address. This results in the hexadecimal value 0x12345678 being stored as
|
||||
0x12345678 with 0x12 in the byte at offset zero, 0x34 in the byte at
|
||||
offset one, etc.. The Motorola M68K and numerous RISC processor families
|
||||
is big endian. Conversely, little endian architectures store the least
|
||||
significant byte of a multi-byte numeric value in the byte with the lowest
|
||||
address. This results in the hexadecimal value 0x12345678 being stored as
|
||||
0x78563412 with 0x78 in the byte at offset zero, 0x56 in the byte at
|
||||
offset one, etc.. The Intel ix86 family is little endian.
|
||||
Interestingly, some CPU models within the PowerPC and MIPS architectures
|
||||
can be switched between big and little endian modes. Most embedded
|
||||
systems use these families strictly in big endian mode.
|
||||
|
||||
RTEMS must be informed of the byte ordering for this microprocessor family
|
||||
and, optionally, endian conversion routines may be provided as part of the
|
||||
port. Conversion between endian formats is often necessary in
|
||||
multiprocessor environments and sometimes needed when interfacing with
|
||||
peripheral controllers.
|
||||
|
||||
@subsection Specifying Processor Endianness
|
||||
|
||||
The CPU_BIG_ENDIAN and CPU_LITTLE_ENDIAN are set to specify the endian
|
||||
format used by this microprocessor. These macros should not be set to the
|
||||
same value. The following example illustrates how these macros should be
|
||||
set on a processor family that is big endian.
|
||||
|
||||
@example
|
||||
#define CPU_BIG_ENDIAN TRUE
|
||||
#define CPU_LITTLE_ENDIAN FALSE
|
||||
@end example
|
||||
|
||||
@subsection Optional Endian Conversion Routines
|
||||
|
||||
In a networked environment, each program communicating must agree on the
|
||||
format of data passed between the various systems in the networked
|
||||
application. Routines such as ntohl() and htonl() are used to convert
|
||||
between the common network format and the native format used on this
|
||||
particular host system. Although RTEMS has a portable implementation of
|
||||
these endian conversion routines, it is often possible to implement these
|
||||
routines more efficiently in a processor specific fashion.
|
||||
|
||||
The CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES is set to TRUE when the port
|
||||
provides its own implementation of the network to host and host to network
|
||||
family of routines. This set of routines include the following:
|
||||
|
||||
@itemize @bullet
|
||||
@item XXX list of routines in bullets
|
||||
@end itemize
|
||||
|
||||
The following example illustrates how this macro should be set when the
|
||||
generic, portable implementation of this family of routines is to be used
|
||||
by this port:
|
||||
|
||||
@example
|
||||
#define CPU_HAS_OWN_HOST_TO_NETWORK_ROUTINES FALSE
|
||||
@end example
|
||||
|
||||
@section Extra Stack for MPCI Receive Thread
|
||||
|
||||
The CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK macro is set to the amount of
|
||||
stack space above the minimum thread stack space required by the MPCI
|
||||
Receive Server Thread. This macro is needed because in a multiprocessor
|
||||
system the MPCI Receive Server Thread must be able to process all
|
||||
directives.
|
||||
|
||||
@example
|
||||
#define CPU_MPCI_RECEIVE_SERVER_EXTRA_STACK 0
|
||||
@end example
|
||||
|
||||
@subsection Endian Swap Unsigned Integers
|
||||
|
||||
The port should provide routines to swap sixteen (CPU_swap_u16) and
|
||||
thirty-bit (CPU_swap_u32) unsigned integers. These are primarily used in
|
||||
two areas of RTEMS - multiprocessing support and the network endian swap
|
||||
routines. The CPU_swap_u32 routine must be implemented as a static
|
||||
routine rather than a macro because its address is taken and used
|
||||
indirectly. On the other hand, the CPU_swap_u16 routine may be
|
||||
implemented as a macro.
|
||||
|
||||
Some CPUs have special instructions that swap a 32-bit quantity in a
|
||||
single instruction (e.g. i486). It is probably best to avoid an "endian
|
||||
swapping control bit" in the CPU. One good reason is that interrupts
|
||||
would probably have to be disabled to insure that an interrupt does not
|
||||
try to access the same "chunk" with the wrong endian. Another good reason
|
||||
is that on some CPUs, the endian bit endianness for ALL fetches -- both
|
||||
code and data -- so the code will be fetched incorrectly.
|
||||
|
||||
The following is an implementation of the CPU_swap_u32 routine that will
|
||||
work on any CPU. It operates by breaking the unsigned thirty-two bit
|
||||
integer into four byte-wide quantities and reassemblying them.
|
||||
|
||||
@example
|
||||
static inline unsigned int CPU_swap_u32(
|
||||
unsigned int value
|
||||
)
|
||||
@{
|
||||
unsigned32 byte1, byte2, byte3, byte4, swapped;
|
||||
|
||||
byte4 = (value >> 24) & 0xff;
|
||||
byte3 = (value >> 16) & 0xff;
|
||||
byte2 = (value >> 8) & 0xff;
|
||||
byte1 = value & 0xff;
|
||||
|
||||
swapped = (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
|
||||
return( swapped );
|
||||
@}
|
||||
@end example
|
||||
|
||||
Although the above implementation is portable, it is not particularly
|
||||
efficient. So if there is a better way to implement this on a particular
|
||||
CPU family or model, please do so. The efficiency of this routine has
|
||||
significant impact on the efficiency of the multiprocessing support code
|
||||
in the shared memory driver and in network applications using the ntohl()
|
||||
family of routines.
|
||||
|
||||
Most microprocessor families have rotate instructions which can be used to
|
||||
greatly improve the CPU_swap_u32 routine. The most common way to do this
|
||||
is to:
|
||||
|
||||
@example
|
||||
swap least significant two bytes with 16-bit rotate
|
||||
swap upper and lower 16-bits
|
||||
swap most significant two bytes with 16-bit rotate
|
||||
@end example
|
||||
|
||||
Some CPUs have special instructions that swap a 32-bit quantity in a
|
||||
single instruction (e.g. i486). It is probably best to avoid an "endian
|
||||
swapping control bit" in the CPU. One good reason is that interrupts
|
||||
would probably have to be disabled to insure that an interrupt does not
|
||||
try to access the same "chunk" with the wrong endian. Another good reason
|
||||
is that on some CPUs, the endian bit endianness for ALL fetches -- both
|
||||
code and data -- so the code will be fetched incorrectly.
|
||||
|
||||
Similarly, here is a portable implementation of the CPU_swap_u16 routine.
|
||||
Just as with the CPU_swap_u32 routine, the porter should provide a better
|
||||
implementation if possible.
|
||||
|
||||
@example
|
||||
#define CPU_swap_u16( value ) \
|
||||
(((value&0xff) << 8) | ((value >> 8)&0xff))
|
||||
@end example
|
||||
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename porting
|
||||
@syncodeindex vr fn
|
||||
@synindex ky cp
|
||||
@paragraphindent 0
|
||||
@c @smallbook
|
||||
@c %**end of header
|
||||
|
||||
@c
|
||||
@c COPYRIGHT (c) 1988-1998.
|
||||
@c On-Line Applications Research Corporation (OAR).
|
||||
@c All rights reserved.
|
||||
@c
|
||||
@c $Id$
|
||||
@c
|
||||
|
||||
@c
|
||||
@c Master file for the Porting Guide
|
||||
@c
|
||||
|
||||
@c Joel's Questions
|
||||
@c
|
||||
@c 1. Why does paragraphindent only impact makeinfo?
|
||||
@c 2. Why does paragraphindent show up in HTML?
|
||||
@c
|
||||
|
||||
@include ../common/setup.texi
|
||||
|
||||
@ignore
|
||||
@ifinfo
|
||||
@format
|
||||
START-INFO-DIR-ENTRY
|
||||
* RTEMS Porting Guide: (porting). The Porting Guide
|
||||
END-INFO-DIR-ENTRY
|
||||
@end format
|
||||
@end ifinfo
|
||||
@end ignore
|
||||
|
||||
@c variable substitution info:
|
||||
@c
|
||||
@set is-C
|
||||
@clear is-Ada
|
||||
@set LANGUAGE C
|
||||
@set STRUCTURE structure
|
||||
@set ROUTINE function
|
||||
@set OR |
|
||||
@set RPREFIX RTEMS_
|
||||
@set DIRPREFIX rtems_
|
||||
@c the language is @value{LANGUAGE}
|
||||
@c NOTE: don't use underscore in the name
|
||||
@c
|
||||
|
||||
@c
|
||||
@c Title Page Stuff
|
||||
@c
|
||||
|
||||
@set edition @value{RTEMS-EDITION}
|
||||
@set version @value{RTEMS-VERSION}
|
||||
@set update-date @value{RTEMS-UPDATE-DATE}
|
||||
@set update-month @value{RTEMS-UPDATE-MONTH}
|
||||
|
||||
@c
|
||||
@c I don't really like having a short title page. --joel
|
||||
@c
|
||||
@c @shorttitlepage RTEMS Porting Guide
|
||||
|
||||
@setchapternewpage odd
|
||||
@settitle RTEMS Porting Guide
|
||||
@titlepage
|
||||
@finalout
|
||||
|
||||
@title RTEMS Porting Guide
|
||||
@subtitle Edition @value{edition}, for RTEMS @value{version}
|
||||
@sp 1
|
||||
@subtitle @value{update-month}
|
||||
@author On-Line Applications Research Corporation
|
||||
@page
|
||||
@include ../common/cpright.texi
|
||||
@end titlepage
|
||||
|
||||
@c This prevents a black box from being printed on "overflow" lines.
|
||||
@c The alternative is to rework a sentence to avoid this problem.
|
||||
|
||||
@include preface.texi
|
||||
@include developtools.texi
|
||||
@include sourcecode.texi
|
||||
@include cpumodels.texi
|
||||
@include cpuinit.texi
|
||||
@include interrupts.texi
|
||||
@include taskcontext.texi
|
||||
@include idlethread.texi
|
||||
@include prioritybitmap.texi
|
||||
@include codetuning.texi
|
||||
@include miscellaneous.texi
|
||||
@ifinfo
|
||||
@node Top, Preface, (dir), (dir)
|
||||
@top porting
|
||||
|
||||
This is the online version of the RTEMS Porting Guide.
|
||||
|
||||
@menu
|
||||
* Preface::
|
||||
* Development Tools::
|
||||
* Source Code Organization::
|
||||
* CPU Model Variations::
|
||||
* CPU Initialization::
|
||||
* Interrupts::
|
||||
* Task Context::
|
||||
* IDLE Thread::
|
||||
* Priority Bitmap Manipulation::
|
||||
* Code Tuning Parameters::
|
||||
* Miscellaneous::
|
||||
* Command and Variable Index::
|
||||
* Concept Index::
|
||||
@end menu
|
||||
|
||||
@end ifinfo
|
||||
@c
|
||||
@c
|
||||
@c Need to copy the emacs stuff and "trailer stuff" (index, toc) into here
|
||||
@c
|
||||
|
||||
@node Command and Variable Index, Concept Index, , Top
|
||||
@unnumbered Command and Variable Index
|
||||
|
||||
There are currently no Command and Variable Index entries.
|
||||
|
||||
@c @printindex fn
|
||||
|
||||
@node Concept Index, , Command and Variable Index, Top
|
||||
@unnumbered Concept Index
|
||||
|
||||
There are currently no Concept Index entries.
|
||||
@c @printindex cp
|
||||
|
||||
@contents
|
||||
@bye
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
|
||||
@chapter Preface
|
||||
|
||||
The purpose of this manual is to provide a roadmap to those people porting
|
||||
RTEMS to a new CPU family. This process includes a variety of activities
|
||||
including the following:
|
||||
|
||||
@itemize @bullet
|
||||
|
||||
@item targeting the GNU development tools
|
||||
|
||||
@item porting the RTEMS executive code
|
||||
|
||||
@item developing a Board Support Package
|
||||
|
||||
@item writing an RTEMS CPU Supplement manual for the completed port.
|
||||
|
||||
@end itemize
|
||||
|
||||
This document focuses on the process of actually porting the RTEMS
|
||||
executive code proper. Each of the data structures, routines, and macro
|
||||
definitions required of a port of RTEMS is described in this document.
|
||||
|
||||
Porting any operating system, including RTEMS, requires knowledge of the
|
||||
operating system, target CPU architecture, and debug environment. It is
|
||||
very desirable to have a CPU simulator or hardware emulator when debugging
|
||||
the port. This manual assumes that the user is familiar with building and
|
||||
using RTEMS, the C programming language, and the target CPU architecture.
|
||||
It is desirable to be familiar with the assembly language for the target
|
||||
CPU family but since only a limited amount of assembly is required to port
|
||||
RTEMS.
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
@chapter Priority Bitmap Manipulation
|
||||
|
||||
@section Introduction
|
||||
|
||||
The RTEMS chain of ready tasks is implemented as an array of FIFOs with
|
||||
each priority having its own FIFO. This makes it very efficient to
|
||||
determine the first and last ready task at each priority. In addition,
|
||||
blocking a task only requires appending the task to the end of the FIFO
|
||||
for its priority rather than a lengthy search down a single chain of all
|
||||
ready tasks. This works extremely well except for one problem. When the
|
||||
currently executing task blocks, there may be no easy way to determine
|
||||
what is the next most important ready task. If the blocking task was the
|
||||
only ready task at its priority, then RTEMS must search all of the FIFOs
|
||||
in the ready chain to determine the highest priority with a ready task.
|
||||
|
||||
RTEMS uses a bitmap array to efficiently solve this problem. The state of
|
||||
each bit in the priority map bit array indicates whether or not there is a
|
||||
ready task at that priority. The bit array can be efficiently searched to
|
||||
determine the highest priority ready task. This family of data type and
|
||||
routines is used to maintain and search the bit map array.
|
||||
|
||||
@section _Priority_Bit_map_control Type
|
||||
|
||||
The _Priority_Bit_map_Control type is the fundamental data type of the
|
||||
priority bit map array used to determine which priorities have ready
|
||||
tasks. This type may be either 16 or 32 bits wide although only the 16
|
||||
least significant bits will be used. The data type is based upon what is
|
||||
the most efficient type for this CPU to manipulate. For example, some
|
||||
CPUs have bit scan instructions that only operate on a particular size of
|
||||
data. In this case, this type will probably be defined to work with this
|
||||
instruction.
|
||||
|
||||
@section Find First Bit Routine
|
||||
|
||||
The _CPU_Bitfield_Find_first_bit routine sets _output to the bit number of
|
||||
the first bit set in _value. _value is of CPU dependent type
|
||||
Priority_Bit_map_control. A stub version of this routine is as follows:
|
||||
|
||||
@example
|
||||
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
|
||||
@{ \
|
||||
(_output) = 0; /* do something to prevent warnings */ \
|
||||
@}
|
||||
@end example
|
||||
|
||||
There are a number of variables in using a "find first bit" type
|
||||
instruction.
|
||||
|
||||
@enumerate
|
||||
|
||||
@item What happens when run on a value of zero?
|
||||
|
||||
@item Bits may be numbered from MSB to LSB or vice-versa.
|
||||
|
||||
@item The numbering may be zero or one based.
|
||||
|
||||
@item The "find first bit" instruction may search from MSB or LSB.
|
||||
|
||||
@end itemize
|
||||
|
||||
RTEMS guarantees that (1) will never happen so it is not a concern.
|
||||
Cases (2),(3), (4) are handled by the macros _CPU_Priority_mask() and
|
||||
_CPU_Priority_bits_index(). These three form a set of routines which must
|
||||
logically operate together. Bits in the _value are set and cleared based
|
||||
on masks built by CPU_Priority_mask(). The basic major and minor values
|
||||
calculated by _Priority_Major() and _Priority_Minor() are "massaged" by
|
||||
_CPU_Priority_bits_index() to properly range between the values returned
|
||||
by the "find first bit" instruction. This makes it possible for
|
||||
_Priority_Get_highest() to calculate the major and directly index into the
|
||||
minor table. This mapping is necessary to ensure that 0 (a high priority
|
||||
major/minor) is the first bit found.
|
||||
|
||||
This entire "find first bit" and mapping process depends heavily on the
|
||||
manner in which a priority is broken into a major and minor components
|
||||
with the major being the 4 MSB of a priority and minor the 4 LSB. Thus (0
|
||||
<< 4) + 0 corresponds to priority 0 -- the highest priority. And (15 <<
|
||||
4) + 14 corresponds to priority 254 -- the next to the lowest priority.
|
||||
|
||||
If your CPU does not have a "find first bit" instruction, then there are
|
||||
ways to make do without it. Here are a handful of ways to implement this
|
||||
in software:
|
||||
|
||||
@itemize @bullet
|
||||
|
||||
@item a series of 16 bit test instructions
|
||||
|
||||
@item a "binary search using if's"
|
||||
|
||||
@item the following algorithm based upon a 16 entry lookup table. In this pseudo-code, bit_set_table[16] has values which indicate the first bit set:
|
||||
|
||||
@example
|
||||
_number = 0 if _value > 0x00ff
|
||||
_value >>=8
|
||||
_number = 8;
|
||||
if _value > 0x0000f
|
||||
_value >=8
|
||||
_number += 4
|
||||
|
||||
_number += bit_set_table[ _value ]
|
||||
@end example
|
||||
|
||||
@end itemize
|
||||
|
||||
The following illustrates how the CPU_USE_GENERIC_BITFIELD_CODE macro may
|
||||
be so the port can use the generic implementation of this bitfield code.
|
||||
This can be used temporarily during the porting process to avoid writing
|
||||
these routines until the end. This results in a functional although lower
|
||||
performance port. This is perfectly acceptable during development and
|
||||
testing phases.
|
||||
|
||||
@example
|
||||
#define CPU_USE_GENERIC_BITFIELD_CODE TRUE
|
||||
#define CPU_USE_GENERIC_BITFIELD_DATA TRUE
|
||||
@end example
|
||||
|
||||
Eventually, CPU specific implementations of these routines are usually
|
||||
written since they dramatically impact the performance of blocking
|
||||
operations. However they may take advantage of instructions which are not
|
||||
available on all models in the CPU family. In this case, one might find
|
||||
something like this stub example did:
|
||||
|
||||
@example
|
||||
#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
|
||||
#define _CPU_Bitfield_Find_first_bit( _value, _output ) \
|
||||
@{ \
|
||||
(_output) = 0; /* do something to prevent warnings */ \
|
||||
@}
|
||||
#endif
|
||||
@end example
|
||||
|
||||
@section Build Bit Field Mask
|
||||
|
||||
The _CPU_Priority_Mask routine builds the mask that corresponds to the bit
|
||||
fields searched by _CPU_Bitfield_Find_first_bit(). See the discussion of
|
||||
that routine for more details.
|
||||
|
||||
The following is a typical implementation when the
|
||||
_CPU_Bitfield_Find_first_bit searches for the most significant bit set:
|
||||
|
||||
@example
|
||||
#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
|
||||
#define _CPU_Priority_Mask( _bit_number ) \
|
||||
( 1 << (_bit_number) )
|
||||
#endif
|
||||
@end example
|
||||
|
||||
@section Bit Scan Support
|
||||
|
||||
The _CPU_Priority_bits_index routine translates the bit numbers returned by _CPU_Bitfield_Find_first_bit() into something suitable for use as a major or minor component of a priority. For example, the find first bit routine may number the bits in a way that is difficult to map into the major and minor components of the priority. This routine allows that unwieldy form to be converted into something easier to process. See the discussion of that routine for more details.
|
||||
|
||||
@example
|
||||
#if (CPU_USE_GENERIC_BITFIELD_CODE == FALSE)
|
||||
#define _CPU_Priority_bits_index( _priority ) \
|
||||
(_priority)
|
||||
#endif
|
||||
@end example
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
@chapter Source Code Organization
|
||||
|
||||
This section describes the organization of the source code within RTEMS
|
||||
that is CPU family and CPU model dependent.
|
||||
|
||||
@section Introduction
|
||||
|
||||
The CPU family dependent files associated with a port of the RTEMS
|
||||
executive code proper to a particular processor family are found in
|
||||
c/src/exec/score/cpu. Support code for this port as well as processor
|
||||
dependent code which may be reused across multiple Board Support Packages
|
||||
is found in c/src/lib/libcpu.
|
||||
|
||||
XXX list the files and directories here
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user