summaryrefslogtreecommitdiffstats
path: root/doc/porting/miscellaneous.t
blob: cba85f7963c0070fb8d496aefcbfc6141fe03092 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
@c
@c  COPYRIGHT (c) 1988-2002.
@c  On-Line Applications Research Corporation (OAR).
@c  All rights reserved.

@chapter Miscellaneous

@section Fatal Error Default Handler

The @code{_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 CPU Context Validation

The test case @code{sptests/spcontext01} ensures that the context switching and
interrupt processing works.  This test uses two support functions provided by
the CPU port.  These two functions are only used for this test and have no
other purpose.

@example
void _CPU_Context_volatile_clobber( uintptr_t pattern );

void _CPU_Context_validate( uintptr_t pattern );
@end example

The @code{_CPU_Context_volatile_clobber()} function clobbers all volatile
registers with values derived from the pattern parameter.  This makes sure that
the interrupt prologue code restores all volatile registers of the interrupted
context.

The @code{_CPU_Context_validate()} function initializes and validates the CPU
context with values derived from the pattern parameter.  This function will not
return if the CPU context remains consistent.  In case this function returns
the CPU port is broken.  The test uses two threads which concurrently validate
the CPU context with a different patterns for each thread.  This ensures that
the context switching code works.

@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 @code{CPU_BIG_ENDIAN} and @code{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

The @code{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 (@code{CPU_swap_u16}) and
thirty-bit (@code{CPU_swap_u32}) unsigned integers.  These are primarily used in
two areas of RTEMS - multiprocessing support and the network endian swap
routines.  The @code{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 @code{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 @code{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 @code{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 @code{CPU_swap_u16}
routine.  Just as with the @code{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