2. Port Specific Information#
This chaper provides a general description of the type of architecture specific information which is in each of the architecture specific chapters that follow. The outline of this chapter is identical to that of the architecture specific chapters.
In each of the architecture specific chapters, this introductory section will provide an overview of the architecture:
Architecture Documents
In each of the architecture specific chapters, this section will provide pointers on where to obtain documentation.
2.1. CPU Model Dependent Features#
Microprocessors are generally classified into families with a variety of CPU models or implementations within that family. Within a processor family, there is a high level of binary compatibility. This family may be based on either an architectural specification or on maintaining compatibility with a popular processor. Recent microprocessor families such as the SPARC or PowerPC are based on an architectural specification which is independent or any particular CPU model or implementation. Older families such as the Motorola 68000 and the Intel x86 evolved as the manufacturer strived to produce higher performance processor models which maintained binary compatibility with older models.
RTEMS takes advantage of the similarity of the various models within a CPU family. Although the models do vary in significant ways, the high level of compatibility makes it possible to share the bulk of the CPU dependent executive code across the entire family. Each processor family supported by RTEMS has a list of features which vary between CPU models within a family. For example, the most common model dependent feature regardless of CPU family is the presence or absence of a floating point unit or coprocessor. When defining the list of features present on a particular CPU model, one simply notes that floating point hardware is or is not present and defines a single constant appropriately. Conditional compilation is utilized to include the appropriate source code for this CPU model’s feature set. It is important to note that this means that RTEMS is thus compiled using the appropriate feature set and compilation flags optimal for this CPU model used. The alternative would be to generate a binary which would execute on all family members using only the features which were always present.
The set of CPU model feature macros are defined in the
cpukit/score/cpu/CPU/rtems/score/cpu.h
based upon the GNU tools
multilib variant that is appropriate for the particular CPU model defined on
the compilation command line.
In each of the architecture specific chapters, this section presents the set of features which vary across various implementations of the architecture that may be of importance to RTEMS application developers.
The subsections will vary amongst the target architecture chapters as the specific features may vary. However, each port will include a few common features such as the CPU Model Name and presence of a hardware Floating Point Unit. The common features are described here.
2.1.1. CPU Model Name#
The macro CPU_MODEL_NAME
is a string which designates the name of this CPU
model. For example, for the MC68020 processor model from the m68k
architecture, this macro is set to the string “mc68020”.
2.1.2. Floating Point Unit#
In most architectures, the presence of a floating point unit is an option. It does not matter whether the hardware floating point support is incorporated on-chip or is an external coprocessor as long as it appears an FPU per the ISA. However, if a hardware FPU is not present, it is possible that the floating point emulation library for this CPU is not reentrant and thus context switched by RTEMS.
RTEMS provides two feature macros to indicate the FPU configuration:
CPU_HARDWARE_FP is set to TRUE to indicate that a hardware FPU is present.
CPU_SOFTWARE_FP is set to TRUE to indicate that a hardware FPU is not present and that the FP software emulation will be context switched.
2.2. Multilibs#
Newlib and GCC provide several target libraries like the libc.a
,
libm.a
and libgcc.a
. These libraries are artifacts of the GCC
build process. Newlib is built together with GCC. To provide optimal support
for various chip derivatives and instruction set revisions multiple variants of
these libraries are available for each architecture. For example one set may
use software floating point support and another set may use hardware floating
point instructions. These sets of libraries are called multilibs. Each
library set corresponds to an application binary interface (ABI) and
instruction set.
A multilib variant can be usually detected via built-in compiler defines at
compile-time. This mechanism is used by RTEMS to select for example the
context switch support for a particular BSP. The built-in compiler defines
corresponding to multilibs are the only architecture specific defines allowed
in the cpukit
area of the RTEMS sources.
Invoking the GCC with the -print-multi-lib
option lists the available
multilibs. Each line of the output describes one multilib variant. The
default variant is denoted by .
which is selected when no or contradicting
GCC machine options are selected. The multilib selection for a target is
specified by target makefile fragments (see file t-rtems
in the GCC
sources and section The Target Makefile Fragment
(https://gcc.gnu.org/onlinedocs/gccint/Target-Fragment.html#Target-Fragment)
in the GCC Internals Manual (https://gcc.gnu.org/onlinedocs/gccint/).
2.3. Calling Conventions#
Each high-level language compiler generates subroutine entry and exit code based upon a set of rules known as the compiler’s calling convention. These rules address the following issues:
register preservation and usage
parameter passing
call and return mechanism
A compiler’s calling convention is of importance when interfacing to subroutines written in another language either assembly or high-level. Even when the high-level language and target processor are the same, different compilers may use different calling conventions. As a result, calling conventions are both processor and compiler dependent.
2.3.1. Calling Mechanism#
In each of the architecture specific chapters, this subsection will describe the instruction(s) used to perform a normal subroutine invocation. All RTEMS directives are invoked as normal C language functions so it is important to the user application to understand the call and return mechanism.
2.3.2. Register Usage#
In each of the architecture specific chapters, this subsection will detail the set of registers which are NOT preserved across subroutine invocations. The registers which are not preserved are assumed to be available for use as scratch registers. Therefore, the contents of these registers should not be assumed upon return from any RTEMS directive.
In some architectures, there may be a set of registers made available automatically as a side-effect of the subroutine invocation mechanism.
2.3.3. Parameter Passing#
In each of the architecture specific chapters, this subsection will describe the mechanism by which the parameters or arguments are passed by the caller to a subroutine. In some architectures, all parameters are passed on the stack while in others some are passed in registers.
2.3.4. User-Provided Routines#
All user-provided routines invoked by RTEMS, such as user extensions, device drivers, and MPCI routines, must also adhere to these calling conventions.
2.4. Memory Model#
A processor may support any combination of memory models ranging from pure physical addressing to complex demand paged virtual memory systems. RTEMS supports a flat memory model which ranges contiguously over the processor’s allowable address space. RTEMS does not support segmentation or virtual memory of any kind. The appropriate memory model for RTEMS provided by the targeted processor and related characteristics of that model are described in this chapter.
2.4.1. Flat Memory Model#
Most RTEMS target processors can be initialized to support a flat address space. Although the size of addresses varies between architectures, on most RTEMS targets, an address is 32-bits wide which defines addresses ranging from 0x00000000 to 0xFFFFFFFF (4 gigabytes). Each address is represented by a 32-bit value and is byte addressable. The address may be used to reference a single byte, word (2-bytes), or long word (4 bytes). Memory accesses within this address space may be performed in little or big endian fashion.
On smaller CPU architectures supported by RTEMS, the address space may only be 20 or 24 bits wide.
If the CPU model has support for virtual memory or segmentation, it is the responsibility of the Board Support Package (BSP) to initialize the MMU hardware to perform address translations which correspond to flat memory model.
In each of the architecture specific chapters, this subsection will describe any architecture characteristics that differ from this general description.
2.5. Interrupt Processing#
Different types of processors respond to the occurrence of an interrupt in its own unique fashion. In addition, each processor type provides a control mechanism to allow for the proper handling of an interrupt. The processor dependent response to the interrupt modifies the current execution state and results in a change in the execution stream. Most processors require that an interrupt handler utilize some special control mechanisms to return to the normal processing stream. Although RTEMS hides many of the processor dependent details of interrupt processing, it is important to understand how the RTEMS interrupt manager is mapped onto the processor’s unique architecture.
RTEMS supports a dedicated interrupt stack for all architectures. On architectures with hardware support for a dedicated interrupt stack, it will be initialized such that when an interrupt occurs, the processor automatically switches to this dedicated stack. On architectures without hardware support for a dedicated interrupt stack which is separate from those of the tasks, RTEMS will support switching to a dedicated stack for interrupt processing.
Without a dedicated interrupt stack, every task in the system must have enough stack space to accommodate the worst case stack usage of that particular task and the interrupt service routines combined. By supporting a dedicated interrupt stack, RTEMS significantly lowers the stack requirements for each task.
A nested interrupt is processed similarly with the exception that since the CPU is already executing on the interrupt stack, there is no need to switch to the interrupt stack.
The interrupt stacks (one for each configured processor) are statically
allocated by the application configuration via <rtems/confdefs.h>
in the
special section .rtemsstack
. This enables an optimal placement of the
interrupt stacks by the Board Support Package (BSP), e.g. a fast on-chip
memory. The amount of memory allocated for each interrupt stack is user
configured and based upon the <rtems/confdefs.h>
parameter
CONFIGURE_INTERRUPT_STACK_SIZE
. This parameter is described in detail in
the Configuring a System chapter of the User’s Guide. Since interrupts are
disabled during the sequential system initialization and the
_Thread_Start_multitasking()
function does not return to the caller each
interrupt stack may be used for the initialization stack on the corresponding
processor.
In each of the architecture specific chapters, this section discusses the interrupt response and control mechanisms of the architecture as they pertain to RTEMS.
2.5.1. Vectoring of an Interrupt Handler#
In each of the architecture specific chapters, this subsection will describe the architecture specific details of the interrupt vectoring process. In particular, it should include a description of the Interrupt Stack Frame (ISF).
2.5.2. Interrupt Levels#
In each of the architecture specific chapters, this subsection will describe how the interrupt levels available on this particular architecture are mapped onto the 255 reserved in the task mode. The interrupt level value of zero (0) should always mean that interrupts are enabled.
Any use of an interrupt level that is is not undefined on a particular architecture may result in behavior that is unpredictable.
2.5.3. Disabling of Interrupts by RTEMS#
During the execution of directive calls, critical sections of code may be executed. When these sections are encountered, RTEMS disables all external interrupts before the execution of this section and restores them to the previous level upon completion of the section. RTEMS has been optimized to ensure that interrupts are disabled for the shortest number of instructions possible. Since the precise number of instructions and their execution time varies based upon target CPU family, CPU model, board memory speed, compiler version, and optimization level, it is not practical to provide the precise number for all possible RTEMS configurations.
Historically, the measurements were made by hand analyzing and counting the execution time of instruction sequences during interrupt disable critical sections. For reference purposes, on a 16 Mhz Motorola MC68020, the maximum interrupt disable period was typically approximately ten (10) to thirteen (13) microseconds. This architecture was memory bound and had a slow bit scan instruction. In contrast, during the same period a 14 Mhz SPARC would have a worst case disable time of approximately two (2) to three (3) microseconds because it had a single cycle bit scan instruction and used fewer cycles for memory accesses.
If you are interested in knowing the worst case execution time for a particular version of RTEMS, please contact OAR Corporation and we will be happy to product the results as a consulting service.
Non-maskable interrupts (NMI) cannot be disabled, and ISRs which execute at this level MUST NEVER issue RTEMS system calls. If a directive is invoked, unpredictable results may occur due to the inability of RTEMS to protect its critical sections. However, ISRs that make no system calls may safely execute as non-maskable interrupts.
2.6. Symmetric Multiprocessing#
This section contains information about the Symmetric Multiprocessing (SMP) status of a particular architecture.
2.7. Thread-Local Storage#
In order to support thread-local storage (TLS) the CPU port must implement the
facilities mandated by the application binary interface (ABI) of the CPU
architecture. The CPU port must initialize the TLS area in the
_CPU_Context_Initialize()
function. There are support functions available
via #include <rtems/score/tls.h>
which implement Variants I and II
according to [Dre13].
_TLS_TCB_at_area_begin_initialize()
Uses Variant I, TLS offsets emitted by linker takes the TCB into account. For a reference implementation see
cpukit/score/cpu/arm/cpu.c
._TLS_TCB_before_TLS_block_initialize()
Uses Variant I, TLS offsets emitted by linker neglects the TCB. For a reference implementation see
c/src/lib/libcpu/powerpc/new-exceptions/cpu.c
._TLS_TCB_after_TLS_block_initialize()
Uses Variant II. For a reference implementation see
cpukit/score/cpu/sparc/cpu.c
.
The board support package (BSP) must provide the following sections and symbols in its linker command file:
.tdata : {
_TLS_Data_begin = .;
*(.tdata .tdata.* .gnu.linkonce.td.*)
_TLS_Data_end = .;
}
.tbss : {
_TLS_BSS_begin = .;
*(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon)
_TLS_BSS_end = .;
}
_TLS_Data_size = _TLS_Data_end - _TLS_Data_begin;
_TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin;
_TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin;
_TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin;
_TLS_Size = _TLS_BSS_end - _TLS_Data_begin;
_TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss));
2.8. CPU counter#
The CPU support must implement the CPU counter interface. A CPU counter is
some free-running counter. It ticks usually with a frequency close to the CPU
or system bus clock. On some architectures the actual implementation is board
support package dependent. The CPU counter is used for profiling of low-level
functions. It is also used to implement two busy wait functions
rtems_counter_delay_ticks()
and rtems_counter_delay_nanoseconds()
which
may be used in device drivers. It may be also used as an entropy source for
random number generators.
The CPU counter interface uses a CPU port specific unsigned integer type
CPU_Counter_ticks
to represent CPU counter values. The CPU port must
provide the following two functions
_CPU_Counter_read()
to read the current CPU counter value, and_CPU_Counter_difference()
to get the difference between two CPU counter values.
2.9. Interrupt Profiling#
The RTEMS profiling needs support by the CPU port for the interrupt entry and
exit times. In case profiling is enabled via the RTEMS build configuration
option --enable-profiling
(in this case the pre-processor symbol
RTEMS_PROFILING
is defined) the CPU port may provide data for the interrupt
entry and exit times of the outer-most interrupt. The CPU port can feed
interrupt entry and exit times with the
_Profiling_Outer_most_interrupt_entry_and_exit()
function (#include
<rtems/score/profiling.h>
). For an example please have a look at
cpukit/score/cpu/arm/arm_exc_interrupt.S
.
2.10. Board Support Packages#
An RTEMS Board Support Package (BSP) must be designed to support a particular processor model and target board combination.
In each of the architecture specific chapters, this section will present a
discussion of architecture specific BSP issues. For more information on
developing a BSP, refer to RTEMS BSP and Driver Guide chapter titled
Board Support Packages
in the RTEMS Classic API Guide.
2.10.1. System Reset#
An RTEMS based application is initiated or re-initiated when the processor is reset or transfer is passed to it from a boot monitor or ROM monitor.
In each of the architecture specific chapters, this subsection describes the actions that the BSP must take assuming the application gets control when the microprocessor is reset.